1 | #ifdef OS2 |
---|
2 | #ifdef NT |
---|
3 | char *ckzv = "Win32 File support, 6.0.115 19 Nov 96"; |
---|
4 | #else /* NT */ |
---|
5 | char *ckzv = "OS/2 File support, 6.0.115 19 Nov 96"; |
---|
6 | #endif /* NT */ |
---|
7 | #else |
---|
8 | #ifdef aegis |
---|
9 | char *ckzv = "Aegis File support, 6.0.115 6 Sep 96"; |
---|
10 | #else |
---|
11 | #ifdef Plan9 |
---|
12 | char *ckzv = "Plan 9 File support, 6.0.115 6 Sep 96"; |
---|
13 | #else |
---|
14 | char *ckzv = "UNIX File support, 6.0.115 6 Sep 96"; |
---|
15 | #endif /* Plan9 */ |
---|
16 | #endif /* aegis */ |
---|
17 | #endif /* OS2 */ |
---|
18 | |
---|
19 | /* C K U F I O -- Kermit file system support for UNIX, OS/2, and Aegis */ |
---|
20 | |
---|
21 | |
---|
22 | /* |
---|
23 | NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be |
---|
24 | compatible with C preprocessors that support only #ifdef, #else, #endif, |
---|
25 | #define, and #undef. Please do not use #if, logical operators, or other |
---|
26 | preprocessor features in any of the portable C-Kermit modules. You can, |
---|
27 | of course, use these constructions in system-specific modules when you they |
---|
28 | are supported. |
---|
29 | */ |
---|
30 | |
---|
31 | /* |
---|
32 | Author: Frank da Cruz (fdc@columbia.edu), |
---|
33 | Columbia University Academic Information Systems, New York City, |
---|
34 | and others noted below. |
---|
35 | |
---|
36 | Copyright (C) 1985, 1996, Trustees of Columbia University in the City of New |
---|
37 | York. All rights reserved. |
---|
38 | */ |
---|
39 | |
---|
40 | /* Include Files */ |
---|
41 | |
---|
42 | #include "ckcsym.h" |
---|
43 | #include "ckcdeb.h" |
---|
44 | #include "ckcasc.h" |
---|
45 | #ifdef OS2 |
---|
46 | #include "ckuusr.h" |
---|
47 | #include <stdio.h> |
---|
48 | _PROTOTYP( int os2settitle, (char *, int) ); |
---|
49 | extern int priority; |
---|
50 | #ifdef NT |
---|
51 | #define timezone _timezone |
---|
52 | #define write _write |
---|
53 | #define fileno _fileno |
---|
54 | #ifndef SEM_INDEFINITE_WAIT |
---|
55 | #define SEM_INDEFINITE_WAIT INFINITE |
---|
56 | #endif /* SEM_INDEFINITE_WAIT */ |
---|
57 | #endif /* NT */ |
---|
58 | #endif /* OS2 */ |
---|
59 | #include <signal.h> |
---|
60 | |
---|
61 | #ifdef MINIX |
---|
62 | #include <limits.h> |
---|
63 | #else |
---|
64 | #ifdef POSIX |
---|
65 | #include <limits.h> |
---|
66 | #else |
---|
67 | #ifdef SVR3 |
---|
68 | #include <limits.h> |
---|
69 | #endif /* SVR3 */ |
---|
70 | #endif /* POSIX */ |
---|
71 | #endif /* MINIX */ |
---|
72 | |
---|
73 | /* Directory structure header file */ |
---|
74 | |
---|
75 | #ifdef OS2 |
---|
76 | /* |
---|
77 | |
---|
78 | C-Kermit's OS/2 support originally by Chris Adie <C.Adie@uk.ac.edinburgh> |
---|
79 | Edinburgh University Computing Service, Scotland, for C-Kermit 4F. Adapted |
---|
80 | to C-Kermit 5A and integrated into the UNIX support module by Kai Uwe Rommel |
---|
81 | <rommel@informatik.tu-muenchen.de>, Muenchen, Germany, December 1991. |
---|
82 | */ |
---|
83 | |
---|
84 | /* |
---|
85 | Directory Separator macros, to allow this module to work with both UNIX and |
---|
86 | OS/2: Because of ambiguity with the command line editor escape \ character, |
---|
87 | the directory separator is currently left as / for OS/2 too, because the |
---|
88 | OS/2 kernel also accepts / as directory separator. But this is subject to |
---|
89 | change in future versions to conform to the normal OS/2 style. |
---|
90 | */ |
---|
91 | #define DIRSEP '/' |
---|
92 | /* #define DIRSEP '\\' */ |
---|
93 | #define ISDIRSEP(c) ((c)=='/'||(c)=='\\') |
---|
94 | #else /* not OS2 */ |
---|
95 | #define DIRSEP '/' |
---|
96 | #define ISDIRSEP(c) ((c)=='/') |
---|
97 | #endif /* OS2 */ |
---|
98 | |
---|
99 | #ifdef SDIRENT |
---|
100 | #define DIRENT |
---|
101 | #endif /* SDIRENT */ |
---|
102 | |
---|
103 | #ifdef XNDIR |
---|
104 | #include <sys/ndir.h> |
---|
105 | #else /* !XNDIR */ |
---|
106 | #ifdef NDIR |
---|
107 | #include <ndir.h> |
---|
108 | #else /* !NDIR, !XNDIR */ |
---|
109 | #ifdef RTU |
---|
110 | #include "/usr/lib/ndir.h" |
---|
111 | #else /* !RTU, !NDIR, !XNDIR */ |
---|
112 | #ifdef DIRENT |
---|
113 | #ifdef SDIRENT |
---|
114 | #include <sys/dirent.h> |
---|
115 | #else |
---|
116 | #include <dirent.h> |
---|
117 | #endif /* SDIRENT */ |
---|
118 | #else |
---|
119 | #ifdef OS2 |
---|
120 | #define OPENDIR |
---|
121 | #define DIRENT |
---|
122 | #include "ckodir.h" |
---|
123 | #else/* !RTU, !NDIR, !XNDIR, !DIRENT, !OS2, i.e. all others */ |
---|
124 | #include <sys/dir.h> |
---|
125 | #endif /* OS2 */ |
---|
126 | #endif /* DIRENT */ |
---|
127 | #endif /* RTU */ |
---|
128 | #endif /* NDIR */ |
---|
129 | #endif /* XNDIR */ |
---|
130 | |
---|
131 | #ifdef OS2 /* OS/2 file system interface */ |
---|
132 | #define BSD4 /* is like Berkeley UNIX */ |
---|
133 | #define NOFILEH /* with no <file.h> */ |
---|
134 | #include <sys/utime.h> |
---|
135 | #include <stdlib.h> |
---|
136 | #include <process.h> |
---|
137 | #include <share.h> |
---|
138 | extern int binary; /* We need to know this for open() */ |
---|
139 | extern int fncact; /* Need this for zchkspa() */ |
---|
140 | extern int tlevel, cmdlvl ; /* Need this for external commands */ |
---|
141 | #ifdef __IBMC__ |
---|
142 | extern FILE *popen(char *, char *); |
---|
143 | extern int pclose(FILE *); |
---|
144 | #else |
---|
145 | #ifndef __EMX__ |
---|
146 | #define popen _popen |
---|
147 | #define pclose _pclose |
---|
148 | #define fopen(n, m) _fsopen(n, m, SH_DENYWR) |
---|
149 | #endif /* __EMX__ */ |
---|
150 | #endif /* __IBMC__ */ |
---|
151 | #ifdef NT |
---|
152 | #include <io.h> |
---|
153 | #endif /* NT */ |
---|
154 | #else /* OS2 */ |
---|
155 | #include <pwd.h> /* Password file for shell name */ |
---|
156 | #endif /* OS2 */ |
---|
157 | |
---|
158 | #ifdef POSIX |
---|
159 | #define UTIMEH |
---|
160 | #endif /* POSIX */ |
---|
161 | |
---|
162 | #ifndef OS2 |
---|
163 | #ifdef SYSUTIMEH /* <sys/utime.h> if requested, */ |
---|
164 | #include <sys/utime.h> /* for extra fields required by */ |
---|
165 | #else /* 88Open spec. */ |
---|
166 | #ifdef UTIMEH /* or <utime.h> if requested */ |
---|
167 | #include <utime.h> /* (SVR4, POSIX) */ |
---|
168 | #define SYSUTIMEH /* Use this for both cases. */ |
---|
169 | #endif /* UTIMEH */ |
---|
170 | #endif /* SYSUTIMEH */ |
---|
171 | #endif /* OS2 */ |
---|
172 | |
---|
173 | #ifdef POSIX |
---|
174 | #define TIMESTAMP |
---|
175 | #endif /* POSIX */ |
---|
176 | |
---|
177 | #ifdef BSD44 /* BSD 4.4 */ |
---|
178 | #ifndef TIMESTAMP |
---|
179 | #define TIMESTAMP /* Can do file dates */ |
---|
180 | #endif /* TIMESTAMP */ |
---|
181 | #include <sys/time.h> |
---|
182 | #include <sys/timeb.h> |
---|
183 | |
---|
184 | #else /* Not BSD44 */ |
---|
185 | |
---|
186 | #ifdef BSD4 /* BSD 4.3 and below */ |
---|
187 | #define TIMESTAMP /* Can do file dates */ |
---|
188 | #include <time.h> /* Need this */ |
---|
189 | #include <sys/timeb.h> /* Need this if really BSD */ |
---|
190 | |
---|
191 | #else /* Not BSD 4.3 and below */ |
---|
192 | |
---|
193 | #ifdef SVORPOSIX /* System V or POSIX */ |
---|
194 | #ifndef TIMESTAMP |
---|
195 | #define TIMESTAMP |
---|
196 | #endif /* TIMESTAMP */ |
---|
197 | #include <time.h> |
---|
198 | |
---|
199 | /* void tzset(); (the "void" type upsets some compilers) */ |
---|
200 | #ifndef IRIX60 |
---|
201 | #ifndef ultrix |
---|
202 | #ifndef CONVEX9 |
---|
203 | /* ConvexOS 9.0, supposedly POSIX, has extern char *timezone(int,int) */ |
---|
204 | #ifndef Plan9 |
---|
205 | extern long timezone; |
---|
206 | #endif /* Plan9 */ |
---|
207 | #endif /* CONVEX9 */ |
---|
208 | #endif /* ultrix */ |
---|
209 | #endif /* IRIX60 */ |
---|
210 | #endif /* SVORPOSIX */ |
---|
211 | #endif /* BSD4 */ |
---|
212 | #endif /* BSD44 */ |
---|
213 | |
---|
214 | /* Is `y' a leap year? */ |
---|
215 | #define leap(y) (((y) % 4 == 0 && (y) % 100 != 0) || (y) % 400 == 0) |
---|
216 | |
---|
217 | /* Number of leap years from 1970 to `y' (not including `y' itself). */ |
---|
218 | #define nleap(y) (((y) - 1969) / 4 - ((y) - 1901) / 100 + ((y) - 1601) / 400) |
---|
219 | |
---|
220 | #ifdef CIE |
---|
221 | #include <stat.h> /* File status */ |
---|
222 | #else |
---|
223 | #include <sys/stat.h> |
---|
224 | |
---|
225 | #ifdef OS2 |
---|
226 | #include <sys/types.h> |
---|
227 | |
---|
228 | /* Because standard stat has trouble with trailing /'s we have to wrap it */ |
---|
229 | |
---|
230 | #ifdef NT |
---|
231 | int os2stat(char *, struct _stat *); |
---|
232 | #else /* NT */ |
---|
233 | int os2stat(char *, struct stat *); |
---|
234 | #endif /* NT */ |
---|
235 | |
---|
236 | #ifdef __IBMC__ |
---|
237 | #ifdef system |
---|
238 | #undef system |
---|
239 | #endif |
---|
240 | #ifdef stat |
---|
241 | #undef stat |
---|
242 | #define __IBMC__STAT |
---|
243 | #endif |
---|
244 | #endif |
---|
245 | #define stat(path, buf) os2stat(path, buf) |
---|
246 | #endif /* OS2 */ |
---|
247 | #endif /* CIE */ |
---|
248 | |
---|
249 | /* |
---|
250 | Functions (n is one of the predefined file numbers from ckcker.h): |
---|
251 | |
---|
252 | zopeni(n,name) -- Opens an existing file for input. |
---|
253 | zopeno(n,name,attr,fcb) -- Opens a new file for output. |
---|
254 | zclose(n) -- Closes a file. |
---|
255 | zchin(n,&c) -- Gets the next character from an input file. |
---|
256 | zsinl(n,&s,x) -- Read a line from file n, max len x, into address s. |
---|
257 | zsout(n,s) -- Write a null-terminated string to output file, buffered. |
---|
258 | zsoutl(n,s) -- Like zsout, but appends a line terminator. |
---|
259 | zsoutx(n,s,x) -- Write x characters to output file, unbuffered. |
---|
260 | zchout(n,c) -- Add a character to an output file, unbuffered. |
---|
261 | zchki(name) -- Check if named file exists and is readable, return size. |
---|
262 | zchko(name) -- Check if named file can be created. |
---|
263 | zchkspa(name,n) -- Check if n bytes available to create new file, name. |
---|
264 | znewn(name,s) -- Make a new unique file name based on the given name. |
---|
265 | zdelet(name) -- Delete the named file. |
---|
266 | zxpand(string) -- Expands the given wildcard string into a list of files. |
---|
267 | znext(string) -- Returns the next file from the list in "string". |
---|
268 | zxcmd(n,cmd) -- Execute the command in a lower fork on file number n. |
---|
269 | zclosf() -- Close input file associated with zxcmd()'s lower fork. |
---|
270 | zrtol(n1,n2) -- Convert remote filename into local form. |
---|
271 | zltor(n1,n2) -- Convert local filename into remote form. |
---|
272 | zchdir(dirnam) -- Change working directory. |
---|
273 | zhome() -- Return pointer to home directory name string. |
---|
274 | zkself() -- Kill self, log out own job. |
---|
275 | zsattr(struct zattr *) -- Return attributes for file which is being sent. |
---|
276 | zstime(f, struct zattr *, x) - Set file creation date from attribute packet. |
---|
277 | zrename(old, new) -- Rename a file. |
---|
278 | zcopy(source,destination) -- Copy a file. |
---|
279 | zmkdir(path) -- Create the directory path if possible |
---|
280 | zfnqfp(fname,len,fullpath) - Determine full path for file name. |
---|
281 | */ |
---|
282 | |
---|
283 | /* Kermit-specific includes */ |
---|
284 | /* |
---|
285 | Definitions here supersede those from system include files. |
---|
286 | ckcdeb.h is included above. |
---|
287 | */ |
---|
288 | #include "ckcker.h" /* Kermit definitions */ |
---|
289 | #include "ckucmd.h" /* For sys-dependent keyword tables */ |
---|
290 | #include "ckuver.h" /* Version herald */ |
---|
291 | |
---|
292 | char *ckzsys = HERALD; |
---|
293 | |
---|
294 | /* |
---|
295 | File access checking ... There are two calls to access() in this module. |
---|
296 | If this program is installed setuid or setgid on a Berkeley-based UNIX |
---|
297 | system that does NOT incorporate the saved-original-effective-uid/gid |
---|
298 | feature, then, when we have swapped the effective and original uid/gid, |
---|
299 | access() fails because it uses what it thinks are the REAL ids, but we have |
---|
300 | swapped them. This occurs on systems where ANYBSD is defined, NOSETREU |
---|
301 | is NOT defined, and SAVEDUID is NOT defined. So, in theory, we should take |
---|
302 | care of this situation like so: |
---|
303 | |
---|
304 | ifdef ANYBSD |
---|
305 | ifndef NOSETREU |
---|
306 | ifndef SAVEDUID |
---|
307 | define SW_ACC_ID |
---|
308 | endif |
---|
309 | endif |
---|
310 | endif |
---|
311 | |
---|
312 | But we can't test such a general scheme everywhere, so let's only do this |
---|
313 | when we know we have to... |
---|
314 | */ |
---|
315 | #ifdef NEXT /* NeXTSTEP 1.0-3.0 */ |
---|
316 | #define SW_ACC_ID |
---|
317 | #endif /* NEXT */ |
---|
318 | |
---|
319 | /* Support for tilde-expansion in file and directory names */ |
---|
320 | |
---|
321 | #ifdef POSIX |
---|
322 | #define NAMEENV "LOGNAME" |
---|
323 | #endif /* POSIX */ |
---|
324 | |
---|
325 | #ifdef BSD4 |
---|
326 | #define NAMEENV "USER" |
---|
327 | #endif /* BSD4 */ |
---|
328 | |
---|
329 | #ifdef ATTSV |
---|
330 | #define NAMEENV "LOGNAME" |
---|
331 | #endif /* ATTSV */ |
---|
332 | |
---|
333 | /* Berkeley Unix Version 4.x */ |
---|
334 | /* 4.1bsd support from Charles E Brooks, EDN-VAX */ |
---|
335 | |
---|
336 | #ifdef BSD4 |
---|
337 | #ifdef MAXNAMLEN |
---|
338 | #define BSD42 |
---|
339 | #endif /* MAXNAMLEN */ |
---|
340 | #endif /* BSD4 */ |
---|
341 | |
---|
342 | /* Definitions of some system commands */ |
---|
343 | |
---|
344 | #ifdef OS2 |
---|
345 | char *CPYCMD = "copy "; /* For file copy */ |
---|
346 | char *DELCMD = "del "; /* For file deletion */ |
---|
347 | char *RENCMD = "rename "; /* For file rename */ |
---|
348 | char *PWDCMD = "chdir "; /* For saying where I am */ |
---|
349 | char *TYPCMD = "type "; /* For typing a file */ |
---|
350 | char *DIRCMD = "dir "; /* For directory listing */ |
---|
351 | char *DIRCM2 = "dir "; /* For directory listing, no args */ |
---|
352 | #ifdef NT |
---|
353 | char *WHOCMD = "@echo Kermit 95 Server"; /* Who's there? */ |
---|
354 | #else /* NT */ |
---|
355 | char *WHOCMD = "@echo K/2 Server"; /* Who's there? */ |
---|
356 | #endif /* NT */ |
---|
357 | char *SPACMD = "dir | find \"bytes free\""; /* For space on disk */ |
---|
358 | char *SPACM2 = "dir | find \"bytes free\""; /* For space on disk */ |
---|
359 | |
---|
360 | #else /* Not OS2, ergo UNIX (or Aegis) */ |
---|
361 | |
---|
362 | char *DELCMD = "rm -f "; /* For file deletion */ |
---|
363 | char *CPYCMD = "cp "; /* For file copy */ |
---|
364 | char *RENCMD = "mv "; /* For file rename */ |
---|
365 | char *PWDCMD = "pwd "; /* For saying where I am */ |
---|
366 | |
---|
367 | #ifdef COMMENT |
---|
368 | #ifdef HPUX10 |
---|
369 | char *DIRCMD = "/usr/bin/ls -l "; /* For directory listing */ |
---|
370 | char *DIRCM2 = "/usr/bin/ls -l "; /* For directory listing, no args */ |
---|
371 | #else |
---|
372 | char *DIRCMD = "/bin/ls -l "; /* For directory listing */ |
---|
373 | char *DIRCM2 = "/bin/ls -l "; /* For directory listing, no args */ |
---|
374 | #endif /* HPUX10 */ |
---|
375 | #else |
---|
376 | char *DIRCMD = "ls -l "; /* For directory listing */ |
---|
377 | char *DIRCM2 = "ls -l "; /* For directory listing, no args */ |
---|
378 | #endif /* COMMENT */ |
---|
379 | |
---|
380 | char *TYPCMD = "cat "; /* For typing a file */ |
---|
381 | |
---|
382 | #ifdef FT18 /* Fortune For:Pro 1.8 */ |
---|
383 | #undef BSD4 |
---|
384 | #endif /* FT18 */ |
---|
385 | |
---|
386 | #ifdef BSD4 |
---|
387 | char *SPACMD = "pwd ; df ."; /* Space in current directory */ |
---|
388 | #else |
---|
389 | #ifdef FT18 |
---|
390 | char *SPACMD = "pwd ; du ; df ."; |
---|
391 | #else |
---|
392 | char *SPACMD = "df "; |
---|
393 | #endif /* FT18 */ |
---|
394 | #endif /* BSD4 */ |
---|
395 | |
---|
396 | char *SPACM2 = "df "; /* For space in specified directory */ |
---|
397 | |
---|
398 | #ifdef FT18 |
---|
399 | #define BSD4 |
---|
400 | #endif /* FT18 */ |
---|
401 | |
---|
402 | #ifdef BSD4 |
---|
403 | char *WHOCMD = "finger "; |
---|
404 | #else |
---|
405 | char *WHOCMD = "who "; |
---|
406 | #endif /* BSD4 */ |
---|
407 | |
---|
408 | #endif /* OS2 */ |
---|
409 | |
---|
410 | #ifdef DTILDE /* For tilde expansion */ |
---|
411 | _PROTOTYP( char * tilde_expand, (char *) ); |
---|
412 | #endif /* DTILDE */ |
---|
413 | |
---|
414 | /* More system-dependent includes, which depend on symbols defined */ |
---|
415 | /* in the Kermit-specific includes. Oh what a tangled web we weave... */ |
---|
416 | |
---|
417 | #ifdef COHERENT /* <sys/file.h> */ |
---|
418 | #define NOFILEH |
---|
419 | #endif /* COHERENT */ |
---|
420 | |
---|
421 | #ifdef MINIX |
---|
422 | #define NOFILEH |
---|
423 | #endif /* MINIX */ |
---|
424 | |
---|
425 | #ifdef aegis |
---|
426 | #define NOFILEH |
---|
427 | #endif /* aegis */ |
---|
428 | |
---|
429 | #ifdef unos |
---|
430 | #define NOFILEH |
---|
431 | #endif /* unos */ |
---|
432 | |
---|
433 | #ifndef NOFILEH |
---|
434 | #include <sys/file.h> |
---|
435 | #endif /* NOFILEH */ |
---|
436 | |
---|
437 | #ifndef is68k /* Whether to include <fcntl.h> */ |
---|
438 | #ifndef BSD41 /* All but a couple UNIXes have it. */ |
---|
439 | #ifndef FT18 |
---|
440 | #ifndef COHERENT |
---|
441 | #include <fcntl.h> |
---|
442 | #endif /* COHERENT */ |
---|
443 | #endif /* FT18 */ |
---|
444 | #endif /* BSD41 */ |
---|
445 | #endif /* not is68k */ |
---|
446 | |
---|
447 | #ifdef COHERENT |
---|
448 | #ifdef _I386 |
---|
449 | #include <fcntl.h> |
---|
450 | #else |
---|
451 | #include <sys/fcntl.h> |
---|
452 | #endif /* _I386 */ |
---|
453 | #endif /* COHERENT */ |
---|
454 | |
---|
455 | /* |
---|
456 | Change argument to "(const char *)" if this causes trouble. |
---|
457 | Or... if it causes trouble, then maybe it was already declared |
---|
458 | in a header file after all, so you can remove this prototype. |
---|
459 | */ |
---|
460 | #ifndef NDGPWNAM /* If not defined No Declare getpwnam... */ |
---|
461 | #ifndef _POSIX_SOURCE |
---|
462 | #ifndef NEXT |
---|
463 | #ifndef SVR4 |
---|
464 | /* POSIX <pwd.h> already gave prototypes for these. */ |
---|
465 | #ifdef IRIX40 |
---|
466 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
467 | #else |
---|
468 | #ifdef IRIX51 |
---|
469 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
470 | #else |
---|
471 | #ifdef M_UNIX |
---|
472 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
473 | #else |
---|
474 | #ifdef HPUX9 |
---|
475 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
476 | #else |
---|
477 | #ifdef HPUX10 |
---|
478 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
479 | #else |
---|
480 | #ifdef DCGPWNAM |
---|
481 | _PROTOTYP( struct passwd * getpwnam, (const char *) ); |
---|
482 | #else |
---|
483 | _PROTOTYP( struct passwd * getpwnam, (char *) ); |
---|
484 | #endif /* DCGPWNAM */ |
---|
485 | #endif /* HPUX10 */ |
---|
486 | #endif /* HPUX9 */ |
---|
487 | #endif /* M_UNIX */ |
---|
488 | #endif /* IRIX51 */ |
---|
489 | #endif /* IRIX40 */ |
---|
490 | #ifndef SUNOS4 |
---|
491 | #ifndef HPUX9 |
---|
492 | #ifndef HPUX10 |
---|
493 | #ifndef _SCO_DS |
---|
494 | _PROTOTYP( struct passwd * getpwuid, (PWID_T) ); |
---|
495 | #endif /* _SCO_DS */ |
---|
496 | #endif /* HPUX10 */ |
---|
497 | #endif /* HPUX9 */ |
---|
498 | #endif /* SUNOS4 */ |
---|
499 | _PROTOTYP( struct passwd * getpwent, (void) ); |
---|
500 | #endif /* SVR4 */ |
---|
501 | #endif /* NEXT */ |
---|
502 | #endif /* _POSIX_SOURCE */ |
---|
503 | #endif /* NDGPWNAM */ |
---|
504 | |
---|
505 | /* Define macros for getting file type */ |
---|
506 | |
---|
507 | #ifdef OXOS |
---|
508 | /* |
---|
509 | Olivetti X/OS 2.3 has S_ISREG and S_ISDIR defined |
---|
510 | incorrectly, so we force their redefinition. |
---|
511 | */ |
---|
512 | #undef S_ISREG |
---|
513 | #undef S_ISDIR |
---|
514 | #endif /* OXOS */ |
---|
515 | |
---|
516 | #ifdef UTSV /* Same deal for Amdahl UTSV */ |
---|
517 | #undef S_ISREG |
---|
518 | #undef S_ISDIR |
---|
519 | #endif /* UTSV */ |
---|
520 | |
---|
521 | #ifdef UNISYS52 /* And for UNISYS UTS V 5.2 */ |
---|
522 | #undef S_ISREG |
---|
523 | #undef S_ISDIR |
---|
524 | #endif /* UNISYS52 */ |
---|
525 | |
---|
526 | #ifdef ICLSVR3 /* And for old ICL versions */ |
---|
527 | #undef S_ISREG |
---|
528 | #undef S_ISDIR |
---|
529 | #endif /* ICLSVR3 */ |
---|
530 | |
---|
531 | #ifdef ISDIRBUG /* Also allow this from command line */ |
---|
532 | #ifdef S_ISREG |
---|
533 | #undef S_ISREG |
---|
534 | #endif /* S_ISREG */ |
---|
535 | #ifdef S_ISDIR |
---|
536 | #undef S_ISDIR |
---|
537 | #endif /* S_ISDIR */ |
---|
538 | #endif /* ISDIRBUG */ |
---|
539 | |
---|
540 | #ifndef S_ISREG |
---|
541 | #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) |
---|
542 | #endif /* S_ISREG */ |
---|
543 | #ifndef S_ISDIR |
---|
544 | #define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR) |
---|
545 | #endif /* S_ISDIR */ |
---|
546 | |
---|
547 | /* Define maximum length for a file name if not already defined */ |
---|
548 | |
---|
549 | #ifdef QNX |
---|
550 | #ifdef _MAX_FNAME |
---|
551 | #define MAXNAMLEN _MAX_FNAME |
---|
552 | #else |
---|
553 | #define MAXNAMLEN 48 |
---|
554 | #endif /* _MAX_FNAME */ |
---|
555 | #else |
---|
556 | #ifndef MAXNAMLEN |
---|
557 | #ifdef sun |
---|
558 | #define MAXNAMLEN 255 |
---|
559 | #else |
---|
560 | #ifdef FILENAME_MAX |
---|
561 | #define MAXNAMLEN FILENAME_MAX |
---|
562 | #else |
---|
563 | #ifdef NAME_MAX |
---|
564 | #define MAXNAMLEN NAME_MAX |
---|
565 | #else |
---|
566 | #ifdef _POSIX_NAME_MAX |
---|
567 | #define MAXNAMLEN _POSIX_NAME_MAX |
---|
568 | #else |
---|
569 | #ifdef _D_NAME_MAX |
---|
570 | #define MAXNAMLEN _D_NAME_MAX |
---|
571 | #else |
---|
572 | #ifdef DIRSIZ |
---|
573 | #define MAXNAMLEN DIRSIZ |
---|
574 | #else |
---|
575 | #define MAXNAMLEN 14 |
---|
576 | #endif /* DIRSIZ */ |
---|
577 | #endif /* _D_NAME_MAX */ |
---|
578 | #endif /* _POSIX_NAME_MAX */ |
---|
579 | #endif /* NAME_MAX */ |
---|
580 | #endif /* FILENAME_MAX */ |
---|
581 | #endif /* sun */ |
---|
582 | #endif /* MAXNAMLEN */ |
---|
583 | #endif /* QNX */ |
---|
584 | |
---|
585 | /* Longest pathname ... */ |
---|
586 | /* |
---|
587 | Beware: MAXPATHLEN is one of UNIX's dirty little secrets. Where is it |
---|
588 | defined? Who knows... <param.h>, <mod.h>, <unistd.h>, <limits.h>, ... |
---|
589 | There is not necessarily even a definition for it anywhere, or it might have |
---|
590 | another name. If you get it wrong, bad things happen with getcwd() and/or |
---|
591 | getwd(). If you allocate a buffer that is too short, getwd() might write |
---|
592 | over memory and getcwd() will fail with ERANGE. The definitions of these |
---|
593 | functions (e.g. in SVID or POSIX.1) do not tell you how to determine the |
---|
594 | maximum path length in order to allocate a buffer that is the right size. |
---|
595 | */ |
---|
596 | #ifdef BSD44 |
---|
597 | #include <sys/param.h> /* For MAXPATHLEN */ |
---|
598 | #endif /* BSD44 */ |
---|
599 | |
---|
600 | #ifdef COHERENT |
---|
601 | #include <sys/param.h> /* for MAXPATHLEN, needed for -DDIRENT */ |
---|
602 | #endif /* COHERENT */ |
---|
603 | |
---|
604 | #ifdef MAXPATHLEN |
---|
605 | #ifdef MAXPATH |
---|
606 | #undef MAXPATH |
---|
607 | #endif /* MAXPATH */ |
---|
608 | #define MAXPATH MAXPATHLEN |
---|
609 | #else |
---|
610 | #ifdef PATH_MAX |
---|
611 | #define MAXPATH PATH_MAX |
---|
612 | #else |
---|
613 | #ifdef _POSIX_PATH_MAX |
---|
614 | #define MAXPATH _POSIX_PATH_MAX |
---|
615 | #else |
---|
616 | #ifdef BSD42 |
---|
617 | #define MAXPATH 1024 |
---|
618 | #else |
---|
619 | #ifdef SVR4 |
---|
620 | #define MAXPATH 1024 |
---|
621 | #else |
---|
622 | #define MAXPATH 255 |
---|
623 | #endif /* SVR4 */ |
---|
624 | #endif /* BSD42 */ |
---|
625 | #endif /* _POSIX_PATH_MAX */ |
---|
626 | #endif /* PATH_MAX */ |
---|
627 | #endif /* MAXPATHLEN */ |
---|
628 | |
---|
629 | /* Maximum number of filenames for wildcard expansion */ |
---|
630 | |
---|
631 | #ifdef PROVX1 |
---|
632 | #define MAXWLD 50 |
---|
633 | #else |
---|
634 | #ifdef pdp11 |
---|
635 | #define MAXWLD 50 |
---|
636 | #else |
---|
637 | #ifdef BIGBUFOK |
---|
638 | #define MAXWLD 4096 |
---|
639 | #else |
---|
640 | #define MAXWLD 1000 |
---|
641 | #endif /* BIGBUFOK */ |
---|
642 | #endif /* pdp11 */ |
---|
643 | #endif /* PROVX1 */ |
---|
644 | |
---|
645 | /* More internal function prototypes */ |
---|
646 | /* |
---|
647 | * The path structure is used to represent the name to match. |
---|
648 | * Each slash-separated segment of the name is kept in one |
---|
649 | * such structure, and they are linked together, to make |
---|
650 | * traversing the name easier. |
---|
651 | */ |
---|
652 | struct path { |
---|
653 | char npart[MAXNAMLEN+4]; /* name part of path segment */ |
---|
654 | struct path *fwd; /* forward ptr */ |
---|
655 | }; |
---|
656 | #ifndef NOPUSH |
---|
657 | _PROTOTYP( int shxpand, (char *, char *[], int ) ); |
---|
658 | extern int nopush; |
---|
659 | #endif /* NOPUSH */ |
---|
660 | _PROTOTYP( static int fgen, (char *, char *[], int ) ); |
---|
661 | _PROTOTYP( static VOID traverse, (struct path *, char *, char *) ); |
---|
662 | _PROTOTYP( static VOID addresult, (char *) ); |
---|
663 | _PROTOTYP( static int match, (char *, char *) ); |
---|
664 | _PROTOTYP( static char * whoami, (void) ); |
---|
665 | #ifdef aegis |
---|
666 | _PROTOTYP( static char * xindex, (char *, char) ); |
---|
667 | #endif /* aegis */ |
---|
668 | _PROTOTYP( UID_T real_uid, (void) ); |
---|
669 | _PROTOTYP( struct path *splitpath, (char *p) ); |
---|
670 | _PROTOTYP( char * zdtstr, (time_t) ); |
---|
671 | _PROTOTYP( time_t zstrdt, (char *, int) ); |
---|
672 | |
---|
673 | /* Some systems define these symbols in include files, others don't... */ |
---|
674 | |
---|
675 | #ifndef R_OK |
---|
676 | #define R_OK 4 /* For access */ |
---|
677 | #endif /* R_OK */ |
---|
678 | |
---|
679 | #ifndef W_OK |
---|
680 | #define W_OK 2 |
---|
681 | #endif /* W_OK */ |
---|
682 | |
---|
683 | #ifndef O_RDONLY |
---|
684 | #define O_RDONLY 000 |
---|
685 | #endif /* O_RDONLY */ |
---|
686 | |
---|
687 | /* Declarations */ |
---|
688 | |
---|
689 | int maxnam = MAXNAMLEN; /* Available to the outside */ |
---|
690 | int maxpath = MAXPATH; |
---|
691 | int ck_znewn = -1; |
---|
692 | |
---|
693 | FILE *fp[ZNFILS] = { /* File pointers */ |
---|
694 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }; |
---|
695 | #ifdef OS2 |
---|
696 | int ispipe[ZNFILS]; /* Flag for file is a pipe */ |
---|
697 | #endif /* OS2 */ |
---|
698 | |
---|
699 | /* Buffers and pointers used in buffered file input and output. */ |
---|
700 | #ifdef DYNAMIC |
---|
701 | extern char *zinbuffer, *zoutbuffer; |
---|
702 | #else |
---|
703 | extern char zinbuffer[], zoutbuffer[]; |
---|
704 | #endif /* DYNAMIC */ |
---|
705 | extern char *zinptr, *zoutptr; |
---|
706 | extern int zincnt, zoutcnt; |
---|
707 | extern int wildxpand; |
---|
708 | |
---|
709 | extern UID_T real_uid(); |
---|
710 | |
---|
711 | static long iflen = -1L; /* Input file length */ |
---|
712 | |
---|
713 | static PID_T pid = 0; /* pid of child fork */ |
---|
714 | static int fcount; /* Number of files in wild group */ |
---|
715 | static char nambuf[MAXNAMLEN+4]; /* Buffer for a filename */ |
---|
716 | #ifndef NOFRILLS |
---|
717 | static char zmbuf[200]; /* For mail, remote print strings */ |
---|
718 | #endif /* NOFRILLS */ |
---|
719 | |
---|
720 | #ifndef OS2 |
---|
721 | /* static */ /* Not static, must be global now. */ |
---|
722 | char **mtchs = NULL; /* Matches found for filename */ |
---|
723 | char **mtchptr = NULL; /* Pointer to current match */ |
---|
724 | #endif /* OS2 */ |
---|
725 | |
---|
726 | #ifdef OS2 |
---|
727 | #ifndef NT |
---|
728 | #define INCL_KBD |
---|
729 | #define INCL_DOSERRORS |
---|
730 | #define INCL_DOSFILEMGR |
---|
731 | #define INCL_DOSPROCESS |
---|
732 | #define INCL_DOSSEMAPHORES |
---|
733 | #include <os2.h> |
---|
734 | typedef unsigned short WORD; |
---|
735 | #undef COMMENT |
---|
736 | |
---|
737 | /* Get/Set All Extended Attributes support */ |
---|
738 | |
---|
739 | #define FreeMem(p) DosFreeMem(p) |
---|
740 | |
---|
741 | #define MAX_GEA 500L /* Max size for a GEA List */ |
---|
742 | #define MAXEACOUNT 128 /* Max number of EA's supported */ |
---|
743 | #define Ref_ASCIIZ 1 /* Reference type for DosEnumAttribute */ |
---|
744 | |
---|
745 | /* Definition of level specifiers, required for File Info */ |
---|
746 | |
---|
747 | #define GetInfoLevel1 1 /* Get info from SFT */ |
---|
748 | #define GetInfoLevel2 2 /* Get size of FEAlist */ |
---|
749 | #define GetInfoLevel3 3 /* Get FEAlist given the GEAlist */ |
---|
750 | #define GetInfoLevel4 4 /* Get whole FEAlist */ |
---|
751 | #define GetInfoLevel5 5 /* Get FSDname */ |
---|
752 | |
---|
753 | #define SetInfoLevel1 1 /* Set info in SFT */ |
---|
754 | #define SetInfoLevel2 2 /* Set FEAlist */ |
---|
755 | |
---|
756 | FEA2LIST *pFEAList = 0; /* Pointer to buffer containing all EA information */ |
---|
757 | ULONG os2attrs = FILE_NORMAL; |
---|
758 | extern unsigned int lf_opts; |
---|
759 | |
---|
760 | #else /* NT */ |
---|
761 | |
---|
762 | #include <windows.h> |
---|
763 | #endif /* NT */ |
---|
764 | char os2filename[MAXPATH]; |
---|
765 | #endif /* OS2 */ |
---|
766 | |
---|
767 | /* Z K S E L F -- Kill Self: log out own job, if possible. */ |
---|
768 | |
---|
769 | /* Note, should get current pid, but if your system doesn't have */ |
---|
770 | /* getppid(), then just kill(0,9)... */ |
---|
771 | |
---|
772 | #ifndef SVR3 |
---|
773 | #ifndef POSIX |
---|
774 | #ifndef OSFPC |
---|
775 | /* Already declared in unistd.h for SVR3 and POSIX */ |
---|
776 | #ifdef CK_ANSIC |
---|
777 | extern PID_T getppid(void); |
---|
778 | #else |
---|
779 | #ifndef PS2AIX10 |
---|
780 | extern PID_T getppid(); |
---|
781 | #endif /* PS2AIX10 */ |
---|
782 | #endif /* CK_ANSIC */ |
---|
783 | #endif /* OSFPC */ |
---|
784 | #endif /* POSIX */ |
---|
785 | #endif /* SVR3 */ |
---|
786 | |
---|
787 | int |
---|
788 | zkself() { /* For "bye", but no guarantee! */ |
---|
789 | #ifdef PROVX1 |
---|
790 | return(kill(0,9)); |
---|
791 | #else |
---|
792 | #ifdef V7 |
---|
793 | return(kill(0,9)); |
---|
794 | #else |
---|
795 | #ifdef TOWER1 |
---|
796 | return(kill(0,9)); |
---|
797 | #else |
---|
798 | #ifdef FT18 |
---|
799 | return(kill(0,9)); |
---|
800 | #else |
---|
801 | #ifdef aegis |
---|
802 | return(kill(0,9)); |
---|
803 | #else |
---|
804 | #ifdef COHERENT |
---|
805 | return(kill((PID_T)getpid(),1)); |
---|
806 | #else |
---|
807 | #ifdef OS2 |
---|
808 | exit(3); |
---|
809 | return(0); |
---|
810 | #else |
---|
811 | #ifdef PID_T |
---|
812 | exit(kill((PID_T)getppid(),1)); |
---|
813 | return(0); |
---|
814 | #else |
---|
815 | exit(kill(getppid(),1)); |
---|
816 | return(0); |
---|
817 | #endif |
---|
818 | #endif |
---|
819 | #endif |
---|
820 | #endif |
---|
821 | #endif |
---|
822 | #endif |
---|
823 | #endif |
---|
824 | #endif |
---|
825 | } |
---|
826 | |
---|
827 | /* Z O P E N I -- Open an existing file for input. */ |
---|
828 | |
---|
829 | int |
---|
830 | zopeni(n,name) int n; char *name; { |
---|
831 | int x, y; |
---|
832 | |
---|
833 | debug(F111," zopeni",name,n); |
---|
834 | debug(F101," fp","", fp[n]); |
---|
835 | if (chkfn(n) != 0) return(0); |
---|
836 | zincnt = 0; /* Reset input buffer */ |
---|
837 | if (n == ZSYSFN) { /* Input from a system function? */ |
---|
838 | /*** Note, this function should not be called with ZSYSFN ***/ |
---|
839 | /*** Always call zxcmd() directly, and give it the real file number ***/ |
---|
840 | /*** you want to use. ***/ |
---|
841 | debug(F110,"zopeni called with ZSYSFN, failing!",name,0); |
---|
842 | *nambuf = '\0'; /* No filename. */ |
---|
843 | return(0); /* fail. */ |
---|
844 | #ifdef COMMENT |
---|
845 | return(zxcmd(n,name)); /* Try to fork the command */ |
---|
846 | #endif |
---|
847 | } |
---|
848 | if (n == ZSTDIO) { /* Standard input? */ |
---|
849 | if (is_a_tty(0)) { |
---|
850 | fprintf(stderr,"Terminal input not allowed"); |
---|
851 | debug(F110,"zopeni: attempts input from unredirected stdin","",0); |
---|
852 | return(0); |
---|
853 | } |
---|
854 | fp[ZIFILE] = stdin; |
---|
855 | #ifdef OS2 |
---|
856 | #ifdef NT |
---|
857 | _setmode(_fileno(stdin),O_BINARY); |
---|
858 | #else |
---|
859 | setmode(fileno(stdin),O_BINARY); |
---|
860 | #endif /* NT */ |
---|
861 | #endif /* OS2 */ |
---|
862 | return(1); |
---|
863 | } |
---|
864 | #ifdef OS2 |
---|
865 | if (n == ZIFILE || n == ZRFILE) { |
---|
866 | strncpy( os2filename, name, MAXPATH ) ; |
---|
867 | errno = 0; |
---|
868 | #ifdef NT |
---|
869 | fp[n] = _fsopen(name,"rb",_SH_DENYWR); /* Binary mode */ |
---|
870 | #else |
---|
871 | fp[n] = fopen(name,"rb");/* Binary mode */ |
---|
872 | #endif /* NT */ |
---|
873 | if (fp[ZIFILE]) { |
---|
874 | x = ferror(fp[ZIFILE]); |
---|
875 | #ifdef ZDEBUG |
---|
876 | printf("ZOPENI errno=%d\n",errno); |
---|
877 | printf("ZOPENI ferror=%d\n",x); |
---|
878 | #endif /* ZDEBUG */ |
---|
879 | } |
---|
880 | #ifdef CK_LABELED |
---|
881 | if (binary == XYFT_L) { |
---|
882 | os2getattr(name); |
---|
883 | os2geteas(name); |
---|
884 | } |
---|
885 | #endif /* CK_LABELED */ |
---|
886 | } else |
---|
887 | #ifdef NT |
---|
888 | fp[n] = _fsopen(name,"rb",_SH_DENYWR); /* Real file, open it. */ |
---|
889 | #else |
---|
890 | fp[n] = fopen(name,"rb");/* Real file, open it. */ |
---|
891 | #endif /* NT */ |
---|
892 | #else /* OS2 */ |
---|
893 | fp[n] = fopen(name,"r"); /* Real file, open it. */ |
---|
894 | #endif /* OS2 */ |
---|
895 | debug(F111," zopeni", name, fp[n]); |
---|
896 | #ifdef ZDEBUG |
---|
897 | printf("ZOPENI fp[%d]=%ld\n",n,fp[n]); |
---|
898 | #endif /* ZDEBUG */ |
---|
899 | if (fp[n] == NULL) |
---|
900 | perror("zopeni"); |
---|
901 | else |
---|
902 | clearerr(fp[n]); |
---|
903 | return((fp[n] != NULL) ? 1 : 0); |
---|
904 | } |
---|
905 | |
---|
906 | /* Z O P E N O -- Open a new file for output. */ |
---|
907 | |
---|
908 | int |
---|
909 | zopeno(n,name,zz,fcb) |
---|
910 | /* zopeno */ int n; char *name; struct zattr *zz; struct filinfo *fcb; { |
---|
911 | |
---|
912 | char p[8]; /* (===OS2 change===) */ |
---|
913 | |
---|
914 | /* As of Version 5A, the attribute structure and the file information */ |
---|
915 | /* structure are included in the arglist. */ |
---|
916 | |
---|
917 | #ifdef DEBUG |
---|
918 | debug(F111,"zopeno",name,n); |
---|
919 | if (fcb) { |
---|
920 | debug(F101,"zopeno fcb disp","",fcb->dsp); |
---|
921 | debug(F101,"zopeno fcb type","",fcb->typ); |
---|
922 | debug(F101,"zopeno fcb char","",fcb->cs); |
---|
923 | } else { |
---|
924 | debug(F100,"zopeno fcb is NULL","",0); |
---|
925 | } |
---|
926 | if (n != ZDFILE) |
---|
927 | debug(F111," zopeno",name,n); |
---|
928 | #endif /* DEBUG */ |
---|
929 | |
---|
930 | if (chkfn(n) != 0) /* Already open? */ |
---|
931 | return(0); /* Nothing to do. */ |
---|
932 | |
---|
933 | if ((n == ZCTERM) || (n == ZSTDIO)) { /* Terminal or standard output */ |
---|
934 | fp[ZOFILE] = stdout; |
---|
935 | #ifdef DEBUG |
---|
936 | if (n != ZDFILE) |
---|
937 | debug(F101," fp[]=stdout", "", fp[n]); |
---|
938 | #endif /* DEBUG */ |
---|
939 | zoutcnt = 0; |
---|
940 | zoutptr = zoutbuffer; |
---|
941 | return(1); |
---|
942 | } |
---|
943 | |
---|
944 | /* A real file. Open it in desired mode (create or append). */ |
---|
945 | |
---|
946 | strcpy(p,"w"); /* Assume write/create mode */ |
---|
947 | if (fcb) { /* If called with an FCB... */ |
---|
948 | if (fcb->dsp == XYFZ_A) { /* Does it say Append? */ |
---|
949 | strcpy(p,"a"); /* Yes. */ |
---|
950 | debug(F100,"zopeno append","",0); |
---|
951 | } |
---|
952 | } |
---|
953 | #ifdef OS2 |
---|
954 | if (n == ZOFILE || n == ZSFILE) { /* OS/2 binary mode */ |
---|
955 | strncpy( os2filename, name, MAXPATH ) ; |
---|
956 | strcat(p,"b"); |
---|
957 | } |
---|
958 | #endif /* OS2 */ |
---|
959 | debug(F110,"zopeno fopen arg",p,0); |
---|
960 | fp[n] = fopen(name,p); /* Try to open the file */ |
---|
961 | |
---|
962 | #ifdef ZDEBUG |
---|
963 | printf("ZOPENO fp[%d]=%ld\n",n,fp[n]); |
---|
964 | #endif /* ZDEBUG */ |
---|
965 | |
---|
966 | if (fp[n] == NULL) { /* Failed */ |
---|
967 | debug(F101,"zopeno failed errno","",errno); |
---|
968 | #ifdef COMMENT /* Let upper levels print message. */ |
---|
969 | perror("Can't open output file"); |
---|
970 | #endif /* COMMENT */ |
---|
971 | } else { /* Succeeded */ |
---|
972 | if (n == ZDFILE) /* If it's the debug log */ |
---|
973 | setbuf(fp[n],NULL); /* make it unbuffered */ |
---|
974 | else |
---|
975 | debug(F100, "zopeno ok", "", 0); |
---|
976 | } |
---|
977 | zoutcnt = 0; /* (PWP) reset output buffer */ |
---|
978 | zoutptr = zoutbuffer; |
---|
979 | return((fp[n] != NULL) ? 1 : 0); |
---|
980 | } |
---|
981 | |
---|
982 | /* Z C L O S E -- Close the given file. */ |
---|
983 | |
---|
984 | /* Returns 0 if arg out of range, 1 if successful, -1 if close failed. */ |
---|
985 | |
---|
986 | int |
---|
987 | zclose(n) int n; { |
---|
988 | int x, x2; |
---|
989 | if (chkfn(n) < 1) return(0); /* Check range of n */ |
---|
990 | |
---|
991 | if ((n == ZOFILE) && (zoutcnt > 0)) /* (PWP) output leftovers */ |
---|
992 | x2 = zoutdump(); |
---|
993 | else |
---|
994 | x2 = 0; |
---|
995 | |
---|
996 | x = 0; /* Initialize return code */ |
---|
997 | if (fp[ZSYSFN] |
---|
998 | #ifdef OS2 |
---|
999 | || ispipe[n] /* If file is really pipe */ |
---|
1000 | #endif /* OS2 */ |
---|
1001 | ) { |
---|
1002 | x = zclosf(n); /* do it specially */ |
---|
1003 | } else { |
---|
1004 | if ((fp[n] != stdout) && (fp[n] != stdin)) |
---|
1005 | x = fclose(fp[n]); |
---|
1006 | fp[n] = NULL; |
---|
1007 | #ifdef OS2 |
---|
1008 | #ifdef CK_LABELED |
---|
1009 | if (binary == XYFT_L) { |
---|
1010 | debug(F111,"zclose LABELED","file number",n); |
---|
1011 | if (n == ZOFILE) { |
---|
1012 | debug(F111,"zclose LABELED", |
---|
1013 | "lf_opts && LBL_EXT", |
---|
1014 | lf_opts && LBL_EXT |
---|
1015 | ); |
---|
1016 | if (lf_opts && LBL_EXT) |
---|
1017 | os2seteas(os2filename); |
---|
1018 | os2setattr(os2filename); |
---|
1019 | } else if (n == ZIFILE && pFEAList) { |
---|
1020 | FreeMem(pFEAList); |
---|
1021 | pFEAList = 0; |
---|
1022 | } |
---|
1023 | } |
---|
1024 | #endif /* CK_LABELED */ |
---|
1025 | #endif /* OS2 */ |
---|
1026 | } |
---|
1027 | iflen = -1L; /* Invalidate file length */ |
---|
1028 | if (x == EOF) { /* if we got a close error */ |
---|
1029 | debug(F101,"zclose fclose fails","",x); |
---|
1030 | return(-1); |
---|
1031 | } else if (x2 < 0) { /* or error flushing last buffer */ |
---|
1032 | debug(F101,"zclose error flushing last buffer","",x2); |
---|
1033 | return(-1); /* then return an error */ |
---|
1034 | } else { |
---|
1035 | debug(F101,"zclose success","",1); |
---|
1036 | return(1); |
---|
1037 | } |
---|
1038 | } |
---|
1039 | |
---|
1040 | /* Z C H I N -- Get a character from the input file. */ |
---|
1041 | |
---|
1042 | /* Returns -1 if EOF, 0 otherwise with character returned in argument */ |
---|
1043 | |
---|
1044 | int |
---|
1045 | zchin(n,c) int n; int *c; { |
---|
1046 | int a, x; |
---|
1047 | |
---|
1048 | /* (PWP) Just in case this gets called when it shouldn't. */ |
---|
1049 | if (n == ZIFILE) { |
---|
1050 | x = zminchar(); |
---|
1051 | *c = x; |
---|
1052 | return(x); |
---|
1053 | } |
---|
1054 | /* if (chkfn(n) < 1) return(-1); */ |
---|
1055 | a = getc(fp[n]); |
---|
1056 | if (a == EOF) return(-1); |
---|
1057 | #ifdef OS2 |
---|
1058 | if (!binary && a == 0x1A) /* Ctrl-Z marks EOF for text mode*/ |
---|
1059 | return(-1); |
---|
1060 | #endif |
---|
1061 | *c = (CHAR) a & 0377; |
---|
1062 | return(0); |
---|
1063 | } |
---|
1064 | |
---|
1065 | /* Z S I N L -- Read a line from a file */ |
---|
1066 | |
---|
1067 | /* |
---|
1068 | Writes the line into the address provided by the caller. |
---|
1069 | n is the Kermit "channel number". |
---|
1070 | Writing terminates when newline is encountered, newline is not copied. |
---|
1071 | Writing also terminates upon EOF or if length x is exhausted. |
---|
1072 | Returns 0 on success, -1 on EOF or error. |
---|
1073 | */ |
---|
1074 | int |
---|
1075 | zsinl(n,s,x) int n, x; char *s; { |
---|
1076 | int a, z = 0; /* z is return code. */ |
---|
1077 | extern CHAR feol; /* Line terminator */ |
---|
1078 | |
---|
1079 | if (chkfn(n) < 1) { /* Make sure file is open */ |
---|
1080 | return(-1); |
---|
1081 | } |
---|
1082 | a = -1; /* Current character, none yet. */ |
---|
1083 | while (x--) { /* Up to given length */ |
---|
1084 | int old; |
---|
1085 | if (feol) old = a; /* Previous character */ |
---|
1086 | |
---|
1087 | if (zchin(n,&a) < 0) { /* Read a character from the file */ |
---|
1088 | debug(F101,"zsinl","",a); |
---|
1089 | z = -1; /* EOF or other error */ |
---|
1090 | break; |
---|
1091 | } |
---|
1092 | |
---|
1093 | if (feol) { /* Single-character line terminator */ |
---|
1094 | if (a == feol) |
---|
1095 | break; |
---|
1096 | } else { /* CRLF line terminator */ |
---|
1097 | if (a == '\015') /* CR, get next character */ |
---|
1098 | continue; |
---|
1099 | if (old == '\015') { /* Previous character was CR */ |
---|
1100 | if (a == '\012') /* This one is LF, so we have a line */ |
---|
1101 | break; |
---|
1102 | else /* Not LF, deposit CR */ |
---|
1103 | *s++ = '\015'; |
---|
1104 | } |
---|
1105 | #ifdef OS2 |
---|
1106 | if (a == '\012') break; /* Here break on single LF too */ |
---|
1107 | #endif /* OS2 */ |
---|
1108 | } |
---|
1109 | *s = a; /* Deposit character */ |
---|
1110 | s++; |
---|
1111 | } |
---|
1112 | *s = '\0'; /* Terminate the string */ |
---|
1113 | return(z); |
---|
1114 | } |
---|
1115 | |
---|
1116 | /* Z X I N -- Read x bytes from a file */ |
---|
1117 | |
---|
1118 | /* |
---|
1119 | Reads x bytes (or less) from channel n and writes them |
---|
1120 | to the address provided by the caller. |
---|
1121 | Returns number of bytes read on success, 0 on EOF or error. |
---|
1122 | */ |
---|
1123 | int |
---|
1124 | zxin(n,s,x) int n, x; char *s; { |
---|
1125 | return(fread(s, sizeof (char), x, fp[n])); |
---|
1126 | } |
---|
1127 | |
---|
1128 | /* |
---|
1129 | Z I N F I L L -- Buffered file input. |
---|
1130 | |
---|
1131 | (re)fill the file input buffer with data. All file input |
---|
1132 | should go through this routine, usually by calling the zminchar() |
---|
1133 | macro defined in ckcker.h. Returns: |
---|
1134 | |
---|
1135 | Value 0..255 on success, the character that was read. |
---|
1136 | -1 on end of file. |
---|
1137 | -2 on any kind of error other than end of file. |
---|
1138 | */ |
---|
1139 | int |
---|
1140 | zinfill() { |
---|
1141 | int x; |
---|
1142 | |
---|
1143 | errno = 0; |
---|
1144 | |
---|
1145 | #ifdef ZDEBUG |
---|
1146 | printf("ZINFILL fp[%d]=%ld\n",ZIFILE,fp[ZIFILE]); |
---|
1147 | #endif /* ZDEBUG */ |
---|
1148 | |
---|
1149 | #ifdef OS2 |
---|
1150 | #ifdef CK_LABELED |
---|
1151 | debug(F101,"zinfill: binary","",binary); |
---|
1152 | debug(F101,"zinfill: pFEAList","",pFEAList); |
---|
1153 | if ( binary == XYFT_L && pFEAList ) { |
---|
1154 | zinptr = zinbuffer ; |
---|
1155 | do_label_send(os2filename) ; |
---|
1156 | if (feof(fp[ZIFILE])) |
---|
1157 | return(-1); |
---|
1158 | clearerr(fp[ZIFILE]); |
---|
1159 | zincnt += fread(zinptr, sizeof (char), INBUFSIZE - zincnt, fp[ZIFILE]); |
---|
1160 | } else { |
---|
1161 | #endif /* CK_LABELED */ |
---|
1162 | #endif /* OS2 */ |
---|
1163 | |
---|
1164 | if (feof(fp[ZIFILE])) { |
---|
1165 | debug(F100,"ZINFILL feof","",0); |
---|
1166 | #ifdef ZDEBUG |
---|
1167 | printf("ZINFILL EOF\n"); |
---|
1168 | #endif /* ZDEBUG */ |
---|
1169 | return(-1); |
---|
1170 | } |
---|
1171 | clearerr(fp[ZIFILE]); |
---|
1172 | zincnt = fread(zinbuffer, sizeof (char), INBUFSIZE, fp[ZIFILE]); |
---|
1173 | debug(F101,"ZINFILL fread","",zincnt); |
---|
1174 | #ifdef ZDEBUG |
---|
1175 | printf("FREAD=%d\n",zincnt); |
---|
1176 | #endif /* ZDEBUG */ |
---|
1177 | #ifdef OS2 |
---|
1178 | #ifdef CK_LABELED |
---|
1179 | } |
---|
1180 | #endif /* CK_LABELED */ |
---|
1181 | #endif /* OS2 */ |
---|
1182 | |
---|
1183 | if (ferror(fp[ZIFILE])) { |
---|
1184 | debug(F100,"ZINFILL ferror","",0); |
---|
1185 | debug(F100,"ZINFILL errno","",errno); |
---|
1186 | #ifdef ZDEBUG |
---|
1187 | printf("ZINFILL errno=%d\n",errno); |
---|
1188 | #endif /* ZDEBUG */ |
---|
1189 | return(-2); |
---|
1190 | } |
---|
1191 | /* In case feof() didn't work just above -- sometimes it doesn't... */ |
---|
1192 | if (zincnt == 0) { |
---|
1193 | if (feof(fp[ZIFILE]) ) { |
---|
1194 | debug(F100,"ZINFILL count 0 EOF return -1","",0); |
---|
1195 | return (-1); |
---|
1196 | } else { |
---|
1197 | debug(F100,"ZINFILL count 0 not EOF return -2","",0); |
---|
1198 | return(-2); |
---|
1199 | } |
---|
1200 | } |
---|
1201 | zinptr = zinbuffer; /* set pointer to beginning, (== &zinbuffer[0]) */ |
---|
1202 | zincnt--; /* One less char in buffer */ |
---|
1203 | return((int)(*zinptr++) & 0377); /* because we return the first */ |
---|
1204 | } |
---|
1205 | |
---|
1206 | /* Z S O U T -- Write a string out to the given file, buffered. */ |
---|
1207 | |
---|
1208 | int |
---|
1209 | zsout(n,s) int n; char *s; { |
---|
1210 | if (chkfn(n) < 1) return(-1); /* Keep this, prevents memory faults */ |
---|
1211 | if (!s) return(0); /* Null pointer, do nothing, succeed */ |
---|
1212 | if (!*s) return(0); /* empty string, ditto */ |
---|
1213 | #ifdef OS2 |
---|
1214 | if (n == ZCTERM) |
---|
1215 | return(Vscrnprintf(s)); |
---|
1216 | #endif /* OS2 */ |
---|
1217 | if (n == ZSFILE) |
---|
1218 | return(write(fileno(fp[n]),s,(int)strlen(s))); |
---|
1219 | return(fputs(s,fp[n]) == EOF ? -1 : 0); |
---|
1220 | } |
---|
1221 | |
---|
1222 | /* Z S O U T L -- Write string to file, with line terminator, buffered */ |
---|
1223 | |
---|
1224 | int |
---|
1225 | zsoutl(n,s) int n; char *s; { |
---|
1226 | if (zsout(n,s) < 0) |
---|
1227 | return(-1); |
---|
1228 | #ifdef OS2 |
---|
1229 | if (n == ZCTERM) |
---|
1230 | return(Vscrnprintf("\n")); |
---|
1231 | #endif /* OS2 */ |
---|
1232 | if (n == ZSFILE) /* But session log is unbuffered */ |
---|
1233 | return(write(fileno(fp[n]),"\n",1)); |
---|
1234 | if (fputs("\n",fp[n]) == EOF) |
---|
1235 | return(-1); /* (===OS2 ? \r\n) */ |
---|
1236 | return(0); |
---|
1237 | } |
---|
1238 | |
---|
1239 | /* Z S O U T X -- Write x characters to file, unbuffered. */ |
---|
1240 | |
---|
1241 | int |
---|
1242 | zsoutx(n,s,x) int n, x; char *s; { |
---|
1243 | #ifdef COMMENT |
---|
1244 | if (chkfn(n) < 1) return(-1); |
---|
1245 | return(write(fp[n]->_file,s,x)); |
---|
1246 | #endif /* COMMENT */ |
---|
1247 | |
---|
1248 | #ifdef OS2 |
---|
1249 | if (n == ZCTERM) { |
---|
1250 | int i; |
---|
1251 | for (i = 0; i < x; i++) |
---|
1252 | if (!Vscrnprintf("%c",s[i])) |
---|
1253 | return(-1); |
---|
1254 | return(x); |
---|
1255 | } |
---|
1256 | #endif /* OS2 */ |
---|
1257 | return(write(fileno(fp[n]),s,x) == x ? x : -1); |
---|
1258 | } |
---|
1259 | |
---|
1260 | /* Z C H O U T -- Add a character to the given file. */ |
---|
1261 | |
---|
1262 | /* Should return 0 or greater on success, -1 on failure (e.g. disk full) */ |
---|
1263 | |
---|
1264 | int |
---|
1265 | #ifdef CK_ANSIC |
---|
1266 | zchout(register int n, char c) |
---|
1267 | #else |
---|
1268 | zchout(n,c) register int n; char c; |
---|
1269 | #endif /* CK_ANSIC */ |
---|
1270 | /* zchout() */ { |
---|
1271 | /* if (chkfn(n) < 1) return(-1); */ |
---|
1272 | #ifdef OS2 |
---|
1273 | if ( n==ZCTERM ) |
---|
1274 | return(Vscrnprintf("%c",c)); |
---|
1275 | #endif /* OS2 */ |
---|
1276 | if (n == ZSFILE) /* Use unbuffered for session log */ |
---|
1277 | return(write(fileno(fp[n]),&c,1) == 1 ? 0 : -1); |
---|
1278 | /* Buffered for everything else */ |
---|
1279 | if (putc(c,fp[n]) == EOF) /* If true, maybe there was an error */ |
---|
1280 | return(ferror(fp[n])?-1:0); /* Check to make sure */ |
---|
1281 | else /* Otherwise... */ |
---|
1282 | return(0); /* There was no error. */ |
---|
1283 | } |
---|
1284 | |
---|
1285 | /* (PWP) buffered character output routine to speed up file IO */ |
---|
1286 | |
---|
1287 | int |
---|
1288 | zoutdump() { |
---|
1289 | int x; |
---|
1290 | zoutptr = zoutbuffer; /* Reset buffer pointer in all cases */ |
---|
1291 | debug(F101,"zoutdump chars","",zoutcnt); |
---|
1292 | if (zoutcnt == 0) { /* Nothing to output */ |
---|
1293 | return(0); |
---|
1294 | } else if (zoutcnt < 0) { /* Unexpected negative argument */ |
---|
1295 | zoutcnt = 0; /* Reset output buffer count */ |
---|
1296 | return(-1); /* and fail. */ |
---|
1297 | } |
---|
1298 | |
---|
1299 | #ifdef CK_LABELED |
---|
1300 | if (binary == XYFT_L ) { |
---|
1301 | x = do_label_recv() ; |
---|
1302 | if ( x > 0 ) { /* more room in the buffer */ |
---|
1303 | debug(F101,"zoutdump do_label_recv unfilled buffer","",zoutcnt); |
---|
1304 | return 0 ; |
---|
1305 | } else if ( x < 0 ) { |
---|
1306 | debug(F101,"zoutdump do_label_recv error","",x); |
---|
1307 | return -1 ; |
---|
1308 | } |
---|
1309 | } |
---|
1310 | #endif /* CK_LABELED */ |
---|
1311 | /* Frank Prindle suggested that replacing this fwrite() by an fflush() */ |
---|
1312 | /* followed by a write() would improve the efficiency, especially when */ |
---|
1313 | /* writing to stdout. Subsequent tests showed a 5-fold improvement! */ |
---|
1314 | /* if (x = fwrite(zoutbuffer, 1, zoutcnt, fp[ZOFILE])) { */ |
---|
1315 | |
---|
1316 | fflush(fp[ZOFILE]); |
---|
1317 | if ((x = write(fileno(fp[ZOFILE]),zoutbuffer,zoutcnt)) == zoutcnt) { |
---|
1318 | debug(F101,"zoutdump write ok","",zoutcnt); |
---|
1319 | zoutcnt = 0; /* Reset output buffer count */ |
---|
1320 | return(0); /* write() worked OK */ |
---|
1321 | } else { |
---|
1322 | debug(F101,"zoutdump write error","",errno); |
---|
1323 | debug(F101,"zoutdump write returns","",x); |
---|
1324 | zoutcnt = 0; /* Reset output buffer count */ |
---|
1325 | return(-1); /* write() failed */ |
---|
1326 | } |
---|
1327 | } |
---|
1328 | |
---|
1329 | /* C H K F N -- Internal function to verify file number is ok */ |
---|
1330 | |
---|
1331 | /* |
---|
1332 | Returns: |
---|
1333 | -1: File number n is out of range |
---|
1334 | 0: n is in range, but file is not open |
---|
1335 | 1: n in range and file is open |
---|
1336 | */ |
---|
1337 | int |
---|
1338 | chkfn(n) int n; { |
---|
1339 | #ifdef COMMENT /* Save some stack space */ |
---|
1340 | switch (n) { |
---|
1341 | case ZCTERM: |
---|
1342 | case ZSTDIO: |
---|
1343 | case ZIFILE: |
---|
1344 | case ZOFILE: |
---|
1345 | case ZDFILE: |
---|
1346 | case ZTFILE: |
---|
1347 | case ZPFILE: |
---|
1348 | case ZSFILE: |
---|
1349 | case ZSYSFN: |
---|
1350 | case ZRFILE: |
---|
1351 | case ZWFILE: |
---|
1352 | #ifdef OS2 |
---|
1353 | case ZPRINT: |
---|
1354 | #endif /* OS2 */ |
---|
1355 | break; |
---|
1356 | default: |
---|
1357 | debug(F101,"chkfn: file number out of range","",n); |
---|
1358 | fprintf(stderr,"?File number out of range - %d\n",n); |
---|
1359 | return(-1); |
---|
1360 | } |
---|
1361 | return( (fp[n] == NULL) ? 0 : 1 ); |
---|
1362 | #else |
---|
1363 | if (n < 0 || n >= ZNFILS) |
---|
1364 | return(-1); |
---|
1365 | else return( (fp[n] == NULL) ? 0 : 1 ); |
---|
1366 | #endif /* COMMENT */ |
---|
1367 | } |
---|
1368 | |
---|
1369 | /* Z C H K I -- Check if input file exists and is readable */ |
---|
1370 | |
---|
1371 | /* |
---|
1372 | Returns: |
---|
1373 | >= 0 if the file can be read (returns the size). |
---|
1374 | -1 if file doesn't exist or can't be accessed, |
---|
1375 | -2 if file exists but is not readable (e.g. a directory file). |
---|
1376 | -3 if file exists but protected against read access. |
---|
1377 | */ |
---|
1378 | /* |
---|
1379 | For Berkeley Unix, a file must be of type "regular" to be readable. |
---|
1380 | Directory files, special files, and symbolic links are not readable. |
---|
1381 | */ |
---|
1382 | long |
---|
1383 | zchki(name) char *name; { |
---|
1384 | #ifdef NT |
---|
1385 | struct _stat buf; |
---|
1386 | #else |
---|
1387 | struct stat buf; |
---|
1388 | #endif /* NT */ |
---|
1389 | int x; |
---|
1390 | |
---|
1391 | #ifdef UNIX |
---|
1392 | x = strlen(name); |
---|
1393 | if (x == 9 && !strcmp(name,"/dev/null")) |
---|
1394 | return(0); |
---|
1395 | #endif /* UNIX */ |
---|
1396 | |
---|
1397 | x = stat(name,&buf); |
---|
1398 | if (x < 0) { |
---|
1399 | debug(F111,"zchki stat fails",name,errno); |
---|
1400 | return(-1); |
---|
1401 | } |
---|
1402 | if (!S_ISREG (buf.st_mode) /* Must be regular file */ |
---|
1403 | #ifdef S_ISFIFO |
---|
1404 | && !S_ISFIFO (buf.st_mode) /* or FIFO */ |
---|
1405 | #endif /* S_ISFIFO */ |
---|
1406 | ) { |
---|
1407 | debug(F111,"zchki skipping:",name,x); |
---|
1408 | return(-2); |
---|
1409 | } |
---|
1410 | debug(F111,"zchki stat ok:",name,x); |
---|
1411 | |
---|
1412 | #ifdef SW_ACC_ID |
---|
1413 | debug(F100,"zchki swapping ids for access()","",0); |
---|
1414 | priv_on(); |
---|
1415 | #endif /* SW_ACC_ID */ |
---|
1416 | #ifdef NT |
---|
1417 | x = _access(name,R_OK); |
---|
1418 | #else |
---|
1419 | x = access(name,R_OK); |
---|
1420 | #endif /* NT */ |
---|
1421 | #ifdef SW_ACC_ID |
---|
1422 | priv_off(); |
---|
1423 | debug(F100,"zchki swapped ids restored","",0); |
---|
1424 | #endif /* SW_ACC_ID */ |
---|
1425 | if (x < 0) { /* Is the file accessible? */ |
---|
1426 | debug(F111," access failed:",name,x); /* No */ |
---|
1427 | return(-3); |
---|
1428 | } else { |
---|
1429 | iflen = buf.st_size; /* Yes, remember size */ |
---|
1430 | strncpy(nambuf,name,MAXNAMLEN); /* and name globally. */ |
---|
1431 | debug(F111," access ok:",name,(int) iflen); |
---|
1432 | return( (iflen > -1L) ? iflen : 0L ); |
---|
1433 | } |
---|
1434 | } |
---|
1435 | |
---|
1436 | /* Z C H K O -- Check if output file can be created */ |
---|
1437 | |
---|
1438 | /* |
---|
1439 | Returns -1 if write permission for the file would be denied, 0 otherwise. |
---|
1440 | */ |
---|
1441 | int |
---|
1442 | zchko(name) char *name; { |
---|
1443 | int i, x; |
---|
1444 | char *s; |
---|
1445 | |
---|
1446 | if (!name) return(-1); /* Watch out for null pointer. */ |
---|
1447 | x = (int)strlen(name); /* Get length of filename */ |
---|
1448 | debug(F101," length","",x); |
---|
1449 | |
---|
1450 | #ifdef UNIX |
---|
1451 | /* |
---|
1452 | Writing to null device is OK. |
---|
1453 | */ |
---|
1454 | if (x == 9 && !strcmp(name,"/dev/null")) |
---|
1455 | return(0); |
---|
1456 | #endif /* UNIX */ |
---|
1457 | |
---|
1458 | if (isdir(name)) /* Directories are not writeable */ |
---|
1459 | return(-1); |
---|
1460 | |
---|
1461 | s = malloc(x+3); /* Must copy because we can't */ |
---|
1462 | if (!s) { /* write into our argument. */ |
---|
1463 | fprintf(stderr,"Malloc error 46\n"); |
---|
1464 | return(-1); |
---|
1465 | } |
---|
1466 | strcpy(s,name); |
---|
1467 | |
---|
1468 | for (i = x; i > 0; i--) /* Strip filename from right. */ |
---|
1469 | if (ISDIRSEP(s[i-1])) break; |
---|
1470 | debug(F101," i","",i); |
---|
1471 | |
---|
1472 | #ifdef COMMENT |
---|
1473 | /* X/OPEN XPG3-compliant systems fail if argument ends with "/"... */ |
---|
1474 | if (i == 0) /* If no path, use current directory */ |
---|
1475 | strcpy(s,"./"); |
---|
1476 | else /* Otherwise, use given one. */ |
---|
1477 | s[i] = '\0'; |
---|
1478 | #else |
---|
1479 | /* So now we use "path/." if path given, or "." if no path given. */ |
---|
1480 | s[i++] = '.'; /* Append "." to path. */ |
---|
1481 | s[i] = '\0'; |
---|
1482 | #endif /* COMMENT */ |
---|
1483 | |
---|
1484 | #ifdef SW_ACC_ID |
---|
1485 | debug(F100,"zchko swapping ids for access()","",0); |
---|
1486 | priv_on(); |
---|
1487 | #endif /* SW_ACC_ID */ |
---|
1488 | #ifdef OS2 /* No unwritable directories in OS/2 */ |
---|
1489 | x = 0; |
---|
1490 | #else |
---|
1491 | #ifdef NT |
---|
1492 | x = _access(s,W_OK); /* Check access of path. */ |
---|
1493 | #else |
---|
1494 | x = access(s,W_OK); /* Check access of path. */ |
---|
1495 | #endif /* NT */ |
---|
1496 | #endif /* OS2 */ |
---|
1497 | #ifdef SW_ACC_ID |
---|
1498 | priv_off(); |
---|
1499 | debug(F100,"zchko swapped ids restored","",0); |
---|
1500 | #endif /* SW_ACC_ID */ |
---|
1501 | if (x < 0) |
---|
1502 | debug(F111,"zchko access failed:",s,errno); |
---|
1503 | else |
---|
1504 | debug(F111,"zchko access ok:",s,x); |
---|
1505 | free(s); /* Free temporary storage */ |
---|
1506 | return((x < 0) ? -1 : 0); /* and return. */ |
---|
1507 | } |
---|
1508 | |
---|
1509 | /* Z D E L E T -- Delete the named file. */ |
---|
1510 | |
---|
1511 | int |
---|
1512 | zdelet(name) char *name; { |
---|
1513 | #ifdef NT |
---|
1514 | return(_unlink(name)); |
---|
1515 | #else /* NT */ |
---|
1516 | return(unlink(name)); |
---|
1517 | #endif /* NT */ |
---|
1518 | } |
---|
1519 | |
---|
1520 | /* Z R T O L -- Convert remote filename into local form */ |
---|
1521 | |
---|
1522 | VOID |
---|
1523 | zrtol(name,name2) char *name, *name2; { |
---|
1524 | char *p; int flag = 0, n = 0; |
---|
1525 | int acase = 0; |
---|
1526 | if (!name || !name2) return; |
---|
1527 | debug(F101,"zrtol original name","",name); |
---|
1528 | p = name2; |
---|
1529 | for ( ; *name != '\0' && n < maxnam; name++) { |
---|
1530 | if (*name > ' ') flag = 1; /* Strip leading blanks and controls */ |
---|
1531 | if (flag == 0 && *name < '!') |
---|
1532 | continue; |
---|
1533 | if (isupper(*name)) /* Check for mixed case */ |
---|
1534 | acase |= 1; |
---|
1535 | else if (islower(*name)) |
---|
1536 | acase |= 2; |
---|
1537 | *p++ = *name; |
---|
1538 | n++; |
---|
1539 | } |
---|
1540 | *p-- = '\0'; /* Terminate */ |
---|
1541 | while (*p < '!' && p > name2) /* Strip trailing blanks & controls */ |
---|
1542 | *p-- = '\0'; |
---|
1543 | |
---|
1544 | if (*name2 == '\0') { /* Nothing left? */ |
---|
1545 | strcpy(name2,"NONAME"); /* do this... */ |
---|
1546 | } else if (acase == 1) { /* All uppercase? */ |
---|
1547 | p = name2; /* So convert all letters to lower */ |
---|
1548 | while (*p) { |
---|
1549 | if (isupper(*p)) |
---|
1550 | *p = tolower(*p); |
---|
1551 | p++; |
---|
1552 | } |
---|
1553 | } |
---|
1554 | #ifdef OS2 |
---|
1555 | if (!IsFileNameValid(name2)) |
---|
1556 | ChangeNameForFAT(name2); |
---|
1557 | #endif /* OS2 */ |
---|
1558 | debug(F110,"zrtol new name",name2,0); |
---|
1559 | } |
---|
1560 | |
---|
1561 | |
---|
1562 | /* Z S T R I P -- Strip device & directory name from file specification */ |
---|
1563 | |
---|
1564 | /* Strip pathname from filename "name", return pointer to result in name2 */ |
---|
1565 | |
---|
1566 | #ifdef pdp11 |
---|
1567 | #define ZSTRPLEN 64 |
---|
1568 | #else |
---|
1569 | #define ZSTRPLEN MAXPATH |
---|
1570 | #endif /* pdp11 */ |
---|
1571 | static char work[ZSTRPLEN+1]; |
---|
1572 | |
---|
1573 | VOID |
---|
1574 | zstrip(name,name2) char *name, **name2; { |
---|
1575 | char *cp, *pp; |
---|
1576 | int n = 0; |
---|
1577 | debug(F110,"zstrip before",name,0); |
---|
1578 | if (!name) { *name2 = ""; return; } |
---|
1579 | pp = work; |
---|
1580 | #ifdef DTILDE |
---|
1581 | /* Strip leading tilde */ |
---|
1582 | if (*name == '~') name++; |
---|
1583 | debug(F110,"zstrip after tilde-stripping",name,0); |
---|
1584 | #else |
---|
1585 | #ifdef OS2 |
---|
1586 | /* Strip disk letter and colon */ |
---|
1587 | if (isalpha(*name) && (*(name+1) == ':')) name += 2; |
---|
1588 | debug(F110,"zstrip after disk-stripping",name,0); |
---|
1589 | #endif /* OS2 */ |
---|
1590 | #endif /* DTILDE */ |
---|
1591 | for (cp = name; *cp; cp++) { |
---|
1592 | if (ISDIRSEP(*cp)) { |
---|
1593 | pp = work; |
---|
1594 | n = 0; |
---|
1595 | } else { |
---|
1596 | *pp++ = *cp; |
---|
1597 | if (n++ >= ZSTRPLEN) |
---|
1598 | break; |
---|
1599 | } |
---|
1600 | } |
---|
1601 | *pp = '\0'; /* Terminate the string */ |
---|
1602 | *name2 = work; |
---|
1603 | debug(F110,"zstrip after",*name2,0); |
---|
1604 | } |
---|
1605 | |
---|
1606 | /* Z L T O R -- Local TO Remote */ |
---|
1607 | |
---|
1608 | VOID |
---|
1609 | zltor(name,name2) char *name, *name2; { |
---|
1610 | char *cp, *pp; |
---|
1611 | int dc = 0; |
---|
1612 | char *dotp = NULL; |
---|
1613 | #ifdef aegis |
---|
1614 | char *namechars; |
---|
1615 | int tilde = 0, bslash = 0; |
---|
1616 | |
---|
1617 | if ((namechars = getenv("NAMECHARS")) != NULL) { |
---|
1618 | if (xindex(namechars, '~' ) != NULL) tilde = '~'; |
---|
1619 | if (xindex(namechars, '\\') != NULL) bslash = '\\'; |
---|
1620 | } else { |
---|
1621 | tilde = '~'; |
---|
1622 | bslash = '\\'; |
---|
1623 | } |
---|
1624 | #endif /* aegis */ |
---|
1625 | |
---|
1626 | debug(F110,"zltor",name,0); |
---|
1627 | pp = work; |
---|
1628 | #ifdef OS2 |
---|
1629 | if (isalpha(*name) && (*(name+1) == ':')) /* Strip disk name */ |
---|
1630 | name += 2; |
---|
1631 | #endif /* OS2 */ |
---|
1632 | for (cp = name; *cp; cp++) { /* Strip path name */ |
---|
1633 | if (ISDIRSEP(*cp)) { |
---|
1634 | dc = 0; /* Start over... */ |
---|
1635 | dotp = NULL; |
---|
1636 | pp = work; |
---|
1637 | } else if (islower(*cp)) /* Uppercase letters */ |
---|
1638 | *pp++ = toupper(*cp); /* Change tilde to 'X' */ |
---|
1639 | else if (*cp == '~') |
---|
1640 | *pp++ = 'X'; |
---|
1641 | else if (*cp == '#') /* Change number sign to 'X' */ |
---|
1642 | *pp++ = 'X'; |
---|
1643 | else if (*cp == '.') { /* Change dot to underscore */ |
---|
1644 | dotp = pp; /* Remember where we last did this */ |
---|
1645 | *pp++ = '_'; |
---|
1646 | } else |
---|
1647 | *pp++ = *cp; |
---|
1648 | } |
---|
1649 | *pp = NUL; /* Tie it off. */ |
---|
1650 | if (dotp) *dotp = '.'; /* Restore last dot (if any) */ |
---|
1651 | cp = name2; /* If nothing before dot, */ |
---|
1652 | if (*work == '.') *cp++ = 'X'; /* insert 'X' */ |
---|
1653 | strcpy(cp,work); |
---|
1654 | debug(F110," name2",name2,0); |
---|
1655 | } |
---|
1656 | |
---|
1657 | |
---|
1658 | /* Z C H D I R -- Change directory */ |
---|
1659 | /* |
---|
1660 | Call with: |
---|
1661 | dirnam = pointer to name of directory to change to, |
---|
1662 | which may be "" or NULL to indicate user's home directory. |
---|
1663 | Returns: |
---|
1664 | 0 on failure |
---|
1665 | 1 on success |
---|
1666 | */ |
---|
1667 | int |
---|
1668 | zchdir(dirnam) char *dirnam; { |
---|
1669 | char *hd, *sp, *p; |
---|
1670 | |
---|
1671 | debug(F110,"zchdir",dirnam,0); |
---|
1672 | if (dirnam == NULL || dirnam == "" || *dirnam == '\0') /* If arg is null */ |
---|
1673 | dirnam = zhome(); /* use user's home directory. */ |
---|
1674 | sp = dirnam; |
---|
1675 | debug(F110,"zchdir 2",dirnam,0); |
---|
1676 | |
---|
1677 | #ifdef DTILDE |
---|
1678 | hd = tilde_expand(dirnam); /* Attempt to expand tilde */ |
---|
1679 | if (*hd == '\0') hd = dirnam; /* in directory name. */ |
---|
1680 | #else |
---|
1681 | hd = dirnam; |
---|
1682 | #endif /* DTILDE */ |
---|
1683 | debug(F110,"zchdir 3",hd,0); |
---|
1684 | #ifdef pdp11 |
---|
1685 | /* Just to save some space */ |
---|
1686 | return(( |
---|
1687 | #ifdef NT |
---|
1688 | _chdir(hd) |
---|
1689 | #else |
---|
1690 | chdir(hd) |
---|
1691 | #endif /* NT */ |
---|
1692 | == 0) ? 1 : 0); |
---|
1693 | #else |
---|
1694 | #ifdef OS2 |
---|
1695 | if (isalpha(hd[0]) && hd[1] == ':') { |
---|
1696 | if (zchdsk(hd[0])) |
---|
1697 | return(0); |
---|
1698 | if (hd[2] == 0) |
---|
1699 | return(1); /* Handle drive-only case */ |
---|
1700 | } |
---|
1701 | { |
---|
1702 | /* strip trailing DIRSEP except after d:; chdir() doesn't like it */ |
---|
1703 | int len = strlen(hd) ; |
---|
1704 | if ( len > 1 && ISDIRSEP(hd[len - 1]) && hd[len - 2] != ':' ) |
---|
1705 | hd[len - 1] = 0; |
---|
1706 | } |
---|
1707 | #endif /* OS2 */ |
---|
1708 | if ( |
---|
1709 | #ifdef NT |
---|
1710 | _chdir(hd) |
---|
1711 | #else |
---|
1712 | chdir(hd) |
---|
1713 | #endif /* NT */ |
---|
1714 | == 0) return(1); /* Try to cd */ |
---|
1715 | else return(0); |
---|
1716 | |
---|
1717 | #ifdef COMMENT |
---|
1718 | /* This doesn't help in Windows or OS/2, and it's wrong in UNIX */ |
---|
1719 | p = sp; /* Failed, lowercase it. */ |
---|
1720 | while (*p) { |
---|
1721 | if (isupper(*p)) *p = tolower(*p); |
---|
1722 | p++; |
---|
1723 | } |
---|
1724 | debug(F110,"zchdir 4",hd,0); |
---|
1725 | #ifdef DTILDE |
---|
1726 | hd = tilde_expand(sp); /* Try again to expand tilde */ |
---|
1727 | if (*hd == '\0') hd = sp; |
---|
1728 | #else |
---|
1729 | hd = sp; /* Point to result */ |
---|
1730 | #endif /* DTILDE */ |
---|
1731 | debug(F110,"zchdir 5",hd,0); |
---|
1732 | return(( |
---|
1733 | #ifdef NT |
---|
1734 | _chdir(hd) |
---|
1735 | #else |
---|
1736 | chdir(hd) |
---|
1737 | #endif /* NT */ |
---|
1738 | == 0) ? 1 : 0); |
---|
1739 | #endif /* COMMENT */ |
---|
1740 | |
---|
1741 | #endif /* pdp11 */ |
---|
1742 | } |
---|
1743 | |
---|
1744 | /* Z H O M E -- Return pointer to user's home directory */ |
---|
1745 | |
---|
1746 | char * |
---|
1747 | zhome() { |
---|
1748 | #ifdef Plan9 |
---|
1749 | char *home = getenv("home"); |
---|
1750 | #else |
---|
1751 | char *home = getenv("HOME"); |
---|
1752 | #endif /* Plan9 */ |
---|
1753 | #ifdef OS2 |
---|
1754 | extern char startupdir[]; |
---|
1755 | return(home ? home : startupdir); |
---|
1756 | #else |
---|
1757 | return(home ? home : "."); |
---|
1758 | #endif /* OS2 */ |
---|
1759 | } |
---|
1760 | |
---|
1761 | /* Z G T D I R -- Return pointer to user's current directory */ |
---|
1762 | |
---|
1763 | #ifdef pdp11 |
---|
1764 | #define CWDBL 80 /* Save every byte we can... */ |
---|
1765 | #else |
---|
1766 | #define CWDBL MAXPATH |
---|
1767 | #endif /* pdp11 */ |
---|
1768 | static char cwdbuf[CWDBL+1]; |
---|
1769 | |
---|
1770 | char * |
---|
1771 | zgtdir() { |
---|
1772 | char *buf; |
---|
1773 | |
---|
1774 | #ifdef BSD44 |
---|
1775 | extern char *getcwd(); |
---|
1776 | buf = cwdbuf; |
---|
1777 | debug(F101,"zgtdir CWDBL","",CWDBL); |
---|
1778 | return(getcwd(buf,CWDBL)); |
---|
1779 | #else |
---|
1780 | #ifdef SVORPOSIX |
---|
1781 | extern char *getcwd(); |
---|
1782 | buf = cwdbuf; |
---|
1783 | debug(F101,"zgtdir CWDBL","",CWDBL); |
---|
1784 | return(getcwd(buf,CWDBL)); |
---|
1785 | #else |
---|
1786 | #ifdef COHERENT |
---|
1787 | #ifdef _I386 |
---|
1788 | extern char *getcwd(); |
---|
1789 | buf = cwdbuf; |
---|
1790 | debug(F101,"zgtdir CWDBL","",CWDBL); |
---|
1791 | return(getcwd(buf,CWDBL)); |
---|
1792 | #else |
---|
1793 | extern char *getwd(); |
---|
1794 | buf = cwdbuf; |
---|
1795 | debug(F101,"zgtdir CWDBL","",CWDBL); |
---|
1796 | return(getwd(buf)); |
---|
1797 | #endif /* _I386 */ |
---|
1798 | #else |
---|
1799 | #ifdef OS2 |
---|
1800 | #ifndef __IBMC__ /* which has a macro for this */ |
---|
1801 | extern char *getcwd(); |
---|
1802 | #endif /* __IBMC__ */ |
---|
1803 | buf = cwdbuf; |
---|
1804 | debug(F101,"zgtdir CWDBL","",CWDBL); |
---|
1805 | #ifdef NT |
---|
1806 | _getcwd(buf,CWDBL); |
---|
1807 | #else |
---|
1808 | getcwd(buf,CWDBL); |
---|
1809 | #endif /* NT */ |
---|
1810 | return(buf); |
---|
1811 | #else /* OS2 */ |
---|
1812 | #ifdef BSD4 |
---|
1813 | extern char *getwd(); |
---|
1814 | buf = cwdbuf; |
---|
1815 | debug(F100,"zgtdir getwd()","",0); |
---|
1816 | return(getwd(buf)); |
---|
1817 | #else |
---|
1818 | return("directory unknown"); |
---|
1819 | #endif /* BSD4 */ |
---|
1820 | #endif /* OS2 */ |
---|
1821 | #endif /* COHERENT */ |
---|
1822 | #endif /* SYSVORPOSIX */ |
---|
1823 | #endif /* BSD44 */ |
---|
1824 | } |
---|
1825 | |
---|
1826 | /* Z X C M D -- Run a system command so its output can be read like a file */ |
---|
1827 | |
---|
1828 | #ifdef NT |
---|
1829 | _PROTOTYP( FILE * win95popen, (char *cmd, char *mode) ); |
---|
1830 | _PROTOTYP( int win95pclose, (FILE *pipe) ); |
---|
1831 | #endif /* NT */ |
---|
1832 | |
---|
1833 | int |
---|
1834 | zxcmd(filnum,comand) int filnum; char *comand; { |
---|
1835 | #ifdef OS2 |
---|
1836 | if (chkfn(filnum) < 0) return(-1); /* Need a valid Kermit file number. */ |
---|
1837 | if (filnum == ZSTDIO || filnum == ZCTERM) /* But not one of these. */ |
---|
1838 | return(0); |
---|
1839 | if (filnum == ZIFILE || filnum == ZRFILE) { /* Input from a command */ |
---|
1840 | if (priv_chk() || |
---|
1841 | #ifdef NT |
---|
1842 | isWin95() ? |
---|
1843 | ((fp[filnum] = win95popen(comand,"rb")) == NULL) : |
---|
1844 | #endif /* NT */ |
---|
1845 | ((fp[filnum] = popen(comand,"rb")) == NULL) |
---|
1846 | ) |
---|
1847 | return(0); |
---|
1848 | } else { /* Output to a command */ |
---|
1849 | if (priv_chk() || |
---|
1850 | #ifdef NT |
---|
1851 | isWin95() ? |
---|
1852 | ((fp[filnum] = win95popen(comand,"w")) == NULL) : |
---|
1853 | #endif /* NT */ |
---|
1854 | ((fp[filnum] = popen(comand,"w")) == NULL) |
---|
1855 | ) |
---|
1856 | return(0); |
---|
1857 | } |
---|
1858 | fp[ZSYSFN] = fp[filnum]; /* remember the pipe handle */ |
---|
1859 | ispipe[filnum] = 1; |
---|
1860 | return(1); |
---|
1861 | #else /* Not OS2 */ |
---|
1862 | int pipes[2]; |
---|
1863 | int out; |
---|
1864 | |
---|
1865 | if (chkfn(filnum) < 0) return(-1); /* Need a valid Kermit file number. */ |
---|
1866 | if (filnum == ZSTDIO || filnum == ZCTERM) /* But not one of these. */ |
---|
1867 | return(0); |
---|
1868 | |
---|
1869 | out = (filnum == ZIFILE || filnum == ZRFILE) ? 0 : 1 ; |
---|
1870 | |
---|
1871 | /* Output to a command */ |
---|
1872 | |
---|
1873 | if (out) { /* Need popen() to do this. */ |
---|
1874 | #ifdef NOPOPEN |
---|
1875 | return(0); /* no popen(), fail. */ |
---|
1876 | #else |
---|
1877 | /* Use popen() to run the command. */ |
---|
1878 | |
---|
1879 | #ifdef _POSIX_SOURCE |
---|
1880 | /* Strictly speaking, popen() is not available in POSIX.1 */ |
---|
1881 | #define DCLPOPEN |
---|
1882 | #endif /* _POSIX_SOURCE */ |
---|
1883 | |
---|
1884 | #ifdef COHERENT |
---|
1885 | #define DCLPOPEN |
---|
1886 | FILE * fdopen(); |
---|
1887 | #endif /* COHERENT */ |
---|
1888 | |
---|
1889 | #ifdef DCLPOPEN |
---|
1890 | /* popen() needs declaring because it's not declared in <stdio.h> */ |
---|
1891 | FILE *popen(); |
---|
1892 | #endif /* DCLPOPEN */ |
---|
1893 | |
---|
1894 | if (priv_chk() || ((fp[filnum] = popen(comand,"w")) == NULL)) |
---|
1895 | return(0); |
---|
1896 | else return(1); |
---|
1897 | #endif /* NOPOPEN */ |
---|
1898 | } |
---|
1899 | |
---|
1900 | /* Input from a command */ |
---|
1901 | |
---|
1902 | if (pipe(pipes) != 0) { |
---|
1903 | debug(F100,"zxcmd pipe failure","",0); |
---|
1904 | return(0); /* can't make pipe, fail */ |
---|
1905 | } |
---|
1906 | |
---|
1907 | /* Create a fork in which to run the named process */ |
---|
1908 | |
---|
1909 | if (( |
---|
1910 | #ifdef aegis |
---|
1911 | pid = vfork() /* child */ |
---|
1912 | #else |
---|
1913 | pid = fork() /* child */ |
---|
1914 | #endif /* aegis */ |
---|
1915 | ) == 0) { |
---|
1916 | |
---|
1917 | /* We're in the fork. */ |
---|
1918 | |
---|
1919 | char *shpath, *shname, *shptr; /* Find user's preferred shell */ |
---|
1920 | #ifndef aegis |
---|
1921 | struct passwd *p; |
---|
1922 | char *defshell; |
---|
1923 | #ifdef HPUX10 /* Default shell */ |
---|
1924 | defshell = "/usr/bin/sh"; |
---|
1925 | #else |
---|
1926 | #ifdef Plan9 |
---|
1927 | defshell = "/bin/rc"; |
---|
1928 | #else |
---|
1929 | defshell = "/bin/sh"; |
---|
1930 | #endif /* Plan9 */ |
---|
1931 | #endif /* HPUX10 */ |
---|
1932 | #endif /* aegis */ |
---|
1933 | if (priv_can()) exit(1); /* Turn off any privileges! */ |
---|
1934 | debug(F101,"zxcmd pid","",pid); |
---|
1935 | close(pipes[0]); /* close input side of pipe */ |
---|
1936 | close(0); /* close stdin */ |
---|
1937 | if (open("/dev/null",0) < 0) return(0); /* replace input by null */ |
---|
1938 | #ifndef OXOS |
---|
1939 | #ifndef SVORPOSIX |
---|
1940 | dup2(pipes[1],1); /* BSD: replace stdout & stderr */ |
---|
1941 | dup2(pipes[1],2); /* by the pipe */ |
---|
1942 | #else |
---|
1943 | close(1); /* AT&T: close stdout */ |
---|
1944 | if ( dup(pipes[1]) != 1 ) /* Send stdout to the pipe */ |
---|
1945 | return(0); |
---|
1946 | close(2); /* Send stderr to the pipe */ |
---|
1947 | if ( dup(pipes[1]) != 2 ) |
---|
1948 | return(0); |
---|
1949 | #endif /* SVORPOSIX */ |
---|
1950 | #else /* OXOS */ |
---|
1951 | dup2(pipes[1],1); |
---|
1952 | dup2(pipes[1],2); |
---|
1953 | #endif /* OXOS */ |
---|
1954 | close(pipes[1]); /* Don't need this any more. */ |
---|
1955 | |
---|
1956 | #ifdef aegis |
---|
1957 | if ((shpath = getenv("SERVERSHELL")) == NULL) |
---|
1958 | shpath = "/bin/sh"; |
---|
1959 | #else |
---|
1960 | shpath = getenv("SHELL"); /* What shell? */ |
---|
1961 | if (shpath == NULL) { |
---|
1962 | p = getpwuid( real_uid() ); /* Get login data */ |
---|
1963 | if (p == (struct passwd *)NULL || !*(p->pw_shell)) |
---|
1964 | shpath = defshell; |
---|
1965 | else shpath = p->pw_shell; |
---|
1966 | } |
---|
1967 | #endif /* aegis */ |
---|
1968 | shptr = shname = shpath; |
---|
1969 | while (*shptr != '\0') |
---|
1970 | if (*shptr++ == '/') |
---|
1971 | shname = shptr; |
---|
1972 | debug(F100,"zxcmd...","",0); |
---|
1973 | debug(F110,shpath,shname,0); |
---|
1974 | |
---|
1975 | execl(shpath,shname,"-c",comand,(char *)NULL); /* Execute the cmd */ |
---|
1976 | exit(0); /* just punt if it failed. */ |
---|
1977 | } else if (pid == (PID_T) -1) { |
---|
1978 | debug(F100,"zxcmd fork failure","",0); |
---|
1979 | return(0); |
---|
1980 | } |
---|
1981 | debug(F101,"zxcmd pid","",pid); |
---|
1982 | if (out) { |
---|
1983 | close(pipes[0]); /* Don't need the input side */ |
---|
1984 | fp[filnum] = fdopen(pipes[1],"w"); /* Open a stream for output. */ |
---|
1985 | fp[ZSYSFN] = fp[filnum]; /* Remember. */ |
---|
1986 | zoutcnt = 0; /* (PWP) reset input buffer */ |
---|
1987 | zoutptr = zoutbuffer; |
---|
1988 | } else { |
---|
1989 | close(pipes[1]); /* Don't need the output side */ |
---|
1990 | fp[filnum] = fdopen(pipes[0],"r"); /* Open a stream for input. */ |
---|
1991 | fp[ZSYSFN] = fp[filnum]; /* Remember. */ |
---|
1992 | zincnt = 0; /* (PWP) reset input buffer */ |
---|
1993 | zinptr = zinbuffer; |
---|
1994 | } |
---|
1995 | return(1); |
---|
1996 | #endif /* OS2 */ |
---|
1997 | } /* zxcmd */ |
---|
1998 | |
---|
1999 | /* Z C L O S F - wait for the child fork to terminate and close the pipe. */ |
---|
2000 | |
---|
2001 | int |
---|
2002 | zclosf(filnum) int filnum; { |
---|
2003 | int wstat; |
---|
2004 | debug(F101,"zclosf filnum","",filnum); |
---|
2005 | #ifndef NOPOPEN |
---|
2006 | #ifdef OS2 |
---|
2007 | if (ispipe[filnum]) { |
---|
2008 | int x; |
---|
2009 | #ifdef NT |
---|
2010 | x = isWin95() ? win95pclose(fp[filnum]) : pclose(fp[filnum]) ; |
---|
2011 | #else /* NT */ |
---|
2012 | x = pclose(fp[filnum]); |
---|
2013 | #endif /* NT */ |
---|
2014 | fp[filnum] = NULL; |
---|
2015 | ispipe[filnum] = 0; |
---|
2016 | #else |
---|
2017 | if (filnum == ZWFILE) { |
---|
2018 | int x; |
---|
2019 | x = pclose(fp[filnum]); |
---|
2020 | fp[filnum] = fp[ZSYSFN] = NULL; |
---|
2021 | #endif /* OS2 */ |
---|
2022 | return((x < 0) ? 0 : 1); |
---|
2023 | } |
---|
2024 | #endif /* NOPOPEN */ |
---|
2025 | debug(F101,"zclosf fp[filnum]","", fp[filnum]); |
---|
2026 | debug(F101,"zclosf fp[ZSYSFN]","", fp[ZSYSFN]); |
---|
2027 | #ifdef OS2 |
---|
2028 | fclose(fp[filnum]); |
---|
2029 | fp[filnum] = NULL; |
---|
2030 | #else |
---|
2031 | if (pid != (PID_T) 0) { |
---|
2032 | debug(F101,"zclosf killing pid","",pid); |
---|
2033 | #ifdef Plan9 |
---|
2034 | kill(pid, SIGKILL); |
---|
2035 | #else |
---|
2036 | kill(pid,9); |
---|
2037 | #endif /* Plan9 */ |
---|
2038 | while ((wstat = wait((WAIT_T *)0)) != pid && wstat != -1) ; |
---|
2039 | pid = 0; |
---|
2040 | } |
---|
2041 | fclose(fp[filnum]); |
---|
2042 | fp[filnum] = fp[ZSYSFN] = NULL; |
---|
2043 | #endif /* OS2 */ |
---|
2044 | return(1); |
---|
2045 | } |
---|
2046 | |
---|
2047 | /* Z X P A N D -- Expand a wildcard string into an array of strings */ |
---|
2048 | /* |
---|
2049 | Returns the number of files that match fn1, with data structures set up |
---|
2050 | so that first file (if any) will be returned by the next znext() call. |
---|
2051 | Depends on external variable wildxpand: 0 means we expand wildcards |
---|
2052 | internally, nonzero means we call the shell to do it. |
---|
2053 | */ |
---|
2054 | |
---|
2055 | #ifdef OS2 |
---|
2056 | /* Z X P A N D -- Expand a wildcard string into an array of strings */ |
---|
2057 | /* |
---|
2058 | Returns the number of files that match fn1, with data structures set up |
---|
2059 | so that first file (if any) will be returned by the next znext() call. |
---|
2060 | Depends on external variable wildxpand: 0 means we expand wildcards |
---|
2061 | internally, nonzero means we call the shell to do it. |
---|
2062 | */ |
---|
2063 | |
---|
2064 | char findpath[MAXPATH]; |
---|
2065 | #ifdef NT |
---|
2066 | WIN32_FIND_DATA finddata; |
---|
2067 | HANDLE findhandle = INVALID_HANDLE_VALUE; |
---|
2068 | #else /* NT */ |
---|
2069 | FILEFINDBUF3 finddata; |
---|
2070 | HDIR findhandle = HDIR_CREATE; |
---|
2071 | ULONG findcount; |
---|
2072 | #endif /* NT */ |
---|
2073 | |
---|
2074 | int |
---|
2075 | zxpand(fn) char *fn; { |
---|
2076 | int i, lasterror = 0; |
---|
2077 | char localfn[MAXPATH]; |
---|
2078 | |
---|
2079 | if ( !fn || !(*fn) ) |
---|
2080 | return(0); |
---|
2081 | |
---|
2082 | debug(F110,"zxpand fn",fn,0); |
---|
2083 | #ifdef NT |
---|
2084 | if (findhandle != INVALID_HANDLE_VALUE) { |
---|
2085 | FindClose(findhandle); |
---|
2086 | findhandle = INVALID_HANDLE_VALUE; |
---|
2087 | } |
---|
2088 | #else |
---|
2089 | if (findhandle != HDIR_CREATE) { |
---|
2090 | DosFindClose(findhandle); |
---|
2091 | findhandle = HDIR_CREATE; |
---|
2092 | } |
---|
2093 | #endif /* NT */ |
---|
2094 | |
---|
2095 | fcount = 0; |
---|
2096 | strcpy(findpath, fn); |
---|
2097 | strcpy(localfn, fn); |
---|
2098 | for (i = strlen(findpath); i >= 0; i--) { |
---|
2099 | if (ISDIRSEP(findpath[i]) |
---|
2100 | || findpath[i] == ':' |
---|
2101 | ) { |
---|
2102 | if (!findpath[i+1]) |
---|
2103 | strcat(localfn, "*"); |
---|
2104 | else |
---|
2105 | findpath[i+1] = '\0'; |
---|
2106 | break; |
---|
2107 | } |
---|
2108 | if (findpath[i] == ':') { |
---|
2109 | if (!findpath[i+1]) { |
---|
2110 | strcat(localfn, "*"); |
---|
2111 | break; |
---|
2112 | } |
---|
2113 | } |
---|
2114 | } |
---|
2115 | if (i < 0) |
---|
2116 | if (zchki(localfn) == -2) { |
---|
2117 | if ( strlen(localfn) == 2 && localfn[1] == ':' ) { |
---|
2118 | strcat(localfn, "./*"); |
---|
2119 | } else { |
---|
2120 | strcat(findpath, "/"); |
---|
2121 | strcat(localfn, "/*"); |
---|
2122 | } |
---|
2123 | } else if (!ISDIRSEP(localfn[0]) && localfn[1] != ':') { |
---|
2124 | findpath[0] = '\0'; |
---|
2125 | strcpy(nambuf, "./"); |
---|
2126 | strcat(nambuf, localfn); |
---|
2127 | strcpy(localfn, nambuf); |
---|
2128 | } |
---|
2129 | |
---|
2130 | debug(F100,"zxpand about to FindFirst","",0); |
---|
2131 | #ifdef NT |
---|
2132 | findhandle = FindFirstFile( localfn, &finddata ); |
---|
2133 | if ( findhandle == INVALID_HANDLE_VALUE ) |
---|
2134 | #else /* NT */ |
---|
2135 | findcount = 1; |
---|
2136 | DosFindFirst(localfn, |
---|
2137 | &findhandle, |
---|
2138 | (ULONG) FILE_NORMAL | FILE_ARCHIVED | FILE_DIRECTORY | |
---|
2139 | FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY, |
---|
2140 | (PVOID) &finddata, (ULONG) sizeof(finddata), |
---|
2141 | &findcount, |
---|
2142 | FIL_STANDARD |
---|
2143 | ); |
---|
2144 | if (findcount != 1) |
---|
2145 | #endif /* NT */ |
---|
2146 | return(fcount); |
---|
2147 | |
---|
2148 | fcount = 1; |
---|
2149 | while ( |
---|
2150 | #ifdef NT |
---|
2151 | FindNextFile( findhandle, &finddata ) |
---|
2152 | #else /* NT */ |
---|
2153 | !(lasterror = DosFindNext(findhandle, |
---|
2154 | (PVOID) &finddata, |
---|
2155 | (ULONG) sizeof(finddata), |
---|
2156 | &findcount)) && |
---|
2157 | findcount == 1 |
---|
2158 | #endif /* NT */ |
---|
2159 | ) |
---|
2160 | fcount++; |
---|
2161 | |
---|
2162 | #ifdef NT |
---|
2163 | lasterror = GetLastError(); |
---|
2164 | FindClose( findhandle ); |
---|
2165 | findhandle = INVALID_HANDLE_VALUE; |
---|
2166 | #else |
---|
2167 | DosFindClose( findhandle ); |
---|
2168 | findhandle = HDIR_CREATE; |
---|
2169 | #endif /* NT */ |
---|
2170 | |
---|
2171 | if (lasterror != ERROR_NO_MORE_FILES) { |
---|
2172 | fcount = 0; |
---|
2173 | return (fcount); |
---|
2174 | } |
---|
2175 | |
---|
2176 | debug(F111,"zxpand","fcount",fcount); |
---|
2177 | |
---|
2178 | #ifdef NT |
---|
2179 | findhandle = FindFirstFile( localfn, &finddata ); |
---|
2180 | #else /* NT */ |
---|
2181 | findcount = 1; |
---|
2182 | DosFindFirst(localfn, |
---|
2183 | &findhandle, |
---|
2184 | (ULONG) FILE_NORMAL | FILE_ARCHIVED | FILE_DIRECTORY | |
---|
2185 | FILE_HIDDEN | FILE_SYSTEM | FILE_READONLY, |
---|
2186 | (PVOID) &finddata, |
---|
2187 | (ULONG) sizeof(finddata), |
---|
2188 | &findcount, |
---|
2189 | FIL_STANDARD |
---|
2190 | ); |
---|
2191 | #endif /* NT */ |
---|
2192 | return(fcount); |
---|
2193 | } |
---|
2194 | |
---|
2195 | /* Z N E X T -- Get name of next file from list created by zxpand(). */ |
---|
2196 | /* |
---|
2197 | Returns > 0 if there's another file, with its name copied into the argument |
---|
2198 | string, or 0 if no more files in list. |
---|
2199 | */ |
---|
2200 | int |
---|
2201 | znext(fn) char *fn; { |
---|
2202 | int lasterror = 0; |
---|
2203 | |
---|
2204 | if (fcount-- > 0 |
---|
2205 | #ifdef NT |
---|
2206 | && findhandle != INVALID_HANDLE_VALUE |
---|
2207 | #else |
---|
2208 | && findhandle != HDIR_CREATE |
---|
2209 | #endif /* NT */ |
---|
2210 | ) { |
---|
2211 | strcpy(fn,findpath); |
---|
2212 | #ifdef NT |
---|
2213 | strcat(fn,finddata.cFileName); |
---|
2214 | if (!FindNextFile( findhandle, &finddata)) { |
---|
2215 | FindClose( findhandle ); |
---|
2216 | findhandle = INVALID_HANDLE_VALUE; |
---|
2217 | fcount = 0; |
---|
2218 | } |
---|
2219 | #else /* NT */ |
---|
2220 | strcat(fn,finddata.achName ); |
---|
2221 | findcount = 1; |
---|
2222 | lasterror = DosFindNext(findhandle, |
---|
2223 | (PVOID) &finddata, |
---|
2224 | (ULONG) sizeof(finddata), |
---|
2225 | &findcount |
---|
2226 | ); |
---|
2227 | if (lasterror || findcount != 1) { |
---|
2228 | DosFindClose(findhandle); |
---|
2229 | findhandle = HDIR_CREATE; |
---|
2230 | fcount = 0; |
---|
2231 | } |
---|
2232 | #endif /* NT */ |
---|
2233 | } else { |
---|
2234 | *fn = '\0'; |
---|
2235 | fcount = -1; |
---|
2236 | } |
---|
2237 | debug(F111,"znext",fn,fcount+1); |
---|
2238 | return(fcount+1); |
---|
2239 | } |
---|
2240 | |
---|
2241 | #else /* Not OS2 */ |
---|
2242 | |
---|
2243 | int |
---|
2244 | zxpand(fn) char *fn; { |
---|
2245 | char *p; |
---|
2246 | #ifdef DTILDE /* Built with tilde-expansion? */ |
---|
2247 | char *tnam; |
---|
2248 | #endif /* DTILDE */ |
---|
2249 | debug(F111,"zxpand entry",fn,wildxpand); |
---|
2250 | if ( !fn || !(*fn) ) /* If no argument provided */ |
---|
2251 | return(0); /* Return zero files found */ |
---|
2252 | |
---|
2253 | #ifdef DTILDE /* Built with tilde-expansion? */ |
---|
2254 | if (*fn == '~') { /* Starts with tilde? */ |
---|
2255 | tnam = tilde_expand(fn); /* Try to expand it. */ |
---|
2256 | if (tnam) fn = tnam; |
---|
2257 | } |
---|
2258 | debug(F110,"zxpand after tilde_x",fn,0); |
---|
2259 | #endif /* DTILDE */ |
---|
2260 | #ifndef NOPUSH |
---|
2261 | if (!nopush && wildxpand) /* Who is expanding wildcards? */ |
---|
2262 | fcount = shxpand(fn,mtchs,MAXWLD); /* Shell */ |
---|
2263 | else |
---|
2264 | #endif /* NOPUSH */ |
---|
2265 | fcount = (mtchs == NULL && /* Kermit */ |
---|
2266 | (mtchs = (char **)malloc(MAXWLD * sizeof(*mtchs))) == NULL) |
---|
2267 | ? 0 |
---|
2268 | : fgen(fn,mtchs,MAXWLD); /* Look up the file. */ |
---|
2269 | |
---|
2270 | if (fcount > 0) { |
---|
2271 | mtchptr = mtchs; /* Save pointer for next. */ |
---|
2272 | debug(F111,"zxpand ok",mtchs[0],fcount); |
---|
2273 | return(fcount); |
---|
2274 | } |
---|
2275 | debug(F111,"zxpand fgen1",fn,fcount); /* Didn't get one, or got too many */ |
---|
2276 | p = malloc((int)strlen(fn) + 10); /* Make space */ |
---|
2277 | if (!p) return(0); |
---|
2278 | zrtol(fn,p); /* Try again, maybe lowercase */ |
---|
2279 | |
---|
2280 | #ifndef NOPUSH |
---|
2281 | if (!nopush && wildxpand) |
---|
2282 | fcount = shxpand(p,mtchs,MAXWLD); /* Shell */ |
---|
2283 | else |
---|
2284 | #endif /* NOPUSH */ |
---|
2285 | fcount = fgen(p,mtchs,MAXWLD); /* Kermit */ |
---|
2286 | if (fcount > 0) { /* Got at least one? */ |
---|
2287 | mtchptr = mtchs; /* Save pointer for next. */ |
---|
2288 | debug(F111,"zxpand fgen2 ok",mtchs[0],fcount); |
---|
2289 | } else debug(F111,"zxpand 2 not ok",p,fcount); |
---|
2290 | free(p); |
---|
2291 | return(fcount); |
---|
2292 | } |
---|
2293 | |
---|
2294 | |
---|
2295 | /* Z N E X T -- Get name of next file from list created by zxpand(). */ |
---|
2296 | /* |
---|
2297 | Returns >0 if there's another file, with its name copied into the arg string, |
---|
2298 | or 0 if no more files in list. |
---|
2299 | */ |
---|
2300 | int |
---|
2301 | znext(fn) char *fn; { |
---|
2302 | if (fcount-- > 0) strcpy(fn,*mtchptr++); |
---|
2303 | else *fn = '\0'; |
---|
2304 | debug(F111,"znext",fn,fcount+1); |
---|
2305 | return(fcount+1); |
---|
2306 | } |
---|
2307 | #endif /* OS2 */ |
---|
2308 | |
---|
2309 | /* Z C H K S P A -- Check if there is enough space to store the file */ |
---|
2310 | |
---|
2311 | /* |
---|
2312 | Call with file specification f, size n in bytes. |
---|
2313 | Returns -1 on error, 0 if not enough space, 1 if enough space. |
---|
2314 | */ |
---|
2315 | int |
---|
2316 | #ifdef CK_ANSIC |
---|
2317 | zchkspa(char *f, long n) |
---|
2318 | #else |
---|
2319 | zchkspa(f,n) char *f; long n; |
---|
2320 | #endif /* CK_ANSIC */ |
---|
2321 | /* zchkspa() */ { |
---|
2322 | #ifdef OS2 |
---|
2323 | /* OS/2 gives us an easy way to do this. */ |
---|
2324 | unsigned long x, filesize = 0L; |
---|
2325 | debug(F111,"zchkspa",f,n); |
---|
2326 | if (isalpha(f[0]) && f[1] == ':') { |
---|
2327 | x = zdskspace(toupper(f[0]) - 'A' + 1); |
---|
2328 | debug(F101,"zchkspa disk: size","",x); |
---|
2329 | } else { |
---|
2330 | x = zdskspace(0); |
---|
2331 | debug(F101,"zchkspa no disk size","",x); |
---|
2332 | } |
---|
2333 | if (fncact == XYFX_U || fncact == XYFX_X) /* Update or Replace */ |
---|
2334 | filesize = zchki(f); |
---|
2335 | |
---|
2336 | return((x+filesize >= n) ? 1 : 0); |
---|
2337 | #else |
---|
2338 | /* In UNIX there is no good (and portable) way. */ |
---|
2339 | return(1); /* Always say OK. */ |
---|
2340 | #endif /* OS2 */ |
---|
2341 | } |
---|
2342 | |
---|
2343 | |
---|
2344 | /* Z N E W N -- Make a new name for the given file */ |
---|
2345 | |
---|
2346 | /* |
---|
2347 | Given the name, fn, of a file that already exists, this function builds a |
---|
2348 | new name of the form "<oldname>.~<n>~", where <oldname> is argument name |
---|
2349 | (fn), and <n> is a version number, one higher than any existing version |
---|
2350 | number for that file, up to 9999. This format is consistent with that used |
---|
2351 | by GNU EMACS. If the constructed name is too long for the system's maximum, |
---|
2352 | enough characters are truncated from the end of <fn> to allow the version |
---|
2353 | number to fit. If no free version numbers exist between 1 and 9999, a |
---|
2354 | version number of "xxxx" is used. Returns a pointer to the new name in |
---|
2355 | argument s. |
---|
2356 | */ |
---|
2357 | |
---|
2358 | VOID |
---|
2359 | znewn(fn,s) char *fn, **s; { |
---|
2360 | #ifdef pdp11 |
---|
2361 | #define ZNEWNBL 63 /* Name buffer length */ |
---|
2362 | #define ZNEWNMD 3 /* Max digits for version number */ |
---|
2363 | #else |
---|
2364 | #define ZNEWNBL 255 |
---|
2365 | #define ZNEWNMD 4 |
---|
2366 | #endif /* pdp11 */ |
---|
2367 | |
---|
2368 | static char buf[ZNEWNBL+1]; |
---|
2369 | char *bp, *xp, *yp; |
---|
2370 | #ifdef OS2 |
---|
2371 | static char localfn[MAXPATH+1]; |
---|
2372 | char *tp=NULL, *zp=NULL, ch, temp[14]; |
---|
2373 | #endif /* OS2 */ |
---|
2374 | int len = 0, d = 0, n, t, i, j, k, power = 1; |
---|
2375 | |
---|
2376 | int max = MAXNAMLEN; /* Maximum name length */ |
---|
2377 | |
---|
2378 | if (max < 14) max = 14; /* Make it reasonable */ |
---|
2379 | if (max > ZNEWNBL) max = ZNEWNBL; |
---|
2380 | bp = buf; /* Buffer for building new name */ |
---|
2381 | yp = fn; |
---|
2382 | while (*yp) { /* Copy old name into buffer */ |
---|
2383 | *bp++ = *yp++; |
---|
2384 | if (len++ > ZNEWNBL) break; /* ...up to buffer length */ |
---|
2385 | } |
---|
2386 | *s = NULL; |
---|
2387 | for (i = 1; i < ZNEWNMD + 1; i++) { /* Version numbers up to 10**i - 1 */ |
---|
2388 | power *= 10; /* Next power of 10 */ |
---|
2389 | j = max - len; /* Space left for version number */ |
---|
2390 | k = 3 + i; /* Space needed for it */ |
---|
2391 | if (j < k) { /* Make room if necessary */ |
---|
2392 | len -= (k - j); /* Adjust length of filename */ |
---|
2393 | bp = buf + len; /* Point to new end */ |
---|
2394 | } |
---|
2395 | *bp++ = '*'; /* Put a star on the end (UNIX) */ |
---|
2396 | *bp-- = '\0'; /* Terminate with null */ |
---|
2397 | |
---|
2398 | debug(F110,"znewn: about to expand",buf,0); |
---|
2399 | n = zxpand(buf); /* Expand the resulting wild name */ |
---|
2400 | /* n is the number of matches */ |
---|
2401 | debug(F101,"znewn matches","",n); |
---|
2402 | while (n-- > 0) { /* Find any existing name.~n~ files */ |
---|
2403 | #ifdef OS2 |
---|
2404 | znext(localfn); |
---|
2405 | xp = localfn; |
---|
2406 | #else /* OS2 */ |
---|
2407 | xp = *mtchptr++; /* Point at matching name */ |
---|
2408 | #endif /* OS2 */ |
---|
2409 | xp += len; /* Look for .~<n>~ at the end of it */ |
---|
2410 | if (*xp == '.' && *(xp+1) == '~') { /* Has a version number */ |
---|
2411 | t = atoi(xp+2); /* Get it */ |
---|
2412 | if (t > d) d = t; /* Save d = highest version number */ |
---|
2413 | } |
---|
2414 | } |
---|
2415 | if (d < power-1) { /* Less than maximum possible? */ |
---|
2416 | debug(F110,"znewn number ok",buf,0); |
---|
2417 | sprintf(bp,".~%d~",d+1); /* Yes, make "name.~<d+1>~" */ |
---|
2418 | *s = buf; /* Point to new name */ |
---|
2419 | ck_znewn = d+1; /* Also make it available globally */ |
---|
2420 | break; /* Done, return it */ |
---|
2421 | } |
---|
2422 | } |
---|
2423 | if (*s == NULL) { |
---|
2424 | debug(F110,"znewn: too many names",buf,0); |
---|
2425 | sprintf(bp,".~xxxx~"); /* Too many, use xxxx. */ |
---|
2426 | ck_znewn = -1; /* Also make it available globally */ |
---|
2427 | *s = buf; |
---|
2428 | } |
---|
2429 | #ifdef OS2 |
---|
2430 | if (IsFileNameValid(buf)) { |
---|
2431 | debug(F110,"znewn: os2 filename valid",buf,0); |
---|
2432 | return; /* HPFS */ |
---|
2433 | } |
---|
2434 | /* otherwise make FAT 8.3 name */ |
---|
2435 | debug(F110,"znewn: os2 filename invalid",buf,0); |
---|
2436 | xp = bp = buf; |
---|
2437 | yp = fn; |
---|
2438 | while (*yp) { /* Copy name into buf */ |
---|
2439 | ch = *bp++ = *yp++; |
---|
2440 | if (ISDIRSEP(ch) || (ch == ':')) xp=bp; |
---|
2441 | } |
---|
2442 | *bp = '\0'; |
---|
2443 | yp = xp; |
---|
2444 | i = 1; |
---|
2445 | while (*yp && (*yp != '.')) { |
---|
2446 | yp++; |
---|
2447 | if (++i<=6) |
---|
2448 | zp=yp; |
---|
2449 | } |
---|
2450 | /* zp points to 6th character in name, or yp, whichever occurs first. */ |
---|
2451 | strcpy(temp,yp); /* Copy extension, if any */ |
---|
2452 | while (zp != xp+8) { |
---|
2453 | if ( zp < xp+5 ) *zp++='0'; |
---|
2454 | else *zp++='?'; /* Pad out with wild cards */ |
---|
2455 | } |
---|
2456 | strcpy(zp,temp); /* Get the extension back */ |
---|
2457 | debug(F110,"znewn: about to expand",buf,0); |
---|
2458 | n = zxpand(buf); /* Expand the resulting wild name */ |
---|
2459 | debug(F101,"znewn: matches","",n); |
---|
2460 | d = 0; /* Index number */ |
---|
2461 | debug(F110,"znewn: temp",temp,0); |
---|
2462 | while (znext(temp)) { |
---|
2463 | #ifdef COMMENT |
---|
2464 | i = atoi(temp+5); |
---|
2465 | if (i > d) d = i; |
---|
2466 | #else |
---|
2467 | if ( tp = strrchr( temp, '/' ) ) |
---|
2468 | tp++; |
---|
2469 | else |
---|
2470 | tp = temp; |
---|
2471 | i = atoi(tp+5); |
---|
2472 | debug(F111,"znewn: tp=atoi(tp+5)",tp,i); |
---|
2473 | if (i > d) d = i; |
---|
2474 | debug(F101,"znewn: d","",d); |
---|
2475 | #endif /* COMMENT */ |
---|
2476 | } |
---|
2477 | sprintf(temp,"%03d",d+1); /* Get the number into a string */ |
---|
2478 | ck_znewn = d+1; |
---|
2479 | memcpy(xp+5, temp, 3); |
---|
2480 | debug(F110,"znewn: os2 file name is FAT",buf,0); |
---|
2481 | #endif /* OS2 */ |
---|
2482 | return; |
---|
2483 | } |
---|
2484 | |
---|
2485 | /* Z R E N A M E -- Rename a file */ |
---|
2486 | /* |
---|
2487 | Call with old and new names. |
---|
2488 | If new name is the name of a directory, the 'old' file is moved to |
---|
2489 | that directory. |
---|
2490 | Returns 0 on success, -1 on failure. |
---|
2491 | */ |
---|
2492 | int |
---|
2493 | zrename(old,new) char *old, *new; { |
---|
2494 | char *p = NULL, *s = new; |
---|
2495 | int x; |
---|
2496 | |
---|
2497 | debug(F110,"zrename old",old,0); |
---|
2498 | debug(F110,"zrename new",s,0); |
---|
2499 | if (isdir(new)) { |
---|
2500 | char *q = NULL; |
---|
2501 | x = strlen(new); |
---|
2502 | if (!(p = malloc(strlen(new) + strlen(old) + 2))) |
---|
2503 | return(-1); |
---|
2504 | strcpy(p,new); /* Directory part */ |
---|
2505 | if (!ISDIRSEP(*(new+x-1))) /* Separator, if needed */ |
---|
2506 | strcat(p,"/"); |
---|
2507 | zstrip(old,&q); /* Strip path part from old name */ |
---|
2508 | strcat(p,q); /* Concatenate to new directory */ |
---|
2509 | s = p; |
---|
2510 | debug(F110,"zrename dir",s,0); |
---|
2511 | } else debug(F110,"zrename no dir",s,0); |
---|
2512 | #ifdef RENAME |
---|
2513 | /* |
---|
2514 | Atomic, preferred, uses a single system call, rename(), if available. |
---|
2515 | OS/2 rename() returns nonzero, but not necessarily -1 (?), on failure. |
---|
2516 | */ |
---|
2517 | x = rename(old,s); |
---|
2518 | if (p) free(p); |
---|
2519 | return(x ? -1 : 0); |
---|
2520 | #else /* !RENAME */ |
---|
2521 | /* |
---|
2522 | This way has a window of vulnerability. |
---|
2523 | */ |
---|
2524 | x = -1; /* Return code. */ |
---|
2525 | if (link(old,s) < 0) { /* Make a link with the new name. */ |
---|
2526 | debug(F111,"zrename link fails, errno",old,errno); |
---|
2527 | } else if ( |
---|
2528 | #ifdef NT |
---|
2529 | _unlink(old) |
---|
2530 | #else |
---|
2531 | unlink(old) |
---|
2532 | #endif /* NT */ |
---|
2533 | < 0) { /* Unlink the old name. */ |
---|
2534 | debug(F111,"zrename unlink fails, errno",old,errno); |
---|
2535 | } else x = 0; |
---|
2536 | if (p) free(p); |
---|
2537 | return(x); |
---|
2538 | #endif /* RENAME */ |
---|
2539 | } |
---|
2540 | |
---|
2541 | /* Z C O P Y -- Copy a file */ |
---|
2542 | /* |
---|
2543 | Call with source and destination names. |
---|
2544 | If destination name is the name of a directory, the source file is |
---|
2545 | copied to that directory with the original name. |
---|
2546 | Returns 0 on success, -1 on failure. |
---|
2547 | */ |
---|
2548 | int |
---|
2549 | zcopy(source,destination) char *source, *destination; { |
---|
2550 | char *p = NULL, *s = destination; |
---|
2551 | int x; |
---|
2552 | |
---|
2553 | debug(F110,"zcopy source",source,0); |
---|
2554 | debug(F110,"zcopy destination",s,0); |
---|
2555 | if (isdir(destination)) { |
---|
2556 | char *q = NULL; |
---|
2557 | x = strlen(destination); |
---|
2558 | if (!(p = malloc(strlen(destination) + strlen(source) + 2))) |
---|
2559 | return(-1); |
---|
2560 | strcpy(p,destination); /* Directory part */ |
---|
2561 | if (!ISDIRSEP(*(destination+x-1))) /* Separator, if needed */ |
---|
2562 | strcat(p,"/"); |
---|
2563 | zstrip(source,&q); /* Strip path part from old name */ |
---|
2564 | strcat(p,q); /* Concatenate to new directory */ |
---|
2565 | s = p; |
---|
2566 | debug(F110,"zcopy dir",s,0); |
---|
2567 | } else debug(F110,"zcopy no dir",s,0); |
---|
2568 | #ifdef OS2 |
---|
2569 | #ifndef NT |
---|
2570 | x = (DosCopy( source, destination, DCPY_FAILEAS ) ? -1 : 0); |
---|
2571 | #else /* NT */ |
---|
2572 | x = (CopyFile( source, destination, FALSE ) ? 0 : -1 ); |
---|
2573 | #endif /* NT */ |
---|
2574 | #else |
---|
2575 | /* not yet implemented */ |
---|
2576 | x = -1; |
---|
2577 | #endif |
---|
2578 | return x; |
---|
2579 | } |
---|
2580 | |
---|
2581 | /* Z S A T T R */ |
---|
2582 | /* |
---|
2583 | Fills in a Kermit file attribute structure for the file which is to be sent. |
---|
2584 | Returns 0 on success with the structure filled in, or -1 on failure. |
---|
2585 | If any string member is null, then it should be ignored. |
---|
2586 | If any numeric member is -1, then it should be ignored. |
---|
2587 | */ |
---|
2588 | int |
---|
2589 | zsattr(xx) struct zattr *xx; { |
---|
2590 | long k; |
---|
2591 | |
---|
2592 | k = iflen % 1024L; /* File length in K */ |
---|
2593 | if (k != 0L) k = 1L; |
---|
2594 | xx->lengthk = (iflen / 1024L) + k; |
---|
2595 | xx->type.len = 0; /* File type can't be filled in here */ |
---|
2596 | xx->type.val = ""; |
---|
2597 | if (*nambuf) { |
---|
2598 | xx->date.val = zfcdat(nambuf); /* File creation date */ |
---|
2599 | xx->date.len = (int)strlen(xx->date.val); |
---|
2600 | } else { |
---|
2601 | xx->date.len = 0; |
---|
2602 | xx->date.val = ""; |
---|
2603 | } |
---|
2604 | xx->creator.len = 0; /* File creator */ |
---|
2605 | xx->creator.val = ""; |
---|
2606 | xx->account.len = 0; /* File account */ |
---|
2607 | xx->account.val = ""; |
---|
2608 | xx->area.len = 0; /* File area */ |
---|
2609 | xx->area.val = ""; |
---|
2610 | xx->password.len = 0; /* Area password */ |
---|
2611 | xx->password.val = ""; |
---|
2612 | xx->blksize = -1L; /* File blocksize */ |
---|
2613 | xx->xaccess.len = 0; /* File access */ |
---|
2614 | xx->xaccess.val = ""; |
---|
2615 | xx->encoding.len = 0; /* Transfer syntax */ |
---|
2616 | xx->encoding.val = 0; |
---|
2617 | xx->disp.len = 0; /* Disposition upon arrival */ |
---|
2618 | xx->disp.val = ""; |
---|
2619 | xx->lprotect.len = 0; /* Local protection */ |
---|
2620 | xx->lprotect.val = ""; |
---|
2621 | xx->gprotect.len = 0; /* Generic protection */ |
---|
2622 | xx->gprotect.val = ""; |
---|
2623 | xx->systemid.len = 2; /* System ID */ |
---|
2624 | #ifdef OS2 |
---|
2625 | xx->systemid.val = "UO"; /* UO = OS/2 */ |
---|
2626 | #else |
---|
2627 | xx->systemid.val = "U1"; /* U1 = UNIX */ |
---|
2628 | #endif /* OS2 */ |
---|
2629 | xx->recfm.len = 0; /* Record format */ |
---|
2630 | xx->recfm.val = ""; |
---|
2631 | xx->sysparam.len = 0; /* System-dependent parameters */ |
---|
2632 | xx->sysparam.val = ""; |
---|
2633 | xx->length = iflen; /* Length */ |
---|
2634 | return(0); |
---|
2635 | } |
---|
2636 | |
---|
2637 | /* Z F C D A T -- Get file creation date */ |
---|
2638 | /* |
---|
2639 | Call with pointer to filename. |
---|
2640 | On success, returns pointer to modification date in yyyymmdd hh:mm:ss format. |
---|
2641 | On failure, returns pointer to null string. |
---|
2642 | */ |
---|
2643 | static char datbuf[40]; |
---|
2644 | |
---|
2645 | char * |
---|
2646 | zdtstr(time) time_t time; { |
---|
2647 | struct tm * time_stamp; |
---|
2648 | struct tm * localtime(); |
---|
2649 | int yy, ss; |
---|
2650 | |
---|
2651 | debug(F101,"zdatstr time","",time); |
---|
2652 | if (time < 0) |
---|
2653 | return(""); |
---|
2654 | time_stamp = localtime(&(time)); |
---|
2655 | if (!time_stamp) { |
---|
2656 | debug(F100,"localtime returns null","",0); |
---|
2657 | return(""); |
---|
2658 | } |
---|
2659 | yy = time_stamp->tm_year; /* Year - 1900 */ |
---|
2660 | yy += 1900; |
---|
2661 | debug(F101,"zdatstr year","",yy); |
---|
2662 | if (yy < 1970) /* By definition of C library */ |
---|
2663 | return(""); |
---|
2664 | |
---|
2665 | if (time_stamp->tm_mon < 0 || time_stamp->tm_mon > 11) |
---|
2666 | return(""); |
---|
2667 | if (time_stamp->tm_mday < 0 || time_stamp->tm_mday > 31) |
---|
2668 | return(""); |
---|
2669 | if (time_stamp->tm_hour < 0 || time_stamp->tm_hour > 23) |
---|
2670 | return(""); |
---|
2671 | if (time_stamp->tm_min < 0 || time_stamp->tm_min > 59) |
---|
2672 | return(""); |
---|
2673 | ss = time_stamp->tm_sec; /* Seconds */ |
---|
2674 | if (ss < 0 || ss > 59) /* Some systems give a BIG number */ |
---|
2675 | ss = 0; |
---|
2676 | sprintf(datbuf, |
---|
2677 | #ifdef pdp11 |
---|
2678 | /* For some reason, 2.1x BSD sprintf gets the last field wrong. */ |
---|
2679 | "%04d%02d%02d %02d:%02d:00", |
---|
2680 | #else |
---|
2681 | "%04d%02d%02d %02d:%02d:%02d", |
---|
2682 | #endif /* pdp11 */ |
---|
2683 | yy, |
---|
2684 | time_stamp->tm_mon + 1, |
---|
2685 | time_stamp->tm_mday, |
---|
2686 | time_stamp->tm_hour, |
---|
2687 | time_stamp->tm_min |
---|
2688 | #ifndef pdp11 |
---|
2689 | , ss |
---|
2690 | #endif /* pdp11 */ |
---|
2691 | ); |
---|
2692 | yy = (int)strlen(datbuf); |
---|
2693 | debug(F111,"zdatstr",datbuf,yy); |
---|
2694 | if (yy > 17) datbuf[17] = '\0'; |
---|
2695 | return(datbuf); |
---|
2696 | } |
---|
2697 | |
---|
2698 | char * |
---|
2699 | zfcdat(name) char *name; { |
---|
2700 | |
---|
2701 | #ifdef TIMESTAMP |
---|
2702 | #ifdef NT |
---|
2703 | struct _stat buffer; |
---|
2704 | #else /* NT */ |
---|
2705 | struct stat buffer; |
---|
2706 | #endif /* NT */ |
---|
2707 | |
---|
2708 | datbuf[0] = '\0'; |
---|
2709 | if (stat(name,&buffer) != 0) { |
---|
2710 | debug(F110,"zfcdat stat failed",name,0); |
---|
2711 | return(""); |
---|
2712 | } |
---|
2713 | return(zdtstr(buffer.st_mtime)); |
---|
2714 | #else |
---|
2715 | return(""); |
---|
2716 | #endif /* TIMESTAMP */ |
---|
2717 | } |
---|
2718 | |
---|
2719 | time_t |
---|
2720 | zstrdt(date,len) char * date; int len; { |
---|
2721 | /* |
---|
2722 | To do: adapt code from OS-9 Kermit's ck9fio.c zstime function, which |
---|
2723 | is more flexible, allowing [yy]yymmdd[ hh:mm[:ss]]. |
---|
2724 | */ |
---|
2725 | #ifndef OS2 |
---|
2726 | #ifdef M_UNIX |
---|
2727 | /* |
---|
2728 | SCO UNIX 3.2v2.0 and ODT 2.0 lack prototypes for ftime(). |
---|
2729 | ODT 3.0 (3.2v4.2 OS) has a prototype, which may vary in |
---|
2730 | dependence on the XPG4 supplement presence. So always use |
---|
2731 | what the system header file supplies in ODT 3.0... |
---|
2732 | */ |
---|
2733 | #ifndef ODT30 |
---|
2734 | #ifndef _SCO_DS |
---|
2735 | extern void ftime(); /* extern void ftime(struct timeb *) */ |
---|
2736 | #endif /* _SCO_DS */ |
---|
2737 | #endif /* ODT30 */ |
---|
2738 | #else |
---|
2739 | extern int ftime(); |
---|
2740 | #endif /* M_UNIX */ |
---|
2741 | extern int stat(); |
---|
2742 | extern struct tm * localtime(); |
---|
2743 | |
---|
2744 | /* and this should have been declared always through a header file */ |
---|
2745 | #endif /* OS2 */ |
---|
2746 | long tmx, days; |
---|
2747 | int i, n, isleapyear; |
---|
2748 | /* J F M A M J J A S O N D */ |
---|
2749 | /* 31 28 31 30 31 30 31 31 30 31 30 31 */ |
---|
2750 | static |
---|
2751 | int monthdays [13] = { 0,0,31,59,90,120,151,181,212,243,273,304,334 }; |
---|
2752 | char s[5]; |
---|
2753 | struct tm *time_stamp; |
---|
2754 | |
---|
2755 | #ifdef BSD44 |
---|
2756 | struct timeval tp[2]; |
---|
2757 | long xtimezone; |
---|
2758 | #else |
---|
2759 | #ifdef OS2 |
---|
2760 | |
---|
2761 | #ifdef NT |
---|
2762 | struct _utimbuf tp; |
---|
2763 | #else /* NT */ |
---|
2764 | struct utimbuf tp; |
---|
2765 | #endif /* NT */ |
---|
2766 | |
---|
2767 | #ifdef __EMX__ |
---|
2768 | long timezone; |
---|
2769 | struct timeb tbp; |
---|
2770 | #endif /* __EMX__ */ |
---|
2771 | #else |
---|
2772 | #ifdef V7 |
---|
2773 | struct utimbuf { |
---|
2774 | time_t timep[2]; /* New access and modificaton time */ |
---|
2775 | } tp; |
---|
2776 | char *tz; |
---|
2777 | long timezone; /* In case timezone not defined in .h file */ |
---|
2778 | #else |
---|
2779 | #ifdef SYSUTIMEH |
---|
2780 | struct utimbuf tp; |
---|
2781 | #else |
---|
2782 | struct utimbuf { |
---|
2783 | time_t atime; |
---|
2784 | time_t mtime; |
---|
2785 | } tp; |
---|
2786 | #endif /* SYSUTIMEH */ |
---|
2787 | #endif /* V7 */ |
---|
2788 | #endif /* OS2 */ |
---|
2789 | #endif /* BSD44 */ |
---|
2790 | |
---|
2791 | #ifdef ANYBSD |
---|
2792 | long timezone = 0L; |
---|
2793 | static struct timeb tbp; |
---|
2794 | #endif /* ANYBSD */ |
---|
2795 | |
---|
2796 | #ifdef BEBOX |
---|
2797 | long timezone = 0L; |
---|
2798 | #endif /* BEBOX */ |
---|
2799 | |
---|
2800 | debug(F111,"zstrdt",date,len); |
---|
2801 | |
---|
2802 | if ((len == 0) |
---|
2803 | || (len != 17) |
---|
2804 | || (date[8] != ' ') |
---|
2805 | || (date[11] != ':') |
---|
2806 | || (date[14] != ':') ) { |
---|
2807 | debug(F111,"Bad creation date ",date,len); |
---|
2808 | return(-1); |
---|
2809 | } |
---|
2810 | debug(F111,"zstime date check 1",date,len); |
---|
2811 | for(i = 0; i < 8; i++) { |
---|
2812 | if (!isdigit(date[i])) { |
---|
2813 | debug(F111,"Bad creation date ",date,len); |
---|
2814 | return(-1); |
---|
2815 | } |
---|
2816 | } |
---|
2817 | debug(F111,"zstime date check 2",date,len); |
---|
2818 | i++; |
---|
2819 | |
---|
2820 | for (; i < 16; i += 3) { |
---|
2821 | if ((!isdigit(date[i])) || (!isdigit(date[i + 1]))) { |
---|
2822 | debug(F111,"Bad creation date ",date,len); |
---|
2823 | return(-1); |
---|
2824 | } |
---|
2825 | } |
---|
2826 | debug(F111,"zstime date check 3",date,len); |
---|
2827 | |
---|
2828 | #ifdef BSD44 |
---|
2829 | { |
---|
2830 | int x; |
---|
2831 | struct timezone tzp; |
---|
2832 | x = gettimeofday(NULL, &tzp); |
---|
2833 | debug(F101,"zstime BSD44 gettimeofday","",x); |
---|
2834 | if (x > -1) |
---|
2835 | xtimezone = tzp.tz_minuteswest * 60L; |
---|
2836 | else |
---|
2837 | xtimezone = 0L; |
---|
2838 | debug(F101,"zstime BSD44 timezone","",xtimezone); |
---|
2839 | } |
---|
2840 | #else |
---|
2841 | #ifdef ANYBSD |
---|
2842 | debug(F100,"zstime BSD calling ftime","",0); |
---|
2843 | ftime(&tbp); |
---|
2844 | debug(F100,"zstime BSD back from ftime","",0); |
---|
2845 | timezone = tbp.timezone * 60L; |
---|
2846 | debug(F101,"zstime BSD timezone","",timezone); |
---|
2847 | #else |
---|
2848 | #ifdef OS2 |
---|
2849 | #ifdef __EMX__ |
---|
2850 | ftime(&tbp); |
---|
2851 | timezone = tbp.timezone * 60L; |
---|
2852 | #endif /* __EMX__ */ |
---|
2853 | #else |
---|
2854 | #ifdef SVORPOSIX |
---|
2855 | tzset(); /* Set timezone */ |
---|
2856 | #else |
---|
2857 | #ifdef V7 |
---|
2858 | if ((tz = getenv("TZ")) == NULL) |
---|
2859 | timezone = 0; /* UTC/GMT */ |
---|
2860 | else |
---|
2861 | timezone = atoi(&tz[3]); /* Set 'timezone'. */ |
---|
2862 | timezone *= 60L; |
---|
2863 | #endif /* V7 */ |
---|
2864 | #endif /* SVORPOSIX */ |
---|
2865 | #endif /* OS2 */ |
---|
2866 | #endif /* ANYBSD */ |
---|
2867 | #endif /* BSD44 */ |
---|
2868 | |
---|
2869 | debug(F100,"zstime so far so good","",0); |
---|
2870 | |
---|
2871 | s[4] = '\0'; |
---|
2872 | for (i = 0; i < 4; i++) /* Fix the year */ |
---|
2873 | s[i] = date[i]; |
---|
2874 | |
---|
2875 | n = atoi(s); |
---|
2876 | debug(F111,"zstime year",s,n); |
---|
2877 | if (n < 1970) { |
---|
2878 | debug(F100,"zstime fails - year","",n); |
---|
2879 | return(-1); |
---|
2880 | } |
---|
2881 | |
---|
2882 | /* Previous year's leap days. This won't work after year 2100. */ |
---|
2883 | |
---|
2884 | isleapyear = (( n % 4 == 0 && n % 100 !=0) || n % 400 == 0); |
---|
2885 | days = (long) (n - 1970) * 365; |
---|
2886 | days += (n - 1968 - 1) / 4 - (n - 1900 - 1) / 100 + (n - 1600 - 1) / 400; |
---|
2887 | |
---|
2888 | s[2] = '\0'; |
---|
2889 | |
---|
2890 | for (i = 4; i < 16; i += 2) { |
---|
2891 | s[0] = date[i]; |
---|
2892 | s[1] = date[i + 1]; |
---|
2893 | n = atoi(s); |
---|
2894 | switch (i) { |
---|
2895 | case 4: /* MM: month */ |
---|
2896 | if ((n < 1 ) || ( n > 12)) { |
---|
2897 | debug(F111,"zstime 4 bad date ",date,len); |
---|
2898 | return(-1); |
---|
2899 | } |
---|
2900 | days += monthdays [n]; |
---|
2901 | if (isleapyear && n > 2) |
---|
2902 | ++days; |
---|
2903 | continue; |
---|
2904 | |
---|
2905 | case 6: /* DD: day */ |
---|
2906 | if ((n < 1 ) || ( n > 31)) { |
---|
2907 | debug(F111,"zstime 6 bad date ",date,len); |
---|
2908 | return(-1); |
---|
2909 | } |
---|
2910 | tmx = (days + n - 1) * 24L * 60L * 60L; |
---|
2911 | i++; /* Skip the space */ |
---|
2912 | continue; |
---|
2913 | |
---|
2914 | case 9: /* hh: hour */ |
---|
2915 | if ((n < 0 ) || ( n > 23)) { |
---|
2916 | debug(F111,"zstime 9 bad date ",date,len); |
---|
2917 | return(-1); |
---|
2918 | } |
---|
2919 | tmx += n * 60L * 60L; |
---|
2920 | i++; /* Skip the colon */ |
---|
2921 | continue; |
---|
2922 | |
---|
2923 | case 12: /* mm: minute */ |
---|
2924 | if ((n < 0 ) || ( n > 59)) { |
---|
2925 | debug(F111,"zstime 12 bad date ",date,len); |
---|
2926 | return(-1); |
---|
2927 | } |
---|
2928 | #ifdef BSD44 /* Correct for time zone */ |
---|
2929 | tmx += xtimezone; |
---|
2930 | debug(F101,"zstime BSD44 tmx","",tmx); |
---|
2931 | #else |
---|
2932 | #ifdef ANYBSD |
---|
2933 | tmx += timezone; |
---|
2934 | #else |
---|
2935 | #ifndef CONVEX9 /* Don't yet know how to do this here */ |
---|
2936 | #ifdef ultrix |
---|
2937 | tmx += (long) timezone; |
---|
2938 | #else |
---|
2939 | #ifdef Plan9 |
---|
2940 | { |
---|
2941 | extern time_t tzoffset; |
---|
2942 | tmx += tzoffset; |
---|
2943 | } |
---|
2944 | #else |
---|
2945 | tmx += timezone; |
---|
2946 | #endif /* Plan9 */ |
---|
2947 | #endif /* ultrix */ |
---|
2948 | #endif /* CONVEX9 */ |
---|
2949 | #endif /* BSD44 */ |
---|
2950 | #endif /* ANYBSD */ |
---|
2951 | tmx += n * 60L; |
---|
2952 | i++; /* Skip the colon */ |
---|
2953 | continue; |
---|
2954 | |
---|
2955 | case 15: /* ss: second */ |
---|
2956 | if ((n < 0 ) || ( n > 59)) { |
---|
2957 | debug(F111,"zstime 15 bad date ",date,len); |
---|
2958 | return(-1); |
---|
2959 | } |
---|
2960 | tmx += n; |
---|
2961 | } |
---|
2962 | time_stamp = localtime(&tmx); |
---|
2963 | if (!time_stamp) |
---|
2964 | return(-1); |
---|
2965 | if (localtime(&tmx)->tm_isdst) |
---|
2966 | tmx -= 60L * 60L; /* Adjust for daylight savings time */ |
---|
2967 | } |
---|
2968 | return(tmx); |
---|
2969 | } |
---|
2970 | |
---|
2971 | /* Z S T I M E -- Set creation date for incoming file */ |
---|
2972 | /* |
---|
2973 | Call with: |
---|
2974 | f = pointer to name of existing file. |
---|
2975 | yy = pointer to a Kermit file attribute structure in which yy->date.val |
---|
2976 | is a date of the form yyyymmdd hh:mm:ss, e.g. 19900208 13:00:00. |
---|
2977 | x = is a function code: 0 means to set the file's creation date as given. |
---|
2978 | 1 means compare the given date with the file creation date. |
---|
2979 | Returns: |
---|
2980 | -1 on any kind of error. |
---|
2981 | 0 if x is 0 and the file date was set successfully. |
---|
2982 | 0 if x is 1 and date from attribute structure <= file creation date. |
---|
2983 | 1 if x is 1 and date from attribute structure > file creation date. |
---|
2984 | */ |
---|
2985 | int |
---|
2986 | zstime(f,yy,x) |
---|
2987 | #ifdef HPUX10 |
---|
2988 | #ifdef CK_ANSIC |
---|
2989 | const |
---|
2990 | #endif /* CK_ANSIC */ |
---|
2991 | #endif /* HPUX10 */ |
---|
2992 | char *f; struct zattr *yy; int x; |
---|
2993 | /* zstime */ { |
---|
2994 | int r = -1; /* Return code */ |
---|
2995 | |
---|
2996 | /* It is ifdef'd TIMESTAMP because it might not work on V7. bk@kullmar.se. */ |
---|
2997 | |
---|
2998 | #ifdef TIMESTAMP |
---|
2999 | #ifndef OS2 |
---|
3000 | #ifdef BSD44 |
---|
3001 | extern int utimes(); |
---|
3002 | #else |
---|
3003 | extern int utime(); |
---|
3004 | #endif /* BSD44 */ |
---|
3005 | #endif /* OS2 */ |
---|
3006 | |
---|
3007 | /* At least, the declarations for int functions are not needed anyway */ |
---|
3008 | |
---|
3009 | #ifdef NT |
---|
3010 | struct _stat sb; |
---|
3011 | #else /* NT */ |
---|
3012 | struct stat sb; |
---|
3013 | #endif /* NT */ |
---|
3014 | |
---|
3015 | #ifdef BSD44 |
---|
3016 | struct timeval tp[2]; |
---|
3017 | long xtimezone; |
---|
3018 | #else |
---|
3019 | #ifdef OS2 |
---|
3020 | |
---|
3021 | #ifdef NT |
---|
3022 | struct _utimbuf tp; |
---|
3023 | #else /* NT */ |
---|
3024 | struct utimbuf tp; |
---|
3025 | #endif /* NT */ |
---|
3026 | |
---|
3027 | #ifdef __EMX__ |
---|
3028 | long timezone; |
---|
3029 | struct timeb tbp; |
---|
3030 | #endif /* __EMX__ */ |
---|
3031 | #else |
---|
3032 | #ifdef V7 |
---|
3033 | struct utimbuf { |
---|
3034 | time_t timep[2]; /* New access and modificaton time */ |
---|
3035 | } tp; |
---|
3036 | char *tz; |
---|
3037 | long timezone; /* In case not defined in .h file */ |
---|
3038 | #else |
---|
3039 | #ifdef SYSUTIMEH |
---|
3040 | struct utimbuf tp; |
---|
3041 | #else |
---|
3042 | struct utimbuf { |
---|
3043 | time_t atime; |
---|
3044 | time_t mtime; |
---|
3045 | } tp; |
---|
3046 | #endif /* SYSUTIMEH */ |
---|
3047 | #endif /* V7 */ |
---|
3048 | #endif /* OS2 */ |
---|
3049 | #endif /* BSD44 */ |
---|
3050 | |
---|
3051 | long tm; |
---|
3052 | |
---|
3053 | debug(F110,"zstime",f,0); |
---|
3054 | debug(F111,"zstime",yy->date.val,yy->date.len); |
---|
3055 | if ((tm = zstrdt(yy->date.val,yy->date.len)) < 0) { |
---|
3056 | debug(F101,"zstime: zstrdt fails","",0); |
---|
3057 | return(-1); |
---|
3058 | } |
---|
3059 | debug(F101,"zstime: tm","",tm); |
---|
3060 | debug(F111,"zstime: A-pkt date ok ",yy->date.val,yy->date.len); |
---|
3061 | |
---|
3062 | if (stat(f,&sb)) { /* Get the time for the file */ |
---|
3063 | debug(F110,"zstime: Can't stat file:",f,0); |
---|
3064 | return(-1); |
---|
3065 | } |
---|
3066 | debug(F101,"zstime: sb.st_atime","",sb.st_atime); |
---|
3067 | |
---|
3068 | #ifdef OS2 |
---|
3069 | tp.modtime = tm; /* Set modif. time to creation date */ |
---|
3070 | tp.actime = sb.st_atime; /* Don't change the access time */ |
---|
3071 | #else |
---|
3072 | #ifdef SYSUTIMEH |
---|
3073 | tp.modtime = tm; /* Set modif. time to creation date */ |
---|
3074 | tp.actime = sb.st_atime; /* Don't change the access time */ |
---|
3075 | #else |
---|
3076 | #ifdef V7 |
---|
3077 | tp.timep[0] = tm; /* Set modif. time to creation date */ |
---|
3078 | tp.timep[1] = sb.st_atime; /* Don't change the access time */ |
---|
3079 | #else |
---|
3080 | #ifdef BSD44 |
---|
3081 | tp[0].tv_sec = sb.st_atime; /* Access time first */ |
---|
3082 | tp[1].tv_sec = tm; /* Update time second */ |
---|
3083 | #else |
---|
3084 | tp.mtime = tm; /* Set modif. time to creation date */ |
---|
3085 | tp.atime = sb.st_atime; /* Don't change the access time */ |
---|
3086 | #endif /* BSD44 */ |
---|
3087 | #endif /* V7 */ |
---|
3088 | #endif /* SYSUTIMEH */ |
---|
3089 | #endif /* OS2 */ |
---|
3090 | |
---|
3091 | switch (x) { /* Execute desired function */ |
---|
3092 | case 0: /* Set the creation date of the file */ |
---|
3093 | if ( |
---|
3094 | #ifdef BSD44 |
---|
3095 | utimes(f,tp) |
---|
3096 | #else |
---|
3097 | #ifdef NT |
---|
3098 | _utime(f,&tp) |
---|
3099 | #else /* NT */ |
---|
3100 | utime(f,&tp) |
---|
3101 | #endif /* NT */ |
---|
3102 | #endif /* BSD44 */ |
---|
3103 | ) { /* Fix modification time */ |
---|
3104 | debug(F110,"zstime 0: can't set modtime for file",f,0); |
---|
3105 | r = -1; |
---|
3106 | } else { |
---|
3107 | debug(F110,"zstime 0: modtime set for file",f,0); |
---|
3108 | r = 0; |
---|
3109 | } |
---|
3110 | break; |
---|
3111 | case 1: /* Compare the dates */ |
---|
3112 | /* |
---|
3113 | This was st_atime, which was wrong. We want the file-data modification |
---|
3114 | time, st_mtime. |
---|
3115 | */ |
---|
3116 | debug(F111,"zstime 1: compare",f,sb.st_mtime); |
---|
3117 | debug(F111,"zstime 1: compare","packet",tm); |
---|
3118 | #ifdef OS2 |
---|
3119 | /* |
---|
3120 | In OS/2, sb.st_mtime, at least on a FAT file system, is always even. |
---|
3121 | In that case, if the incoming file is only one second newer than the |
---|
3122 | local file, consider them the same. (THERE MUST BE A BETTER FIX FOR THIS!) |
---|
3123 | */ |
---|
3124 | if ((sb.st_mtime & 1) == 0) |
---|
3125 | if ((tm - sb.st_mtime) == 1) |
---|
3126 | tm--; |
---|
3127 | #endif /* OS2 */ |
---|
3128 | r = (sb.st_mtime < tm) ? 0 : 1; |
---|
3129 | break; |
---|
3130 | |
---|
3131 | default: /* Error */ |
---|
3132 | r = -1; |
---|
3133 | } |
---|
3134 | #endif /* TIMESTAMP */ |
---|
3135 | return(r); |
---|
3136 | } |
---|
3137 | |
---|
3138 | /* Find initialization file. */ |
---|
3139 | |
---|
3140 | #ifdef NOTUSED |
---|
3141 | int |
---|
3142 | zkermini() { |
---|
3143 | /* nothing here for Unix. This function added for benefit of VMS Kermit. */ |
---|
3144 | return(0); |
---|
3145 | } |
---|
3146 | #endif /* NOTUSED */ |
---|
3147 | |
---|
3148 | #ifndef NOFRILLS |
---|
3149 | int |
---|
3150 | zmail(p,f) char *p; char *f; { /* Send file f as mail to address p */ |
---|
3151 | /* |
---|
3152 | Returns 0 on success |
---|
3153 | 2 if mail delivered but temp file can't be deleted |
---|
3154 | -2 if mail can't be delivered |
---|
3155 | The UNIX version always returns 0 because it can't get a good return |
---|
3156 | code from zsyscmd. |
---|
3157 | */ |
---|
3158 | #ifdef BSD4 |
---|
3159 | /* The idea is to use /usr/ucb/mail, rather than regular mail, so that */ |
---|
3160 | /* a subject line can be included with -s. Since we can't depend on the */ |
---|
3161 | /* user's path, we use the convention that /usr/ucb/Mail = /usr/ucb/mail */ |
---|
3162 | /* and even if Mail has been moved to somewhere else, this should still */ |
---|
3163 | /* find it... The search could be made more reliable by actually using */ |
---|
3164 | /* access() to see if /usr/ucb/Mail exists. */ |
---|
3165 | |
---|
3166 | /* Should also make some check on zmbuf overflow... */ |
---|
3167 | |
---|
3168 | #ifdef DGUX540 |
---|
3169 | sprintf(zmbuf,"mailx -s %c%s%c %s < %s", '"', f, '"', p, f); |
---|
3170 | #else |
---|
3171 | sprintf(zmbuf,"Mail -s %c%s%c %s < %s", '"', f, '"', p, f); |
---|
3172 | #endif /* DGUX540 */ |
---|
3173 | zsyscmd(zmbuf); |
---|
3174 | #else |
---|
3175 | #ifdef SVORPOSIX |
---|
3176 | #ifndef OXOS |
---|
3177 | sprintf(zmbuf,"mail %s < %s", p, f); |
---|
3178 | #else /* OXOS */ |
---|
3179 | sprintf(zmbuf,"mailx -s %c%s%c %s < %s", '"', f, '"', p, f); |
---|
3180 | #endif /* OXOS */ |
---|
3181 | zsyscmd(zmbuf); |
---|
3182 | #else |
---|
3183 | *zmbuf = '\0'; |
---|
3184 | #endif |
---|
3185 | #endif |
---|
3186 | return(0); |
---|
3187 | } |
---|
3188 | #endif /* NOFRILLS */ |
---|
3189 | |
---|
3190 | #ifndef NOFRILLS |
---|
3191 | int |
---|
3192 | zprint(p,f) char *p; char *f; { /* Print file f with options p */ |
---|
3193 | extern char * printfile; /* From ckuus3.c */ |
---|
3194 | extern int printpipe; |
---|
3195 | |
---|
3196 | debug(F110,"zprint file",f,0); |
---|
3197 | debug(F110,"zprint flags",p,0); |
---|
3198 | debug(F110,"zprint printfile",printfile,0); |
---|
3199 | debug(F101,"zprint printpipe","",printpipe); |
---|
3200 | |
---|
3201 | #ifdef NT |
---|
3202 | if (printfile) { |
---|
3203 | if (printpipe) |
---|
3204 | sprintf(zmbuf,"COPY /B %s | %s", f, printfile); |
---|
3205 | else |
---|
3206 | sprintf(zmbuf,"COPY /B %s %s", f, printfile); |
---|
3207 | } else { |
---|
3208 | sprintf(zmbuf,"COPY /B %s PRN", f); |
---|
3209 | } |
---|
3210 | debug(F110,"zprint command",zmbuf,0); |
---|
3211 | zsyscmd(zmbuf); |
---|
3212 | #else |
---|
3213 | #ifdef OS2 |
---|
3214 | if (printfile) { |
---|
3215 | if (printpipe) |
---|
3216 | sprintf(zmbuf,"COPY /B %s | %s", f, printfile); |
---|
3217 | else |
---|
3218 | sprintf(zmbuf,"COPY /B %s %s", f, printfile); |
---|
3219 | } else { |
---|
3220 | sprintf(zmbuf,"print %s %s", p, f); /* Construct print command */ |
---|
3221 | } |
---|
3222 | debug(F110,"zprint command",zmbuf,0); |
---|
3223 | zsyscmd(zmbuf); |
---|
3224 | #else |
---|
3225 | #ifdef UNIX |
---|
3226 | #ifdef ANYBSD /* BSD uses lpr to spool */ |
---|
3227 | #ifdef DGUX540 /* And DG/UX */ |
---|
3228 | #define SPOOLER "lp" |
---|
3229 | #else |
---|
3230 | #define SPOOLER "lpr" |
---|
3231 | #endif /* DGUX540 */ |
---|
3232 | #else /* Sys V uses lp */ |
---|
3233 | #ifdef TRS16 /* except for Tandy-16/6000... */ |
---|
3234 | #define SPOOLER "lpr" |
---|
3235 | #else |
---|
3236 | #define SPOOLER "lp" |
---|
3237 | #endif |
---|
3238 | #endif |
---|
3239 | /* |
---|
3240 | Note use of standard input redirection. In some systems, lp[r] runs |
---|
3241 | setuid to lp (or ...?), so if user has sent a file into a directory |
---|
3242 | that lp does not have read access to, it can't be printed unless it is |
---|
3243 | fed to lp[r] as standard input. |
---|
3244 | */ |
---|
3245 | if (printpipe && printfile) { |
---|
3246 | sprintf(zmbuf,"cat %s | %s", f, printfile); |
---|
3247 | } else if (printfile) { |
---|
3248 | sprintf(zmbuf,"cat %s >> %s", f, printfile); |
---|
3249 | } else { |
---|
3250 | sprintf(zmbuf,"%s %s < %s", SPOOLER, p, f); |
---|
3251 | } |
---|
3252 | debug(F110,"zprint command",zmbuf,0); |
---|
3253 | zsyscmd(zmbuf); |
---|
3254 | #else /* Not UNIX */ |
---|
3255 | *zmbuf = '\0'; |
---|
3256 | #endif /* UNIX */ |
---|
3257 | #endif /* OS2 */ |
---|
3258 | #endif /* NT */ |
---|
3259 | return(0); |
---|
3260 | } |
---|
3261 | #endif /* NOFRILLS */ |
---|
3262 | |
---|
3263 | /* |
---|
3264 | Wildcard expansion functions. C-Kermit used to insist on doing this itself |
---|
3265 | New code (version 5A, 1990-91) gives user option to ask UNIX to do it. |
---|
3266 | This lets users use the wildcard expansion features of their favorite shell. |
---|
3267 | Operation is slower because of the forking & piping, but flexibility is |
---|
3268 | greater and program is smaller. For OS/2, C-Kermit still does this itself. |
---|
3269 | */ |
---|
3270 | static char scratch[MAXPATH+4]; /* Used by both methods */ |
---|
3271 | |
---|
3272 | #ifndef OS2 |
---|
3273 | static int oldmtchs = 0; /* Let shell (ls) expand them. */ |
---|
3274 | #ifdef COMMENT |
---|
3275 | static char *lscmd = "/bin/ls -d"; /* Command to use. */ |
---|
3276 | #else |
---|
3277 | static char *lscmd = "echo"; /* Command to use. */ |
---|
3278 | #endif /* COMMENT */ |
---|
3279 | |
---|
3280 | #ifndef NOPUSH |
---|
3281 | int |
---|
3282 | shxpand(pat,namlst,len) char *pat, *namlst[]; int len; { |
---|
3283 | char *fgbuf = NULL; /* Buffer for forming ls command */ |
---|
3284 | char *p, *q; /* Workers */ |
---|
3285 | int i, x, retcode; char c; /* ... */ |
---|
3286 | |
---|
3287 | x = (int)strlen(pat) + (int)strlen(lscmd) + 3; /* Length of ls command */ |
---|
3288 | for (i = 0; i < oldmtchs; i++) { /* Free previous file list */ |
---|
3289 | if (namlst[i] ) { /* If memory is allocated */ |
---|
3290 | free(namlst[i]); /* Free the memory */ |
---|
3291 | namlst[i] = NULL ; /* Remember no memory is allocated */ |
---|
3292 | } |
---|
3293 | } |
---|
3294 | oldmtchs = 0 ; /* Remember there are no matches */ |
---|
3295 | fgbuf = malloc(x); /* Get buffer for command */ |
---|
3296 | if (!fgbuf) return(-1); /* Fail if cannot */ |
---|
3297 | sprintf(fgbuf,"%s %s",lscmd,pat); /* Form the command */ |
---|
3298 | zxcmd(ZIFILE,fgbuf); /* Start the command */ |
---|
3299 | i = 0; /* File counter */ |
---|
3300 | p = scratch; /* Point to scratch area */ |
---|
3301 | retcode = -1; /* Assume failure */ |
---|
3302 | while ((x = zminchar()) != -1) { /* Read characters from command */ |
---|
3303 | c = (char) x; |
---|
3304 | if (c == ' ' || c == '\n') { /* Got newline or space? */ |
---|
3305 | *p = '\0'; /* Yes, terminate string */ |
---|
3306 | p = scratch; /* Point back to beginning */ |
---|
3307 | if (zchki(p) == -1) /* Does file exist? */ |
---|
3308 | continue; /* No, continue */ |
---|
3309 | x = (int)strlen(p); /* Yes, get length of name */ |
---|
3310 | q = malloc(x+1); /* Allocate space for it */ |
---|
3311 | if (!q) goto shxfin; /* Fail if space can't be obtained */ |
---|
3312 | strcpy(q,scratch); /* Copy name to space */ |
---|
3313 | namlst[i++] = q; /* Copy pointer to name into array */ |
---|
3314 | if (i >= len) goto shxfin; /* Fail if too many */ |
---|
3315 | } else { /* Regular character */ |
---|
3316 | *p++ = c; /* Copy it into scratch area */ |
---|
3317 | } |
---|
3318 | } |
---|
3319 | retcode = i; /* Return number of matching files */ |
---|
3320 | shxfin: /* Common exit point */ |
---|
3321 | free(fgbuf); /* Free command buffer */ |
---|
3322 | fgbuf = NULL; |
---|
3323 | zclosf(ZIFILE); /* Delete the command fork. */ |
---|
3324 | oldmtchs = i; /* Remember how many files */ |
---|
3325 | return(retcode); |
---|
3326 | } |
---|
3327 | #endif /* NOPUSH */ |
---|
3328 | #endif /* OS2 */ |
---|
3329 | |
---|
3330 | /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */ |
---|
3331 | |
---|
3332 | /* Define the size of the string space for filename expansion. */ |
---|
3333 | |
---|
3334 | #ifndef DYNAMIC |
---|
3335 | #ifdef PROVX1 |
---|
3336 | #define SSPACE 500 |
---|
3337 | #else |
---|
3338 | #ifdef BSD29 |
---|
3339 | #define SSPACE 500 |
---|
3340 | #else |
---|
3341 | #ifdef pdp11 |
---|
3342 | #define SSPACE 500 |
---|
3343 | #else |
---|
3344 | #ifdef aegis |
---|
3345 | #define SSPACE 10000 /* size of string-generating buffer */ |
---|
3346 | #else /* Default static buffer size */ |
---|
3347 | #ifdef BIGBUFOK |
---|
3348 | #define SSPACE 32768 /* size of string-generating buffer */ |
---|
3349 | #else |
---|
3350 | #define SSPACE 2000 /* size of string-generating buffer */ |
---|
3351 | #endif /* BIGBUFOK */ |
---|
3352 | #endif /* aegis */ |
---|
3353 | #endif /* pdp11 */ |
---|
3354 | #endif /* BSD29 */ |
---|
3355 | #endif /* PROVX1 */ |
---|
3356 | static char sspace[SSPACE]; /* Buffer for generating filenames */ |
---|
3357 | #else /* is DYNAMIC */ |
---|
3358 | #ifdef BIGBUFOK |
---|
3359 | #define SSPACE 32768 |
---|
3360 | #else |
---|
3361 | #define SSPACE 10000 |
---|
3362 | #endif /* BIGBUFOK */ |
---|
3363 | static char *sspace = (char *)0; |
---|
3364 | #endif /* DYNAMIC */ |
---|
3365 | static int ssplen = SSPACE; /* Length of string space buffer */ |
---|
3366 | |
---|
3367 | static char *freeptr, **resptr; /* copies of caller's arguments */ |
---|
3368 | static int remlen; /* remaining length in caller's array*/ |
---|
3369 | static int numfnd; /* number of matches found */ |
---|
3370 | |
---|
3371 | #ifdef aegis |
---|
3372 | static char bslash; |
---|
3373 | #endif /* aegis */ |
---|
3374 | |
---|
3375 | /* |
---|
3376 | * splitpath: |
---|
3377 | * takes a string and splits the slash-separated portions into |
---|
3378 | * a list of path structures. Returns the head of the list. The |
---|
3379 | * structures are allocated by malloc, so they must be freed. |
---|
3380 | * Splitpath is used internally by the filename generator. |
---|
3381 | * |
---|
3382 | * Input: A string. |
---|
3383 | * Returns: A linked list of the slash-separated segments of the input. |
---|
3384 | */ |
---|
3385 | |
---|
3386 | struct path * |
---|
3387 | splitpath(p) char *p; { |
---|
3388 | struct path *head,*cur,*prv; |
---|
3389 | int i; |
---|
3390 | |
---|
3391 | debug(F110,"splitpath",p,0); |
---|
3392 | |
---|
3393 | head = prv = NULL; |
---|
3394 | if (ISDIRSEP(*p)) p++; /* skip leading slash */ |
---|
3395 | #ifdef OS2 |
---|
3396 | if ( *p == '\0' ) { /* the user wants the root directory */ |
---|
3397 | cur = (struct path *) malloc(sizeof(struct path)); |
---|
3398 | debug(F101,"splitpath malloc","",cur); |
---|
3399 | if (cur == NULL) { |
---|
3400 | debug(F100,"splitpath malloc failure","",0); |
---|
3401 | return((struct path *)NULL); |
---|
3402 | } |
---|
3403 | cur->fwd = NULL; |
---|
3404 | cur->npart[0] = '.'; |
---|
3405 | cur->npart[1] = '\0'; |
---|
3406 | head = cur; |
---|
3407 | return head; |
---|
3408 | } |
---|
3409 | #endif /* OS2 */ |
---|
3410 | while (*p != '\0') { |
---|
3411 | cur = (struct path *) malloc(sizeof (struct path)); |
---|
3412 | debug(F101,"splitpath malloc","",cur); |
---|
3413 | if (cur == NULL) { |
---|
3414 | debug(F100,"splitpath malloc failure","",0); |
---|
3415 | return((struct path *)NULL); |
---|
3416 | } |
---|
3417 | cur -> fwd = NULL; |
---|
3418 | if (head == NULL) |
---|
3419 | head = cur; |
---|
3420 | else |
---|
3421 | prv -> fwd = cur; /* link into chain */ |
---|
3422 | prv = cur; |
---|
3423 | #ifdef aegis |
---|
3424 | /* treat backslash as "../" */ |
---|
3425 | if (bslash && *p == bslash) { |
---|
3426 | strcpy(cur->npart, ".."); |
---|
3427 | ++p; |
---|
3428 | } else { |
---|
3429 | for (i=0; i < MAXNAMLEN && *p && *p != '/' && *p != bslash; i++) |
---|
3430 | cur -> npart[i] = *p++; |
---|
3431 | cur -> npart[i] = '\0'; /* end this segment */ |
---|
3432 | if (i >= MAXNAMLEN) |
---|
3433 | while (*p && *p != '/' && *p != bslash) |
---|
3434 | p++; |
---|
3435 | } |
---|
3436 | if (*p == '/') p++; |
---|
3437 | #else |
---|
3438 | #ifdef OS2 |
---|
3439 | for (i = 0; |
---|
3440 | i < MAXNAMLEN && !ISDIRSEP(*p) && *p != ':' && *p != '\0'; |
---|
3441 | i++ ) |
---|
3442 | cur -> npart[i] = *p++; |
---|
3443 | if ( *p == ':' ) { |
---|
3444 | cur -> npart[i++] = *p++; |
---|
3445 | if ( !ISDIRSEP(*p) ) |
---|
3446 | cur -> npart[i++] = '.'; |
---|
3447 | } |
---|
3448 | #else |
---|
3449 | for (i=0; i < MAXNAMLEN && !ISDIRSEP(*p) && *p != '\0'; i++) { |
---|
3450 | cur -> npart[i] = *p++; |
---|
3451 | } |
---|
3452 | #endif /* OS2 */ |
---|
3453 | cur -> npart[i] = '\0'; /* end this segment */ |
---|
3454 | if (i >= MAXNAMLEN) |
---|
3455 | while (!ISDIRSEP(*p) && *p != '\0') p++; |
---|
3456 | if (ISDIRSEP(*p)) |
---|
3457 | p++; |
---|
3458 | |
---|
3459 | #endif /* aegis */ |
---|
3460 | } |
---|
3461 | return(head); |
---|
3462 | } |
---|
3463 | |
---|
3464 | /* |
---|
3465 | * fgen: |
---|
3466 | * This is the actual name generator. It is passed a string, |
---|
3467 | * possibly containing wildcards, and an array of character pointers. |
---|
3468 | * It finds all the matching filenames and stores pointers to them in the |
---|
3469 | * array. The returned strings are allocated from a static buffer local to |
---|
3470 | * this module (so the caller doesn't have to worry about deallocating |
---|
3471 | * them); this means that successive calls to fgen will wipe out |
---|
3472 | * the results of previous calls. This isn't a problem here |
---|
3473 | * because we process one wildcard string at a time. |
---|
3474 | * |
---|
3475 | * Input: a wildcard string, an array to write names to, the |
---|
3476 | * length of the array. |
---|
3477 | * Returns: the number of matches. The array is filled with filenames |
---|
3478 | * that matched the pattern. If there wasn't enough room in the |
---|
3479 | * array, -1 is returned. |
---|
3480 | * Originally by: Jeff Damens, CUCCA, 1984. Many changes since then. |
---|
3481 | */ |
---|
3482 | static int |
---|
3483 | fgen(pat,resarry,len) char *pat,*resarry[]; int len; { |
---|
3484 | struct path *head; |
---|
3485 | char *sptr; |
---|
3486 | #ifdef aegis |
---|
3487 | char *namechars; |
---|
3488 | int tilde = 0, bquote = 0; |
---|
3489 | |
---|
3490 | if ((namechars = getenv("NAMECHARS")) != NULL) { |
---|
3491 | if (xindex(namechars, '~' ) != NULL) tilde = '~'; |
---|
3492 | if (xindex(namechars, '\\') != NULL) bslash = '\\'; |
---|
3493 | if (xindex(namechars, '`' ) != NULL) bquote = '`'; |
---|
3494 | } else { |
---|
3495 | tilde = '~'; bslash = '\\'; bquote = '`'; |
---|
3496 | } |
---|
3497 | sptr = scratch; |
---|
3498 | |
---|
3499 | /* copy "`node_data", etc. anchors */ |
---|
3500 | if (bquote && *pat == bquote) |
---|
3501 | while (*pat && *pat != '/' && *pat != bslash) |
---|
3502 | *sptr++ = *pat++; |
---|
3503 | else if (tilde && *pat == tilde) |
---|
3504 | *sptr++ = *pat++; |
---|
3505 | while (*pat == '/') |
---|
3506 | *sptr++ = *pat++; |
---|
3507 | if (sptr == scratch) { |
---|
3508 | strcpy(scratch,"./"); |
---|
3509 | sptr = scratch+2; |
---|
3510 | } /* init buffer correctly */ |
---|
3511 | if (!(head = splitpath(pat))) return(-1); |
---|
3512 | #else /* not aegis */ |
---|
3513 | debug(F110,"fgen pat",pat,0); |
---|
3514 | #ifdef OS2 |
---|
3515 | head = splitpath(pat); |
---|
3516 | #else /* not OS2 */ |
---|
3517 | if (!(head = splitpath(pat))) return(-1); |
---|
3518 | #endif /* OS2 */ |
---|
3519 | sptr = scratch; |
---|
3520 | if (!ISDIRSEP(*pat)) |
---|
3521 | *sptr++ = '.'; /* init buffer correctly */ |
---|
3522 | *sptr++ = DIRSEP; |
---|
3523 | #ifdef OS2 |
---|
3524 | if (isalpha(pat[0]) && pat[1] == ':') |
---|
3525 | sptr = scratch; /* reset in case of leading drive: */ |
---|
3526 | #endif /* OS2 */ |
---|
3527 | #endif /* aegis */ |
---|
3528 | numfnd = 0; /* none found yet */ |
---|
3529 | #ifdef DYNAMIC |
---|
3530 | if (!sspace) { /* Need to allocate string space? */ |
---|
3531 | while (ssplen > 50) { |
---|
3532 | if ((sspace = malloc(ssplen+2))) { /* Got it. */ |
---|
3533 | debug(F101,"fgen string space","",ssplen); |
---|
3534 | break; |
---|
3535 | } |
---|
3536 | ssplen = (ssplen / 2) + (ssplen / 4); /* Didn't, reduce by 3/4 */ |
---|
3537 | } |
---|
3538 | if (ssplen <= 50) { /* Did we get it? */ |
---|
3539 | fprintf(stderr,"fgen can't malloc string space\n"); |
---|
3540 | return(-1); |
---|
3541 | } |
---|
3542 | } |
---|
3543 | #endif /* DYNAMIC */ |
---|
3544 | freeptr = sspace; /* this is where matches are copied */ |
---|
3545 | resptr = resarry; /* static copies of these so */ |
---|
3546 | remlen = len; /* recursive calls can alter them */ |
---|
3547 | traverse(head,scratch,sptr); /* go walk the directory tree */ |
---|
3548 | #ifdef COMMENT |
---|
3549 | /* |
---|
3550 | This code, circa 1984, has never worked right - it references the head |
---|
3551 | pointer after it has already been freed. Lord knows what might have been |
---|
3552 | happening because of this. Thanks to Steve Walton for finding & fixing |
---|
3553 | this bug. |
---|
3554 | */ |
---|
3555 | for (; head != NULL; head = head -> fwd) { |
---|
3556 | free(head); /* return the path segments */ |
---|
3557 | head = NULL; |
---|
3558 | } |
---|
3559 | #else |
---|
3560 | while (head != NULL) { |
---|
3561 | struct path *next = head -> fwd; |
---|
3562 | free(head); |
---|
3563 | head = next; |
---|
3564 | } |
---|
3565 | #endif /* COMMENT */ |
---|
3566 | return(numfnd); /* and return the number of matches */ |
---|
3567 | } |
---|
3568 | |
---|
3569 | /* traverse: |
---|
3570 | * Walks the directory tree looking for matches to its arguments. |
---|
3571 | * The algorithm is, briefly: |
---|
3572 | * If the current pattern segment contains no wildcards, that |
---|
3573 | * segment is added to what we already have. If the name so far |
---|
3574 | * exists, we call ourselves recursively with the next segment |
---|
3575 | * in the pattern string; otherwise, we just return. |
---|
3576 | * |
---|
3577 | * If the current pattern segment contains wildcards, we open the name |
---|
3578 | * we've accumulated so far (assuming it is really a directory), then read |
---|
3579 | * each filename in it, and, if it matches the wildcard pattern segment, add |
---|
3580 | * that filename to what we have so far and call ourselves recursively on the |
---|
3581 | * next segment. |
---|
3582 | * |
---|
3583 | * Finally, when no more pattern segments remain, we add what's accumulated |
---|
3584 | * so far to the result array and increment the number of matches. |
---|
3585 | * |
---|
3586 | * Input: a pattern path list (as generated by splitpath), a string |
---|
3587 | * pointer that points to what we've traversed so far (this |
---|
3588 | * can be initialized to "/" to start the search at the root |
---|
3589 | * directory, or to "./" to start the search at the current |
---|
3590 | * directory), and a string pointer to the end of the string |
---|
3591 | * in the previous argument. |
---|
3592 | * Returns: nothing. |
---|
3593 | */ |
---|
3594 | static VOID |
---|
3595 | traverse(pl,sofar,endcur) struct path *pl; char *sofar, *endcur; { |
---|
3596 | |
---|
3597 | /* Define LONGFN (long file names) automatically for BSD 2.9 and 4.2 */ |
---|
3598 | /* LONGFN can also be defined on the cc command line. */ |
---|
3599 | |
---|
3600 | #ifdef BSD29 |
---|
3601 | #ifndef LONGFN |
---|
3602 | #define LONGFN |
---|
3603 | #endif |
---|
3604 | #endif |
---|
3605 | |
---|
3606 | #ifdef BSD42 |
---|
3607 | #ifndef LONGFN |
---|
3608 | #define LONGFN |
---|
3609 | #endif |
---|
3610 | #endif |
---|
3611 | |
---|
3612 | /* Appropriate declarations for directory routines and structures */ |
---|
3613 | /* #define OPENDIR means to use opendir(), readdir(), closedir() */ |
---|
3614 | /* If OPENDIR not defined, we use open(), read(), close() */ |
---|
3615 | |
---|
3616 | #ifdef DIRENT /* New way, <dirent.h> */ |
---|
3617 | #define OPENDIR |
---|
3618 | DIR *fd, *opendir(); |
---|
3619 | struct dirent *dirbuf; |
---|
3620 | struct dirent *readdir(); |
---|
3621 | #else /* !DIRENT */ |
---|
3622 | #ifdef LONGFN /* Old way, <dir.h> with opendir() */ |
---|
3623 | #define OPENDIR |
---|
3624 | DIR *fd, *opendir(); |
---|
3625 | struct direct *dirbuf; |
---|
3626 | #else /* !LONGFN */ |
---|
3627 | int fd; /* Old way, <dir.h> with open() */ |
---|
3628 | struct direct dir_entry; |
---|
3629 | struct direct *dirbuf = &dir_entry; |
---|
3630 | #endif /* LONGFN */ |
---|
3631 | #endif /* DIRENT */ |
---|
3632 | |
---|
3633 | #ifdef NT |
---|
3634 | struct _stat statbuf; /* for file info */ |
---|
3635 | #else /* NT */ |
---|
3636 | struct stat statbuf; /* for file info */ |
---|
3637 | #endif /* NT */ |
---|
3638 | |
---|
3639 | if (pl == NULL) { |
---|
3640 | *--endcur = '\0'; /* end string, overwrite trailing / */ |
---|
3641 | addresult(sofar); |
---|
3642 | return; |
---|
3643 | } |
---|
3644 | if (!iswild(pl -> npart)) { |
---|
3645 | strcpy(endcur,pl -> npart); |
---|
3646 | endcur += (int)strlen(pl -> npart); |
---|
3647 | *endcur = '\0'; /* end current string */ |
---|
3648 | if (stat(sofar,&statbuf) == 0) { /* if current piece exists */ |
---|
3649 | #ifdef OS2 |
---|
3650 | if (endcur - sofar == 3 && endcur[-1] == '.' && endcur[-2] == ':') |
---|
3651 | endcur--; |
---|
3652 | else |
---|
3653 | #endif /* OS2 */ |
---|
3654 | *endcur++ = DIRSEP; /* add slash to end */ |
---|
3655 | *endcur = '\0'; /* and end the string */ |
---|
3656 | traverse(pl -> fwd,sofar,endcur); |
---|
3657 | } |
---|
3658 | return; |
---|
3659 | } |
---|
3660 | |
---|
3661 | /* Segment contains wildcards, have to search directory */ |
---|
3662 | |
---|
3663 | *endcur = '\0'; /* end current string */ |
---|
3664 | if (stat(sofar,&statbuf) == -1) return; /* doesn't exist, forget it */ |
---|
3665 | if (!S_ISDIR (statbuf.st_mode)) return; /* not a directory, skip */ |
---|
3666 | |
---|
3667 | #ifdef OPENDIR |
---|
3668 | if ((fd = opendir(sofar)) == NULL) return; /* Can't open, fail. */ |
---|
3669 | while (dirbuf = readdir(fd)) |
---|
3670 | #else /* !OPENDIR */ |
---|
3671 | if ((fd = open(sofar,O_RDONLY)) < 0) return; /* Can't open, fail. */ |
---|
3672 | while (read(fd, (char *)dirbuf, sizeof dir_entry)) |
---|
3673 | #endif /* OPENDIR */ |
---|
3674 | { |
---|
3675 | /* Get null-terminated copy!!! */ |
---|
3676 | strncpy(nambuf,dirbuf->d_name,MAXNAMLEN); |
---|
3677 | nambuf[MAXNAMLEN] = '\0'; |
---|
3678 | #ifdef unos |
---|
3679 | if (dirbuf->d_ino != -1 && match(pl -> npart,nambuf)) |
---|
3680 | #else |
---|
3681 | /* #ifdef _POSIX_SOURCE */ |
---|
3682 | /* |
---|
3683 | Directory reading is not specified in POSIX.1. POSIX.2 gives us glob() and |
---|
3684 | fnmatch(), which are not yet supported by C-Kermit. Meanwhile, maybe POSIX |
---|
3685 | implementations should force "set wildcard shell" and remove all of this |
---|
3686 | code. |
---|
3687 | */ |
---|
3688 | #ifdef QNX |
---|
3689 | if (dirbuf->d_stat.st_ino != 0 && match(pl -> npart,nambuf)) |
---|
3690 | #else |
---|
3691 | #ifdef SOLARIS |
---|
3692 | if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) |
---|
3693 | #else |
---|
3694 | #ifdef sun |
---|
3695 | if (dirbuf->d_fileno != 0 && match(pl -> npart,nambuf)) |
---|
3696 | #else |
---|
3697 | #ifdef bsdi |
---|
3698 | if (dirbuf->d_fileno != 0 && match(pl -> npart,nambuf)) |
---|
3699 | #else |
---|
3700 | #ifdef __386BSD__ |
---|
3701 | if (dirbuf->d_fileno != 0 && match(pl -> npart,nambuf)) |
---|
3702 | #else |
---|
3703 | #ifdef __FreeBSD__ |
---|
3704 | if (dirbuf->d_fileno != 0 && match(pl -> npart,nambuf)) |
---|
3705 | #else |
---|
3706 | #ifdef ultrix |
---|
3707 | if (dirbuf->gd_ino != 0 && match(pl -> npart,nambuf)) |
---|
3708 | #else |
---|
3709 | #ifdef Plan9 |
---|
3710 | if (match(pl->npart,nambuf)) |
---|
3711 | #else |
---|
3712 | if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) |
---|
3713 | #endif /* Plan9 */ |
---|
3714 | #endif /* ultrix */ |
---|
3715 | #endif /* __FreeBSD__ */ |
---|
3716 | #endif /* __386BSD__ */ |
---|
3717 | #endif /* bsdi */ |
---|
3718 | #endif /* sun */ |
---|
3719 | #endif /* SOLARIS */ |
---|
3720 | #endif /* QNX */ |
---|
3721 | |
---|
3722 | /* #else */ /* not _POSIX_SOURCE */ |
---|
3723 | /* if (dirbuf->d_ino != 0 && match(pl -> npart,nambuf)) */ |
---|
3724 | /* #endif */ /* _POSIX_SOURCE */ |
---|
3725 | |
---|
3726 | #endif /* unos */ |
---|
3727 | { |
---|
3728 | char *eos; |
---|
3729 | strcpy(endcur,nambuf); |
---|
3730 | eos = endcur + (int)strlen(nambuf); |
---|
3731 | *eos++ = DIRSEP; /* end this segment */ |
---|
3732 | traverse(pl -> fwd,sofar,eos); |
---|
3733 | } |
---|
3734 | } |
---|
3735 | #ifdef OPENDIR |
---|
3736 | closedir(fd); |
---|
3737 | #else /* !OPENDIR */ |
---|
3738 | close(fd); |
---|
3739 | #endif /* OPENDIR */ |
---|
3740 | } |
---|
3741 | |
---|
3742 | /* |
---|
3743 | * addresult: |
---|
3744 | * Adds a result string to the result array. Increments the number |
---|
3745 | * of matches found, copies the found string into our string |
---|
3746 | * buffer, and puts a pointer to the buffer into the caller's result |
---|
3747 | * array. Our free buffer pointer is updated. If there is no |
---|
3748 | * more room in the caller's array, the number of matches is set to -1. |
---|
3749 | * Input: a result string. |
---|
3750 | * Returns: nothing. |
---|
3751 | */ |
---|
3752 | static VOID |
---|
3753 | addresult(str) char *str; { |
---|
3754 | int l; |
---|
3755 | debug(F111,"addresult",str,remlen); |
---|
3756 | if (str[0] == '.' && ISDIRSEP(str[1])) str += 2; /* (===OS2 change===) */ |
---|
3757 | if (--remlen < 0) { |
---|
3758 | numfnd = -1; |
---|
3759 | return; |
---|
3760 | } |
---|
3761 | l = (int)strlen(str) + 1; /* size this will take up */ |
---|
3762 | if ((freeptr + l) > (sspace + ssplen)) { |
---|
3763 | numfnd = -1; /* do not record if not enough space */ |
---|
3764 | return; |
---|
3765 | } |
---|
3766 | strcpy(freeptr,str); |
---|
3767 | *resptr++ = freeptr; |
---|
3768 | freeptr += l; |
---|
3769 | numfnd++; |
---|
3770 | } |
---|
3771 | |
---|
3772 | /* |
---|
3773 | * match: |
---|
3774 | * pattern matcher. Takes a string and a pattern possibly containing |
---|
3775 | * the wildcard characters '*' and '?'. Returns true if the pattern |
---|
3776 | * matches the string, false otherwise. |
---|
3777 | * by: Jeff Damens, CUCCA, 1984 |
---|
3778 | * skipping over dot files and backslash quoting added by fdc, 1990. |
---|
3779 | * |
---|
3780 | * Input: a string and a wildcard pattern. |
---|
3781 | * Returns: 1 if match, 0 if no match. |
---|
3782 | */ |
---|
3783 | static int |
---|
3784 | match(pattern,string) char *pattern,*string; { |
---|
3785 | char *psave,*ssave; /* back up pointers for failure */ |
---|
3786 | int q = 0; /* quote flag */ |
---|
3787 | |
---|
3788 | debug(F110,"match str",string,0); |
---|
3789 | psave = ssave = NULL; |
---|
3790 | #ifndef MATCHDOT |
---|
3791 | if (*string == '.' && *pattern != '.') { |
---|
3792 | debug(F110,"match skip",string,0); |
---|
3793 | return(0); |
---|
3794 | } |
---|
3795 | #endif |
---|
3796 | while (1) { |
---|
3797 | #ifdef OS2 |
---|
3798 | for (; tolower(*pattern) == tolower(*string); pattern++,string++) |
---|
3799 | #else |
---|
3800 | for (; *pattern == *string; pattern++,string++) /* skip first */ |
---|
3801 | #endif /* OS2 */ |
---|
3802 | if (*string == '\0') return(1); /* end of strings, succeed */ |
---|
3803 | |
---|
3804 | if (*pattern == '\\' && q == 0) { /* Watch out for quoted */ |
---|
3805 | q = 1; /* metacharacters */ |
---|
3806 | pattern++; /* advance past quote */ |
---|
3807 | if (*pattern != *string) return(0); |
---|
3808 | continue; |
---|
3809 | } else q = 0; |
---|
3810 | |
---|
3811 | if (q) { |
---|
3812 | return(0); |
---|
3813 | } else { |
---|
3814 | if (*string != '\0' && *pattern == '?') { |
---|
3815 | pattern++; /* '?', let it match */ |
---|
3816 | string++; |
---|
3817 | } else if (*pattern == '*') { /* '*' ... */ |
---|
3818 | psave = ++pattern; /* remember where we saw it */ |
---|
3819 | ssave = string; /* let it match 0 chars */ |
---|
3820 | } else if (ssave != NULL && *ssave != '\0') { /* if not at end */ |
---|
3821 | /* ...have seen a star */ |
---|
3822 | string = ++ssave; /* skip 1 char from string */ |
---|
3823 | pattern = psave; /* and back up pattern */ |
---|
3824 | } else return(0); /* otherwise just fail */ |
---|
3825 | } |
---|
3826 | } |
---|
3827 | } |
---|
3828 | |
---|
3829 | /* |
---|
3830 | The following two functions are for expanding tilde in filenames |
---|
3831 | Contributed by Howie Kaye, CUCCA, developed for CCMD package. |
---|
3832 | */ |
---|
3833 | |
---|
3834 | /* W H O A M I -- Get user's username. */ |
---|
3835 | |
---|
3836 | /* |
---|
3837 | 1) Get real uid |
---|
3838 | 2) See if the $USER environment variable is set ($LOGNAME on AT&T) |
---|
3839 | 3) If $USER's uid is the same as ruid, realname is $USER |
---|
3840 | 4) Otherwise get logged in user's name |
---|
3841 | 5) If that name has the same uid as the real uid realname is loginname |
---|
3842 | 6) Otherwise, get a name for ruid from /etc/passwd |
---|
3843 | */ |
---|
3844 | static char * |
---|
3845 | whoami () { |
---|
3846 | #ifdef DTILDE |
---|
3847 | #ifdef pdp11 |
---|
3848 | #define WHOLEN 100 |
---|
3849 | #else |
---|
3850 | #define WHOLEN 257 |
---|
3851 | #endif /* pdp11 */ |
---|
3852 | static char realname[256]; /* user's name */ |
---|
3853 | static int ruid = -1; /* user's real uid */ |
---|
3854 | char loginname[256], envname[256]; /* temp storage */ |
---|
3855 | char *c; |
---|
3856 | struct passwd *p; |
---|
3857 | _PROTOTYP(extern char * getlogin, (void) ); |
---|
3858 | |
---|
3859 | if (ruid != -1) |
---|
3860 | return(realname); |
---|
3861 | |
---|
3862 | ruid = real_uid(); /* get our uid */ |
---|
3863 | |
---|
3864 | /* how about $USER or $LOGNAME? */ |
---|
3865 | if ((c = getenv(NAMEENV)) != NULL) { /* check the env variable */ |
---|
3866 | strcpy (envname, c); |
---|
3867 | if ((p = getpwnam(envname)) != NULL) { |
---|
3868 | if (p->pw_uid == ruid) { /* get passwd entry for envname */ |
---|
3869 | strcpy (realname, envname); /* if the uid's are the same */ |
---|
3870 | return(realname); |
---|
3871 | } |
---|
3872 | } |
---|
3873 | } |
---|
3874 | |
---|
3875 | /* can we use loginname() ? */ |
---|
3876 | |
---|
3877 | if ((c = getlogin()) != NULL) { /* name from utmp file */ |
---|
3878 | strcpy (loginname, c); |
---|
3879 | if ((p = getpwnam(loginname)) != NULL) /* get passwd entry */ |
---|
3880 | if (p->pw_uid == ruid) { /* for loginname */ |
---|
3881 | strcpy (realname, loginname); /* if the uid's are the same */ |
---|
3882 | return(realname); |
---|
3883 | } |
---|
3884 | } |
---|
3885 | |
---|
3886 | /* Use first name we get for ruid */ |
---|
3887 | |
---|
3888 | if ((p = getpwuid(ruid)) == NULL) { /* name for uid */ |
---|
3889 | realname[0] = '\0'; /* no user name */ |
---|
3890 | ruid = -1; |
---|
3891 | return(NULL); |
---|
3892 | } |
---|
3893 | strcpy (realname, p->pw_name); |
---|
3894 | return(realname); |
---|
3895 | #else |
---|
3896 | return(NULL); |
---|
3897 | #endif /* DTILDE */ |
---|
3898 | } |
---|
3899 | |
---|
3900 | /* T I L D E _ E X P A N D -- expand ~user to the user's home directory. */ |
---|
3901 | |
---|
3902 | char * |
---|
3903 | tilde_expand(dirname) char *dirname; { |
---|
3904 | #ifdef DTILDE |
---|
3905 | #ifdef pdp11 |
---|
3906 | #define BUFLEN 100 |
---|
3907 | #else |
---|
3908 | #define BUFLEN 257 |
---|
3909 | #endif /* pdp11 */ |
---|
3910 | struct passwd *user; |
---|
3911 | static char olddir[BUFLEN]; |
---|
3912 | static char oldrealdir[BUFLEN]; |
---|
3913 | static char temp[BUFLEN]; |
---|
3914 | int i, j; |
---|
3915 | |
---|
3916 | debug(F111,"tilde_expand",dirname,dirname[0]); |
---|
3917 | |
---|
3918 | if (dirname[0] != '~') /* Not a tilde...return param */ |
---|
3919 | return(dirname); |
---|
3920 | if (!strcmp(olddir,dirname)) { /* Same as last time */ |
---|
3921 | return(oldrealdir); /* so return old answer. */ |
---|
3922 | } else { |
---|
3923 | j = (int)strlen(dirname); |
---|
3924 | for (i = 0; i < j; i++) /* find username part of string */ |
---|
3925 | if (!ISDIRSEP(dirname[i])) |
---|
3926 | temp[i] = dirname[i]; |
---|
3927 | else break; |
---|
3928 | temp[i] = '\0'; /* tie off with a NULL */ |
---|
3929 | if (i == 1) { /* if just a "~" */ |
---|
3930 | user = getpwnam(whoami()); /* get info on current user */ |
---|
3931 | } else { |
---|
3932 | user = getpwnam(&temp[1]); /* otherwise on the specified user */ |
---|
3933 | } |
---|
3934 | } |
---|
3935 | if (user != NULL) { /* valid user? */ |
---|
3936 | strcpy(olddir, dirname); /* remember the directory */ |
---|
3937 | strcpy(oldrealdir,user->pw_dir); /* and their home directory */ |
---|
3938 | strcat(oldrealdir,&dirname[i]); |
---|
3939 | return(oldrealdir); |
---|
3940 | } else { /* invalid? */ |
---|
3941 | strcpy(olddir, dirname); /* remember for next time */ |
---|
3942 | strcpy(oldrealdir, dirname); |
---|
3943 | return(oldrealdir); |
---|
3944 | } |
---|
3945 | #else |
---|
3946 | return(NULL); |
---|
3947 | #endif /* DTILDE */ |
---|
3948 | } |
---|
3949 | |
---|
3950 | /* |
---|
3951 | Functions for executing system commands. |
---|
3952 | zsyscmd() executes the system command in the normal, default way for |
---|
3953 | the system. In UNIX, it does what system() does. Thus, its results |
---|
3954 | are always predictable. |
---|
3955 | zshcmd() executes the command using the user's preferred shell. |
---|
3956 | */ |
---|
3957 | int |
---|
3958 | zsyscmd(s) char *s; { |
---|
3959 | #ifdef aegis |
---|
3960 | if (!priv_chk()) return(system(s)); |
---|
3961 | #else |
---|
3962 | #ifdef OS2 |
---|
3963 | /* |
---|
3964 | We must set the priority back to normal. Otherwise all of children |
---|
3965 | processes are going to inherit our FOREGROUNDSERVER priority |
---|
3966 | and that would not be good for the system or ourselves. |
---|
3967 | */ |
---|
3968 | |
---|
3969 | if (!priv_chk()) { |
---|
3970 | ULONG rc = 0; |
---|
3971 | #ifndef KUI |
---|
3972 | char title[80]; |
---|
3973 | title[0] = '\0'; |
---|
3974 | os2gettitle( title, 80 ); |
---|
3975 | RequestScreenMutex(SEM_INDEFINITE_WAIT); |
---|
3976 | #endif /* KUI */ |
---|
3977 | KbdHandlerCleanup(); |
---|
3978 | ResetThreadPrty(); |
---|
3979 | rc = system(s); |
---|
3980 | SetThreadPrty(priority,15); |
---|
3981 | KbdHandlerInit(); |
---|
3982 | #ifndef KUI |
---|
3983 | if ( |
---|
3984 | #ifndef NOSPL |
---|
3985 | cmdlvl == 0 |
---|
3986 | #else |
---|
3987 | tlevel < 0 |
---|
3988 | #endif /* NOSPL */ |
---|
3989 | ) |
---|
3990 | OS2WaitForKey(); |
---|
3991 | ReleaseScreenMutex(); |
---|
3992 | os2settitle( title, FALSE ); |
---|
3993 | #endif /* KUI */ |
---|
3994 | return rc; |
---|
3995 | } |
---|
3996 | return 0; |
---|
3997 | #else |
---|
3998 | PID_T shpid; |
---|
3999 | #ifdef COMMENT |
---|
4000 | /* This doesn't work... */ |
---|
4001 | WAIT_T status; |
---|
4002 | #else |
---|
4003 | int status; |
---|
4004 | #endif /* COMMENT */ |
---|
4005 | |
---|
4006 | if (shpid = fork()) { |
---|
4007 | if (shpid < (PID_T)0) return(-1); /* Parent */ |
---|
4008 | while (shpid != (PID_T) wait(&status)) |
---|
4009 | ; |
---|
4010 | return(status); |
---|
4011 | } |
---|
4012 | if (priv_can()) { /* Child: cancel any priv's */ |
---|
4013 | printf("?Privilege cancellation failure\n"); |
---|
4014 | _exit(255); |
---|
4015 | } |
---|
4016 | #ifdef HPUX10 |
---|
4017 | execl("/usr/bin/sh","sh","-c",s,NULL); |
---|
4018 | perror("/usr/bin/sh"); |
---|
4019 | #else |
---|
4020 | #ifdef Plan9 |
---|
4021 | execl("/bin/rc", "rc", "-c", s, NULL); |
---|
4022 | perror("/bin/rc"); |
---|
4023 | #else |
---|
4024 | execl("/bin/sh","sh","-c",s,NULL); |
---|
4025 | perror("/bin/sh"); |
---|
4026 | #endif /* Plan9 */ |
---|
4027 | #endif /* HPUX10 */ |
---|
4028 | _exit(255); |
---|
4029 | return(0); /* Shut up ANSI compilers. */ |
---|
4030 | #endif /* OS2 */ |
---|
4031 | #endif /* aegis */ |
---|
4032 | } |
---|
4033 | |
---|
4034 | /* |
---|
4035 | UNIX code by H. Fischer; copyright rights assigned to Columbia Univ. |
---|
4036 | Adapted to use getpwuid to find login shell because many systems do not |
---|
4037 | have SHELL in environment, and to use direct calling of shell rather |
---|
4038 | than intermediate system() call. -- H. Fischer |
---|
4039 | Call with s pointing to command to execute. |
---|
4040 | */ |
---|
4041 | |
---|
4042 | int |
---|
4043 | zshcmd(s) char *s; { |
---|
4044 | PID_T pid; |
---|
4045 | |
---|
4046 | #ifdef OS2 |
---|
4047 | int rc; |
---|
4048 | char title[80]; |
---|
4049 | #ifdef NT |
---|
4050 | SIGTYP (* savint)(int); |
---|
4051 | #endif /* NT */ |
---|
4052 | char *shell = getenv("SHELL"); |
---|
4053 | if ( !shell ) |
---|
4054 | shell = getenv("COMSPEC"); |
---|
4055 | |
---|
4056 | if (!priv_chk()) { |
---|
4057 | #ifndef KUI |
---|
4058 | os2gettitle( title, 80 ); |
---|
4059 | RequestScreenMutex(SEM_INDEFINITE_WAIT); |
---|
4060 | #endif /* KUI */ |
---|
4061 | KbdHandlerCleanup(); |
---|
4062 | ResetThreadPrty(); |
---|
4063 | #ifdef NT |
---|
4064 | savint = signal( SIGINT, SIG_IGN ); |
---|
4065 | #endif /* NT */ |
---|
4066 | |
---|
4067 | if (!s || *s == '\0') |
---|
4068 | rc = system(shell) == 0; /* was _spawnlp(P_WAIT, shell, NULL) */ |
---|
4069 | else |
---|
4070 | rc = system(s) == 0; |
---|
4071 | #ifdef NT |
---|
4072 | signal( SIGINT, savint ); |
---|
4073 | #endif /* NT */ |
---|
4074 | |
---|
4075 | SetThreadPrty(priority,15); |
---|
4076 | KbdHandlerInit(); |
---|
4077 | #ifndef KUI |
---|
4078 | if ( |
---|
4079 | #ifndef NOSPL |
---|
4080 | cmdlvl == 0 |
---|
4081 | #else /* NOSPL */ |
---|
4082 | tlevel < 0 |
---|
4083 | #endif /* NOSPL */ |
---|
4084 | ) |
---|
4085 | OS2WaitForKey(); |
---|
4086 | ReleaseScreenMutex(); |
---|
4087 | os2settitle( title, FALSE ); |
---|
4088 | #endif /* KUI */ |
---|
4089 | return(rc); |
---|
4090 | } |
---|
4091 | return(0); |
---|
4092 | #else /* OS2 */ |
---|
4093 | #ifdef AMIGA |
---|
4094 | if (!priv_chk()) system(s); |
---|
4095 | #else |
---|
4096 | #ifdef datageneral |
---|
4097 | if (priv_chk) return(1); |
---|
4098 | if (*s == '\0') /* Interactive shell requested? */ |
---|
4099 | #ifdef mvux |
---|
4100 | system("/bin/sh "); |
---|
4101 | #else |
---|
4102 | system("x :cli prefix Kermit_Baby:"); |
---|
4103 | #endif /* mvux */ |
---|
4104 | else /* Otherwise, */ |
---|
4105 | system(s); /* Best for aos/vs?? */ |
---|
4106 | |
---|
4107 | #else |
---|
4108 | #ifdef aegis |
---|
4109 | if ((pid = vfork()) == 0) { /* Make child quickly */ |
---|
4110 | char *shpath, *shname, *shptr; /* For finding desired shell */ |
---|
4111 | |
---|
4112 | if (priv_can()) exit(1); /* Turn off privs. */ |
---|
4113 | if ((shpath = getenv("SHELL")) == NULL) shpath = "/com/sh"; |
---|
4114 | |
---|
4115 | #else /* All Unix systems */ |
---|
4116 | if ((pid = fork()) == 0) { /* Make child */ |
---|
4117 | char *shpath, *shname, *shptr; /* For finding desired shell */ |
---|
4118 | struct passwd *p; |
---|
4119 | #ifdef HPUX10 /* Default */ |
---|
4120 | char *defshell = "/usr/bin/sh"; |
---|
4121 | #else |
---|
4122 | #ifdef Plan9 |
---|
4123 | char *defshell = "/bin/rc"; |
---|
4124 | #else |
---|
4125 | char *defshell = "/bin/sh"; |
---|
4126 | #endif /* Plan9 */ |
---|
4127 | #endif /* HPUX10 */ |
---|
4128 | if (priv_can()) exit(1); /* Turn off privs. */ |
---|
4129 | #ifdef COMMENT |
---|
4130 | /* Old way always used /etc/passwd shell */ |
---|
4131 | p = getpwuid(real_uid()); /* Get login data */ |
---|
4132 | if (p == (struct passwd *) NULL || !*(p->pw_shell)) |
---|
4133 | shpath = defshell; |
---|
4134 | else |
---|
4135 | shpath = p->pw_shell; |
---|
4136 | #else |
---|
4137 | /* New way lets user override with SHELL variable, but does not rely on it. */ |
---|
4138 | /* This allows user to specify a different shell. */ |
---|
4139 | shpath = getenv("SHELL"); /* What shell? */ |
---|
4140 | if (shpath == NULL) { |
---|
4141 | p = getpwuid( real_uid() ); /* Get login data */ |
---|
4142 | if (p == (struct passwd *)NULL || !*(p->pw_shell)) |
---|
4143 | shpath = defshell; |
---|
4144 | else shpath = p->pw_shell; |
---|
4145 | } |
---|
4146 | #endif /* COMMENT */ |
---|
4147 | #endif /* aegis */ |
---|
4148 | shptr = shname = shpath; |
---|
4149 | while (*shptr != '\0') |
---|
4150 | if (*shptr++ == DIRSEP) |
---|
4151 | shname = shptr; |
---|
4152 | if (s == NULL || *s == '\0') { /* Interactive shell requested? */ |
---|
4153 | execl(shpath,shname,"-i",NULL); /* Yes, do that */ |
---|
4154 | } else { /* Otherwise, */ |
---|
4155 | execl(shpath,shname,"-c",s,NULL); /* exec the given command */ |
---|
4156 | } /* If execl() failed, */ |
---|
4157 | exit(BAD_EXIT); /* return bad return code. */ |
---|
4158 | |
---|
4159 | } else { /* Parent */ |
---|
4160 | |
---|
4161 | int wstat; /* ... must wait for child */ |
---|
4162 | int child; /* Child's exit status */ |
---|
4163 | SIGTYP (*istat)(), (*qstat)(); |
---|
4164 | |
---|
4165 | if (pid == (PID_T) -1) return(-1); /* fork() failed? */ |
---|
4166 | |
---|
4167 | istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */ |
---|
4168 | qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */ |
---|
4169 | |
---|
4170 | #ifdef UNIX |
---|
4171 | #define CK_CHILD /* Assume this is safe in UNIX */ |
---|
4172 | #endif /* UNIX */ |
---|
4173 | |
---|
4174 | #ifdef CK_CHILD |
---|
4175 | while (((wstat = wait(&child)) != pid) && (wstat != -1)) |
---|
4176 | #else |
---|
4177 | while (((wstat = wait((WAIT_T *)0)) != pid) && (wstat != -1)) |
---|
4178 | #endif /* CK_CHILD */ |
---|
4179 | ; /* Wait for fork */ |
---|
4180 | signal(SIGINT,istat); /* Restore interrupts */ |
---|
4181 | signal(SIGQUIT,qstat); |
---|
4182 | #ifdef CK_CHILD |
---|
4183 | return(child == 0 ? 1 : 0); /* Return child's status */ |
---|
4184 | #endif /* CK_CHILD */ |
---|
4185 | } |
---|
4186 | #endif |
---|
4187 | #endif |
---|
4188 | #endif /* OS2 */ |
---|
4189 | return(1); |
---|
4190 | } |
---|
4191 | |
---|
4192 | #ifdef aegis |
---|
4193 | /* |
---|
4194 | Replacement for strchr() and index(), neither of which seem to be universal. |
---|
4195 | */ |
---|
4196 | static char * |
---|
4197 | #ifdef CK_ANSIC |
---|
4198 | xindex(char * s, char c) |
---|
4199 | #else |
---|
4200 | xindex(s,c) char *s, c; |
---|
4201 | #endif /* CK_ANSIC */ |
---|
4202 | /* xindex */ { |
---|
4203 | while (*s != '\0' && *s != c) s++; |
---|
4204 | if (*s == c) return(s); else return(NULL); |
---|
4205 | } |
---|
4206 | #endif /* aegis */ |
---|
4207 | |
---|
4208 | /* I S W I L D -- Check if filespec is "wild" */ |
---|
4209 | |
---|
4210 | /* |
---|
4211 | Returns 0 if it is a single file, 1 if it contains wildcard characters. |
---|
4212 | Note: must match the algorithm used by match(), hence no [a-z], etc. |
---|
4213 | */ |
---|
4214 | int |
---|
4215 | iswild(filespec) char *filespec; { |
---|
4216 | char c; int x; char *p; |
---|
4217 | if (wildxpand) { |
---|
4218 | if ((x = zxpand(filespec)) > 1) return(1); |
---|
4219 | if (x == 0) return(0); /* File does not exist */ |
---|
4220 | p = malloc(MAXNAMLEN + 20); |
---|
4221 | znext(p); |
---|
4222 | #ifdef OS2 |
---|
4223 | x = ( |
---|
4224 | #ifdef NT |
---|
4225 | _stricmp(filespec,p) |
---|
4226 | #else |
---|
4227 | stricmp(filespec,p) |
---|
4228 | #endif /* NT */ |
---|
4229 | != 0); |
---|
4230 | #else |
---|
4231 | x = (strcmp(filespec,p) != 0); |
---|
4232 | #endif /* OS2 */ |
---|
4233 | free(p); |
---|
4234 | p = NULL; |
---|
4235 | return(x); |
---|
4236 | } else { |
---|
4237 | while ((c = *filespec++) != '\0') |
---|
4238 | if (c == '*' || c == '?') return(1); |
---|
4239 | return(0); |
---|
4240 | } |
---|
4241 | } |
---|
4242 | |
---|
4243 | /* |
---|
4244 | Tell if string pointer s is the name of an existing directory. |
---|
4245 | Returns 1 if directory, 0 if not a directory. |
---|
4246 | */ |
---|
4247 | int |
---|
4248 | isdir(s) char *s; { |
---|
4249 | int x; |
---|
4250 | #ifdef NT |
---|
4251 | struct _stat statbuf; |
---|
4252 | #else /* NT */ |
---|
4253 | struct stat statbuf; |
---|
4254 | #endif /* NT */ |
---|
4255 | |
---|
4256 | |
---|
4257 | if (!s) return(0); |
---|
4258 | if (!*s) return(0); |
---|
4259 | |
---|
4260 | #ifdef OS2 |
---|
4261 | /* Disk letter like A: is top-level directory on a disk */ |
---|
4262 | if (((int)strlen(s) == 2) && (isalpha(*s)) && (*(s+1) == ':')) |
---|
4263 | return(1); |
---|
4264 | #endif /* OS2 */ |
---|
4265 | x = stat(s,&statbuf); |
---|
4266 | debug(F111,"isdir stat",s,x); |
---|
4267 | if (x == -1) { |
---|
4268 | debug(F101,"isdir errno","",errno); |
---|
4269 | return(0); |
---|
4270 | } else { |
---|
4271 | debug(F101,"isdir statbuf.st_mode","",statbuf.st_mode); |
---|
4272 | return( S_ISDIR (statbuf.st_mode) ? 1 : 0 ); |
---|
4273 | } |
---|
4274 | } |
---|
4275 | |
---|
4276 | #ifdef CK_MKDIR |
---|
4277 | /* Some systems don't have mkdir(), e.g. Tandy Xenix 3.2.. */ |
---|
4278 | |
---|
4279 | /* Z M K D I R -- Create directory(s) if necessary */ |
---|
4280 | /* |
---|
4281 | Call with: |
---|
4282 | A pointer to a file specification that might contain directory |
---|
4283 | information. The filename is expected to be included. |
---|
4284 | If the file specification does not include any directory separators, |
---|
4285 | then it is assumed to be a plain file. |
---|
4286 | If one or more directories are included in the file specification, |
---|
4287 | this routine tries to create them if they don't already exist. |
---|
4288 | Returns: |
---|
4289 | 0 on success, i.e. the directory was created |
---|
4290 | -1 on failure to create the directory |
---|
4291 | */ |
---|
4292 | int |
---|
4293 | zmkdir(path) char *path; { |
---|
4294 | char *xp, *tp, c; |
---|
4295 | int x; |
---|
4296 | |
---|
4297 | x = strlen(path); |
---|
4298 | debug(F111,"zmkdir",path,x); |
---|
4299 | if (x < 1 || x > MAXPATH) /* Check length */ |
---|
4300 | return(-1); |
---|
4301 | if (!(tp = malloc(x+1))) /* Make a temporary copy */ |
---|
4302 | return(-1); |
---|
4303 | strcpy(tp,path); |
---|
4304 | #ifdef DTILDE |
---|
4305 | if (*tp == '~') { /* Starts with tilde? */ |
---|
4306 | xp = tilde_expand(tp); /* Attempt to expand tilde */ |
---|
4307 | if (*xp) { |
---|
4308 | char *zp; |
---|
4309 | debug(F110,"zmkdir tilde_expand",xp,0); |
---|
4310 | if (!(zp = malloc(strlen(xp) + 1))) { /* Make a place for it */ |
---|
4311 | free(tp); |
---|
4312 | tp = NULL; |
---|
4313 | return(-1); |
---|
4314 | } |
---|
4315 | free(tp); /* Free previous buffer */ |
---|
4316 | tp = zp; /* Point to new one */ |
---|
4317 | strcpy(tp,xp); /* Copy expanded name to new buffer */ |
---|
4318 | } |
---|
4319 | debug(F110,"zmkdir tp after tilde_expansion",tp,0); |
---|
4320 | } |
---|
4321 | #endif /* DTILDE */ |
---|
4322 | xp = tp; |
---|
4323 | if (ISDIRSEP(*xp)) /* Don't create root directory! */ |
---|
4324 | xp++; |
---|
4325 | |
---|
4326 | /* Go thru filespec from left to right... */ |
---|
4327 | |
---|
4328 | for (; *xp; xp++) { /* Create parts that don't exist */ |
---|
4329 | if (!ISDIRSEP(*xp)) /* Find next directory separator */ |
---|
4330 | continue; |
---|
4331 | c = *xp; /* Got one. */ |
---|
4332 | *xp = NUL; /* Make this the end of the string. */ |
---|
4333 | if (!isdir(tp)) { /* This directory exists already? */ |
---|
4334 | debug(F110,"zmkdir making",tp,0); |
---|
4335 | x = /* No, try to create it */ |
---|
4336 | #ifdef NOMKDIR |
---|
4337 | -1 /* Systems without mkdir() */ |
---|
4338 | #else |
---|
4339 | #ifdef OS2 /* OS/2 */ |
---|
4340 | _mkdir(tp) /* The IBM way */ |
---|
4341 | #else |
---|
4342 | mkdir(tp,0777) /* UNIX */ |
---|
4343 | #endif /* OS2 */ |
---|
4344 | #endif /* NOMKDIR */ |
---|
4345 | ; |
---|
4346 | if (x < 0) { |
---|
4347 | debug(F101,"zmkdir failed, errno","",errno); |
---|
4348 | free(tp); /* Free temporary buffer. */ |
---|
4349 | tp = NULL; |
---|
4350 | return(-1); /* Freturn failure code. */ |
---|
4351 | } |
---|
4352 | } |
---|
4353 | *xp = c; /* Replace the separator. */ |
---|
4354 | } |
---|
4355 | free(tp); /* Free temporary buffer. */ |
---|
4356 | return(0); /* Return success code. */ |
---|
4357 | } |
---|
4358 | #endif /* CK_MKDIR */ |
---|
4359 | |
---|
4360 | /* Z F S E E K -- Position input file pointer */ |
---|
4361 | /* |
---|
4362 | Call with: |
---|
4363 | Long int, 0-based, indicating desired position. |
---|
4364 | Returns: |
---|
4365 | 0 on success. |
---|
4366 | -1 on failure. |
---|
4367 | */ |
---|
4368 | #ifndef NORESEND |
---|
4369 | int |
---|
4370 | #ifdef CK_ANSIC |
---|
4371 | zfseek(long pos) |
---|
4372 | #else |
---|
4373 | zfseek(pos) long pos; |
---|
4374 | #endif /* CK_ANSIC */ |
---|
4375 | /* zfseek */ { |
---|
4376 | #ifdef NT |
---|
4377 | fpos_t fpos = pos ; |
---|
4378 | #endif /* NT */ |
---|
4379 | |
---|
4380 | zincnt = -1 ; /* must empty the input buffer */ |
---|
4381 | |
---|
4382 | debug(F101,"zfseek","",pos); |
---|
4383 | #ifdef NT |
---|
4384 | return(fsetpos(fp[ZIFILE], &fpos)?-1:0); |
---|
4385 | #else |
---|
4386 | return(fseek(fp[ZIFILE], pos, 0)?-1:0); |
---|
4387 | #endif |
---|
4388 | } |
---|
4389 | #endif /* NORESEND */ |
---|
4390 | |
---|
4391 | struct zfnfp * |
---|
4392 | zfnqfp(fname, buflen, buf) char * fname; int buflen; char * buf; { |
---|
4393 | int x = 0, y = 0; |
---|
4394 | char * xp; |
---|
4395 | static struct zfnfp fnfp; |
---|
4396 | |
---|
4397 | if (!fname) |
---|
4398 | return(NULL); |
---|
4399 | |
---|
4400 | /* initialize the data structure */ |
---|
4401 | fnfp.len = buflen; |
---|
4402 | fnfp.fpath = buf; |
---|
4403 | fnfp.fname = NULL; |
---|
4404 | |
---|
4405 | #ifdef OS2 |
---|
4406 | #ifdef NT |
---|
4407 | if ( GetFullPathName( fname, buflen, fnfp.fpath, &fnfp.fname ) ) |
---|
4408 | return(&fnfp); |
---|
4409 | else |
---|
4410 | #else /* NT */ |
---|
4411 | if (!DosQueryPathInfo(fname,5 /* Full Path Info */, fnfp.fpath,buflen)) { |
---|
4412 | x = strlen(fnfp.fpath); |
---|
4413 | for (x = x + 1; x >= 0; x--) /* Find where the filename starts */ |
---|
4414 | if (fnfp.fpath[x] == '/' |
---|
4415 | || fnfp.fpath[x] == '\\' |
---|
4416 | ) /* There is guaranteed to be one */ |
---|
4417 | fnfp.fname = fnfp.fpath + x; /* Got it, set pointer */ |
---|
4418 | return(&fnfp); /* and return. */ |
---|
4419 | } else |
---|
4420 | #endif /* NT */ |
---|
4421 | #else /* OS2 */ |
---|
4422 | |
---|
4423 | #ifdef DTILDE |
---|
4424 | if (*fname == '~') { /* Starts with tilde? */ |
---|
4425 | xp = tilde_expand(fname); /* Attempt to expand tilde */ |
---|
4426 | if (*xp) |
---|
4427 | fname = xp; |
---|
4428 | } |
---|
4429 | #endif /* DTILDE */ |
---|
4430 | |
---|
4431 | if (*fname == '/' |
---|
4432 | ) { /* Pathname is absolute */ |
---|
4433 | strncpy(buf,fname,buflen); |
---|
4434 | x = strlen(buf); |
---|
4435 | y = 0; |
---|
4436 | } else { /* Pathname is relative */ |
---|
4437 | char * p; |
---|
4438 | if (p = zgtdir()) { /* So get current directory */ |
---|
4439 | strncpy(buf,p,buflen); |
---|
4440 | x = strlen(buf); |
---|
4441 | buf[x++] = '/'; |
---|
4442 | buflen -= x; /* How much room left in buffer */ |
---|
4443 | if ((y = (int)strlen(fname)) > buflen) /* If enough room... */ |
---|
4444 | return(NULL); |
---|
4445 | strncpy(buf+x,fname,buflen); /* ... append the filename */ |
---|
4446 | } else { |
---|
4447 | return(NULL); |
---|
4448 | } |
---|
4449 | } |
---|
4450 | |
---|
4451 | for (x = x + y - 1; x > -1; x--) /* Find where the filename starts */ |
---|
4452 | if (buf[x] == '/' |
---|
4453 | ) { /* There is guaranteed to be one */ |
---|
4454 | fnfp.fname = buf + x; /* Got it, set pointer */ |
---|
4455 | return(&fnfp); /* and return. */ |
---|
4456 | } |
---|
4457 | #endif /* OS2 */ |
---|
4458 | return(NULL); |
---|
4459 | } |
---|
4460 | |
---|
4461 | #ifdef OS2 |
---|
4462 | |
---|
4463 | /* Z C H D S K -- Change currently selected disk device */ |
---|
4464 | |
---|
4465 | /* Returns -1 if error, otherwise 0 */ |
---|
4466 | |
---|
4467 | zchdsk(c) int c; { |
---|
4468 | int i = toupper(c) - 64; |
---|
4469 | return( _chdrive(i)); |
---|
4470 | } |
---|
4471 | |
---|
4472 | #undef stat |
---|
4473 | #ifdef __IBMC__STAT |
---|
4474 | #define stat(p, s) _stat(p, s) |
---|
4475 | #endif /* __IBMC__STAT */ |
---|
4476 | |
---|
4477 | os2stat(char *path, |
---|
4478 | #ifdef NT |
---|
4479 | struct _stat *st |
---|
4480 | #else |
---|
4481 | struct stat *st |
---|
4482 | #endif /* NT */ |
---|
4483 | ) { |
---|
4484 | char local[MAXPATH]; |
---|
4485 | int len; |
---|
4486 | |
---|
4487 | strcpy(local, path); |
---|
4488 | len = strlen(local); |
---|
4489 | |
---|
4490 | if ( len == 2 && local[1] == ':' ) |
---|
4491 | local[2] = DIRSEP, local[3] = 0; /* if drive only, append / */ |
---|
4492 | else if ( len == 0 ) |
---|
4493 | local[0] = DIRSEP, local[1] = 0; /* if empty path, take / instead */ |
---|
4494 | else if ( len > 1 && ISDIRSEP(local[len - 1]) && local[len - 2] != ':' ) |
---|
4495 | local[len - 1] = 0; /* strip trailing / except after d: */ |
---|
4496 | |
---|
4497 | #ifdef NT |
---|
4498 | return _stat(local, st); |
---|
4499 | #else /* NT */ |
---|
4500 | return stat(local, st); |
---|
4501 | #endif /* NT */ |
---|
4502 | } |
---|
4503 | |
---|
4504 | #ifdef CK_LABELED |
---|
4505 | /* O S 2 S E T L O N G N A M E -- Set .LONGNAME Extended Attribute */ |
---|
4506 | |
---|
4507 | /* Returns -1 if error, otherwise 0 */ |
---|
4508 | |
---|
4509 | int |
---|
4510 | os2setlongname( char * fn, char * ln ) { |
---|
4511 | EAOP2 FileInfoBuf; |
---|
4512 | ULONG FileInfoSize; |
---|
4513 | ULONG PathInfoFlags; |
---|
4514 | APIRET rc; |
---|
4515 | char FEA2List[1024]; |
---|
4516 | FEA2 * pfea2; |
---|
4517 | WORD * pEAdata; |
---|
4518 | |
---|
4519 | debug(F110,"os2setlongname: filename is",fn,0); |
---|
4520 | debug(F110,"os2setlongname: longname is",ln,0); |
---|
4521 | |
---|
4522 | FileInfoSize = sizeof( EAOP2 ); |
---|
4523 | PathInfoFlags = DSPI_WRTTHRU; /* complete write operation before return */ |
---|
4524 | |
---|
4525 | FileInfoBuf.fpGEA2List = 0; |
---|
4526 | FileInfoBuf.fpFEA2List = (PFEA2LIST) &FEA2List; |
---|
4527 | pfea2 = FileInfoBuf.fpFEA2List->list; |
---|
4528 | |
---|
4529 | pfea2->oNextEntryOffset = 0; |
---|
4530 | pfea2->fEA = 0; |
---|
4531 | pfea2->cbName = 9; /* length of ".LONGNAME" without \0 */ |
---|
4532 | pfea2->cbValue = strlen( ln ) + 2 * sizeof( WORD ); |
---|
4533 | strcpy( pfea2->szName, ".LONGNAME" ); |
---|
4534 | |
---|
4535 | pEAdata = (WORD *) pfea2->szName + 10/sizeof(WORD); |
---|
4536 | *pEAdata = EAT_ASCII; |
---|
4537 | pEAdata++; |
---|
4538 | *pEAdata = strlen( ln ); |
---|
4539 | pEAdata++; |
---|
4540 | strcpy( (char *) pEAdata, ln ); |
---|
4541 | pEAdata += (strlen( ln )+1)/sizeof(WORD); |
---|
4542 | |
---|
4543 | FileInfoBuf.fpFEA2List->cbList = (char *) pEAdata - |
---|
4544 | (char *) FileInfoBuf.fpFEA2List; |
---|
4545 | |
---|
4546 | rc = DosSetPathInfo( fn, 2, &FileInfoBuf, FileInfoSize, PathInfoFlags ); |
---|
4547 | debug(F101,"os2setlongname: rc=","",rc); |
---|
4548 | if ( !rc ) |
---|
4549 | return 0; |
---|
4550 | else |
---|
4551 | return -1; |
---|
4552 | } |
---|
4553 | |
---|
4554 | /* O S 2 G E T L O N G N A M E -- Get .LONGNAME Extended Attribute */ |
---|
4555 | |
---|
4556 | /* Returns -1 if error, otherwise 0 */ |
---|
4557 | |
---|
4558 | int |
---|
4559 | os2getlongname( char * fn, char ** ln ) { |
---|
4560 | static char * LongNameBuf = 0; |
---|
4561 | EAOP2 FileInfoBuf; |
---|
4562 | ULONG FileInfoSize; |
---|
4563 | ULONG PathInfoFlags; |
---|
4564 | APIRET rc; |
---|
4565 | char FEA2List[1024]; |
---|
4566 | FEA2 * pfea2; |
---|
4567 | char GEA2List[1024]; |
---|
4568 | GEA2 * pgea2; |
---|
4569 | WORD * pEAdata; |
---|
4570 | WORD LongNameLength; |
---|
4571 | |
---|
4572 | *ln = 0; |
---|
4573 | if ( !LongNameBuf ) |
---|
4574 | LongNameBuf = strdup( "Initialization of LongNameBuf" ); |
---|
4575 | debug(F110,"os2getlongname: filename is",fn,0); |
---|
4576 | |
---|
4577 | FileInfoSize = sizeof( EAOP2 ); |
---|
4578 | PathInfoFlags = DSPI_WRTTHRU; /* Complete write operation before return */ |
---|
4579 | |
---|
4580 | FileInfoBuf.fpGEA2List = (PGEA2LIST) &GEA2List; |
---|
4581 | FileInfoBuf.fpFEA2List = (PFEA2LIST) &FEA2List; |
---|
4582 | pgea2 = FileInfoBuf.fpGEA2List->list; |
---|
4583 | pfea2 = FileInfoBuf.fpFEA2List->list; |
---|
4584 | |
---|
4585 | pfea2->oNextEntryOffset = 0; |
---|
4586 | pfea2->fEA = 0; |
---|
4587 | pfea2->cbName = 9; /* Length of ".LONGNAME" without \0 */ |
---|
4588 | pfea2->cbValue = MAXPATH; |
---|
4589 | strcpy( pfea2->szName, ".LONGNAME" ); |
---|
4590 | |
---|
4591 | FileInfoBuf.fpGEA2List->cbList = sizeof(GEA2LIST) |
---|
4592 | + pgea2->cbName + 1; |
---|
4593 | pgea2->oNextEntryOffset = 0; |
---|
4594 | pgea2->cbName = pfea2->cbName; |
---|
4595 | strcpy(pgea2->szName,pfea2->szName); |
---|
4596 | |
---|
4597 | FileInfoBuf.fpFEA2List->cbList = 1024; |
---|
4598 | |
---|
4599 | rc = DosQueryPathInfo(fn,FIL_QUERYEASFROMLIST,&FileInfoBuf,FileInfoSize ); |
---|
4600 | LongNameLength = |
---|
4601 | *(WORD *)((char *)pfea2 + sizeof(FEA2) + pfea2->cbName + sizeof(WORD)); |
---|
4602 | debug(F101,"os2getlongname: rc=","",rc); |
---|
4603 | debug(F101," cbValue:","",pfea2->cbValue); |
---|
4604 | debug(F101," cbName:","",pfea2->cbName); |
---|
4605 | debug(F101," EA Value Length:","",LongNameLength ); |
---|
4606 | debug(F110," EA Value:",(char *)pfea2 + sizeof(FEA2) |
---|
4607 | + pfea2->cbName + (2 * sizeof(WORD)),0 ); |
---|
4608 | if ( rc ) { |
---|
4609 | return -1; |
---|
4610 | } else if ( pfea2->cbValue ) { |
---|
4611 | if (LongNameBuf) { |
---|
4612 | free(LongNameBuf); |
---|
4613 | LongNameBuf = NULL; |
---|
4614 | } |
---|
4615 | LongNameBuf = (char *) malloc( LongNameLength + 1 ); |
---|
4616 | if (LongNameBuf) { |
---|
4617 | strncpy(LongNameBuf, (char *)pfea2 + sizeof(FEA2) |
---|
4618 | + pfea2->cbName + (2 * sizeof(WORD)), |
---|
4619 | LongNameLength |
---|
4620 | ); |
---|
4621 | LongNameBuf[LongNameLength] = '\0'; |
---|
4622 | debug(F110,"os2getlongname: longname is",LongNameBuf,0); |
---|
4623 | } else |
---|
4624 | debug(F100,"os2getlongname: malloc failed","",0); |
---|
4625 | } else { |
---|
4626 | if ( LongNameBuf ) |
---|
4627 | free( LongNameBuf ); |
---|
4628 | LongNameBuf = strdup( "" ); |
---|
4629 | debug(F110, |
---|
4630 | "os2getlongname: there is no longname attribute", |
---|
4631 | LongNameBuf, |
---|
4632 | 0 |
---|
4633 | ); |
---|
4634 | } |
---|
4635 | *ln = LongNameBuf; |
---|
4636 | return 0; |
---|
4637 | } |
---|
4638 | |
---|
4639 | |
---|
4640 | _PROTOTYP( VOID GetMem, (PVOID *, ULONG) ); |
---|
4641 | |
---|
4642 | /* O S 2 G E T E A S - Get all OS/2 Extended Attributes */ |
---|
4643 | |
---|
4644 | /* Returns 0 on success, -1 on failure */ |
---|
4645 | |
---|
4646 | int |
---|
4647 | os2geteas( char * name ) { |
---|
4648 | CHAR *pAllocc=NULL; /* Holds the FEA struct returned by DosEnumAttribute */ |
---|
4649 | /* used to create the GEA2LIST for DosQueryPathInfo */ |
---|
4650 | |
---|
4651 | ULONG ulEntryNum = 1; /* count of current EA to read (1-relative) */ |
---|
4652 | ULONG ulEnumCnt; /* Number of EAs for Enum to return, always 1 */ |
---|
4653 | |
---|
4654 | ULONG FEAListSize = sizeof(ULONG);/* starting size of buffer necessary to |
---|
4655 | hold all FEA blocks */ |
---|
4656 | ULONG GEAListSize = MAXEACOUNT * sizeof(GEA2) + sizeof(ULONG); |
---|
4657 | |
---|
4658 | FEA2 *pFEA; /* Used to read from Enum's return buffer */ |
---|
4659 | GEA2 *pGEA, *pLastGEAIn; /* Used to write to pGEAList buffer */ |
---|
4660 | GEA2LIST *pGEAList;/*Ptr used to set up buffer for DosQueryPathInfo call */ |
---|
4661 | EAOP2 eaopGet; /* Used to call DosQueryPathInfo */ |
---|
4662 | APIRET rc; |
---|
4663 | int offset; |
---|
4664 | |
---|
4665 | /* Allocate enough room for any GEA List */ |
---|
4666 | GetMem((PPVOID)&pAllocc, MAX_GEA); |
---|
4667 | pFEA = (FEA2 *) pAllocc; /* pFEA always uses pAlloc buffer */ |
---|
4668 | |
---|
4669 | GetMem((PPVOID)&pGEAList, GEAListSize ); /* alloc buffer for GEA2 list */ |
---|
4670 | pGEAList->cbList = GEAListSize; |
---|
4671 | pGEA = pGEAList->list; |
---|
4672 | pLastGEAIn = 0; |
---|
4673 | |
---|
4674 | if ( !pAllocc || ! pGEAList ) { |
---|
4675 | FreeMem( pAllocc ); |
---|
4676 | FreeMem( pGEAList ); |
---|
4677 | return -1; |
---|
4678 | } |
---|
4679 | if ( pFEAList ) { |
---|
4680 | FreeMem( pFEAList ); |
---|
4681 | pFEAList = 0; |
---|
4682 | } |
---|
4683 | while(TRUE) { /* Loop continues until there are no more EAs */ |
---|
4684 | ulEnumCnt = 1; /* Only want to get one EA at a time */ |
---|
4685 | if(DosEnumAttribute(Ref_ASCIIZ, /* Read into pAlloc Buffer */ |
---|
4686 | name, /* Note that this does not */ |
---|
4687 | ulEntryNum, /* get the aValue field, */ |
---|
4688 | pAllocc, /* so DosQueryPathInfo must*/ |
---|
4689 | MAX_GEA, /* be called to get it. */ |
---|
4690 | &ulEnumCnt, |
---|
4691 | (LONG) GetInfoLevel1)) { |
---|
4692 | FreeMem(pGEAList); /* There was some sort of error */ |
---|
4693 | FreeMem(pAllocc); |
---|
4694 | return (-1); |
---|
4695 | } |
---|
4696 | if(ulEnumCnt != 1) /* All the EAs have been read */ |
---|
4697 | break; |
---|
4698 | |
---|
4699 | ulEntryNum++; |
---|
4700 | FEAListSize += sizeof(FEA2LIST) + pFEA->cbName+1 + |
---|
4701 | pFEA->cbValue + 4; |
---|
4702 | |
---|
4703 | if (pLastGEAIn) |
---|
4704 | pLastGEAIn->oNextEntryOffset = (BYTE *)pGEA - (BYTE *)pLastGEAIn; |
---|
4705 | pLastGEAIn = pGEA; |
---|
4706 | |
---|
4707 | pGEA->oNextEntryOffset = 0L; |
---|
4708 | pGEA->cbName = pFEA->cbName; |
---|
4709 | strcpy(pGEA->szName, pFEA->szName); |
---|
4710 | |
---|
4711 | /* must align GEA2 blocks on double word boundaries */ |
---|
4712 | offset = sizeof(GEA2) + pGEA->cbName + 1; |
---|
4713 | offset += ( offset % 4 ? (4 - offset % 4) : 0 ); |
---|
4714 | pGEA = (GEA2 *) ((BYTE *) pGEA + offset); |
---|
4715 | } |
---|
4716 | debug(F111,"os2geteas: EA count",name,ulEntryNum-1); |
---|
4717 | GetMem( (PPVOID) &pFEAList, FEAListSize ); |
---|
4718 | pFEAList->cbList = FEAListSize; |
---|
4719 | |
---|
4720 | eaopGet.fpGEA2List = pGEAList; |
---|
4721 | eaopGet.fpFEA2List = pFEAList; |
---|
4722 | |
---|
4723 | rc = DosQueryPathInfo(name, /* Get the complete EA info */ |
---|
4724 | GetInfoLevel3, |
---|
4725 | (PVOID) &eaopGet, |
---|
4726 | sizeof(EAOP2)); |
---|
4727 | |
---|
4728 | debug(F111,"os2geteas: DosQueryPathInfo",name,rc); |
---|
4729 | FreeMem( pGEAList ); |
---|
4730 | FreeMem( pAllocc ); |
---|
4731 | return ( rc ? -1 : 0 ); |
---|
4732 | } |
---|
4733 | |
---|
4734 | /* O S 2 S E T E A S - Set all OS/2 Extended Attributes */ |
---|
4735 | |
---|
4736 | /* Returns 0 on success, -1 on failure */ |
---|
4737 | |
---|
4738 | int |
---|
4739 | os2seteas( char * name ) { |
---|
4740 | EAOP2 eaopSet; /* Used to call DosSetPathInfo */ |
---|
4741 | APIRET rc; |
---|
4742 | |
---|
4743 | if ( !pFEAList ) { |
---|
4744 | debug(F100,"os2seteas: EA List is empty","",0); |
---|
4745 | return 0; |
---|
4746 | } |
---|
4747 | eaopSet.fpGEA2List = 0; |
---|
4748 | eaopSet.fpFEA2List = pFEAList; |
---|
4749 | |
---|
4750 | rc = DosSetPathInfo(name, /* Set the EA info */ |
---|
4751 | SetInfoLevel2, |
---|
4752 | (PVOID) &eaopSet, |
---|
4753 | sizeof(EAOP2), |
---|
4754 | DSPI_WRTTHRU); |
---|
4755 | debug(F111,"os2seteas: DosSetPathInfo",name,rc); |
---|
4756 | |
---|
4757 | if ( !rc ) { |
---|
4758 | FreeMem( pFEAList ); |
---|
4759 | pFEAList = 0; |
---|
4760 | } |
---|
4761 | return ( rc ? -1 : 0 ); |
---|
4762 | } |
---|
4763 | |
---|
4764 | /* O S 2 G E T A T T R - Get all OS/2 Normal Attributes */ |
---|
4765 | |
---|
4766 | /* Returns 0 on success, -1 on failure */ |
---|
4767 | |
---|
4768 | int |
---|
4769 | os2getattr( char * name ) { |
---|
4770 | FILESTATUS3 FileInfoBuf; |
---|
4771 | APIRET rc; |
---|
4772 | |
---|
4773 | rc = DosQueryPathInfo(name, /* Get the complete EA info */ |
---|
4774 | GetInfoLevel1, |
---|
4775 | (PVOID) &FileInfoBuf, |
---|
4776 | sizeof(FILESTATUS3)); |
---|
4777 | |
---|
4778 | if ( !rc ) { |
---|
4779 | os2attrs = FileInfoBuf.attrFile; |
---|
4780 | return 0; |
---|
4781 | } |
---|
4782 | else { |
---|
4783 | os2attrs = FILE_NORMAL; |
---|
4784 | return -1; |
---|
4785 | } |
---|
4786 | } |
---|
4787 | |
---|
4788 | /* O S 2 S E T A T T R - Set all OS/2 Normal Attributes */ |
---|
4789 | |
---|
4790 | /* Returns 0 on success, -1 on failure */ |
---|
4791 | |
---|
4792 | int |
---|
4793 | os2setattr( char * name ) { |
---|
4794 | FILESTATUS3 FileInfoBuf; |
---|
4795 | APIRET rc; |
---|
4796 | |
---|
4797 | rc = DosQueryPathInfo(name, /* Get the complete EA info */ |
---|
4798 | GetInfoLevel1, |
---|
4799 | (PVOID) &FileInfoBuf, |
---|
4800 | sizeof(FILESTATUS3)); |
---|
4801 | |
---|
4802 | if ( !rc ) { |
---|
4803 | FileInfoBuf.attrFile = lf_opts & os2attrs; |
---|
4804 | rc = DosSetPathInfo( name, |
---|
4805 | GetInfoLevel1, |
---|
4806 | (PVOID) &FileInfoBuf, |
---|
4807 | sizeof(FILESTATUS3), |
---|
4808 | 0); |
---|
4809 | if ( !rc ) |
---|
4810 | return 0; |
---|
4811 | } |
---|
4812 | return -1; |
---|
4813 | } |
---|
4814 | |
---|
4815 | /****************************************************************\ |
---|
4816 | * * |
---|
4817 | * Name: GetMem (ppv, cb) * |
---|
4818 | * * |
---|
4819 | * Purpose: This routine returns a pointer to a available* * |
---|
4820 | * memory space. * |
---|
4821 | * * |
---|
4822 | * Usage : * |
---|
4823 | * Method : Routine should be bullet proof as it does its own * |
---|
4824 | * error checking. It assumes that hwnd points to the * |
---|
4825 | * correct window with the name listbox in it. * |
---|
4826 | * * |
---|
4827 | * Returns: The current EA as determined by querying the l-box * |
---|
4828 | * selector. * |
---|
4829 | * * |
---|
4830 | \****************************************************************/ |
---|
4831 | VOID GetMem (PVOID *ppv, ULONG cb) { |
---|
4832 | BOOL f; |
---|
4833 | |
---|
4834 | f =(BOOL) DosAllocMem(ppv, cb, fPERM|PAG_COMMIT); |
---|
4835 | if (f) { |
---|
4836 | *ppv = NULL; |
---|
4837 | return; |
---|
4838 | } |
---|
4839 | return; |
---|
4840 | } |
---|
4841 | |
---|
4842 | extern CHAR os2version[50]; |
---|
4843 | extern long vernum; |
---|
4844 | |
---|
4845 | /* D O _ L A B E L _ S E N D - Generate Label Header from EA List */ |
---|
4846 | |
---|
4847 | /* Return 0 on success, -1 on failure */ |
---|
4848 | |
---|
4849 | int |
---|
4850 | do_label_send(char * name) { |
---|
4851 | char scratch[100]; |
---|
4852 | long buffreespace = INBUFSIZE; |
---|
4853 | long easleft = 0; |
---|
4854 | long memtocpy = 0; |
---|
4855 | static BYTE * p = 0; |
---|
4856 | |
---|
4857 | debug(F110,"do_label_send",name,0); |
---|
4858 | if ( !pFEAList ) { |
---|
4859 | debug(F101," no EA list","",pFEAList); |
---|
4860 | return 0; |
---|
4861 | } |
---|
4862 | |
---|
4863 | if ( !p ) { |
---|
4864 | debug(F100,"do_label_send: generate header","",0); |
---|
4865 | zinptr += sprintf(zinptr,"KERMIT LABELED FILE:02UO04VERS"); |
---|
4866 | |
---|
4867 | sprintf(scratch,"%d",strlen(get_os2_vers())); |
---|
4868 | zinptr += sprintf(zinptr,"%02d%d%s", |
---|
4869 | strlen(scratch), |
---|
4870 | strlen(get_os2_vers()), |
---|
4871 | get_os2_vers()); |
---|
4872 | |
---|
4873 | sprintf(scratch,"%d",vernum); |
---|
4874 | zinptr += sprintf(zinptr,"05KVERS02%02d%d", strlen(scratch), vernum); |
---|
4875 | |
---|
4876 | sprintf(scratch,"%d",strlen(name)); |
---|
4877 | zinptr += sprintf(zinptr,"08FILENAME%02d%d%s", strlen(scratch), |
---|
4878 | strlen(name), name); |
---|
4879 | |
---|
4880 | zinptr += sprintf(zinptr,"04ATTR%02d",sizeof(ULONG)); |
---|
4881 | memcpy( zinptr, (BYTE *) &os2attrs, sizeof(ULONG) ); |
---|
4882 | zinptr += sizeof(ULONG); |
---|
4883 | |
---|
4884 | sprintf( scratch, "%d", pFEAList->cbList ); |
---|
4885 | zinptr += sprintf(zinptr,"09EABUFSIZE%02d%ld", strlen(scratch), |
---|
4886 | pFEAList->cbList); |
---|
4887 | p = (BYTE *) pFEAList; |
---|
4888 | buffreespace -= (BYTE *) zinptr - (BYTE *) zinbuffer; |
---|
4889 | } |
---|
4890 | |
---|
4891 | easleft = pFEAList->cbList - ( (BYTE *) p - (BYTE *) pFEAList ); |
---|
4892 | memtocpy = buffreespace > easleft ? easleft : buffreespace; |
---|
4893 | memcpy( zinptr, p, memtocpy ); |
---|
4894 | zinptr = (BYTE *) zinptr + memtocpy; |
---|
4895 | p = (BYTE *) p + memtocpy; |
---|
4896 | buffreespace -= memtocpy; |
---|
4897 | |
---|
4898 | if ( buffreespace > 0 ) { |
---|
4899 | p = 0; |
---|
4900 | FreeMem( pFEAList ); |
---|
4901 | pFEAList = 0; |
---|
4902 | debug(F100,"do_label_send: terminate header","",0); |
---|
4903 | } |
---|
4904 | zincnt = (zinptr - zinbuffer); /* Size of this beast */ |
---|
4905 | return(0); |
---|
4906 | } |
---|
4907 | |
---|
4908 | /* D O _ L A B E L _ R E C V - Receive label info and create EA List */ |
---|
4909 | |
---|
4910 | /* Return 0 on success, -1 on failure */ |
---|
4911 | |
---|
4912 | int |
---|
4913 | do_label_recv() { |
---|
4914 | char *recv_ptr = zoutbuffer; |
---|
4915 | int lblen; |
---|
4916 | char buffer[16]; |
---|
4917 | size_t memtocpy, lefttocpy; |
---|
4918 | static BYTE * pFEA = 0; |
---|
4919 | |
---|
4920 | if ( !pFEAList |
---|
4921 | && strncmp(zoutbuffer,"KERMIT LABELED FILE:02UO04VERS",30) != 0) { |
---|
4922 | debug(F100,"do_label_recv: not a labeled file","",0); |
---|
4923 | return(0); /* Just continue if unlabeled */ |
---|
4924 | } |
---|
4925 | |
---|
4926 | if ( !pFEAList ) { |
---|
4927 | recv_ptr += 30; /* start at front of buffer */ |
---|
4928 | zoutcnt -= 30; |
---|
4929 | |
---|
4930 | /* get length of length of OS/2 version */ |
---|
4931 | memcpy(buffer, recv_ptr, 2); |
---|
4932 | recv_ptr += 2; |
---|
4933 | zoutcnt -= 2; |
---|
4934 | buffer[2] = '\0'; |
---|
4935 | lblen = atoi(buffer); |
---|
4936 | |
---|
4937 | /* get length of OS/2 version */ |
---|
4938 | memcpy(buffer, recv_ptr, lblen); |
---|
4939 | recv_ptr += lblen; |
---|
4940 | zoutcnt -= lblen; |
---|
4941 | buffer[lblen] = '\0'; |
---|
4942 | lblen = atoi(buffer); |
---|
4943 | |
---|
4944 | /* get os2 version */ |
---|
4945 | memcpy(buffer, recv_ptr, lblen); |
---|
4946 | recv_ptr += lblen; |
---|
4947 | zoutcnt -= lblen; |
---|
4948 | buffer[lblen] = '\0'; |
---|
4949 | debug(F111," file created under OS/2: ",buffer,lblen); |
---|
4950 | |
---|
4951 | /* check sync with Kermit Version */ |
---|
4952 | memcpy(buffer, recv_ptr, 7); |
---|
4953 | recv_ptr += 7; |
---|
4954 | zoutcnt -= 7; |
---|
4955 | if (strncmp(buffer, "05KVERS", 7) != 0) { |
---|
4956 | debug(F111," lost sync at KVERS",recv_ptr-7,zoutcnt+7); |
---|
4957 | return(-1); |
---|
4958 | } |
---|
4959 | |
---|
4960 | /* get length of length of C-Kermit version */ |
---|
4961 | memcpy(buffer, recv_ptr, 2); |
---|
4962 | recv_ptr += 2; |
---|
4963 | zoutcnt -= 2; |
---|
4964 | buffer[2] = '\0'; |
---|
4965 | lblen = atoi(buffer); |
---|
4966 | |
---|
4967 | /* get length of C-Kermit version */ |
---|
4968 | memcpy(buffer, recv_ptr, lblen); |
---|
4969 | recv_ptr += lblen; |
---|
4970 | zoutcnt -= lblen; |
---|
4971 | buffer[lblen] = '\0'; |
---|
4972 | lblen = atoi(buffer); |
---|
4973 | |
---|
4974 | /* get C-Kermit version */ |
---|
4975 | memcpy(buffer, recv_ptr, lblen); |
---|
4976 | recv_ptr += lblen; |
---|
4977 | zoutcnt -= lblen; |
---|
4978 | buffer[lblen] = '\0'; |
---|
4979 | debug(F111," file created with OS/2 C-Kermit: ",buffer,lblen); |
---|
4980 | |
---|
4981 | /* check sync with FILENAME */ |
---|
4982 | memcpy(buffer, recv_ptr, 10); |
---|
4983 | recv_ptr += 10; |
---|
4984 | zoutcnt -= 10; |
---|
4985 | if (strncmp(buffer, "08FILENAME", 10) != 0) { |
---|
4986 | debug(F111," lost sync at FILENAME",recv_ptr-10,zoutcnt+10); |
---|
4987 | return(-1); |
---|
4988 | } |
---|
4989 | |
---|
4990 | /* get length of length of Filename */ |
---|
4991 | memcpy(buffer, recv_ptr, 2); |
---|
4992 | recv_ptr += 2; |
---|
4993 | zoutcnt -= 2; |
---|
4994 | buffer[2] = '\0'; |
---|
4995 | lblen = atoi(buffer); |
---|
4996 | |
---|
4997 | /* get length of File Name */ |
---|
4998 | memcpy(buffer, recv_ptr, lblen); |
---|
4999 | recv_ptr += lblen; |
---|
5000 | zoutcnt -= lblen; |
---|
5001 | buffer[lblen] = '\0'; |
---|
5002 | lblen = atoi(buffer); |
---|
5003 | |
---|
5004 | /* get File Name */ |
---|
5005 | memcpy(buffer, recv_ptr, lblen); |
---|
5006 | recv_ptr += lblen; |
---|
5007 | zoutcnt -= lblen; |
---|
5008 | buffer[lblen] = '\0'; |
---|
5009 | debug(F111," file sent with name: ",buffer,lblen); |
---|
5010 | |
---|
5011 | /* check sync with ATTR */ |
---|
5012 | memcpy(buffer, recv_ptr, 6); |
---|
5013 | recv_ptr += 6; |
---|
5014 | zoutcnt -= 6; |
---|
5015 | if (strncmp(buffer, "04ATTR", 6) != 0) { |
---|
5016 | debug(F111," lost sync at ATTR",recv_ptr-6,zoutcnt+6); |
---|
5017 | return(-1); |
---|
5018 | } |
---|
5019 | |
---|
5020 | /* get length of attributes - should be sizeof(ULONG) */ |
---|
5021 | memcpy(buffer, recv_ptr, 2); |
---|
5022 | recv_ptr += 2; |
---|
5023 | zoutcnt -= 2; |
---|
5024 | buffer[2] = '\0'; |
---|
5025 | lblen = atoi(buffer); |
---|
5026 | if ( lblen != sizeof(ULONG) ) { |
---|
5027 | debug(F101," Attributes have wrong length","",lblen); |
---|
5028 | return(-1); |
---|
5029 | } |
---|
5030 | |
---|
5031 | /* get attributes */ |
---|
5032 | memcpy(&os2attrs, recv_ptr, sizeof(ULONG)); |
---|
5033 | recv_ptr += sizeof(ULONG); |
---|
5034 | zoutcnt -= sizeof(ULONG); |
---|
5035 | |
---|
5036 | /* check sync with EABUFSIZE */ |
---|
5037 | memcpy(buffer, recv_ptr, 11); |
---|
5038 | recv_ptr += 11; |
---|
5039 | zoutcnt -= 11; |
---|
5040 | if (strncmp(buffer, "09EABUFSIZE", 11) != 0) { |
---|
5041 | debug(F111," lost sync at EABUFSIZE",recv_ptr-11,zoutcnt+11); |
---|
5042 | return(-1); |
---|
5043 | } |
---|
5044 | |
---|
5045 | /* get length of length of EA Buffer Size */ |
---|
5046 | memcpy(buffer, recv_ptr, 2); |
---|
5047 | recv_ptr += 2; |
---|
5048 | zoutcnt -= 2; |
---|
5049 | buffer[2] = '\0'; |
---|
5050 | lblen = atoi(buffer); |
---|
5051 | |
---|
5052 | /* get length of EA Buffer Size */ |
---|
5053 | memcpy(buffer, recv_ptr, lblen); |
---|
5054 | recv_ptr += lblen; |
---|
5055 | zoutcnt -= lblen; |
---|
5056 | buffer[lblen] = '\0'; |
---|
5057 | lblen = atoi(buffer); |
---|
5058 | debug(F101," EA Buffer Size:","",lblen); |
---|
5059 | |
---|
5060 | GetMem( (PPVOID) &pFEAList, (ULONG) lblen ); |
---|
5061 | if ( !pFEAList ) { |
---|
5062 | debug(F101," pFEAList","",pFEAList); |
---|
5063 | return -1; |
---|
5064 | } |
---|
5065 | pFEAList->cbList = lblen; |
---|
5066 | pFEA = (BYTE *) pFEAList; |
---|
5067 | } |
---|
5068 | |
---|
5069 | if ( pFEAList && pFEA ) { |
---|
5070 | /* get EA Buffer */ |
---|
5071 | lefttocpy = pFEAList->cbList - ( (BYTE *) pFEA - (BYTE *) pFEAList ); |
---|
5072 | memtocpy = ( zoutcnt < lefttocpy ? zoutcnt : lefttocpy ); |
---|
5073 | memcpy(pFEA, recv_ptr, memtocpy); |
---|
5074 | recv_ptr += memtocpy; |
---|
5075 | zoutcnt -= memtocpy; |
---|
5076 | pFEA += memtocpy; |
---|
5077 | debug(F101," memtocpy","",memtocpy); |
---|
5078 | debug(F101," zoutcnt","",zoutcnt); |
---|
5079 | |
---|
5080 | if ( pFEA == ( (BYTE *) pFEAList + pFEAList->cbList ) ) { |
---|
5081 | pFEA = 0; /* we are done copying the EA's to the EA List */ |
---|
5082 | debug(F100," done copying EA's","",0); |
---|
5083 | } |
---|
5084 | } |
---|
5085 | |
---|
5086 | /* if we have processed some of the data in the output buffer */ |
---|
5087 | /* then move the data in the buffer so that it is properly */ |
---|
5088 | /* aligned with the beginning of the buffer and reset the ptr */ |
---|
5089 | if ( recv_ptr != zoutbuffer ) { |
---|
5090 | memmove(zoutbuffer, recv_ptr, zoutcnt); |
---|
5091 | if ( pFEA ) { |
---|
5092 | zoutptr = zoutbuffer + zoutcnt ; |
---|
5093 | return(1); /* Go fill some more */ |
---|
5094 | } |
---|
5095 | } |
---|
5096 | return (0); |
---|
5097 | } |
---|
5098 | #endif /* CK_LABELED */ |
---|
5099 | |
---|
5100 | #endif /* OS2 */ |
---|