home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / zip19 / part02 < prev    next >
Encoding:
Text File  |  1992-08-22  |  60.4 KB  |  2,184 lines

  1. Newsgroups: comp.sources.misc
  2. From: zip-bugs@cs.ucla.edu (Info-ZIP group)
  3. Subject:  v31i094:  zip19 - Info-ZIP portable Zip, version 1.9, Part02/11
  4. Message-ID: <1992Aug23.064513.28972@sparky.imd.sterling.com>
  5. X-Md4-Signature: cf491d96f8441d411222c18f4edf15b0
  6. Date: Sun, 23 Aug 1992 06:45:13 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: zip-bugs@cs.ucla.edu (Info-ZIP group)
  10. Posting-number: Volume 31, Issue 94
  11. Archive-name: zip19/part02
  12. Supersedes: zip: Volume 23, Issue 88-96
  13. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, XOS, !AMIGA, ATARI, symlink, SGI, DEC, Cray, Convex, Amdahl, Sun, PC
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  atari/stzip.lnk fileio.c
  22. # Wrapped by kent@sparky on Sun Aug 23 01:00:42 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 11)."'
  26. if test -f 'atari/stzip.lnk' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'atari/stzip.lnk'\"
  28. else
  29.   echo shar: Extracting \"'atari/stzip.lnk'\" \(180 characters\)
  30.   sed "s/^X//" >'atari/stzip.lnk' <<'END_OF_FILE'
  31. X\TC\lib\c0.o
  32. Xzip.o
  33. X\TC\lib\tcstdlib.lib
  34. Xatari.o
  35. Xzipfile.o
  36. Xzipup.o
  37. Xfileio.o
  38. Xutil.o
  39. Xglobals.o
  40. Xdeflate.o
  41. Xtrees.o
  42. Xbits.o
  43. X\TC\lib\tcstdlib.lib
  44. X\TC\lib\tcextlib.lib
  45. X\TC\lib\tctoslib.lib
  46. END_OF_FILE
  47.   if test 180 -ne `wc -c <'atari/stzip.lnk'`; then
  48.     echo shar: \"'atari/stzip.lnk'\" unpacked with wrong size!
  49.   fi
  50.   # end of 'atari/stzip.lnk'
  51. fi
  52. if test -f 'fileio.c' -a "${1}" != "-c" ; then 
  53.   echo shar: Will not clobber existing file \"'fileio.c'\"
  54. else
  55.   echo shar: Extracting \"'fileio.c'\" \(57097 characters\)
  56.   sed "s/^X//" >'fileio.c' <<'END_OF_FILE'
  57. X/*
  58. X
  59. X Copyright (C) 1990-1992 Mark Adler, Richard B. Wales, Jean-loup Gailly,
  60. X Kai Uwe Rommel and Igor Mandrichenko.
  61. X Permission is granted to any individual or institution to use, copy, or
  62. X redistribute this software so long as all of the original files are included
  63. X unmodified, that it is not sold for profit, and that this copyright notice
  64. X is retained.
  65. X
  66. X*/
  67. X
  68. X/*
  69. X *  fileio.c by Mark Adler.
  70. X */
  71. X
  72. X#include "zip.h"
  73. X
  74. X#include <time.h>
  75. X
  76. X#ifdef WIN32
  77. X#  include <sys/utime.h>
  78. X#  include <windows.h> /* for findfirst/findnext */
  79. X#endif
  80. X
  81. X#ifdef MACOS
  82. X#  define EXDEV 1
  83. X#endif
  84. X
  85. X#ifdef OSF
  86. X#  define EXDEV 18    /* avoid a bug in the DEC OSF/1 header files. */
  87. X#else
  88. X#  include <errno.h>
  89. X#endif
  90. X
  91. X#ifdef MINIX
  92. X#  ifdef S_IWRITE
  93. X#    undef S_IWRITE
  94. X#  endif /* S_IWRITE */
  95. X#  define S_IWRITE S_IWUSR
  96. X#endif /* S_IWUSR */
  97. X
  98. X#ifdef ATARI_ST
  99. X#  undef MSDOS
  100. X#endif
  101. X
  102. X#ifdef MSDOS
  103. X#  include <io.h>
  104. X#  if (defined(__TURBOC__) || defined(__GO32__))
  105. X#    include <dir.h>
  106. X#  else /* !__TURBOC__ */
  107. X#    if !defined(__EMX__) && !defined(__WATCOMC__)
  108. X#      include <direct.h>
  109. X#    endif
  110. X#  endif /* ?__TURBOC__ */
  111. X#  define link rename
  112. X#  ifdef OS2
  113. X#    define MATCH shmatch
  114. X#  else /* !OS2 */
  115. X#    define MATCH dosmatch
  116. X#  endif /* ?OS2 */
  117. X#else /* !MSDOS */
  118. X   extern int errno;    /* error number from system functions */
  119. X#  ifdef VMS
  120. X#    define RMDIR
  121. X#    define link rename
  122. X#    include "VMSmunch.h"
  123. X#  endif /* VMS */
  124. X#  ifdef MACOS
  125. X#    define link rename
  126. X#    define mktemp tmpnam
  127. X#  endif
  128. X#  define MATCH shmatch
  129. X#endif /* ?MSDOS */
  130. X
  131. X#ifdef ATARI_ST
  132. X#  define MSDOS 1
  133. X#endif
  134. X
  135. X#ifdef UTS
  136. X#  define RMDIR
  137. X#endif /* UTS */
  138. X
  139. X
  140. X/* Extra malloc() space in names for cutpath() */
  141. X#ifdef VMS
  142. X#  define PAD 3         /* may have to change .FOO] to ]FOO.DIR */
  143. X#else /* !VMS */
  144. X#  define PAD 0
  145. X#endif /* ?VMS */
  146. X
  147. X
  148. X/* For now, assume DIRENT implies System V implies TERMIO */
  149. X#if defined(DIRENT) && !defined(MINIX) && !defined(TERMIO)
  150. X#  define TERMIO
  151. X#endif
  152. X
  153. X
  154. X#ifdef CRYPT
  155. X#  ifdef MSVMS
  156. X#    ifdef MSDOS
  157. X#      ifdef __EMX__
  158. X#        define getch() _read_kbd(0, 1, 0)
  159. X#      else
  160. X#        ifdef __GO32__
  161. X#          include <pc.h>
  162. X#          define getch() getkey()
  163. X#        else
  164. X#          include <conio.h>
  165. X#        endif
  166. X#      endif
  167. X#    else /* !MSDOS */
  168. X#      define getch() getc(stderr)
  169. X#      define echoff(f) echo(0)   /* for echo control */
  170. X#      define echon()   echo(1)
  171. X#      include <iodef.h>
  172. X#      include <ttdef.h>
  173. X#      if !defined(SS$_NORMAL)
  174. X#        define SS$_NORMAL 1   /* only thing we need from <ssdef.h> */
  175. X#      endif
  176. X#    endif /* ?MSDOS */
  177. X#  else /* !MSVMS */
  178. X#    ifdef TERMIO       /* Amdahl, Cray, all SysV? */
  179. X#      ifdef CONVEX
  180. X#        include <sys/termios.h>
  181. X#        include <sgtty.h>
  182. X#        define O_BINARY 0
  183. X#      else /* !CONVEX */
  184. X#        ifdef LINUX 
  185. X#          include <termios.h>
  186. X#        else /* !LINUX */
  187. X#          include <sys/termio.h>
  188. X#        endif /* ?LINUX */
  189. X#        define sgttyb termio
  190. X#        define sg_flags c_lflag
  191. X         int ioctl OF((int, int, voidp *));
  192. X#      endif /* ?CONVEX */
  193. X#      define GTTY(f,s) ioctl(f,TCGETA,s)
  194. X#      define STTY(f,s) ioctl(f,TCSETAW,s)
  195. X#    else /* !TERMIO */
  196. X#      ifndef MINIX
  197. X#        include <sys/ioctl.h>
  198. X#      endif /* !MINIX */
  199. X#      include <sgtty.h>
  200. X       int gtty OF((int, struct sgttyb *));
  201. X       int stty OF((int, struct sgttyb *));
  202. X#      define GTTY gtty
  203. X#      define STTY stty
  204. X#    endif /* ?TERMIO */
  205. X     int isatty OF((int));
  206. X     char *ttyname OF((int));
  207. X     int open OF((char *, int, ...));
  208. X     int close OF((int));
  209. X     int read OF((int, voidp *, int));
  210. X#  endif /* ?MSVMS */
  211. X#endif /* ?CRYPT */
  212. X
  213. X#ifdef VMS
  214. X#  include <descrip.h>
  215. X#  include <rms.h>
  216. X#endif
  217. X
  218. X/* For directory access. (This is getting rather messy. Cleanup
  219. X * scheduled for version 17.9.)
  220. X */
  221. X#ifndef UTIL
  222. X
  223. X#ifdef SYSV                     /* use readdir()  */
  224. X#  include <dirent.h>
  225. X#  define dstrm DIR
  226. X#  define direct dirent
  227. X#else
  228. X
  229. X#ifdef DIRENT                   /* use getdents() */
  230. X#  if defined(MINIX) || defined(OSF)
  231. X#    include <dirent.h>
  232. X#  else /* !MINIX */
  233. X#    include <sys/dirent.h>
  234. X#  endif /* ?MINIX */
  235. X#  define direct dirent
  236. X#  ifdef MINIX
  237. X     int getdents OF((int, char *, unsigned));
  238. X#  else /* !MINIX */
  239. X     int getdents OF((int, char *, int));
  240. X#  endif /* ?MINIX */
  241. X#  define DBSZ 4096     /* This has to be bigger than a directory block */
  242. X   typedef struct {     /* directory stream buffer */
  243. X     int f;             /* file descriptor for the directory "file" */
  244. X     char *p;           /* pointer to next entry in buffer */
  245. X     char *q;           /* pointer after end of buffer contents */
  246. X     char b[DBSZ];              /* buffer */
  247. X   } dstrm;
  248. X
  249. X#else /* !DIRENT */             /* use opendir(), etc. */
  250. X#  if defined(CONVEX) || defined(ultrix)
  251. X#    include <dirent.h>
  252. X#    ifdef direct
  253. X#      undef direct /* ultrix 4.2, at least if !__POSIX */
  254. X#    endif
  255. X#    define direct dirent
  256. X#  endif /* CONVEX || ultrix */
  257. X#  ifdef NDIR
  258. X#    include "ndir.h"           /* for HPUX */
  259. X#  else /* !NDIR */
  260. X#    ifdef MSDOS
  261. X#     ifdef OS2
  262. X#      include "os2zip.h"
  263. X#     else /* !OS2 */
  264. X#      ifndef ATARI_ST
  265. X#        include <dos.h>
  266. X#      endif
  267. X#      if (defined(__TURBOC__) || defined(__GO32__))
  268. X#        define FATTR           FA_HIDDEN+FA_SYSTEM+FA_DIREC
  269. X#        define FFIRST(n,d)     findfirst(n,(struct ffblk *)d,FATTR)
  270. X#        define FNEXT(d)        findnext((struct ffblk *)d)
  271. X#      else /* !__TURBOC__ */
  272. X#        define FATTR           _A_HIDDEN+_A_SYSTEM+_A_SUBDIR
  273. X#        define FFIRST(n,d)     _dos_findfirst(n,FATTR,(struct find_t *)d)
  274. X#        define FNEXT(d)        _dos_findnext((struct find_t *)d)
  275. X#      endif /* ?__TURBOC__ */
  276. X       typedef struct direct {
  277. X         char d_reserved[30];
  278. X         char d_name[13];
  279. X     int d_first;
  280. X#ifdef WIN32
  281. X     HANDLE d_hFindFile;
  282. X#endif
  283. X       } DIR;
  284. X#     endif /* ?OS2 */
  285. X#    else /* !MSDOS */
  286. X#      ifdef VMS
  287. X#        include <ssdef.h>
  288. X         typedef struct direct {
  289. X             int d_wild;                /* flag for wildcard vs. non-wild */
  290. X             struct FAB fab;
  291. X             struct NAM nam;
  292. X             char d_qualwildname[NAM$C_MAXRSS + 1];
  293. X             char d_name[NAM$C_MAXRSS + 1];
  294. X         } DIR;
  295. X#      else /* !VMS */
  296. X#        ifdef MACOS
  297. X           typedef struct direct {
  298. X             int d_wild;                /* flag for wildcard vs. non-wild */
  299. X             char *d_name;
  300. X          } DIR;
  301. X#        endif
  302. X#        ifdef M_XENIX
  303. X#          include <sys/ndir.h>
  304. X#        else /* !M_XENIX */
  305. X#          include <sys/dir.h>
  306. X#        endif /* ?M_XENIX */
  307. X#        ifdef NODIR                    /* for AT&T 3B1 */
  308. X#          define dirent direct
  309. X           typedef FILE DIR;
  310. X#          define dstrm DIR
  311. X#        endif /* NODIR */
  312. X#      endif /* ?VMS */
  313. X#    endif /* ?MSDOS */
  314. X#  endif /* ?NDIR */
  315. X#  define dstrm DIR
  316. X#  ifndef NODIR
  317. X     DIR *opendir OF((char *));
  318. X#  endif /* !NODIR */
  319. X#  ifndef CONVEX
  320. X     struct direct *readdir OF((DIR *));
  321. X#  endif /* !CONVEX */
  322. X#endif /* ?DIRENT */
  323. X#endif /* ?SYSV */
  324. X#endif /* !UTIL */
  325. X
  326. X
  327. X/* Library functions not in (most) header files */
  328. X
  329. X#if defined(__IBMC__) || defined(__WATCOMC__)
  330. X#  define NO_MKTEMP
  331. X#endif
  332. Xchar *mktemp OF((char *));
  333. X
  334. X#ifdef __GO32__
  335. X  char *strlwr OF((char *));
  336. X#else
  337. X  int link OF((char *, char *));
  338. X  int unlink OF((char *));
  339. X# if defined(MSDOS)
  340. X   int chmod OF((char *, int));
  341. X   /* For many targets, chmod is already defined by sys/stat.h, and second
  342. X    * parameter is an unsigned long.
  343. X    */
  344. X# endif
  345. X#endif
  346. X
  347. X
  348. X#ifndef UTIL    /* the companion #endif is a bit of ways down ... */
  349. X
  350. X#ifndef __TURBOC__
  351. X   int utime OF((char *, time_t *));
  352. X#endif /* !__TURBOC__ */
  353. X#ifndef MSDOS
  354. X   int open OF((char *, int, ...));
  355. X   int close OF((int));
  356. X#  ifndef RMDIR
  357. X     int rmdir OF((char *));
  358. X#  endif /* !RMDIR */
  359. X#endif /* !MSDOS */
  360. X
  361. X
  362. X/* Local globals (kinda like "military intelligence" or "broadcast quality") */
  363. Xlocal int exflag = 0;           /* Exclude flag */
  364. X
  365. X#ifdef VMS
  366. X  typedef int statime;
  367. X#else /* !VMS */
  368. X  typedef time_t statime;
  369. X#endif /* ?VMS */
  370. X
  371. X/* Local functions */
  372. X#ifdef PROTO
  373. X#  ifdef VMS
  374. X     local void vms_wild(char *, dstrm *);
  375. X#  endif /* VMS */
  376. X#  ifdef DIRENT
  377. X     local dstrm *opend(char *);
  378. X     local void closed(dstrm *);
  379. X#  endif /* DIRENT */
  380. X   local char *readd(dstrm *);
  381. X   local int fqcmp(voidp *, voidp *);
  382. X   local int fqcmpz(voidp *, voidp *);
  383. X   local char *last(char *);
  384. X   local char *msname(char *);
  385. X#  ifdef VMS
  386. X     local char *strlower(char *);
  387. X     local char *strupper(char *);
  388. X#  endif /* VMS */
  389. X   local char *ex2in(char *, int *);
  390. X   local int newname(char *);
  391. X   local void inctime(struct tm *);
  392. X   local ulg unix2dostime(statime *);
  393. X#  if !defined(__TURBOC__) && !defined(OS2) && !defined(__GO32__)
  394. X     local int cmptime(struct tm *, struct tm *);
  395. X     local time_t invlocal(struct tm *);
  396. X#  endif /* !__TURBOC__ */
  397. X#endif /* PROTO */
  398. X
  399. X
  400. X#if defined(MSDOS) && !defined(OS2)
  401. Xdstrm *opendir(n)
  402. Xchar *n;                /* directory to open */
  403. X/* Start searching for files in the MSDOS directory n */
  404. X{
  405. X  dstrm *d;             /* malloc'd return value */
  406. X  char *p;              /* malloc'd temporary string */
  407. X
  408. X  if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
  409. X      (p = malloc(strlen(n) + 5)) == NULL)
  410. X    return NULL;
  411. X  strcat(strcpy(p, n), "/*.*");
  412. X#ifdef WIN32
  413. X  {
  414. X  WIN32_FIND_DATA fd;
  415. X  DWORD dwAttr;
  416. X  BOOL bAttr;
  417. X
  418. X  if ((HANDLE)0xFFFFFFFF == (d->d_hFindFile = FindFirstFile(p, &fd)))
  419. X    {
  420. X    free((voidp *)p);
  421. X    return NULL;
  422. X    }
  423. X  else
  424. X    strcpy(d->d_name, fd.cFileName);
  425. X  if (-1 != (dwAttr = GetFileAttributes(fd.cFileName)))
  426. X    {
  427. X    bAttr = FALSE;
  428. X    if (FILE_ATTRIBUTE_SYSTEM == (dwAttr & FILE_ATTRIBUTE_SYSTEM))
  429. X    bAttr = TRUE;
  430. X    if (FILE_ATTRIBUTE_HIDDEN == (dwAttr & FILE_ATTRIBUTE_HIDDEN))
  431. X    bAttr = TRUE;
  432. X    if (FILE_ATTRIBUTE_DIRECTORY == (dwAttr & FILE_ATTRIBUTE_DIRECTORY))
  433. X    bAttr = TRUE;
  434. X    if (!bAttr)
  435. X    {
  436. X    free ((voidp *)p);
  437. X    free ((void *) d);
  438. X    return NULL;
  439. X    }
  440. X    }
  441. X
  442. X  }
  443. X#else
  444. X  if (FFIRST(p, d))
  445. X  {
  446. X    free((voidp *)p);
  447. X    return NULL;
  448. X  }
  449. X  free((voidp *)p);
  450. X#endif
  451. X  d->d_first = 1;
  452. X  return d;
  453. X}
  454. X
  455. Xstruct direct *readdir(d)
  456. Xdstrm *d;               /* directory stream to read from */
  457. X/* Return pointer to first or next directory entry, or NULL if end. */
  458. X{
  459. X  if (d->d_first)
  460. X    d->d_first = 0;
  461. X  else
  462. X#ifdef WIN32
  463. X    {
  464. X    WIN32_FIND_DATA fd;
  465. X
  466. X    if (!FindNextFile(d->d_hFindFile, &fd))
  467. X    return NULL;
  468. X    else
  469. X    strcpy(d->d_name, fd.cFileName);
  470. X    }
  471. X#else /* !WIN32 */
  472. X    if (FNEXT(d))
  473. X      return NULL;
  474. X#endif
  475. X  return (struct direct *)d;
  476. X}
  477. X#  define closedir free
  478. X
  479. X#endif /* MSDOS && !OS2 */
  480. X
  481. X
  482. X#ifdef VMS
  483. X
  484. X/*---------------------------------------------------------------------------
  485. X
  486. X    _vms_findfirst() and _vms_findnext(), based on public-domain DECUS C
  487. X    fwild() and fnext() routines (originally written by Martin Minow, poss-
  488. X    ibly modified by Jerry Leichter for bintnxvms.c), were written by Greg
  489. X    Roelofs and are still in the public domain.  Routines approximate the
  490. X    behavior of MS-DOS (MSC and Turbo C) findfirst and findnext functions.
  491. X
  492. X  ---------------------------------------------------------------------------*/
  493. Xlocal void vms_wild(p, d)
  494. Xchar *p;
  495. Xdstrm *d;
  496. X{
  497. X  /*
  498. X   * Do wildcard setup
  499. X   */
  500. X  /* set up the FAB and NAM blocks. */
  501. X  d->fab = cc$rms_fab;             /* initialize fab */
  502. X  d->nam = cc$rms_nam;             /* initialize nam */
  503. X
  504. X  d->fab.fab$l_nam = &d->nam;           /* fab -> nam */
  505. X  d->fab.fab$l_fna = p;                 /* argument wild name */
  506. X  d->fab.fab$b_fns = strlen(p);         /* length */
  507. X
  508. X  d->nam.nam$l_esa = d->d_qualwildname; /* qualified wild name */
  509. X  d->nam.nam$b_ess = NAM$C_MAXRSS;      /* max length */
  510. X  d->nam.nam$l_rsa = d->d_name;         /* matching file name */
  511. X  d->nam.nam$b_rss = NAM$C_MAXRSS;      /* max length */
  512. X
  513. X  /* parse the file name */
  514. X  if (sys$parse(&d->fab) != RMS$_NORMAL)
  515. X    return;
  516. X  /* Does this replace d->fab.fab$l_fna with a new string in its own space?
  517. X     I sure hope so, since p is free'ed before this routine returns. */
  518. X
  519. X  /* have qualified wild name (i.e., disk:[dir.subdir]*.*); null-terminate
  520. X   * and set wild-flag */
  521. X  d->d_qualwildname[d->nam.nam$b_esl] = '\0';
  522. X  d->d_wild = (d->nam.nam$l_fnb & NAM$M_WILDCARD)? 1 : 0;   /* not used... */
  523. X#ifdef DEBUG
  524. X  printf("  incoming wildname:  %s\n", p);
  525. X  printf("  qualified wildname:  %s\n", d->d_qualwildname);
  526. X#endif /* DEBUG */
  527. X}
  528. X
  529. Xdstrm *opendir(n)
  530. Xchar *n;                /* directory to open */
  531. X/* Start searching for files in the VMS directory n */
  532. X{
  533. X  char *c;              /* scans VMS path */
  534. X  dstrm *d;             /* malloc'd return value */
  535. X  int m;                /* length of name */
  536. X  char *p;              /* malloc'd temporary string */
  537. X
  538. X  if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL ||
  539. X      (p = malloc((m = strlen(n)) + 4)) == NULL)
  540. X    return NULL;
  541. X  /* Directory may be in form "[DIR.SUB1.SUB2]" or "[DIR.SUB1]SUB2.DIR;1".
  542. X     If latter, convert to former. */
  543. X  if (m > 0  &&  *(c = strcpy(p,n)+m-1) != ']')
  544. X  {
  545. X    while (--c > p  &&  *c != ';')
  546. X      ;
  547. X    if (c-p < 5  ||  strncmp(c-4, ".DIR", 4))
  548. X    {
  549. X      free((voidp *)d);  free((voidp *)p);
  550. X      return NULL;
  551. X    }
  552. X    c -= 3;
  553. X    *c-- = '\0';        /* terminate at "DIR;#" */
  554. X    *c = ']';           /* "." --> "]" */
  555. X    while (c > p  &&  *--c != ']')
  556. X      ;
  557. X    *c = '.';           /* "]" --> "." */
  558. X  }
  559. X  strcat(p, "*.*");
  560. X  vms_wild(p, d);       /* set up wildcard */
  561. X  free((voidp *)p);
  562. X  return d;
  563. X}
  564. X
  565. Xstruct direct *readdir(d)
  566. Xdstrm *d;               /* directory stream to read from */
  567. X/* Return pointer to first or next directory entry, or NULL if end. */
  568. X{
  569. X  int r;                /* return code */
  570. X
  571. X  do {
  572. X    d->fab.fab$w_ifi = 0;       /* internal file index:  what does this do? */
  573. X
  574. X    /* get next match to possible wildcard */
  575. X    if ((r = sys$search(&d->fab)) == RMS$_NORMAL)
  576. X    {
  577. X        d->d_name[d->nam.nam$b_rsl] = '\0';   /* null terminate */
  578. X        return (struct direct *)d;   /* OK */
  579. X    }
  580. X  } while (r == RMS$_PRV);
  581. X  return NULL;
  582. X}
  583. X#  define closedir free
  584. X#endif /* VMS */
  585. X
  586. X
  587. X#ifdef NODIR                    /* for AT&T 3B1 */
  588. X/*
  589. X**  Apparently originally by Rich Salz.
  590. X**  Cleaned up and modified by James W. Birdsall.
  591. X*/
  592. X
  593. X#  define opendir(path) fopen(path, "r")
  594. Xstruct direct *readdir(dirp)
  595. XDIR *dirp;
  596. X{
  597. X  static struct direct entry;
  598. X
  599. X  if (dirp == NULL) 
  600. X    return NULL;
  601. X  for (;;)
  602. X    if (fread (&entry, sizeof (struct direct), 1, dirp) == 0) 
  603. X      return NULL;
  604. X    else if (entry.d_ino) 
  605. X      return (&entry);
  606. X} /* end of readdir() */
  607. X
  608. X#  define closedir(dirp) fclose(dirp)
  609. X#endif /* NODIR */
  610. X
  611. X
  612. X#ifdef DIRENT
  613. Xlocal dstrm *opend(n)
  614. Xchar *n;                /* directory name to open */
  615. X/* Open the directory *n, returning a pointer to an allocated dstrm, or
  616. X   NULL if error. */
  617. X{
  618. X  dstrm *d;             /* pointer to malloc'ed directory stream */
  619. X
  620. X  if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
  621. X    return NULL;
  622. X  if ((d->f = open(n, 0, 0)) < 0)               /* open directory */
  623. X    return NULL;
  624. X  d->p = d->q = d->b;                           /* buffer is empty */
  625. X  return d;
  626. X}
  627. X#else /* !DIRENT */
  628. X#  define opend opendir                         /* just use opendir() */
  629. X#endif /* ?DIRENT */
  630. X
  631. X
  632. Xlocal char *readd(d)
  633. Xdstrm *d;               /* directory stream to read from */
  634. X/* Return a pointer to the next name in the directory stream d, or NULL if
  635. X   no more entries or an error occurs. */
  636. X{
  637. X  struct direct *e;     /* directory entry read */
  638. X
  639. X#ifdef DIRENT
  640. X  int n;                /* number of entries read by getdents */
  641. X
  642. X  if (d->p >= d->q)                             /* if empty, fill buffer */
  643. X    if ((n = getdents(d->f, d->b, DBSZ)) <= 0)
  644. X      return NULL;
  645. X    else
  646. X      d->q = n + (d->p = d->b);
  647. X  e = (struct direct *)(d->p);                  /* point to entry */
  648. X  d->p += ((struct direct *)(d->p))->d_reclen;  /* advance */
  649. X  return e->d_name;                             /* return name */
  650. X#else /* !DIRENT */
  651. X  return (e = readdir(d)) == NULL ? (char *)NULL : e->d_name;
  652. X#endif /* ?DIRENT */
  653. X}
  654. X
  655. X
  656. X#ifdef DIRENT
  657. Xlocal void closed(d)
  658. Xdstrm *d;               /* directory stream to close */
  659. X/* Close the directory stream */
  660. X{
  661. X  close(d->f);
  662. X  free((voidp *)d);
  663. X}
  664. X#else /* !DIRENT */
  665. X#  define closed closedir
  666. X#endif /* ?DIRENT */
  667. X
  668. X
  669. X#ifdef MSDOS
  670. X
  671. Xint wild(w)
  672. Xchar *w;                /* path/pattern to match */
  673. X/* If not in exclude mode, expand the pattern based on the contents of the
  674. X   file system.  Return an error code in the ZE_ class. */
  675. X{
  676. X  char *a;              /* alloc'ed space for name */
  677. X  dstrm *d;             /* stream for reading directory */
  678. X  char *e;              /* name found in directory */
  679. X  int f;                /* true if there was a match */
  680. X  char *n;              /* constructed name from directory */
  681. X  char *p;              /* path */
  682. X  char *q;              /* name */
  683. X  int r;                /* temporary variable */
  684. X  char v[5];            /* space for device current directory */
  685. X
  686. X  /* Allocate and copy pattern */
  687. X  if ((p = a = malloc(strlen(w) + 1)) == NULL)
  688. X    return ZE_MEM;
  689. X  strcpy(p, w);
  690. X
  691. X  /* Normalize pattern to upper case, path delimiter as '/'. */
  692. X#if defined(FORCE_UPPER)
  693. X#ifndef OS2
  694. X  strupr(p);                            /* convert to upper case */
  695. X#else /* OS2 */
  696. X  if (IsFileSystemFAT(p)) strupr(p);
  697. X#endif /* !OS2 */
  698. X#endif
  699. X  for (q = p; *q; q++)                  /* use / consistently */
  700. X    if (*q == '\\')
  701. X      *q = '/';
  702. X
  703. X  /* If excluding, don't bother with file system */
  704. X  if (exflag)
  705. X  {
  706. X    r = procname(p);
  707. X    free((voidp *)a);
  708. X    return r;
  709. X  }
  710. X
  711. X  /* Only name can have special matching characters */
  712. X  if ((q = isshexp(p)) != NULL &&
  713. X      (strrchr(q, '/') != NULL || strrchr(q, ':') != NULL))
  714. X  {
  715. X    free((voidp *)a);
  716. X    return ZE_PARMS;
  717. X  }
  718. X
  719. X  /* Separate path and name into p and q */
  720. X  if ((q = strrchr(p, '/')) != NULL && (q == p || q[-1] != ':'))
  721. X  {
  722. X    *q++ = 0;                           /* path/name -> path, name */
  723. X    if (*p == 0)                        /* path is just / */
  724. X      p = strcpy(v, "/.");
  725. X  }
  726. X  else if ((q = strrchr(p, ':')) != NULL)
  727. X  {                                     /* has device and no or root path */
  728. X    *q++ = 0;
  729. X    p = strcat(strcpy(v, p), ":");      /* copy device as path */
  730. X    if (*q == '/')                      /* -> device:/., name */
  731. X    {
  732. X      strcat(p, "/");
  733. X      q++;
  734. X    }
  735. X    strcat(p, ".");
  736. X  }
  737. X  else                                  /* no path or device */
  738. X  {
  739. X    q = p;
  740. X    p = strcpy(v, ".");
  741. X  }
  742. X
  743. X  /* Search that level for matching names */
  744. X  if ((d = opend(p)) == NULL)
  745. X  {
  746. X    free((voidp *)a);
  747. X    return ZE_MISS;
  748. X  }
  749. X  if ((r = strlen(p)) > 1 &&
  750. X      (strcmp(p + r - 2, ":.") == 0 || strcmp(p + r - 2, "/.") == 0))
  751. X    *(p + r - 1) = 0;
  752. X  f = 0;
  753. X  while ((e = readd(d)) != NULL)
  754. X    if (strcmp(e, ".") && strcmp(e, "..") && MATCH(q, e))
  755. X    {
  756. X      f = 1;
  757. X      if (strcmp(p, ".") == 0)                  /* path is . */
  758. X        procname(e);                            /* name is name */
  759. X      else
  760. X      {
  761. X        if ((n = malloc(strlen(p) + strlen(e) + 2)) == NULL)
  762. X        {
  763. X          free((voidp *)a);
  764. X          return ZE_MEM;
  765. X        }
  766. X        n = strcpy(n, p);
  767. X        if (n[r = strlen(n) - 1] != '/' && n[r] != ':')
  768. X          strcat(n, "/");
  769. X        r = procname(strcat(n, e));             /* name is path/name */
  770. X        free((voidp *)n);
  771. X        if (r)
  772. X        {
  773. X          free((voidp *)a);
  774. X          return r;
  775. X        }
  776. X      }
  777. X    }
  778. X  closed(d);
  779. X
  780. X  /* Done */
  781. X  free((voidp *)a);
  782. X  return f ? ZE_OK : ZE_MISS;
  783. X}
  784. X
  785. X#endif /* MSDOS */
  786. X
  787. X
  788. X#ifdef VMS
  789. Xint wild(p)
  790. Xchar *p;                /* path/pattern to match */
  791. X/* Expand the pattern based on the contents of the file system.  Return an
  792. X   error code in the ZE_ class. */
  793. X{
  794. X  dstrm *d;             /* stream for reading directory */
  795. X  char *e;              /* name found in directory */
  796. X  int f;                /* true if there was a match */
  797. X
  798. X  /* Search given pattern for matching names */
  799. X  if ((d = (dstrm *)malloc(sizeof(dstrm))) == NULL)
  800. X    return ZE_MEM;
  801. X  vms_wild(p, d);       /* pattern may be more than just directory name */
  802. X  f = 0;
  803. X  while ((e = readd(d)) != NULL)        /* "dosmatch" is already built in */
  804. X    if (procname(e) == ZE_OK)
  805. X      f = 1;
  806. X  closed(d);
  807. X
  808. X  /* Done */
  809. X  return f ? ZE_OK : ZE_MISS;
  810. X}
  811. X#endif /* VMS */
  812. X
  813. X
  814. Xchar *getnam(n)
  815. Xchar *n;                /* where to put name (must have >=FNMAX+1 bytes) */
  816. X/* Read a space, \n, \r, or \t delimited name from stdin into n, and return
  817. X   n.  If EOF, then return NULL.  Also, if the name read is too big, return
  818. X   NULL. */
  819. X{
  820. X  int c;                /* last character read */
  821. X  char *p;              /* pointer into name area */
  822. X
  823. X  p = n;
  824. X  while ((c = getchar()) == ' ' || c == '\n' || c == '\r' || c == '\t')
  825. X    ;
  826. X  if (c == EOF)
  827. X    return NULL;
  828. X  do {
  829. X    if (p - n >= FNMAX)
  830. X      return NULL;
  831. X    *p++ = (char)c;
  832. X    c = getchar();
  833. X  } while (c != EOF && c != ' ' && c != '\n' && c != '\r' && c != '\t');
  834. X  *p = 0;
  835. X  return n;
  836. X}
  837. X
  838. X
  839. Xstruct flist far *fexpel(f)
  840. Xstruct flist far *f;    /* entry to delete */
  841. X/* Delete the entry *f in the doubly-linked found list.  Return pointer to
  842. X   next entry to allow stepping through list. */
  843. X{
  844. X  struct flist far *t;  /* temporary variable */
  845. X
  846. X  t = f->nxt;
  847. X  *(f->lst) = t;                        /* point last to next, */
  848. X  if (t != NULL)
  849. X    t->lst = f->lst;                    /* and next to last */
  850. X  if (f->name != NULL)                  /* free memory used */
  851. X    free((voidp *)(f->name));
  852. X  if (f->zname != NULL)
  853. X    free((voidp *)(f->zname));
  854. X  farfree((voidp far *)f);
  855. X  fcount--;                             /* decrement count */
  856. X  return t;                             /* return pointer to next */
  857. X}
  858. X
  859. X
  860. Xlocal int fqcmp(a, b)
  861. Xvoidp *a, *b;           /* pointers to pointers to found entries */
  862. X/* Used by qsort() to compare entries in the found list by name. */
  863. X{
  864. X  return strcmp((*(struct flist far **)a)->name,
  865. X                (*(struct flist far **)b)->name);
  866. X}
  867. X
  868. X
  869. Xlocal int fqcmpz(a, b)
  870. Xvoidp *a, *b;           /* pointers to pointers to found entries */
  871. X/* Used by qsort() to compare entries in the found list by zname. */
  872. X{
  873. X  return strcmp((*(struct flist far **)a)->zname,
  874. X                (*(struct flist far **)b)->zname);
  875. X}
  876. X
  877. X
  878. Xlocal char *last(p)
  879. Xchar *p;                /* sequence of / delimited path components */
  880. X/* Return a pointer to the start of the last path component. */
  881. X{
  882. X  char *t;              /* temporary variable */
  883. X
  884. X#ifdef VMS
  885. X  if ((t = strrchr(p, ']')) != NULL)
  886. X#else /* !VMS */
  887. X  if ((t = strrchr(p, '/')) != NULL)
  888. X#endif /* ?VMS */
  889. X    return t + 1;
  890. X  else
  891. X    return p;
  892. X}
  893. X
  894. X
  895. Xlocal char *msname(n)
  896. Xchar *n;
  897. X/* Reduce all path components to MSDOS upper case 8.3 style names.  Probably
  898. X   should also check for invalid characters, but I don't know which ones
  899. X   those are. */
  900. X{
  901. X  int c;                /* current character */
  902. X  int f;                /* characters in current component */
  903. X  char *p;              /* source pointer */
  904. X  char *q;              /* destination pointer */
  905. X
  906. X  p = q = n;
  907. X  f = 0;
  908. X  while ((c = *p++) != 0)
  909. X    if (c == '/')
  910. X    {
  911. X      *q++ = (char)c;
  912. X      f = 0;                            /* new component */
  913. X    }
  914. X    else if (c == '.')
  915. X      if (f < 9)
  916. X      {
  917. X        *q++ = (char)c;
  918. X        f = 9;                          /* now in file type */
  919. X      }
  920. X      else
  921. X        f = 12;                         /* now just excess characters */
  922. X    else
  923. X      if (f < 12 && f != 8)
  924. X      {
  925. X        *q++ = (char)(to_up(c));
  926. X        f++;                            /* do until end of name or type */
  927. X      }
  928. X  *q = 0;
  929. X  return n;
  930. X}
  931. X
  932. X
  933. X#ifdef VMS
  934. Xlocal char *strlower(s)
  935. Xchar *s;                /* string to convert */
  936. X/* Convert all uppercase letters to lowercase in string s */
  937. X{
  938. X  char *p;              /* scans string */
  939. X
  940. X  for (p = s; *p; p++)
  941. X    if (*p >= 'A' && *p <= 'Z')
  942. X      *p += 'a' - 'A';
  943. X  return s;
  944. X}
  945. X
  946. Xlocal char *strupper(s)
  947. Xchar *s;                /* string to convert */
  948. X/* Convert all lowercase letters to uppercase in string s */
  949. X{
  950. X  char *p;              /* scans string */
  951. X
  952. X  for (p = s; *p; p++)
  953. X    if (*p >= 'a' && *p <= 'z')
  954. X      *p -= 'a' - 'A';
  955. X  return s;
  956. X}
  957. X#endif /* VMS */
  958. X
  959. Xlocal char *ex2in(x, pdosflag)
  960. Xchar *x;                /* external file name */
  961. Xint *pdosflag;          /* output: force MSDOS file attributes? */
  962. X/* Convert the external file name to a zip file name, returning the malloc'ed
  963. X   string or NULL if not enough memory. */
  964. X{
  965. X  char *n;              /* internal file name (malloc'ed) */
  966. X  char *t;              /* shortened name */
  967. X  int dosflag;
  968. X
  969. X#ifdef OS2
  970. X  dosflag = dosify || IsFileSystemFAT(x);
  971. X  if ( !dosify && use_longname_ea && (t = GetLongPathEA(x)) != NULL )
  972. X  {
  973. X    x = t;
  974. X    dosflag = 0;
  975. X  }
  976. X#else
  977. X# ifdef MSDOS
  978. X  dosflag = 1;
  979. X# else /* !MSDOS */
  980. X  dosflag = dosify; /* default for non-DOS and non-OS/2 */
  981. X# endif /* MSDOS */
  982. X#endif /* OS2 */
  983. X
  984. X  /* Find starting point in name before doing malloc */
  985. X#ifdef MSDOS                            /* msdos */
  986. X  t = *x && *(x + 1) == ':' ? x + 2 : x;
  987. X  while (*t == '/' || *t == '\\')
  988. X    t++;
  989. X#else /* !MSDOS */
  990. X#  ifdef VMS                            /* vms */
  991. X  t = x;
  992. X  if ((n = strrchr(t, ':')) != NULL)
  993. X    t = n + 1;
  994. X  if (*t == '[' && (n = strrchr(t, ']')) != NULL)
  995. X    if ((x = strchr(t, '.')) != NULL && x < n)
  996. X      t = x + 1;
  997. X    else
  998. X      t = n + 1;
  999. X#  else /* !VMS */                      /* unix */
  1000. X  for (t = x; *t == '/'; t++)
  1001. X    ;
  1002. X#  endif /* ?VMS */
  1003. X#endif /* ?MSDOS */
  1004. X
  1005. X  /* Make changes, if any, to the copied name (leave original intact) */
  1006. X#ifdef MSDOS
  1007. X  for (n = t; *n; n++)
  1008. X    if (*n == '\\')
  1009. X      *n = '/';
  1010. X#endif /* MSDOS */
  1011. X
  1012. X  if (!pathput)
  1013. X    t = last(t);
  1014. X
  1015. X  /* Malloc space for internal name and copy it */
  1016. X  if ((n = malloc(strlen(t) + 1)) == NULL)
  1017. X    return NULL;
  1018. X  strcpy(n, t);
  1019. X
  1020. X#ifdef VMS
  1021. X  if ((t = strrchr(n, ']')) != NULL)
  1022. X  {
  1023. X    *t = '/';
  1024. X    while (--t > n)
  1025. X      if (*t == '.')
  1026. X        *t = '/';
  1027. X  }
  1028. X
  1029. X  /* Fix from Greg Roelofs: */
  1030. X  /* Get current working directory and strip from n (t now = n) */
  1031. X  {
  1032. X    char cwd[256], *p, *q;
  1033. X    int c;
  1034. X
  1035. X    if (getcwd(cwd, 256) && ((p = strchr(cwd, '.')) != NULL))
  1036. X    {
  1037. X      ++p;
  1038. X      if ((q = strrchr(p, ']')) != NULL)
  1039. X      {
  1040. X        *q = '/';
  1041. X        while (--q > p)
  1042. X          if (*q == '.')
  1043. X            *q = '/';
  1044. X        /* strip bogus path parts from n */
  1045. X        if (strncmp(n, p, (c=strlen(p))) == 0)
  1046. X        {
  1047. X          q = n + c;
  1048. X          while (*t++ = *q++)
  1049. X            ;
  1050. X        }
  1051. X      }
  1052. X    }
  1053. X  }
  1054. X  strlower(n);
  1055. X  if (!vmsver)
  1056. X    if ((t = strrchr(n, ';')) != NULL)
  1057. X      *t = 0;
  1058. X
  1059. X  if( (t = strrchr(n, '.')) != NULL )
  1060. X  {
  1061. X    if( t[1] == 0 )               /* "filename." -> "filename" */
  1062. X      *t = 0;
  1063. X    else if( t[1] == ';' )        /* "filename.;vvv" -> "filename;vvv" */
  1064. X    {
  1065. X      char *f;
  1066. X      for( f=t+1; *t++ = *f++; )
  1067. X        ;
  1068. X    }
  1069. X  }
  1070. X#endif /* VMS */
  1071. X  if (dosify)
  1072. X    msname(n);
  1073. X#if defined(MSDOS) && !defined(OS2) && !defined(FORCE_UPPER)
  1074. X  else
  1075. X    strlwr(n);
  1076. X#endif
  1077. X  /* Returned malloc'ed name */
  1078. X  if (pdosflag) 
  1079. X    *pdosflag = dosflag;
  1080. X  return n;
  1081. X}
  1082. X
  1083. X
  1084. Xchar *in2ex(n)
  1085. Xchar *n;                /* internal file name */
  1086. X/* Convert the zip file name to an external file name, returning the malloc'ed
  1087. X   string or NULL if not enough memory. */
  1088. X{
  1089. X  char *x;              /* external file name */
  1090. X#ifdef VMS
  1091. X  char *t;              /* scans name */
  1092. X
  1093. X  if ((t = strrchr(n, '/')) == NULL)
  1094. X#endif /* VMS */
  1095. X  {
  1096. X    if ((x = malloc(strlen(n) + 1 + PAD)) == NULL)
  1097. X      return NULL;
  1098. X    strcpy(x, n);
  1099. X  }
  1100. X#ifdef VMS
  1101. X  else
  1102. X  {
  1103. X    if ((x = malloc(strlen(n) + 3 + PAD)) == NULL)
  1104. X      return NULL;
  1105. X    strcpy(x, "[.");
  1106. X    strcpy(x + 2, n);
  1107. X    *(t = x + 2 + (t - n)) = ']';
  1108. X    while (--t > x)
  1109. X      if (*t == '/')
  1110. X        *t = '.';
  1111. X  }
  1112. X  strupper(x);
  1113. X#endif /* VMS */
  1114. X#ifdef OS2
  1115. X  if ( !IsFileNameValid(x) )
  1116. X    ChangeNameForFAT(x);
  1117. X#endif /* !OS2 */
  1118. X#if defined(FORCE_UPPER) && defined(MSDOS)
  1119. X  /* Don't convert to upper case, causes wrong warnings. Keep the
  1120. X   * name as it was before in the old zip file.
  1121. X   */
  1122. X  strupr(x);
  1123. X#endif
  1124. X  return x;
  1125. X}
  1126. X
  1127. X
  1128. Xint exclude()
  1129. X/* Change from including to excluding names when procname() called.  Return
  1130. X   an error code in the ZE_ class. */
  1131. X{
  1132. X  struct flist far *f;          /* steps through found linked list */
  1133. X  extent j;                     /* index for s */
  1134. X  struct flist far **s;         /* sorted table */
  1135. X
  1136. X  /* sort found list, remove duplicates */
  1137. X  if (fcount)
  1138. X  {
  1139. X    if ((s = (struct flist far **)malloc(
  1140. X         fcount * sizeof(struct flist far *))) == NULL)
  1141. X      return ZE_MEM;
  1142. X    for (j = 0, f = found; f != NULL; f = f->nxt)
  1143. X      s[j++] = f;
  1144. X    qsort((char *)s, fcount, sizeof(struct flist far *), fqcmp);
  1145. X    for (j = fcount - 1; j > 0; j--)
  1146. X      if (strcmp(s[j - 1]->name, s[j]->name) == 0)
  1147. X        fexpel(s[j]);           /* fexpel() changes fcount */
  1148. X    qsort((char *)s, fcount, sizeof(struct flist far *), fqcmpz);
  1149. X    for (j = 1; j < fcount; j++)
  1150. X      if (strcmp(s[j - 1]->zname, s[j]->zname) == 0)
  1151. X      {
  1152. X        warn("name in zip file repeated: ", s[j]->zname);
  1153. X        warn("  first full name: ", s[j - 1]->name);
  1154. X        warn(" second full name: ", s[j]->name);
  1155. X        return ZE_PARMS;
  1156. X      }
  1157. X    free((voidp *)s);
  1158. X  }
  1159. X  exflag = 1;
  1160. X  return ZE_OK;
  1161. X}
  1162. X
  1163. X
  1164. Xlocal int newname(n)
  1165. Xchar *n;                /* name to add (or exclude) */
  1166. X/* Add (or exclude) a name that is not in the zip file.  Return an error
  1167. X   code in the ZE_ class. */
  1168. X{
  1169. X  char *m;
  1170. X  struct flist far *f;  /* where in found, or new found entry */
  1171. X  struct zlist far *z;  /* where in zfiles (if found) */
  1172. X  int dosflag;
  1173. X
  1174. X  /* Search for name in zip file.  If there, mark it, else add to
  1175. X     list of new names to do (or remove from that list). */
  1176. X  if ((m = ex2in(n, &dosflag)) == NULL)
  1177. X    return ZE_MEM;
  1178. X  if ((z = zsearch(m)) != NULL)
  1179. X    if (exflag)
  1180. X    {
  1181. X      z->mark = 0;
  1182. X      free((voidp *)m);
  1183. X      if (verbose)
  1184. X        printf("zip diagnostic: excluding %s\n", z->name);
  1185. X    }
  1186. X    else
  1187. X    {
  1188. X      free((voidp *)(z->name));
  1189. X      free((voidp *)(z->zname));
  1190. X      if ((z->name = malloc(strlen(n) + 1 + PAD)) == NULL)
  1191. X        return ZE_MEM;
  1192. X      strcpy(z->name, n);
  1193. X      z->zname = m;
  1194. X      z->mark = 1;
  1195. X      z->dosflag = dosflag;
  1196. X      if (verbose)
  1197. X        printf("zip diagnostic: including %s\n", z->name);
  1198. X    }
  1199. X  else
  1200. X    if (exflag)
  1201. X    {
  1202. X      /* search list for name--if there, remove it */
  1203. X      for (f = found; f != NULL; f = f->nxt)
  1204. X        if (namecmp(n, f->name) == 0)
  1205. X        {
  1206. X          fexpel(f);
  1207. X          break;
  1208. X        }
  1209. X      free((voidp *)m);
  1210. X    }
  1211. X    else
  1212. X    {
  1213. X      /* allocate space and add to list */
  1214. X      if ((f = (struct flist far *)farmalloc(sizeof(struct flist))) == NULL ||
  1215. X          (f->name = malloc(strlen(n) + 1 + PAD)) == NULL)
  1216. X      {
  1217. X        if (f != NULL)
  1218. X          farfree((voidp far *)f);
  1219. X        return ZE_MEM;
  1220. X      }
  1221. X      strcpy(f->name, n);
  1222. X      f->zname = m;
  1223. X      f->dosflag = dosflag;
  1224. X      *fnxt = f;
  1225. X      f->lst = fnxt;
  1226. X      f->nxt = NULL;
  1227. X      fnxt = &f->nxt;
  1228. X      fcount++;
  1229. X    }
  1230. X  return ZE_OK;
  1231. X}
  1232. X
  1233. X
  1234. Xint procname(n)
  1235. Xchar *n;                /* name to process */
  1236. X/* Process a name or sh expression to operate on (or exclude).  Return
  1237. X   an error code in the ZE_ class. */
  1238. X{
  1239. X  char *a;              /* path and name for recursion */
  1240. X  dstrm *d;             /* directory stream from opend() */
  1241. X  char *e;              /* pointer to name from readd() */
  1242. X  struct flist far *f;  /* steps through found list */
  1243. X  int m;                /* matched flag */
  1244. X  char *p;              /* path for recursion */
  1245. X  struct stat s;        /* result of stat() */
  1246. X  struct zlist far *z;  /* steps through zfiles list */
  1247. X
  1248. X  if (strcmp(n, "-") == 0)   /* if compressing stdin */
  1249. X    return newname(n);
  1250. X  else if (
  1251. X#ifdef S_IFLNK          /* if symbolic links exist ... */
  1252. X      linkput ? lstat(n, &s) :
  1253. X#endif /* S_IFLNK */
  1254. X      SSTAT(n, &s)
  1255. X#if defined(__TURBOC__) || defined(VMS)
  1256. X       /* Borland and VMS C bug: stat() succeeds on wild card names! */
  1257. X      || isshexp(n)
  1258. X#endif
  1259. X     )
  1260. X  {
  1261. X    /* Not a file or directory--search for shell expression in zip file */
  1262. X    p = ex2in(n, NULL);         /* shouldn't affect matching chars */
  1263. X    m = 1;
  1264. X    for (z = zfiles; z != NULL; z = z->nxt)
  1265. X      if (MATCH(p, z->zname))
  1266. X      {
  1267. X        z->mark = !exflag;
  1268. X        if (verbose)
  1269. X          printf("zip diagnostic: %scluding %s\n",
  1270. X                 exflag ? "ex" : "in", z->name);
  1271. X        m = 0;
  1272. X      }
  1273. X    /* If excluding, also search for expression in found list */
  1274. X    if (exflag)
  1275. X    {
  1276. X      for (f = found; f != NULL;)
  1277. X        if (MATCH(p, f->zname))
  1278. X        {
  1279. X          f = fexpel(f);
  1280. X          m = 0;
  1281. X        }
  1282. X        else
  1283. X          f = f->nxt;
  1284. X    }
  1285. X    free((voidp *)p);
  1286. X    if (m)
  1287. X      return ZE_MISS;           /* no match */
  1288. X  }
  1289. X  else
  1290. X  {
  1291. X    /* Live name--use if file, recurse if directory */
  1292. X#if defined(FORCE_UPPER) && defined(MSDOS)
  1293. X# ifndef OS2
  1294. X    strupr(n);                  /* convert to upper case */
  1295. X# else /* OS2 */
  1296. X    if (IsFileSystemFAT(n)) strupr(n);
  1297. X# endif /* !OS2 */
  1298. X#endif
  1299. X
  1300. X#ifdef MSDOS
  1301. X    for (p = n; *p; p++)          /* use / consistently */
  1302. X      if (*p == '\\')
  1303. X        *p = '/';
  1304. X#endif /* MSDOS */
  1305. X    if ((s.st_mode & S_IFDIR) == 0)
  1306. X    {
  1307. X      /* add or remove name of file */
  1308. X        if ((m = newname(n)) != ZE_OK)
  1309. X          return m;
  1310. X    } else {
  1311. X        /* recurse into directory */
  1312. X        if (recurse && (d = opend(n)) != NULL)
  1313. X        {
  1314. X#ifdef VMS
  1315. X          while ((e = readd(d)) != NULL)
  1316. X            if ((m = procname(e)) != ZE_OK)     /* recurse on name */
  1317. X            {
  1318. X              /* want to just set warning error and continue */
  1319. X              closed(d);
  1320. X              return m;
  1321. X            }
  1322. X#else /* !VMS */
  1323. X          if ((p = malloc(strlen(n)+2)) == NULL)
  1324. X            return ZE_MEM;
  1325. X          if (strcmp(n, ".") == 0)
  1326. X            *p = 0; /* avoid "./" prefix and do not create zip entry */
  1327. X          else
  1328. X          {
  1329. X            strcpy(p, n);
  1330. X            a = p + strlen(p);
  1331. X            if (a[-1] != '/')
  1332. X              strcpy(a, "/");
  1333. X            if ((m = newname(p)) != ZE_OK)
  1334. X              return m;
  1335. X          }
  1336. X          while ((e = readd(d)) != NULL)
  1337. X            if (strcmp(e, ".") && strcmp(e, ".."))
  1338. X            {
  1339. X              if ((a = malloc(strlen(p) + strlen(e) + 1)) == NULL)
  1340. X              {
  1341. X                free((voidp *)p);
  1342. X                closed(d);
  1343. X                return ZE_MEM;
  1344. X              }
  1345. X              strcat(strcpy(a, p), e);
  1346. X              if ((m = procname(a)) != ZE_OK)   /* recurse on name */
  1347. X              {
  1348. X                free((voidp *)a);  free((voidp *)p);
  1349. X                closed(d);
  1350. X                return m;
  1351. X              }
  1352. X              free((voidp *)a);
  1353. X            }
  1354. X          free((voidp *)p);
  1355. X#endif /* ?VMS */
  1356. X          closed(d);
  1357. X        }
  1358. X      }
  1359. X    }
  1360. X  return ZE_OK;
  1361. X}
  1362. X
  1363. X
  1364. X#if !defined(CRAY) && !defined(__TURBOC__) && !defined(OS2) /* and ... */
  1365. X#if !defined( __GO32__)
  1366. X
  1367. Xlocal int cmptime(p, q)
  1368. Xstruct tm *p, *q;       /* times to compare */
  1369. X/* Return negative if time p is before time q, positive if after, and
  1370. X   zero if the same */
  1371. X{
  1372. X  int r;                /* temporary variable */
  1373. X
  1374. X  if (p == NULL)
  1375. X    return -1;
  1376. X  else if ((r = p->tm_year - q->tm_year) != 0)
  1377. X    return r;
  1378. X  else if ((r = p->tm_mon - q->tm_mon) != 0)
  1379. X    return r;
  1380. X  else if ((r = p->tm_mday - q->tm_mday) != 0)
  1381. X    return r;
  1382. X  else if ((r = p->tm_hour - q->tm_hour) != 0)
  1383. X    return r;
  1384. X  else if ((r = p->tm_min - q->tm_min) != 0)
  1385. X    return r;
  1386. X  else
  1387. X    return p->tm_sec - q->tm_sec;
  1388. X}
  1389. X
  1390. X
  1391. Xlocal time_t invlocal(t)
  1392. Xstruct tm *t;           /* time to convert */
  1393. X/* Find inverse of localtime() using bisection.  This routine assumes that
  1394. X   time_t is an integer type, either signed or unsigned.  The expectation
  1395. X   is that sometime before the year 2038, time_t will be made a 64-bit
  1396. X   integer, and this routine will still work. */
  1397. X{
  1398. X  time_t i;             /* midpoint of current root range */
  1399. X  time_t l;             /* lower end of root range */
  1400. X  time_t u;             /* upper end of root range */
  1401. X
  1402. X  /* Bracket the root [0,largest time_t].  Note: if time_t is a 32-bit signed
  1403. X     integer, then the upper bound is GMT 1/19/2038 03:14:07, after which all
  1404. X     the Unix systems in the world come to a grinding halt.  Either that, or
  1405. X     all those systems will suddenly find themselves transported to December
  1406. X     of 1901 ... */
  1407. X  l = 0;
  1408. X  u = 1;
  1409. X  while (u < (u << 1))
  1410. X    u = (u << 1) + 1;
  1411. X
  1412. X  /* Find the root */
  1413. X  while (u - l > 1)
  1414. X  {
  1415. X    i = l + ((u - l) >> 1);
  1416. X    if (cmptime(localtime(&i), t) <= 0)
  1417. X      l = i;
  1418. X    else
  1419. X      u = i;
  1420. X  }
  1421. X  return l;
  1422. X}
  1423. X#endif
  1424. X#endif
  1425. X
  1426. X
  1427. Xvoid stamp(f, d)
  1428. Xchar *f;                /* name of file to change */
  1429. Xulg d;                  /* dos-style time to change it to */
  1430. X/* Set last updated and accessed time of file f to the DOS time d. */
  1431. X{
  1432. X#if defined(MACOS)
  1433. X  warn("timestamp not implemented yet", "");
  1434. X#else
  1435. X#ifdef __TURBOC__
  1436. X  int h;                /* file handle */
  1437. X
  1438. X  if ((h = open(f, 0)) != -1)
  1439. X  {
  1440. X#ifdef ATARI_ST
  1441. X    d = ( d >> 16 ) | ( d << 16 );
  1442. X#endif
  1443. X    setftime(h, (struct ftime *)&d);
  1444. X    close(h);
  1445. X  }
  1446. X#else /* !__TURBOC__ */
  1447. X#ifdef VMS
  1448. X  int tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year;
  1449. X  char timbuf[24];
  1450. X  static char *month[] = {"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  1451. X                          "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
  1452. X  struct VMStimbuf {
  1453. X      char *actime;           /* VMS revision date, ASCII format */
  1454. X      char *modtime;          /* VMS creation date, ASCII format */
  1455. X  } ascii_times = {timbuf, timbuf};
  1456. X
  1457. X  /* Convert DOS time to ASCII format for VMSmunch */
  1458. X  tm_sec = (int)(d << 1) & 0x3e;
  1459. X  tm_min = (int)(d >> 5) & 0x3f;
  1460. X  tm_hour = (int)(d >> 11) & 0x1f;
  1461. X  tm_mday = (int)(d >> 16) & 0x1f;
  1462. X  tm_mon = ((int)(d >> 21) & 0xf) - 1;
  1463. X  tm_year = ((int)(d >> 25) & 0x7f) + 1980;
  1464. X  sprintf(timbuf, "%02d-%3s-%04d %02d:%02d:%02d.00", tm_mday, month[tm_mon],
  1465. X    tm_year, tm_hour, tm_min, tm_sec);
  1466. X
  1467. X  /* Set updated and accessed times of f */
  1468. X  if (VMSmunch(f, SET_TIMES, &ascii_times) != RMS$_NMF)
  1469. X    warn("can't set zipfile time: ", f);
  1470. X
  1471. X#else /* !VMS */
  1472. X#ifdef OS2
  1473. X  SetFileTime(f, d);
  1474. X#else /* !OS2 */
  1475. X  struct tm t;          /* argument for mktime() or invlocal() */
  1476. X  time_t u[2];          /* argument for utime() */
  1477. X#ifndef __GO32__
  1478. X  extern time_t mktime OF((struct tm *));
  1479. X#endif
  1480. X
  1481. X  /* Convert DOS time to time_t format in u[0] and u[1] */
  1482. X  t.tm_sec = (int)(d << 1) & 0x3e;
  1483. X  t.tm_min = (int)(d >> 5) & 0x3f;
  1484. X  t.tm_hour = (int)(d >> 11) & 0x1f;
  1485. X  t.tm_mday = (int)(d >> 16) & 0x1f;
  1486. X  t.tm_mon = ((int)(d >> 21) & 0xf) - 1;
  1487. X  t.tm_year = ((int)(d >> 25) & 0x7f) + 80;
  1488. X#if defined(MSDOS) || defined(OS2) || defined(CRAY)
  1489. X  /* mktime() is more reliable than invlocal() because the time range is
  1490. X   * wider on MSDOS than on Unix; required for Cray because invlocal assumes
  1491. X   * 32-bit ints
  1492. X   */
  1493. X  u[0] = u[1] = mktime(&t);
  1494. X#else
  1495. X  u[0] = u[1] = invlocal(&t);
  1496. X#endif
  1497. X
  1498. X  /* Set updated and accessed times of f */
  1499. X  utime(f, u);
  1500. X#endif /* ?OS2 */
  1501. X#endif /* ?VMS */
  1502. X#endif /* ?__TURBOC__ */
  1503. X#endif /* ?MACOS */
  1504. X}
  1505. X
  1506. X
  1507. Xlocal void inctime(s)
  1508. Xstruct tm *s;           /* time to increment in place */
  1509. X/* Increment the time structure *s by one second, return the result in
  1510. X   place. */
  1511. X{
  1512. X  int y;                /* temporary variable */
  1513. X
  1514. X  /* days in each month, except for February */
  1515. X  static int days[] = {31,0,31,30,31,30,31,31,30,31,30,31};
  1516. X
  1517. X  /* Set days in February from year (1900 is a leap year, 2000 is not) */
  1518. X  y = s->tm_year + 1900;
  1519. X  days[1] = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) ? 29 : 28;
  1520. X
  1521. X  /* Increment time with carry */
  1522. X  if (s->tm_sec != 59)
  1523. X    s->tm_sec++;
  1524. X  else if (s->tm_sec = 0, s->tm_min != 59)
  1525. X    s->tm_min++;
  1526. X  else if (s->tm_min = 0, s->tm_hour != 23)
  1527. X    s->tm_hour++;
  1528. X  else if (s->tm_hour = 0, s->tm_mday != days[s->tm_mon])
  1529. X    s->tm_mday++;
  1530. X  else if (s->tm_mday = 1, s->tm_mon != 11)
  1531. X    s->tm_mon++;
  1532. X  else
  1533. X  {
  1534. X    s->tm_mon = 0;
  1535. X    s->tm_year++;
  1536. X  }
  1537. X}
  1538. X
  1539. X
  1540. Xulg dostime(y, n, d, h, m, s)
  1541. Xint y;                  /* year */
  1542. Xint n;                  /* month */
  1543. Xint d;                  /* day */
  1544. Xint h;                  /* hour */
  1545. Xint m;                  /* minute */
  1546. Xint s;                  /* second */
  1547. X/* Convert the date y/n/d and time h:m:s to a four byte DOS date and
  1548. X   time (date in high two bytes, time in low two bytes allowing magnitude
  1549. X   comparison). */
  1550. X{
  1551. X  return y < 1980 ? dostime(1980, 1, 1, 0, 0, 0) :
  1552. X        (((ulg)y - 1980) << 25) | ((ulg)n << 21) | ((ulg)d << 16) |
  1553. X        ((ulg)h << 11) | ((ulg)m << 5) | ((ulg)s >> 1);
  1554. X}
  1555. X
  1556. X
  1557. Xlocal ulg unix2dostime(t)
  1558. Xstatime *t;             /* unix time to convert */
  1559. X/* Return the Unix time t in DOS format, rounded up to the next two
  1560. X   second boundary. */
  1561. X{
  1562. X  struct tm *s;         /* result of localtime() */
  1563. X
  1564. X  s = localtime(t);             /* Use local time since MSDOS does */
  1565. X  inctime(s);                   /* Add one second to round up */
  1566. X  return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
  1567. X                 s->tm_hour, s->tm_min, s->tm_sec);
  1568. X}
  1569. X
  1570. X
  1571. Xulg filetime(f, a, n)
  1572. Xchar *f;                /* name of file to get info on */
  1573. Xulg *a;                 /* return value: file attributes */
  1574. Xlong *n;                /* return value: file size */
  1575. X/* If file *f does not exist, return 0.  Else, return the file's last
  1576. X   modified date and time as an MSDOS date and time.  The date and
  1577. X   time is returned in a long with the date most significant to allow
  1578. X   unsigned integer comparison of absolute times.  Also, if a is not
  1579. X   a NULL pointer, store the file attributes there, with the high two
  1580. X   bytes being the Unix attributes, and the low byte being a mapping
  1581. X   of that to DOS attributes.  If n is not NULL, store the file size
  1582. X   there.
  1583. X   If f is "-", use standard input as the file. If f is a device, return
  1584. X   a file size of -1 */
  1585. X{
  1586. X  struct stat s;        /* results of stat() */
  1587. X  char name[FNMAX];
  1588. X  int len = strlen(f);
  1589. X
  1590. X  strcpy(name, f);
  1591. X  if (name[len - 1] == '/')
  1592. X    name[len - 1] = 0; 
  1593. X  /* not all systems allow stat'ing a file with / appended */
  1594. X
  1595. X  if (strcmp(f, "-") == 0) {
  1596. X    if (fstat(fileno(stdin), &s) != 0)
  1597. X      error("fstat(stdin)");
  1598. X  } else if ((
  1599. X#ifdef S_IFLNK
  1600. X             linkput ? lstat(name, &s) :
  1601. X#endif
  1602. X             SSTAT(name, &s)) != 0 /* || (s.st_mode & S_IFDIR) != 0 */ )
  1603. X             /* Accept about any file kind except directories */
  1604. X    return 0;
  1605. X
  1606. X  if (a != NULL)
  1607. X#ifdef OS2
  1608. X    *a = (s.st_mode << 16) | GetFileMode(name);
  1609. X#else
  1610. X    *a = (s.st_mode << 16) | !(s.st_mode & S_IWRITE);
  1611. X#endif
  1612. X  if (n != NULL)
  1613. X    *n = (s.st_mode & S_IFREG) == 0 ? -1L : s.st_size;
  1614. X
  1615. X#ifdef OS2
  1616. X  return GetFileTime(name);
  1617. X#else /* !OS2 */
  1618. X#  ifdef VMS
  1619. X     return unix2dostime(&s.st_ctime);   /* Use creation time in VMS */
  1620. X#  else /* !VMS */
  1621. X#    ifdef ATARI_ST
  1622. X       return s.st_mtime; /* Turbo C doesn't use UNIX times */
  1623. X#    else
  1624. X       return unix2dostime(&s.st_mtime);
  1625. X#    endif
  1626. X#  endif /* ?VMS */
  1627. X#endif /* ?OS2 */
  1628. X}
  1629. X
  1630. X
  1631. Xint issymlnk(a)
  1632. Xulg a;                  /* Attributes returned by filetime() */
  1633. X/* Return true if the attributes are those of a symbolic link */
  1634. X{
  1635. X#ifdef S_IFLNK
  1636. X  return ((a >> 16) & S_IFMT) == S_IFLNK;
  1637. X#else /* !S_IFLNK */
  1638. X  return (int)a & 0;    /* avoid warning on unused parameter */
  1639. X#endif /* ?S_IFLNK */
  1640. X}
  1641. X
  1642. X
  1643. Xint deletedir(d)
  1644. Xchar *d;                /* directory to delete */
  1645. X/* Delete the (empty) directory *d.  Return the result of rmdir(), delete(),
  1646. X   or system(). */
  1647. X{
  1648. X#ifdef MACOS
  1649. X  warn("deletedir not implemented yet", "");
  1650. X  return 127;
  1651. X#else
  1652. X#ifdef RMDIR
  1653. X  /* code from Greg Roelofs, who horked it from Mark Edwards (unzip) */
  1654. X  int r, len;
  1655. X  char *s;              /* malloc'd string for system command */
  1656. X
  1657. X  len = strlen(d);
  1658. X  if ((s = malloc(len + 34)) == NULL)
  1659. X    return 127;
  1660. X
  1661. X#ifdef VMS
  1662. X  {
  1663. X    char *c;            /* pointer into VMS path */
  1664. X    /* convert "DEV:[DIR.SUB1.SUB2]" form to "DEV:[DIR.SUB1]SUB2.DIR;0" */
  1665. X    strcat(strcpy(s, "set prot=(o:rwed) "), d);   /* d starts at s+18 */
  1666. X    if (*(c = s+17+len) != ']')
  1667. X    {
  1668. X      free(s);
  1669. X      return 127;
  1670. X    }
  1671. X    strcpy(c, ".DIR;0");        /* 0 translates to highest version */
  1672. X    while (--c > s+18  &&  *c != '.'  &&  *c != '[') ;
  1673. X    if (c == s+18)
  1674. X    {
  1675. X      free(s);
  1676. X      return 127;
  1677. X    }
  1678. X    if (*c == '.')
  1679. X      *c = ']';
  1680. X    else if (*--c == ']')  /* presumably of form "DEV:[DIR.SUB1.][SUB2]" */
  1681. X    {                      /* (possible to have "DEV:[DIR.SUB1.][][SUB2]"?) */
  1682. X      char *b = c + 2;
  1683. X      c[-1] = ']';
  1684. X      while (*c++ = *b++) ;
  1685. X    }
  1686. X    else        /* must have reached device name:  can't delete top level */
  1687. X    {
  1688. X      free(s);
  1689. X      return 127;
  1690. X    }
  1691. X  }
  1692. X  /* unprotect directory and delete it as a file.  May fail if exists 
  1693. X     normal file "foo.dir" on top of directory "foo.dir" */
  1694. X  system(s);
  1695. X  r = delete(s+18);
  1696. X#else /* !VMS */
  1697. X  sprintf(s, "IFS=\" \t\n\" /bin/rmdir %s 2>/dev/null", d);
  1698. X  r = system(s);
  1699. X#endif /* ?VMS */
  1700. X  free(s);
  1701. X  return r;
  1702. X#else /* !RMDIR */
  1703. X  return rmdir(d);
  1704. X#endif /* ?RMDIR */
  1705. X#endif /* ?MACOS */
  1706. X}
  1707. X
  1708. X
  1709. X#endif /* !UTIL */
  1710. X
  1711. Xint destroy(f)
  1712. Xchar *f;                /* file to delete */
  1713. X/* Delete the file *f, returning non-zero on failure. */
  1714. X{
  1715. X  return unlink(f);
  1716. X}
  1717. X
  1718. X
  1719. Xint replace(d, s)
  1720. Xchar *d, *s;            /* destination and source file names */
  1721. X/* Replace file *d by file *s, removing the old *s.  Return an error code
  1722. X   in the ZE_ class. */
  1723. X{
  1724. X  struct stat t;        /* results of stat() */
  1725. X
  1726. X  if (SSTAT(d, &t) == 0 && unlink(d))
  1727. X    return ZE_CREAT;                    /* Can't erase zip file--give up */
  1728. X  if (link(s, d))                       /* Just move s on top of d */
  1729. X#if !defined(VMS) && !defined(ATARI_ST)
  1730. X    /* For VMS & ATARI assume failure is EXDEV */
  1731. X    if (errno != EXDEV
  1732. X#  ifdef ENOTSAM
  1733. X       && errno != ENOTSAM /* Used at least on Turbo C */
  1734. X#  endif
  1735. X        ) return ZE_CREAT;
  1736. X    else
  1737. X#endif
  1738. X    {
  1739. X      FILE *f, *g;      /* source and destination files */
  1740. X      int r;            /* temporary variable */
  1741. X
  1742. X      if ((f = fopen(s, FOPR)) == NULL) {
  1743. X        fprintf(stderr," replace: can't open %s\n", s);
  1744. X        return ZE_TEMP;
  1745. X      }
  1746. X      if ((g = fopen(d, FOPW)) == NULL)
  1747. X      {
  1748. X        fclose(f);
  1749. X        return ZE_CREAT;
  1750. X      }
  1751. X      r = fcopy(f, g, (ulg)-1L);
  1752. X      fclose(f);
  1753. X      if (fclose(g) || r != ZE_OK)
  1754. X      {
  1755. X        unlink(d);
  1756. X        return r ? (r == ZE_TEMP ? ZE_WRITE : r) : ZE_WRITE;
  1757. X      }
  1758. X#ifdef VMS /* only delete if rename failed:  previous version may exist */
  1759. X      unlink(s);
  1760. X    }
  1761. X#else /* !VMS */
  1762. X    }
  1763. X  unlink(s);
  1764. X#endif /* !VMS */
  1765. X  return ZE_OK;
  1766. X}
  1767. X
  1768. X
  1769. Xint getfileattr(f)
  1770. Xchar *f;                /* file path */
  1771. X/* Return the file attributes for file f or 0 if failure */
  1772. X{
  1773. X  struct stat s;
  1774. X
  1775. X  return SSTAT(f, &s) == 0 ? s.st_mode : 0;
  1776. X}
  1777. X
  1778. X
  1779. Xint setfileattr(f, a)
  1780. Xchar *f;                /* file path */
  1781. Xint a;                  /* attributes returned by getfileattr() */
  1782. X/* Give the file f the attributes a, return non-zero on failure */
  1783. X{
  1784. X#if defined (VMS) || defined(MACOS)
  1785. X  return 0;
  1786. X#else /* !VMS */
  1787. X  return chmod(f, a);
  1788. X#endif /* ?VMS */
  1789. X}
  1790. X
  1791. X
  1792. X#ifdef NO_MKTEMP
  1793. X
  1794. Xchar *tempname(zip)
  1795. X  char *zip;              /* path name of zip file to generate temp name for */
  1796. X
  1797. X/* Return a temporary file name in its own malloc'ed space.
  1798. X * This function might accidentally destroy an existing file
  1799. X * with extension .$z$ . Use mktemp below if you have it on your system.
  1800. X */
  1801. X{
  1802. X  char *p;              /* temporary pointer */
  1803. X  char *t;              /* malloc'ed space for name */
  1804. X
  1805. X  if ((t = malloc(strlen(zip)+5)) == NULL)
  1806. X    return NULL;
  1807. X  strcpy(t, zip);
  1808. X  if ((p = strrchr(t, '.')) != NULL &&
  1809. X      (!strncmp(p, ".zip", 4) || !strncmp(p, ".ZIP", 4)))
  1810. X      /* strncmp to avoid problems with VMS ';' */
  1811. X    strcpy(p, ".$z$");
  1812. X  else
  1813. X    strcat(t, ".$z$");
  1814. X
  1815. X  return t;
  1816. X}
  1817. X#else /* !NO_MKTEMP */
  1818. X
  1819. Xchar *tempname(zip)
  1820. X  char *zip;              /* path name of zip file to generate temp name for */
  1821. X
  1822. X/* Return a temporary file name in its own malloc'ed space, using tempath. */
  1823. X{
  1824. X  char *t = zip;   /* malloc'ed space for name (use zip to avoid warning) */
  1825. X
  1826. X  if (tempath != NULL)
  1827. X  {
  1828. X    if ((t = malloc(strlen(tempath)+10)) == NULL)
  1829. X      return NULL;
  1830. X    strcpy(t, tempath);
  1831. X#ifndef VMS
  1832. X    if (t[strlen(t)-1] != '/')
  1833. X      strcat(t, "/");
  1834. X#endif
  1835. X  }
  1836. X  else
  1837. X  {
  1838. X    if ((t = malloc(9)) == NULL)
  1839. X      return NULL;
  1840. X    *t = 0;
  1841. X  }
  1842. X  strcat(t, "_ZXXXXXX");
  1843. X  return mktemp(t);
  1844. X}
  1845. X
  1846. X#endif /* NO_MKTEMP */
  1847. X
  1848. X
  1849. Xint fcopy(f, g, n)
  1850. XFILE *f, *g;            /* source and destination files */
  1851. Xulg n;                  /* number of bytes to copy or -1 for all */
  1852. X/* Copy n bytes from file *f to file *g, or until EOF if n == -1.  Return
  1853. X   an error code in the ZE_ class. */
  1854. X{
  1855. X  char *b;              /* malloc'ed buffer for copying */
  1856. X  extent k;             /* result of fread() */
  1857. X  ulg m;                /* bytes copied so far */
  1858. X
  1859. X  if ((b = malloc(CBSZ)) == NULL)
  1860. X    return ZE_MEM;
  1861. X  m = 0;
  1862. X  while (n == -1L || m < n)
  1863. X  {
  1864. X    if ((k = fread(b, 1, n == -1 ?
  1865. X                   CBSZ : (n - m < CBSZ ? (extent)(n - m) : CBSZ), f)) == 0)
  1866. X      if (ferror(f))
  1867. X      {
  1868. X        free((voidp *)b);
  1869. X        return ZE_READ;
  1870. X      }
  1871. X      else
  1872. X        break;
  1873. X    if (fwrite(b, 1, k, g) != k)
  1874. X    {
  1875. X      free((voidp *)b);
  1876. X      fprintf(stderr," fcopy: write error\n");
  1877. X      return ZE_TEMP;
  1878. X    }
  1879. X    m += k;
  1880. X  }
  1881. X  free((voidp *)b);
  1882. X  return ZE_OK;
  1883. X}
  1884. X
  1885. X
  1886. X#ifdef CRYPT
  1887. X
  1888. X#ifndef MSDOS
  1889. X
  1890. X#ifdef VMS
  1891. X
  1892. Xint echo(opt)
  1893. X    int opt;
  1894. X{
  1895. X/*---------------------------------------------------------------------------
  1896. X    Based on VMSmunch.c, which in turn was based on Joe Meadows' file.c code.
  1897. X  ---------------------------------------------------------------------------
  1898. X     * For VMS v5.x:
  1899. X     *   IO$_SENSEMODE/SETMODE info:  Programming, Vol. 7A, System Programming,
  1900. X     *     I/O User's: Part I, sec. 8.4.1.1, 8.4.3, 8.4.5, 8.6
  1901. X     *   sys$assign(), sys$qio() info:  Programming, Vol. 4B, System Services,
  1902. X     *     System Services Reference Manual, pp. sys-23, sys-379
  1903. X     *   fixed-length descriptor info:  Programming, Vol. 3, System Services,
  1904. X     *     Intro to System Routines, sec. 2.9.2
  1905. X     * GRR, 15 Aug 91
  1906. X  ---------------------------------------------------------------------------*/
  1907. X    static struct dsc$descriptor_s DevDesc =
  1908. X        {9, DSC$K_DTYPE_T, DSC$K_CLASS_S, "SYS$INPUT"};
  1909. X     /* {dsc$w_length, dsc$b_dtype, dsc$b_class, dsc$a_pointer}; */
  1910. X    static short           DevChan, iosb[4];
  1911. X    static long            i, status;
  1912. X    static unsigned long   oldmode[2], newmode[2];   /* each = 8 bytes */
  1913. X  
  1914. X
  1915. X/*---------------------------------------------------------------------------
  1916. X    Assign a channel to standard input.
  1917. X  ---------------------------------------------------------------------------*/
  1918. X
  1919. X    status = sys$assign(&DevDesc, &DevChan, 0, 0);
  1920. X    if (!(status & 1))
  1921. X        return status;
  1922. X
  1923. X/*---------------------------------------------------------------------------
  1924. X    Use sys$qio and the IO$_SENSEMODE function to determine the current tty
  1925. X    status (for password reading, could use IO$_READVBLK function instead,
  1926. X    but echo on/off will be more general).
  1927. X  ---------------------------------------------------------------------------*/
  1928. X
  1929. X    status = sys$qio(0, DevChan, IO$_SENSEMODE, &iosb, 0, 0,
  1930. X                     oldmode, 8, 0, 0, 0, 0);
  1931. X    if (!(status & 1))
  1932. X        return status;
  1933. X    status = iosb[0];
  1934. X    if (!(status & 1))
  1935. X        return status;
  1936. X
  1937. X/*---------------------------------------------------------------------------
  1938. X    Copy old mode into new-mode buffer, then modify to be either NOECHO or
  1939. X    ECHO (depending on function argument opt).
  1940. X  ---------------------------------------------------------------------------*/
  1941. X
  1942. X    newmode[0] = oldmode[0];
  1943. X    newmode[1] = oldmode[1];
  1944. X    if (opt == 0)
  1945. X        newmode[1] |= TT$M_NOECHO;                      /* set NOECHO bit */
  1946. X    else
  1947. X        newmode[1] &= ~((unsigned long) TT$M_NOECHO);   /* clear NOECHO bit */
  1948. X
  1949. X/*---------------------------------------------------------------------------
  1950. X    Use the IO$_SETMODE function to change the tty status.
  1951. X  ---------------------------------------------------------------------------*/
  1952. X
  1953. X    status = sys$qio(0, DevChan, IO$_SETMODE, &iosb, 0, 0,
  1954. X                     newmode, 8, 0, 0, 0, 0);
  1955. X    if (!(status & 1))
  1956. X        return status;
  1957. X    status = iosb[0];
  1958. X    if (!(status & 1))
  1959. X        return status;
  1960. X
  1961. X/*---------------------------------------------------------------------------
  1962. X    Deassign the sys$input channel by way of clean-up, then exit happily.
  1963. X  ---------------------------------------------------------------------------*/
  1964. X
  1965. X    status = sys$dassgn(DevChan);
  1966. X    if (!(status & 1))
  1967. X        return status;
  1968. X
  1969. X    return SS$_NORMAL;   /* we be happy */
  1970. X
  1971. X} /* end function echo() */
  1972. X
  1973. X
  1974. X#else /* !VMS */
  1975. X
  1976. Xlocal int echofd = -1;  /* file descriptor whose echo is off */
  1977. X
  1978. Xvoid echoff(f)
  1979. Xint f;                  /* file descriptor to turn echo off on */
  1980. X/* Turn echo off for file descriptor f.  Assumes that f is a tty device. */
  1981. X{
  1982. X  struct sgttyb sg;     /* tty device structure */
  1983. X
  1984. X  echofd = f;
  1985. X  GTTY(f, &sg);                                 /* get settings */
  1986. X  sg.sg_flags &= ~ECHO;                         /* turn echo off */
  1987. X  STTY(f, &sg);
  1988. X}
  1989. X
  1990. Xvoid echon()
  1991. X/* Turn echo back on for file descriptor echofd. */
  1992. X{
  1993. X  struct sgttyb sg;     /* tty device structure */
  1994. X
  1995. X  if (echofd != -1)
  1996. X  {
  1997. X    GTTY(echofd, &sg);                          /* get settings */
  1998. X    sg.sg_flags |= ECHO;                        /* turn echo on */
  1999. X    STTY(echofd, &sg);
  2000. X    echofd = -1;
  2001. X  }
  2002. X}
  2003. X
  2004. X#endif /* ?VMS */
  2005. X
  2006. X#endif /* !MSDOS */
  2007. X
  2008. X
  2009. Xchar *getp(m, p, n)
  2010. Xchar *m;                /* prompt for password */
  2011. Xchar *p;                /* return value: line input */
  2012. Xint n;                  /* bytes available in p[] */
  2013. X/* Get a password of length n-1 or less into *p using the prompt *m.
  2014. X   The entered password is not echoed.  Return p on success, NULL on
  2015. X   failure (can't get controlling tty). */
  2016. X{
  2017. X  char c;               /* one-byte buffer for read() to use */
  2018. X  int i;                /* number of characters input */
  2019. X  char *w;              /* warning on retry */
  2020. X
  2021. X#ifndef MSDOS
  2022. X#ifndef VMS
  2023. X  int f;                /* file decsriptor for tty device */
  2024. X
  2025. X  /* Turn off echo on tty */
  2026. X  if (!isatty(2))
  2027. X    return NULL;                                /* error if not tty */
  2028. X  if ((f = open(ttyname(2), 0, 0)) == -1)
  2029. X    return NULL;
  2030. X#endif /* !VMS */
  2031. X  echoff(f);                                    /* turn echo off */
  2032. X#endif /* !MSDOS */
  2033. X
  2034. X  /* Get password */
  2035. X  w = "";
  2036. X  do {
  2037. X#ifdef VMS   /* bug:  VMS adds '\n' to NULL fputs (apparently) */
  2038. X    if (*w)
  2039. X#endif /* VMS */
  2040. X    fputs(w, stderr);                           /* warning if back again */
  2041. X    fputs(m, stderr);                           /* prompt */
  2042. X    fflush(stderr);
  2043. X    i = 0;
  2044. X    do {                                        /* read line, keeping n */
  2045. X#ifdef MSVMS
  2046. X      if ((c = (char)getch()) == '\r')
  2047. X        c = '\n';
  2048. X#else /* !MSVMS */
  2049. X      read(f, &c, 1);
  2050. X#endif /* ?MSVMS */
  2051. X      if (i < n)
  2052. X        p[i++] = c;
  2053. X    } while (c != '\n');
  2054. X    putc('\n', stderr);  fflush(stderr);
  2055. X    w = "(line too long--try again)\n";
  2056. X  } while (p[i-1] != '\n');
  2057. X  p[i-1] = 0;                                   /* terminate at newline */
  2058. X
  2059. X#ifndef MSDOS
  2060. X  echon();                                      /* turn echo back on */
  2061. X#ifndef VMS
  2062. X  close(f);
  2063. X#endif /* !VMS */
  2064. X#endif /* !MSDOS */
  2065. X
  2066. X  /* Return pointer to password */
  2067. X  return p;
  2068. X}
  2069. X
  2070. X#endif /* ?CRYPT */
  2071. X
  2072. X
  2073. X#ifdef ZMEM
  2074. X
  2075. X/************************/
  2076. X/*  Function memset()  */
  2077. X/************************/
  2078. X
  2079. X/*
  2080. X * memset - for systems without it
  2081. X *  bill davidsen - March 1990
  2082. X */
  2083. X
  2084. Xchar *
  2085. Xmemset(buf, init, len)
  2086. Xregister char *buf;     /* buffer loc */
  2087. Xregister int init;      /* initializer */
  2088. Xregister unsigned int len;   /* length of the buffer */
  2089. X{
  2090. X    char *start;
  2091. X
  2092. X    start = buf;
  2093. X    while (len--) *(buf++) = init;
  2094. X    return(start);
  2095. X}
  2096. X
  2097. X
  2098. X/************************/
  2099. X/*  Function memcpy()  */
  2100. X/************************/
  2101. X
  2102. Xchar *
  2103. Xmemcpy(dst,src,len)           /* v2.0f */
  2104. Xregister char *dst, *src;
  2105. Xregister unsigned int len;
  2106. X{
  2107. X    char *start;
  2108. X
  2109. X    start = dst;
  2110. X    while (len--)
  2111. X        *dst++ = *src++;
  2112. X    return(start);
  2113. X}
  2114. X
  2115. X
  2116. X/************************/
  2117. X/*  Function memcmp()  */
  2118. X/************************/
  2119. X
  2120. Xint
  2121. Xmemcmp(b1,b2,len)                     /* jpd@usl.edu -- 11/16/90 */
  2122. Xregister char *b1, *b2;
  2123. Xregister unsigned int len;
  2124. X{
  2125. X
  2126. X    if (len) do {             /* examine each byte (if any) */
  2127. X      if (*b1++ != *b2++)
  2128. X        return (*((uch *)b1-1) - *((uch *)b2-1));  /* exit when miscompare */
  2129. X       } while (--len);
  2130. X
  2131. X    return(0);        /* no miscompares, yield 0 result */
  2132. X}
  2133. X
  2134. X#endif  /* ZMEM */
  2135. X
  2136. X#ifdef __TURBOC__
  2137. X
  2138. X/************************/
  2139. X/*  Function fcalloc()  */
  2140. X/************************/
  2141. X
  2142. X/* Turbo C malloc() does not allow dynamic allocation of 64K bytes
  2143. X * and farmalloc(64K) returns a pointer with an offset of 8, so we
  2144. X * must fix the pointer. Warning: the pointer must be put back to its
  2145. X * original form in order to free it.
  2146. X * For MSC, use halloc instead of this function (see tailor.h).
  2147. X */
  2148. Xvoid far * fcalloc(items, size)
  2149. X    unsigned items; /* number of items */
  2150. X    unsigned size;  /* item size */
  2151. X{
  2152. X    void far * buf = farmalloc((ulg)items*size + 16L);
  2153. X    /* Normalize the pointer to seg:0 */
  2154. X    *((int*)&buf+1) += ((unsigned)((uch*)buf-0) + 15) >> 4;
  2155. X    *(int*)&buf = 0;
  2156. X    return buf; /* buf stays NULL if alloc failed */
  2157. X}
  2158. X
  2159. X#endif /* __TURBOC__ */
  2160. END_OF_FILE
  2161.   if test 57097 -ne `wc -c <'fileio.c'`; then
  2162.     echo shar: \"'fileio.c'\" unpacked with wrong size!
  2163.   fi
  2164.   # end of 'fileio.c'
  2165. fi
  2166. echo shar: End of archive 2 \(of 11\).
  2167. cp /dev/null ark2isdone
  2168. MISSING=""
  2169. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2170.     if test ! -f ark${I}isdone ; then
  2171.     MISSING="${MISSING} ${I}"
  2172.     fi
  2173. done
  2174. if test "${MISSING}" = "" ; then
  2175.     echo You have unpacked all 11 archives.
  2176.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2177. else
  2178.     echo You still must unpack the following archives:
  2179.     echo "        " ${MISSING}
  2180. fi
  2181. exit 0
  2182. exit 0 # Just in case...
  2183.