home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #18 / NN_1992_18.iso / spool / comp / sources / misc / 3844 < prev    next >
Encoding:
Text File  |  1992-08-22  |  60.6 KB  |  2,190 lines

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