home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume23 / zip / part02 < prev    next >
Text File  |  1991-10-21  |  55KB  |  2,044 lines

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