home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume44 / unzip / part02 < prev    next >
Internet Message Format  |  1994-09-19  |  71KB

  1. From: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  2. Newsgroups: comp.sources.misc
  3. Subject: v44i067:  unzip - Info-ZIP portable UnZip, version 5.12, Part02/20
  4. Date: 18 Sep 1994 23:14:15 -0500
  5. Organization: Sterling Software
  6. Sender: kent@sparky.sterling.com
  7. Approved: kent@sparky.sterling.com
  8. Message-ID: <35j36n$ql8@sparky.sterling.com>
  9. X-Md4-Signature: 47ae4012b7e9e158096699c48e706456
  10.  
  11. Submitted-by: zip-bugs@wkuvx1.wku.edu (Info-ZIP group)
  12. Posting-number: Volume 44, Issue 67
  13. Archive-name: unzip/part02
  14. Environment: UNIX, VMS, OS/2, MS-DOS, MACINTOSH, WIN-NT, LINUX, MINIX, COHERENT, AMIGA?, ATARI TOS, SGI, DEC, Cray, Convex, Amdahl, Sun
  15. Supersedes: unzip50: Volume 31, Issue 104-117
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then feed it
  19. # into a shell via "sh file" or similar.  To overwrite existing files,
  20. # type "sh file -c".
  21. # Contents:  unzip-5.12/nt/Contents unzip-5.12/unzip.c
  22. # Wrapped by kent@sparky on Sat Sep 17 23:33:36 1994
  23. PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:/usr/lbin:$PATH ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 2 (of 20)."'
  26. if test -f 'unzip-5.12/nt/Contents' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'unzip-5.12/nt/Contents'\"
  28. else
  29.   echo shar: Extracting \"'unzip-5.12/nt/Contents'\" \(202 characters\)
  30.   sed "s/^X//" >'unzip-5.12/nt/Contents' <<'END_OF_FILE'
  31. XContents of the "nt" sub-archive for UnZip 5.1 and later:
  32. X
  33. X  Contents      this file
  34. X  Makefile      makefile for UnZip and MS NT SDK or VC++, or DEC C/C++
  35. X  nt.c          NT-specific support routines
  36. X
  37. END_OF_FILE
  38.   if test 202 -ne `wc -c <'unzip-5.12/nt/Contents'`; then
  39.     echo shar: \"'unzip-5.12/nt/Contents'\" unpacked with wrong size!
  40.   fi
  41.   # end of 'unzip-5.12/nt/Contents'
  42. fi
  43. if test -f 'unzip-5.12/unzip.c' -a "${1}" != "-c" ; then 
  44.   echo shar: Will not clobber existing file \"'unzip-5.12/unzip.c'\"
  45. else
  46.   echo shar: Extracting \"'unzip-5.12/unzip.c'\" \(66790 characters\)
  47.   sed "s/^X//" >'unzip-5.12/unzip.c' <<'END_OF_FILE'
  48. X/*---------------------------------------------------------------------------
  49. X
  50. X  unzip.c
  51. X
  52. X  UnZip - a zipfile extraction utility.  See below for make instructions, or
  53. X  read the comments in Makefile and the various Contents files for more de-
  54. X  tailed explanations.  To report a bug, send a *complete* description to
  55. X  zip-bugs@wkuvx1.wku.edu; include machine type, operating system and ver-
  56. X  sion, compiler and version, and reasonably detailed error messages or prob-
  57. X  lem report.  To join Info-ZIP, see the instructions in README.
  58. X
  59. X  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
  60. X  which in turn was almost a complete rewrite of version 3.x.  For a detailed
  61. X  revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of
  62. X  the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
  63. X  distribution.
  64. X
  65. X  ---------------------------------------------------------------------------
  66. X
  67. X  [from original zipinfo.c]
  68. X
  69. X  This program reads great gobs of totally nifty information, including the
  70. X  central directory stuff, from ZIP archives ("zipfiles" for short).  It
  71. X  started as just a testbed for fooling with zipfiles, but at this point it
  72. X  is actually a useful utility.  It also became the basis for the rewrite of
  73. X  UnZip (3.16 -> 4.0), using the central directory for processing rather than
  74. X  the individual (local) file headers.
  75. X
  76. X  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
  77. X  If the executable is named "unzip" (or "unzip.exe", depending), it behaves
  78. X  like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
  79. X  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
  80. X  option; for example, "unzip -Z [zipinfo_options] archive.zip".
  81. X
  82. X  Another dandy product from your buddies at Newtware!
  83. X
  84. X  Author:  Greg Roelofs, newt@uchicago.edu, 23 August 1990 -> ... 1994
  85. X
  86. X  ---------------------------------------------------------------------------
  87. X
  88. X  Version:  unzip512.{tar.Z | zip | zoo} for Unix, VMS, OS/2, MS-DOS, Windows,
  89. X              Windows NT, Macintosh, Amiga, Atari, Human68K and TOPS-20.  De-
  90. X              cryption requires sources in zcrypt23.zip, and Windows (not NT)
  91. X              support requires sources in wunz20sr.zip (not up to date).  See
  92. X              accompanying file "Where" in the main source distribution for
  93. X              ftp, uucp and mail-server sites.
  94. X
  95. X  Copyrights:  see accompanying file "COPYING" in UnZip source distribution.
  96. X
  97. X  ---------------------------------------------------------------------------*/
  98. X
  99. X
  100. X
  101. X#include "unzip.h"        /* includes, typedefs, macros, prototypes, etc. */
  102. X#include "crypt.h"
  103. X#include "version.h"
  104. X#ifdef MSWIN
  105. X#  include "wizunzip.h"
  106. X#endif
  107. X
  108. X
  109. X
  110. X/**********************/
  111. X/*  Global Variables  */
  112. X/**********************/
  113. X
  114. Xint zipinfo_mode;     /* behave like ZipInfo or like normal UnZip? */
  115. X
  116. Xint aflag=0;          /* -a: do ASCII-EBCDIC and/or end-of-line translation */
  117. Xint cflag=0;          /* -c: output to stdout */
  118. Xint C_flag=0;         /* -C: match filenames case-insensitively */
  119. Xint dflag=0;          /* -d: all args are files/dirs to be extracted */
  120. Xint fflag=0;          /* -f: "freshen" (extract only newer files) */
  121. Xint hflag=0;          /* -h: header line (zipinfo) */
  122. Xint jflag=0;          /* -j: junk pathnames (unzip) */
  123. Xint lflag=(-1);       /* -12slmv: listing format (zipinfo) */
  124. Xint L_flag=0;         /* -L: convert filenames from some OSes to lowercase */
  125. Xint overwrite_none=0; /* -n: never overwrite files (no prompting) */
  126. Xint overwrite_all=0;  /* -o: OK to overwrite files without prompting */
  127. Xint force_flag=0;     /* (shares -o for now): force to override errors, etc. */
  128. Xint qflag=0;          /* -q: produce a lot less output */
  129. X#ifdef DOS_NT_OS2
  130. X   int sflag=0;       /* -s: convert filename spaces (blanks) to underscores */
  131. X   int volflag=0;     /* -$: extract volume labels */
  132. X#endif
  133. Xint tflag=0;          /* -t: test (unzip) or totals line (zipinfo) */
  134. Xint T_flag=0;         /* -T: decimal time format (zipinfo) */
  135. Xint uflag=0;          /* -u: "update" (extract only newer & brand-new files) */
  136. Xint vflag=0;          /* -v: (verbosely) list directory */
  137. Xint V_flag=0;         /* -V: don't strip VMS version numbers */
  138. X#ifdef VMS
  139. X   int secinf=0;      /* -X: keep owner/protection */
  140. X#endif
  141. Xint zflag=0;          /* -z: display the zipfile comment (only, for unzip) */
  142. X
  143. Xint filespecs;        /* number of real file specifications to be matched */
  144. Xint xfilespecs;       /* number of excluded filespecs to be matched */
  145. Xint process_all_files = 0;
  146. Xint create_dirs;      /* used by main(), mapname(), checkdir() */
  147. Xint extract_flag;
  148. X
  149. X#if (defined(CRYPT) || !defined(NO_ZIPINFO))
  150. X   int newzip;        /* used in extract.c, crypt.c, zipinfo.c */
  151. X#endif
  152. X
  153. XLONGINT real_ecrec_offset, expect_ecrec_offset;
  154. X
  155. Xlong csize;           /* used by list_files(), ReadByte(): must be signed */
  156. Xlong ucsize;          /* used by list_files(), unReduce(), explode() */
  157. Xlong used_csize;      /* used by extract_or_test_member(), explode() */
  158. X
  159. Xstatic char *fnames[2] = {"*", NULL};   /* default filenames vector */
  160. Xchar **pfnames = fnames, **pxnames = &fnames[1];
  161. Xchar near sig[5];
  162. Xchar near answerbuf[10];
  163. X
  164. Xmin_info info[DIR_BLKSIZ], *pInfo=info;
  165. X
  166. X/*---------------------------------------------------------------------------
  167. X    unreduce/unshrink/explode/inflate working storage and globals:
  168. X  ---------------------------------------------------------------------------*/
  169. X
  170. Xunion work area;              /* see unzip.h for the definition of work */
  171. Xulg crc32val;
  172. X
  173. Xush near mask_bits[] = {
  174. X    0x0000,
  175. X    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
  176. X    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
  177. X};
  178. X
  179. X/*---------------------------------------------------------------------------
  180. X    Input file variables:
  181. X  ---------------------------------------------------------------------------*/
  182. X
  183. Xuch *inbuf, *inptr;             /* input buffer (any size is OK) and pointer */
  184. Xint incnt;
  185. X
  186. Xulg bitbuf;
  187. Xint bits_left;
  188. Xboolean zipeof;
  189. X
  190. X#ifdef SFX
  191. X   char *argv0;                 /* used for NT and EXE_EXTENSION */
  192. X#else
  193. X   char *wildzipfn;
  194. X#endif
  195. Xchar *zipfn;    /* GRR:  MSWIN:  must nuke any malloc'd zipfn... */
  196. X
  197. Xint zipfd;                      /* zipfile file handle */
  198. XLONGINT ziplen;
  199. X
  200. Xuch *hold;
  201. Xchar near local_hdr_sig[5];     /* initialize signatures at runtime so unzip */
  202. Xchar near central_hdr_sig[5];   /*  executable won't look like a zipfile */
  203. Xchar near end_central_sig[5];
  204. X/* char extd_local_sig[5];  NOT USED YET */
  205. X
  206. Xcdir_file_hdr crec;             /* used in unzip.c, extract.c, misc.c */
  207. Xlocal_file_hdr lrec;            /* used in unzip.c, extract.c */
  208. Xecdir_rec ecrec;                /* used in unzip.c, extract.c */
  209. Xstruct stat statbuf;            /* used by main, mapname, check_for_newer */
  210. X
  211. XLONGINT cur_zipfile_bufstart;   /* extract_or_test_files, readbuf, ReadByte */
  212. XLONGINT extra_bytes = 0;        /* used in unzip.c, misc.c */
  213. X
  214. Xuch *extra_field = (uch *)NULL; /* used by VMS, Mac and OS/2 versions */
  215. X
  216. X#ifdef MACOS
  217. X   short  gnVRefNum;
  218. X   long  glDirID;
  219. X   OSType  gostCreator;
  220. X   OSType  gostType;
  221. X   boolean  fMacZipped;
  222. X   boolean  macflag;
  223. X   CursHandle  rghCursor[4];    /* status cursors */
  224. X   short  giCursor = 0;
  225. X#endif
  226. X
  227. X/*---------------------------------------------------------------------------
  228. X    Output stream variables:
  229. X  ---------------------------------------------------------------------------*/
  230. X
  231. Xint mem_mode = 0;
  232. Xint disk_full;
  233. X#ifdef SYMLINKS
  234. X   int symlnk;
  235. X#endif
  236. XFILE *outfile;
  237. Xuch *outbuf;
  238. Xuch *outptr;
  239. Xulg outcnt;                     /* number of chars stored in outbuf */
  240. X#ifdef SMALL_MEM
  241. X   uch *outbuf2;                /* initialized in main() (never changes) */
  242. X#else
  243. X   uch *outbuf2 = (uch *)NULL;  /* malloc'd ONLY if unshrink and -a */
  244. X#endif
  245. X#ifdef MSWIN
  246. X   char *filename;
  247. X#else
  248. X   char near filename[FILNAMSIZ];  /* also used by NT for temporary SFX path */
  249. X#endif
  250. X
  251. X
  252. X
  253. X
  254. X
  255. X/********************/
  256. X/*  Global strings  */
  257. X/********************/
  258. X
  259. Xchar Far UnzipVersion[] = UZ_VERSION;   /* now defined in version.h */
  260. X#ifndef NO_ZIPINFO
  261. X   char Far ZipinfoVersion[] = ZI_VERSION;
  262. X#endif
  263. X
  264. Xchar Far EndSigMsg[] = "\nnote:\
  265. X  didn't find end-of-central-dir signature at end of central dir.\n";
  266. Xchar Far CentSigMsg[] =
  267. X  "error:  expected central file header signature not found (file #%u).\n";
  268. Xchar Far SeekMsg[] =
  269. X  "error [%s]:  attempt to seek before beginning of zipfile\n%s";
  270. Xchar Far FilenameNotMatched[] = "caution: filename not matched:  %s\n";
  271. Xchar Far ExclFilenameNotMatched[] =
  272. X  "caution: excluded filename not matched:  %s\n";
  273. X
  274. X#ifndef SFX
  275. X  char Far CompiledWith[] = "Compiled with %s%s for %s%s%s%s.\n\n";
  276. X#endif
  277. X
  278. X#ifdef VMS
  279. X  char Far ReportMsg[] = "\
  280. X  (please check that you have transferred or created the zipfile in the\n\
  281. X  appropriate BINARY mode--this includes ftp, Kermit, AND unzip'd zipfiles)\n";
  282. X#else
  283. X  char Far ReportMsg[] = "\
  284. X  (please check that you have transferred or created the zipfile in the\n\
  285. X  appropriate BINARY mode and that you have compiled unzip properly)\n";
  286. X#endif
  287. X
  288. X/*******************/
  289. X/*  Local strings  */
  290. X/*******************/
  291. X
  292. X#ifndef SFX
  293. X   static char Far EnvUnZip[] = ENV_UNZIP;
  294. X   static char Far EnvUnZip2[] = ENV_UNZIP2;
  295. X   static char Far EnvZipInfo[] = ENV_ZIPINFO;
  296. X   static char Far EnvZipInfo2[] = ENV_ZIPINFO2;
  297. X#endif
  298. X
  299. X#if (!defined(SFX) || defined(SFX_EXDIR))
  300. X   static char Far NotExtracting[] = "caution:  not extracting; -d ignored\n";
  301. X   static char Far MustGiveExdir[] =
  302. X     "error:  must specify directory to which to extract with -d option\n";
  303. X#endif
  304. X
  305. Xstatic char Far CentDirTooLong[] =
  306. X  "error [%s]:  reported length of central directory is\n\
  307. X  %d bytes too long (Atari STZip zipfile?  J.H.Holm ZIPSPLIT 1.1\n\
  308. X  zipfile?).  Compensating...\n";
  309. Xstatic char Far InvalidOptionsMsg[] = "error:\
  310. X  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
  311. Xstatic char Far IgnoreOOptionMsg[] =
  312. X  "caution:  both -n and -o specified; ignoring -o\n";
  313. Xstatic char Far CantAllocateBuffers[] =
  314. X  "error:  can't allocate unzip buffers\n";
  315. X
  316. X/* usage() strings */
  317. X#ifndef VMSCLI
  318. X#ifndef SFX
  319. X#ifdef VMS
  320. X    static char Far Example2[] = "vms.c";
  321. X    static char Far Example1[] = 
  322. X"unzip \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS";
  323. X#else
  324. X    static char Far Example2[] = "ReadMe";
  325. X    static char Far Example1[] =
  326. X"unzip -p foo | more  => send contents of foo.zip via pipe into program more";
  327. X#endif /* ?VMS */
  328. X
  329. X#ifdef DOS_NT_OS2
  330. X    static char Far loc_str[] = " -$  label removables (-$$ => fixed disks)";
  331. X    static char Far loc2str[] = "\
  332. X                                             -s  spaces in filenames => '_'\n";
  333. X#else /* !DOS_NT_OS2 */
  334. X#ifdef VMS
  335. X    static char Far loc_str[] = "\"-X\" restore owner/protection info";
  336. X    static char Far loc2str[] = "\n";
  337. X#else
  338. X    static char Far loc_str[] = "";   /* Unix, Amiga, Mac, etc. */
  339. X /* char Far loc_str[] = " -X  restore UID/GID info";    Unix version, in 5.2 */
  340. X    static char Far loc2str[] = "";
  341. X#endif /* ?VMS */
  342. X#endif /* ?DOS_NT_OS2 */
  343. X#endif /* !SFX */
  344. X
  345. X#ifndef NO_ZIPINFO
  346. X#ifdef VMSWILD
  347. X   static char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
  348. X#else
  349. X   static char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
  350. X#endif
  351. Xstatic char Far ZipInfoUsageLine1[] = "\
  352. XZipInfo %s, by Newtware and the fine folks at Info-ZIP.\n\
  353. X\n\
  354. XList name, date/time, attribute, size, compression method, etc., about files\n\
  355. Xin list (excluding those in xlist) contained in the specified .zip archive(s).\
  356. X\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
  357. X   usage:  zipinfo [-12smlvhtTz] file[.zip] [list...] [-x xlist...]\n\
  358. X      or:  unzip %s-Z%s [-12smlvhtTz] file[.zip] [list...] [-x xlist...]\n";
  359. X
  360. Xstatic char Far ZipInfoUsageLine2[] = "\nmain\
  361. X listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
  362. X  -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
  363. X  -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
  364. X                                         -v  verbose, multi-page format\n";
  365. X
  366. Xstatic char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
  367. X  -h  print header line       -t  print totals for listed files or for all\n\
  368. X  -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
  369. X\n  -x  exclude filenames that follow from listing\n";
  370. X/*"  -p  disable automatic \"more\" function (for pipes) [not implemented]\n";*/
  371. X#endif /* !NO_ZIPINFO */
  372. X#endif /* !VMSCLI */
  373. X
  374. X#ifdef BETA
  375. X   static char Far BetaVersion[] = "%s\
  376. X      THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
  377. X#endif
  378. X
  379. X#ifdef SFX
  380. X# if (defined(SFX_EXDIR) && !defined(VMS))
  381. X   static char Far UnzipSFXUsage[] = "\
  382. XUnZipSFX %s, by Info-ZIP (zip-bugs@wkuvx1.wku.edu).\n\
  383. XValid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCLV%s.\n";
  384. X# else
  385. X   static char Far UnzipSFXUsage[] = "\
  386. XUnZipSFX %s, by Info-ZIP (zip-bugs@wkuvx1.wku.edu).\n\
  387. XValid options are -tfupcz; modifiers are -abjnoqCLV%s.\n";
  388. X# endif
  389. X   static char Far CantFindMyself[] =
  390. X     "unzipsfx:  can't find myself! [%s]\n";
  391. X#else /* !SFX */
  392. X   static char Far CompileOptions[] = "UnZip special compilation options:\n";
  393. X   static char Far CompileOptFormat[] = "\t%s\n";
  394. X   static char Far EnvOptions[] = "\nUnZip and ZipInfo environment options:\n";
  395. X   static char Far EnvOptFormat[] = "%16s:  %s\n";
  396. X   static char Far None[] = "[none]";
  397. X#  ifdef NO_ZIPINFO
  398. X     static char Far No_ZipInfo[] = "NO_ZIPINFO";
  399. X#  endif
  400. X#  ifdef CHECK_EOF
  401. X     static char Far Check_EOF[] = "CHECK_EOF";
  402. X#  endif
  403. X#  ifdef DOSWILD
  404. X     static char Far DosWild[] = "DOSWILD";
  405. X#  endif
  406. X#  ifdef VMSWILD
  407. X     static char Far VmsWild[] = "VMSWILD";
  408. X#  endif
  409. X#  ifdef VMSCLI
  410. X     static char Far VmsCLI[] = "VMSCLI";
  411. X#  endif
  412. X#  ifdef ASM_INFLATECODES
  413. X     static char Far AsmInflateCodes[] = "ASM_INFLATECODES";
  414. X#  endif
  415. X#  ifdef ASM_CRC
  416. X     static char Far AsmCRC[] = "ASM_CRC";
  417. X#  endif
  418. X#  ifdef REGARGS
  419. X     static char Far RegArgs[] = "REGARGS";
  420. X#  endif
  421. X#  ifdef OLD_EXDIR
  422. X     static char Far Old_Exdir[] = "OLD_EXDIR";
  423. X#  endif
  424. X#  ifdef CHECK_VERSIONS
  425. X     static char Far Check_Versions[] = "CHECK_VERSIONS";
  426. X#  endif
  427. X#  ifdef RETURN_CODES
  428. X     static char Far Return_Codes[] = "RETURN_CODES";
  429. X#  endif
  430. X#  ifdef RETURN_SEVERITY
  431. X     static char Far Return_Severity[] = "RETURN_SEVERITY";
  432. X#  endif
  433. X#  ifdef DEBUG
  434. X     static char Far Debug[] = "DEBUG";
  435. X#  endif
  436. X#  ifdef DEBUG_TIME
  437. X     static char Far DebugTime[] = "DEBUG_TIME";
  438. X#  endif
  439. X#  ifdef CRYPT
  440. X     static char Far Decryption[] = "[decryption]";
  441. X#  endif
  442. X#  ifdef __EMX__
  443. X     static char Far EnvEMX[] = "EMX";
  444. X     static char Far EnvEMXOPT[] = "EMXOPT";
  445. X#  endif
  446. X#  ifdef __GO32__
  447. X     static char Far EnvGO32[] = "GO32";
  448. X     static char Far EnvGO32TMP[] = "GO32TMP";
  449. X#  endif
  450. X
  451. X/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
  452. Xchar Far UnzipUsageLine1[] = "\
  453. XUnZip %s, by Info-ZIP.  Portions (c) 1989 by S. H. Smith.\n\
  454. XSend bug reports to authors at zip-bugs@wkuvx1.wku.edu; see README for details.\
  455. X\n\n";
  456. Xstatic char Far UnzipUsageLine2a[] = "\
  457. XLatest sources and executables are always in ftp.uu.net:/pub/archiving/zip, at\
  458. X\nleast as of date of this release; see \"Where\" for other ftp and non-ftp \
  459. Xsites.\n\n";
  460. X
  461. X#ifndef VMSCLI
  462. Xstatic char Far UnzipUsageLine2[] = "\
  463. XUsage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
  464. X Default action is to extract files in list, except those in xlist, to exdir;\n\
  465. X  file[.zip] may be a wildcard.  %s\n\n";
  466. X
  467. X#ifdef NO_ZIPINFO
  468. X#  define ZIPINFO_MODE_OPTION  ""
  469. X   static char Far ZipinfoMode[] =
  470. X     "(ZipInfo mode is disabled in this version.)";
  471. X#else
  472. X#  define ZIPINFO_MODE_OPTION  "[-Z] "
  473. X#  ifdef VMS
  474. X     static char Far ZipinfoMode[] =
  475. X       "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
  476. X#  else
  477. X     static char Far ZipinfoMode[] =
  478. X       "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
  479. X#  endif
  480. X#endif /* ?NO_ZIPINFO */
  481. X
  482. Xstatic char Far UnzipUsageLine3[] = "\
  483. X  -p  extract files to pipe, no messages     -l  list files (short format)\n\
  484. X  -f  freshen existing files, create none    -t  test compressed archive data\n\
  485. X  -u  update files, create if necessary      -z  display archive comment\n\
  486. X  -x  exclude files which follow (in xlist)  -d  extract files into exdir\n\n";
  487. X
  488. Xstatic char Far UnzipUsageLine4[] = "\
  489. Xmodifiers:                                   -q  quiet mode (-qq => quieter)\n\
  490. X  -n  never overwrite existing files         -a  auto-convert any text files\n\
  491. X  -o  overwrite files WITHOUT prompting      -aa treat ALL files as text\n \
  492. X -j  junk paths (don't make directories)    -v  be verbose/print version info\n\
  493. X %c-C%c match filenames case-insensitively    %c-L%c make (some) names \
  494. Xlowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
  495. X
  496. Xstatic char Far UnzipUsageLine5[] = "\
  497. XExamples (see unzip.doc for more info):\n\
  498. X  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
  499. X  %s\n\
  500. X  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
  501. X#endif /* !VMSCLI */
  502. X
  503. X/* process_zipfiles() strings */
  504. X   static char Far FilesProcessOK[] = "%d archive%s successfully processed.\n";
  505. X   static char Far ArchiveWarning[] =
  506. X     "%d archive%s had warnings but no fatal errors.\n";
  507. X   static char Far ArchiveFatalError[] = "%d archive%s had fatal errors.\n";
  508. X   static char Far FileHadNoZipfileDir[] =
  509. X     "%d file%s had no zipfile directory.\n";
  510. X   static char Far ZipfileWasDir[] = "1 \"zipfile\" was a directory.\n";
  511. X   static char Far ManyZipfilesWereDir[] =
  512. X     "%d \"zipfiles\" were directories.\n";
  513. X   static char Far NoZipfileFound[] = "No zipfiles found.\n";
  514. X#endif /* ?SFX */
  515. X
  516. X/* do_seekable() strings */
  517. X#ifndef SFX
  518. X#ifdef UNIX
  519. X   static char Far CantFindZipfileDirMsg[] =
  520. X     "%s:  can't find zipfile directory in one of %s or\n\
  521. X        %s%s.zip, and can't find %s, period.\n";
  522. X   static char Far CantFindEitherZipfile[] =
  523. X     "%s:  can't find %s, %s.zip or %s, so there.\n";
  524. X#else /* !UNIX */
  525. X   static char Far CantFindZipfileDirMsg[] =
  526. X     "%s:  can't find zipfile directory in %s,\n\
  527. X        %sand can't find %s, period.\n";
  528. X   static char Far CantFindEitherZipfile[] =
  529. X     "%s:  can't find either %s or %s, so there.\n";
  530. X#endif /* ?UNIX */
  531. X   static char Far MaybeExe[] =
  532. X     "note:  %s may be a plain executable, not an archive\n";
  533. X   static char Far CentDirNotInZipMsg[] = "\n\
  534. X     Zipfile is part of a multi-disk archive, and this is not the disk on\n\
  535. X     which the central zipfile directory begins.\n";
  536. X#ifdef NO_MULTIPART
  537. X   static char Far NoMultiDiskArcSupport[] =
  538. X     "\nerror [%s]:  zipfile is part of multi-disk archive\n\
  539. X  (sorry, not yet supported).\n";
  540. X   static char Far MaybePakBug[] = "warning [%s]:\
  541. X  zipfile claims to be 2nd disk of a 2-part archive;\n\
  542. X  attempting to process anyway.  If no further errors occur, this archive\n\
  543. X  was probably created by PAK v2.51 or earlier.  This bug was reported to\n\
  544. X  NoGate in March 1991 and was supposed to have been fixed by mid-1991; as\n\
  545. X  of mid-1992 it still hadn't been.  (If further errors do occur, archive\n\
  546. X  was probably created by PKZIP 2.04c or later; UnZip does not yet support\n\
  547. X  multi-part archives.)\n";
  548. X#else
  549. X   static char Far MaybePakBug[] = "warning [%s]:\
  550. X  zipfile claims to be last disk of a multi-part archive;\n\
  551. X  attempting to process anyway, assuming all parts have been concatenated\n\
  552. X  together in order.  Expect \"errors\" and warnings...true multi-part support\
  553. X\n  doesn't exist yet (coming soon).\n";
  554. X#endif
  555. X   static char Far ExtraBytesAtStart[] =
  556. X     "warning [%s]:  extra %ld bytes at beginning or within zipfile\n\
  557. X  (attempting to process anyway)\n";
  558. X#endif /* !SFX */
  559. X
  560. Xstatic char Far MissingBytes[] =
  561. X  "error [%s]:  missing %ld bytes in zipfile\n\
  562. X  (attempting to process anyway)\n";
  563. Xstatic char Far NullCentDirOffset[] =
  564. X  "error [%s]:  NULL central directory offset\n\
  565. X  (attempting to process anyway)\n";
  566. Xstatic char Far ZipfileEmpty[] = "warning [%s]:  zipfile is empty\n";
  567. Xstatic char Far CentDirStartNotFound[] =
  568. X  "error [%s]:  start of central directory not found;\n\
  569. X  zipfile corrupt.\n%s";
  570. Xstatic char Far ZipfileCommTrunc1[] = "\ncaution:  zipfile comment truncated\n";
  571. X
  572. X
  573. X
  574. X
  575. X
  576. X#ifdef MSWIN
  577. X#  include "winsetup.c"   /* duplicates some code in main() */
  578. X#else /* !MSWIN */
  579. X
  580. X
  581. X
  582. X/******************/
  583. X/*  Main program  */
  584. X/******************/
  585. X
  586. Xint MAIN(argc, argv)   /* return PK-type error code (except under VMS) */
  587. X    int argc;
  588. X    char *argv[];
  589. X{
  590. X#ifndef NO_ZIPINFO
  591. X    char *p;
  592. X#endif
  593. X    int error=FALSE;
  594. X#if defined(__IBMC__) && defined(__DEBUG_ALLOC__)
  595. X    extern void DebugMalloc(void);
  596. X
  597. X
  598. X    atexit(DebugMalloc);
  599. X#endif
  600. X
  601. X/*---------------------------------------------------------------------------
  602. X    Macintosh initialization code.
  603. X  ---------------------------------------------------------------------------*/
  604. X
  605. X#ifdef MACOS
  606. X    int a;
  607. X
  608. X    for (a = 0;  a < 4;  ++a)
  609. X        rghCursor[a] = GetCursor(a+128);
  610. X    giCursor = 0;
  611. X
  612. X    aflag=cflag=dflag=fflag=L_flag=jflag=qflag=tflag=uflag=vflag=zflag = 0;
  613. X    local_hdr_sig[1] = central_hdr_sig[1] = end_central_sig[1] = '\0';
  614. X/*  extd_local_sig[1] = '\0';  */
  615. X    error = FALSE;
  616. X
  617. X    overwrite_none = overwrite_all = force_flag = 0;
  618. X#endif /* MACOS */
  619. X
  620. X#ifdef MALLOC_WORK
  621. X    area.Slide = (uch *)calloc(8193, sizeof(short)+sizeof(char)+sizeof(char));
  622. X    area.shrink.Prefix_of = (short *)area.Slide;
  623. X    area.shrink.Suffix_of = area.Slide + (sizeof(short)*(HSIZE+1));
  624. X    area.shrink.Stack = area.Slide + (sizeof(short) + sizeof(char))*(HSIZE+1);
  625. X#endif
  626. X
  627. X/*---------------------------------------------------------------------------
  628. X    Human68K initialization code.
  629. X  ---------------------------------------------------------------------------*/
  630. X
  631. X#ifdef __human68k__
  632. X    InitTwentyOne();
  633. X#endif
  634. X
  635. X/*---------------------------------------------------------------------------
  636. X    Set signal handler for restoring echo, warn of zipfile corruption, etc.
  637. X  ---------------------------------------------------------------------------*/
  638. X
  639. X    signal(SIGINT, handler);
  640. X#ifdef SIGTERM                 /* some systems really have no SIGTERM */
  641. X    signal(SIGTERM, handler);
  642. X#endif
  643. X#ifdef SIGBUS
  644. X    signal(SIGBUS, handler);
  645. X#endif
  646. X#ifdef SIGSEGV
  647. X    signal(SIGSEGV, handler);
  648. X#endif
  649. X
  650. X/*---------------------------------------------------------------------------
  651. X    First figure out if we're running in UnZip mode or ZipInfo mode, and put
  652. X    the appropriate environment-variable options into the queue.  Then rip
  653. X    through any command-line options lurking about...
  654. X  ---------------------------------------------------------------------------*/
  655. X
  656. X#ifdef SFX
  657. X    argv0 = argv[0];
  658. X#if defined(OS2) || defined(NT)
  659. X    zipfn = GetLoadPath();   /* non-MSC NT puts path into filename[] */
  660. X#else
  661. X    zipfn = argv0;
  662. X#endif
  663. X    zipinfo_mode = FALSE;
  664. X    if ((error = uz_opts(&argc, &argv)) != 0)
  665. X        RETURN(error);
  666. X
  667. X#else /* !SFX */
  668. X
  669. X#ifdef MSDOS
  670. X    /* extract MKS extended argument list from environment (before envargs!) */
  671. X    mksargs(&argc, &argv);
  672. X#endif
  673. X
  674. X#ifdef VMSCLI
  675. X    {
  676. X        ulg status = vms_unzip_cmdline(&argc, &argv);
  677. X        if (!(status & 1))
  678. X            return status;
  679. X    }
  680. X#endif /* VMSCLI */
  681. X
  682. X#ifndef NO_ZIPINFO
  683. X    if ((p = strrchr(argv[0], DIR_END)) == (char *)NULL)
  684. X        p = argv[0];
  685. X    else
  686. X        ++p;
  687. X
  688. X    if (STRNICMP(p, "zipinfo", 7) == 0 || STRNICMP(p, "ii", 2) == 0 ||
  689. X        (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
  690. X    {
  691. X        zipinfo_mode = TRUE;
  692. X        envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),
  693. X          LoadFarStringSmall2(EnvZipInfo2));
  694. X        error = zi_opts(&argc, &argv);
  695. X    } else
  696. X#endif /* NO_ZIPINFO */
  697. X    {
  698. X        zipinfo_mode = FALSE;
  699. X        envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),
  700. X          LoadFarStringSmall2(EnvUnZip2));
  701. X        error = uz_opts(&argc, &argv);
  702. X    }
  703. X    if ((argc < 0) || error)
  704. X        RETURN(error);
  705. X
  706. X#endif /* ?SFX */
  707. X
  708. X/*---------------------------------------------------------------------------
  709. X    Now get the zipfile name from the command line and then process any re-
  710. X    maining options and file specifications.
  711. X  ---------------------------------------------------------------------------*/
  712. X
  713. X#ifdef DOS_NT_OS2
  714. X    /* convert MSDOS-style directory separators to Unix-style ones for
  715. X     * user's convenience (include zipfile name itself)
  716. X     */
  717. X    pfnames = argv;
  718. X    while (*pfnames != NULL) {
  719. X        char *q;
  720. X
  721. X        for (q = *pfnames;  *q;  ++q)
  722. X            if (*q == '\\')
  723. X                *q = '/';
  724. X        ++pfnames;
  725. X    }
  726. X#endif /* DOS_NT_OS2 */
  727. X
  728. X#ifndef SFX
  729. X    wildzipfn = *argv++;
  730. X#endif
  731. X
  732. X#if (defined(OLD_EXDIR) || (defined(SFX) && !defined(SFX_EXDIR)))
  733. X
  734. X#ifndef SFX
  735. X    if (argc > 0) {
  736. X        /* -d:  "name/" immediately after zipfile name is a stored directory to
  737. X         * be extracted--do NOT treat as directory to which to extract files
  738. X         */
  739. X        if (extract_flag && !dflag) {
  740. X            create_dirs = !fflag;
  741. X            if ((error = checkdir(*argv, ROOT)) > 2)  /* mem, or file in way */
  742. X                RETURN(error);
  743. X            else if (!error) {   /* it IS extract-to dir, so adjust pointers */
  744. X                ++argv;
  745. X                --argc;
  746. X            }
  747. X        }
  748. X    }
  749. X#endif /* !SFX */
  750. X
  751. X    filespecs = argc;
  752. X    xfilespecs = 0;
  753. X
  754. X    if (argc > 0) {
  755. X        char **pp = argv-1;
  756. X
  757. X        pfnames = argv;
  758. X        while (*++pp)
  759. X            if (strcmp(*pp, "-x") == 0) {
  760. X                if (pp > argv) {
  761. X                    *pp = 0;           /* terminate pfnames */
  762. X                    filespecs = pp - pfnames;
  763. X                } else {
  764. X                    pfnames = fnames;  /* defaults */
  765. X                    filespecs = 0;
  766. X                }
  767. X                pxnames = pp + 1;      /* excluded-names ptr starts after -x */
  768. X                xfilespecs = argc - filespecs - 1;
  769. X                break;                 /* skip rest of args */
  770. X            }
  771. X        process_all_files = FALSE;
  772. X    } else
  773. X        process_all_files = TRUE;       /* for speed */
  774. X
  775. X#else /* !(OLD_EXDIR || (SFX && !SFX_EXDIR)) */
  776. X
  777. X    filespecs = argc;
  778. X    xfilespecs = 0;
  779. X
  780. X    if (argc > 0) {
  781. X        int in_files=FALSE, in_xfiles=FALSE;
  782. X        char **pp = argv-1;
  783. X
  784. X        process_all_files = FALSE;
  785. X        pfnames = argv;
  786. X        while (*++pp) {
  787. X            Trace((stderr, "pp - argv = %d\n", pp-argv));
  788. X            if (!dflag && strncmp(*pp, "-d", 2) == 0) {
  789. X                char *q = *pp;
  790. X                int firstarg = (pp == argv);
  791. X
  792. X                dflag = TRUE;
  793. X                if (in_files) {      /* ... zipfile ... -d exdir ... */
  794. X                    *pp = 0;                    /* terminate pfnames */
  795. X                    filespecs = pp - pfnames;
  796. X                    in_files = FALSE;
  797. X                } else if (in_xfiles) {
  798. X                    *pp = 0;                    /* terminate pxnames */
  799. X                    xfilespecs = pp - pxnames;
  800. X                    /* "... -x xlist -d exdir":  nothing left */
  801. X                }
  802. X                /* first check for "-dpath", then for "-d path" */
  803. X                if (q[2])
  804. X                    q += 2;
  805. X                else if (*++pp)
  806. X                    q = *pp;
  807. X                else {
  808. X                    FPRINTF(stderr, LoadFarString(MustGiveExdir));
  809. X                    RETURN(PK_PARAM);  /* don't extract here by accident */
  810. X                }
  811. X                if (extract_flag) {
  812. X                    create_dirs = !fflag;
  813. X                    if ((error = checkdir(q, ROOT)) > 2)
  814. X                        RETURN(error);  /* out of memory, or file in way */
  815. X                } else
  816. X                    FPRINTF(stderr, LoadFarString(NotExtracting));
  817. X                if (firstarg)   /* ... zipfile -d exdir ... */
  818. X                    if (pp[1]) {
  819. X                        pfnames = pp + 1;  /* argv+2 */
  820. X                        filespecs = argc - (pfnames-argv);  /* for now... */
  821. X                    } else {
  822. X                        process_all_files = TRUE;
  823. X                        pfnames = fnames;  /* GRR: necessary? */
  824. X                        filespecs = 0;     /* GRR: necessary? */
  825. X                        break;
  826. X                    }
  827. X            } else if (!in_xfiles) {
  828. X                if (strcmp(*pp, "-x") == 0) {
  829. X                    in_xfiles = TRUE;
  830. X                    if (pp == argv || (pp == argv+2 && dflag)) {
  831. X                        pfnames = fnames;  /* defaults */
  832. X                        filespecs = 0;
  833. X                    } else if (in_files) {
  834. X                        *pp = 0;                   /* terminate pfnames */
  835. X                        filespecs = pp - pfnames;  /* adjust count */
  836. X                        in_files = FALSE;
  837. X                    }
  838. X                    pxnames = pp + 1;  /* excluded-names ptr starts after -x */
  839. X                    xfilespecs = argc - (pxnames-argv);  /* anything left... */
  840. X                } else
  841. X                    in_files = TRUE;
  842. X            }
  843. X        }
  844. X    } else
  845. X        process_all_files = TRUE;      /* for speed */
  846. X
  847. X#endif /* ?(OLD_EXDIR || (SFX && !SFX_EXDIR)) */
  848. X
  849. X/*---------------------------------------------------------------------------
  850. X    Okey dokey, we have everything we need to get started.  Let's roll.
  851. X  ---------------------------------------------------------------------------*/
  852. X
  853. X    inbuf = (uch *)malloc(INBUFSIZ + 4);    /* 4 extra for hold[] (below) */
  854. X    outbuf = (uch *)malloc(OUTBUFSIZ + 1);  /* 1 extra for string termin. */
  855. X
  856. X    if ((inbuf == (uch *)NULL) || (outbuf == (uch *)NULL)) {
  857. X        FPRINTF(stderr, LoadFarString(CantAllocateBuffers));
  858. X        RETURN(PK_MEM);
  859. X    }
  860. X    hold = inbuf + INBUFSIZ;     /* to check for boundary-spanning signatures */
  861. X#ifdef SMALL_MEM
  862. X    outbuf2 = outbuf+RAWBUFSIZ;  /* never changes */
  863. X#endif
  864. X
  865. X    RETURN(process_zipfiles());  /* keep passing errors back... */
  866. X
  867. X} /* end main() */
  868. X
  869. X
  870. X
  871. X
  872. X
  873. X/**********************/
  874. X/* Function uz_opts() */
  875. X/**********************/
  876. X
  877. Xint uz_opts(pargc, pargv)
  878. X    int *pargc;
  879. X    char ***pargv;
  880. X{
  881. X    char **argv, *s;
  882. X    int argc, c, error=FALSE, negative=0;
  883. X
  884. X
  885. X    argc = *pargc;
  886. X    argv = *pargv;
  887. X
  888. X    while (--argc > 0 && (*++argv)[0] == '-') {
  889. X        s = argv[0] + 1;
  890. X        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  891. X            switch (c) {
  892. X                case ('-'):
  893. X                    ++negative;
  894. X                    break;
  895. X                case ('a'):
  896. X                    if (negative) {
  897. X                        aflag = MAX(aflag-negative,0);
  898. X                        negative = 0;
  899. X                    } else
  900. X                        ++aflag;
  901. X                    break;
  902. X                case ('b'):
  903. X                    if (negative)
  904. X                        negative = 0;   /* do nothing:  "-b" is default */
  905. X                    else
  906. X                        aflag = 0;
  907. X                    break;
  908. X                case ('c'):
  909. X                    if (negative) {
  910. X                        cflag = FALSE, negative = 0;
  911. X#ifdef NATIVE
  912. X                        aflag = 0;
  913. X#endif
  914. X                    } else {
  915. X                        cflag = TRUE;
  916. X#ifdef NATIVE
  917. X                        aflag = 2;  /* so you can read it on the screen */
  918. X#endif
  919. X                    }
  920. X                    break;
  921. X                case ('C'):    /* -C:  match filenames case-insensitively */
  922. X                    if (negative)
  923. X                        C_flag = FALSE, negative = 0;
  924. X                    else
  925. X                        C_flag = TRUE;
  926. X                    break;
  927. X                case ('d'):  /* arg after zipfn is stored dir, not extract-to */
  928. X#ifdef OLD_EXDIR
  929. X                    if (negative)
  930. X                        dflag = FALSE, negative = 0;
  931. X                    else
  932. X                        dflag = TRUE;
  933. X#endif
  934. X                    break;
  935. X                case ('e'):    /* just ignore -e, -x options (extract) */
  936. X                    break;
  937. X                case ('f'):    /* "freshen" (extract only newer files) */
  938. X                    if (negative)
  939. X                        fflag = uflag = FALSE, negative = 0;
  940. X                    else
  941. X                        fflag = uflag = TRUE;
  942. X                    break;
  943. X                case ('j'):    /* junk pathnames/directory structure */
  944. X                    if (negative)
  945. X                        jflag = FALSE, negative = 0;
  946. X                    else
  947. X                        jflag = TRUE;
  948. X                    break;
  949. X#ifndef SFX
  950. X                case ('l'):
  951. X                    if (negative) {
  952. X                        vflag = MAX(vflag-negative,0);
  953. X                        negative = 0;
  954. X                    } else
  955. X                        ++vflag;
  956. X                    break;
  957. X#endif /* !SFX */
  958. X                case ('L'):    /* convert (some) filenames to lowercase */
  959. X                    if (negative)
  960. X                        L_flag = FALSE, negative = 0;
  961. X                    else
  962. X                        L_flag = TRUE;
  963. X                    break;
  964. X                case ('n'):    /* don't overwrite any files */
  965. X                    if (negative)
  966. X                        overwrite_none = FALSE, negative = 0;
  967. X                    else
  968. X                        overwrite_none = TRUE;
  969. X                    break;
  970. X                case ('o'):    /* OK to overwrite files without prompting */
  971. X                    if (negative) {
  972. X                        overwrite_all = MAX(overwrite_all-negative,0);
  973. X                        force_flag = MAX(force_flag-negative,0);
  974. X                        negative = 0;
  975. X                    } else {
  976. X                        ++overwrite_all;
  977. X                        ++force_flag;  /* (share -o for now) force to cont. */
  978. X                    }
  979. X                    break;
  980. X                case ('p'):    /* pipes:  extract to stdout, no messages */
  981. X                    if (negative) {
  982. X                        cflag = FALSE;
  983. X                        qflag = MAX(qflag-999,0);
  984. X                        negative = 0;
  985. X                    } else {
  986. X                        cflag = TRUE;
  987. X                        qflag += 999;
  988. X                    }
  989. X                    break;
  990. X                case ('q'):    /* quiet:  fewer comments/messages */
  991. X                    if (negative) {
  992. X                        qflag = MAX(qflag-negative,0);
  993. X                        negative = 0;
  994. X                    } else
  995. X                        ++qflag;
  996. X                    break;
  997. X#ifdef DOS_NT_OS2
  998. X                case ('s'):    /* spaces in filenames:  allow by default */
  999. X                    if (negative)
  1000. X                        sflag = FALSE, negative = 0;
  1001. X                    else
  1002. X                        sflag = TRUE;
  1003. X                    break;
  1004. X#endif
  1005. X                case ('t'):
  1006. X                    if (negative)
  1007. X                        tflag = FALSE, negative = 0;
  1008. X                    else
  1009. X                        tflag = TRUE;
  1010. X                    break;
  1011. X                case ('u'):    /* update (extract only new and newer files) */
  1012. X                    if (negative)
  1013. X                        uflag = FALSE, negative = 0;
  1014. X                    else
  1015. X                        uflag = TRUE;
  1016. X                    break;
  1017. X                case ('U'):    /* obsolete; to be removed in future release */
  1018. X                    if (negative)
  1019. X                        L_flag = TRUE, negative = 0;
  1020. X                    else
  1021. X                        L_flag = FALSE;
  1022. X                    break;
  1023. X#ifndef SFX
  1024. X                case ('v'):    /* verbose */
  1025. X                    if (negative) {
  1026. X                        vflag = MAX(vflag-negative,0);
  1027. X                        negative = 0;
  1028. X                    } else if (vflag)
  1029. X                        ++vflag;
  1030. X                    else
  1031. X                        vflag = 2;
  1032. X                    break;
  1033. X#endif /* !SFX */
  1034. X                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
  1035. X                    if (negative)
  1036. X                        V_flag = FALSE, negative = 0;
  1037. X                    else
  1038. X                        V_flag = TRUE;
  1039. X                    break;
  1040. X                case ('x'):    /* extract:  default */
  1041. X                    break;
  1042. X#ifdef VMS
  1043. X                case ('X'):   /* restore owner/protection info (need privs?) */
  1044. X                    if (negative)
  1045. X                        secinf = FALSE, negative = 0;
  1046. X                    else
  1047. X                        secinf = TRUE;
  1048. X                    break;
  1049. X#endif /* VMS */
  1050. X                case ('z'):    /* display only the archive comment */
  1051. X                    if (negative) {
  1052. X                        zflag -= negative;
  1053. X                        negative = 0;
  1054. X                    } else
  1055. X                        ++zflag;
  1056. X                    break;
  1057. X#ifdef DOS_NT_OS2
  1058. X                case ('$'):
  1059. X                    if (negative) {
  1060. X                        volflag = MAX(volflag-negative,0);
  1061. X                        negative = 0;
  1062. X                    } else
  1063. X                        ++volflag;
  1064. X                    break;
  1065. X#endif /* DOS_NT_OS2 */
  1066. X                default:
  1067. X                    error = TRUE;
  1068. X                    break;
  1069. X
  1070. X            } /* end switch */
  1071. X        } /* end while (not end of argument string) */
  1072. X    } /* end while (not done with switches) */
  1073. X
  1074. X/*---------------------------------------------------------------------------
  1075. X    Check for nonsensical combinations of options.
  1076. X  ---------------------------------------------------------------------------*/
  1077. X
  1078. X    if ((cflag && tflag) || (cflag && uflag) || (tflag && uflag) ||
  1079. X        (fflag && overwrite_none)) {
  1080. X        FPRINTF(stderr, LoadFarString(InvalidOptionsMsg));
  1081. X        error = TRUE;
  1082. X    }
  1083. X    if (aflag > 2)
  1084. X        aflag = 2;
  1085. X    if (overwrite_all && overwrite_none) {
  1086. X        FPRINTF(stderr, LoadFarString(IgnoreOOptionMsg));
  1087. X        overwrite_all = FALSE;
  1088. X    }
  1089. X
  1090. X#ifdef SFX
  1091. X    if (error)
  1092. X#else
  1093. X    if ((argc-- == 0) || error)
  1094. X#endif
  1095. X    {
  1096. X        *pargc = argc;
  1097. X        *pargv = argv;
  1098. X#ifndef SFX
  1099. X        if (vflag >= 2 && argc == -1) {
  1100. X            if (qflag > 3)
  1101. X                PRINTF("%d\n", (UZ_MAJORVER*100 + UZ_MINORVER*10 + PATCHLEVEL));
  1102. X            else {
  1103. X                char *envptr, *getenv();
  1104. X                int numopts = 0;
  1105. X
  1106. X                PRINTF(LoadFarString(UnzipUsageLine1),
  1107. X                  LoadFarStringSmall(UnzipVersion));
  1108. X                PRINTF(LoadFarString(UnzipUsageLine2a));
  1109. X                version();
  1110. X                PRINTF(LoadFarString(CompileOptions));
  1111. X#ifdef NO_ZIPINFO
  1112. X                PRINTF(LoadFarString(CompileOptFormat),
  1113. X                  LoadFarStringSmall(No_ZipInfo));
  1114. X                ++numopts;
  1115. X#endif
  1116. X#ifdef CHECK_EOF
  1117. X                PRINTF(LoadFarString(CompileOptFormat),
  1118. X                  LoadFarStringSmall(Check_EOF));
  1119. X                ++numopts;
  1120. X#endif
  1121. X#ifdef DOSWILD
  1122. X                PRINTF(LoadFarString(CompileOptFormat),
  1123. X                  LoadFarStringSmall(DosWild));
  1124. X                ++numopts;
  1125. X#endif
  1126. X#ifdef VMSWILD
  1127. X                PRINTF(LoadFarString(CompileOptFormat),
  1128. X                  LoadFarStringSmall(VmsWild));
  1129. X                ++numopts;
  1130. X#endif
  1131. X#ifdef VMSCLI
  1132. X                PRINTF(LoadFarString(CompileOptFormat),
  1133. X                  LoadFarStringSmall(VmsCLI));
  1134. X                ++numopts;
  1135. X#endif
  1136. X#ifdef ASM_INFLATECODES
  1137. X                PRINTF(LoadFarString(CompileOptFormat),
  1138. X                  LoadFarStringSmall(AsmInflateCodes));
  1139. X                ++numopts;
  1140. X#endif
  1141. X#ifdef ASM_CRC
  1142. X                PRINTF(LoadFarString(CompileOptFormat),
  1143. X                  LoadFarStringSmall(AsmCRC));
  1144. X                ++numopts;
  1145. X#endif
  1146. X#ifdef REGARGS
  1147. X                PRINTF(LoadFarString(CompileOptFormat),
  1148. X                  LoadFarStringSmall(RegArgs));
  1149. X                ++numopts;
  1150. X#endif
  1151. X#ifdef OLD_EXDIR
  1152. X                PRINTF(LoadFarString(CompileOptFormat),
  1153. X                  LoadFarStringSmall(Old_Exdir));
  1154. X                ++numopts;
  1155. X#endif
  1156. X#ifdef CHECK_VERSIONS
  1157. X                PRINTF(LoadFarString(CompileOptFormat),
  1158. X                  LoadFarStringSmall(Check_Versions));
  1159. X                ++numopts;
  1160. X#endif
  1161. X#ifdef RETURN_CODES
  1162. X                PRINTF(LoadFarString(CompileOptFormat),
  1163. X                  LoadFarStringSmall(Return_Codes));
  1164. X                ++numopts;
  1165. X#endif
  1166. X#ifdef RETURN_SEVERITY
  1167. X                PRINTF(LoadFarString(CompileOptFormat),
  1168. X                  LoadFarStringSmall(Return_Severity));
  1169. X                ++numopts;
  1170. X#endif
  1171. X#ifdef DEBUG
  1172. X                PRINTF(LoadFarString(CompileOptFormat),
  1173. X                  LoadFarStringSmall(Debug));
  1174. X                ++numopts;
  1175. X#endif
  1176. X#ifdef DEBUG_TIME
  1177. X                PRINTF(LoadFarString(CompileOptFormat),
  1178. X                  LoadFarStringSmall(DebugTime));
  1179. X                ++numopts;
  1180. X#endif
  1181. X#ifdef CRYPT
  1182. X                PRINTF(LoadFarString(CompileOptFormat),
  1183. X                  LoadFarStringSmall(Decryption));
  1184. X                ++numopts;
  1185. X#endif
  1186. X                if (numopts == 0)
  1187. X                    PRINTF(LoadFarString(CompileOptFormat),
  1188. X                      LoadFarStringSmall(None));
  1189. X
  1190. X                PRINTF(LoadFarString(EnvOptions));
  1191. X                envptr = getenv(LoadFarStringSmall(EnvUnZip));
  1192. X                PRINTF(LoadFarString(EnvOptFormat),
  1193. X                  LoadFarStringSmall(EnvUnZip),
  1194. X                  (envptr == (char *)NULL || *envptr == 0)?
  1195. X                  LoadFarStringSmall2(None) : envptr);
  1196. X                envptr = getenv(LoadFarStringSmall(EnvUnZip2));
  1197. X                PRINTF(LoadFarString(EnvOptFormat),
  1198. X                  LoadFarStringSmall(EnvUnZip2),
  1199. X                  (envptr == (char *)NULL || *envptr == 0)?
  1200. X                  LoadFarStringSmall2(None) : envptr);
  1201. X                envptr = getenv(LoadFarStringSmall(EnvZipInfo));
  1202. X                PRINTF(LoadFarString(EnvOptFormat),
  1203. X                  LoadFarStringSmall(EnvZipInfo),
  1204. X                  (envptr == (char *)NULL || *envptr == 0)?
  1205. X                  LoadFarStringSmall2(None) : envptr);
  1206. X                envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
  1207. X                PRINTF(LoadFarString(EnvOptFormat),
  1208. X                  LoadFarStringSmall(EnvZipInfo2),
  1209. X                  (envptr == (char *)NULL || *envptr == 0)?
  1210. X                  LoadFarStringSmall2(None) : envptr);
  1211. X#ifdef __EMX__
  1212. X                envptr = getenv(LoadFarStringSmall(EnvEMX));
  1213. X                PRINTF(LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvEMX),
  1214. X                  (envptr == (char *)NULL || *envptr == 0)?
  1215. X                  LoadFarStringSmall2(None) : envptr);
  1216. X                envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
  1217. X                PRINTF(LoadFarString(EnvOptFormat),
  1218. X                  LoadFarStringSmall(EnvEMXOPT),
  1219. X                  (envptr == (char *)NULL || *envptr == 0)?
  1220. X                  LoadFarStringSmall2(None) : envptr);
  1221. X#endif /* __EMX__ */
  1222. X#ifdef __GO32__
  1223. X                envptr = getenv(LoadFarStringSmall(EnvGO32));
  1224. X                PRINTF(LoadFarString(EnvOptFormat), LoadFarStringSmall(EnvGO32),
  1225. X                  (envptr == (char *)NULL || *envptr == 0)?
  1226. X                  LoadFarStringSmall2(None) : envptr);
  1227. X                envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
  1228. X                PRINTF(LoadFarString(EnvOptFormat),
  1229. X                  LoadFarStringSmall(EnvGO32TMP),
  1230. X                  (envptr == (char *)NULL || *envptr == 0)?
  1231. X                  LoadFarStringSmall2(None) : envptr);
  1232. X#endif /* __GO32__ */
  1233. X            }
  1234. X            return 0;
  1235. X        } else
  1236. X#endif /* !SFX */
  1237. X            return usage(error);
  1238. X    }
  1239. X
  1240. X    if (cflag || tflag || vflag)
  1241. X        extract_flag = FALSE;
  1242. X    else
  1243. X        extract_flag = TRUE;
  1244. X
  1245. X    *pargc = argc;
  1246. X    *pargv = argv;
  1247. X    return 0;
  1248. X
  1249. X} /* end function uz_opts() */
  1250. X
  1251. X
  1252. X
  1253. X
  1254. X
  1255. X/********************/
  1256. X/* Function usage() */
  1257. X/********************/
  1258. X
  1259. X#ifdef SFX
  1260. X#  ifdef VMS
  1261. X#    define LOCAL "X.  Quote uppercase options"
  1262. X#  else
  1263. X#    ifdef DOS_NT_OS2
  1264. X#      define LOCAL "s$"
  1265. X#    else
  1266. X#       ifdef AMIGA
  1267. X#         define LOCAL "$"
  1268. X#       else
  1269. X#         define LOCAL ""
  1270. X#       endif
  1271. X#    endif /* ?DOS_NT_OS2 */
  1272. X#  endif /* ?VMS */
  1273. X
  1274. Xint usage(error)   /* return PK-type error code */
  1275. X    int error;
  1276. X{
  1277. X    FILE *usagefp;
  1278. X
  1279. X    if (error)
  1280. X        usagefp = (FILE *)stderr;
  1281. X    else
  1282. X        usagefp = (FILE *)stdout;
  1283. X
  1284. X    FPRINTF(usagefp, LoadFarString(UnzipSFXUsage),
  1285. X      LoadFarStringSmall(UnzipVersion), LOCAL);
  1286. X#ifdef BETA
  1287. X    FPRINTF(usagefp, LoadFarString(BetaVersion), "\n", "SFX");
  1288. X#endif
  1289. X
  1290. X    if (error)
  1291. X        return PK_PARAM;
  1292. X    else
  1293. X        return PK_COOL;     /* just wanted usage screen: no error */
  1294. X
  1295. X} /* end function usage() */
  1296. X
  1297. X
  1298. X
  1299. X
  1300. X
  1301. X#else /* !SFX */
  1302. X#ifndef VMSCLI
  1303. X
  1304. Xint usage(error)   /* return PK-type error code */
  1305. X    int error;
  1306. X{
  1307. X#ifdef VMS
  1308. X#  define QUOT '\"'
  1309. X#  define QUOTS "\""
  1310. X#else
  1311. X#  define QUOT ' '
  1312. X#  define QUOTS ""
  1313. X#endif
  1314. X
  1315. X    FILE *usagefp;
  1316. X
  1317. X
  1318. X/*---------------------------------------------------------------------------
  1319. X    If user requested usage, send it to stdout; else send to stderr.
  1320. X  ---------------------------------------------------------------------------*/
  1321. X
  1322. X    if (error)
  1323. X        usagefp = (FILE *)stderr;
  1324. X    else
  1325. X        usagefp = (FILE *)stdout;
  1326. X
  1327. X/*---------------------------------------------------------------------------
  1328. X    Print either ZipInfo usage or UnZip usage, depending on incantation.
  1329. X    (Strings must be no longer than 512 bytes for Turbo C, apparently.)
  1330. X  ---------------------------------------------------------------------------*/
  1331. X
  1332. X    if (zipinfo_mode) {
  1333. X
  1334. X#ifndef NO_ZIPINFO
  1335. X
  1336. X        FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine1),
  1337. X          LoadFarStringSmall(ZipinfoVersion),
  1338. X          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS);
  1339. X        FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine2));
  1340. X        FPRINTF(usagefp, LoadFarString(ZipInfoUsageLine3), QUOT,QUOT);
  1341. X#ifdef VMS
  1342. X        FPRINTF(usagefp, "\nRemember that non-lowercase filespecs must be\
  1343. X quoted in VMS (e.g., \"Makefile\").\n");
  1344. X#endif
  1345. X
  1346. X#endif /* !NO_ZIPINFO */
  1347. X
  1348. X    } else {   /* UnZip mode */
  1349. X
  1350. X        FPRINTF(usagefp, LoadFarString(UnzipUsageLine1),
  1351. X          LoadFarStringSmall(UnzipVersion));
  1352. X#ifdef BETA
  1353. X        FPRINTF(usagefp, LoadFarString(BetaVersion), "", "");
  1354. X#endif
  1355. X        FPRINTF(usagefp, LoadFarString(UnzipUsageLine2), ZIPINFO_MODE_OPTION,
  1356. X          LoadFarStringSmall(ZipinfoMode));
  1357. X
  1358. X        FPRINTF(usagefp, LoadFarString(UnzipUsageLine3));
  1359. X
  1360. X        FPRINTF(usagefp, LoadFarString(UnzipUsageLine4), QUOT,QUOT, QUOT,QUOT,
  1361. X                LoadFarStringSmall(loc_str), QUOT,QUOT,
  1362. X                LoadFarStringSmall2(loc2str));
  1363. X
  1364. X        /* This is extra work for SMALL_MEM, but it will work since
  1365. X         * LoadFarStringSmall2 uses the same buffer.  Remember, this
  1366. X         * is a hack. */
  1367. X        FPRINTF(usagefp, LoadFarString(UnzipUsageLine5),
  1368. X                LoadFarStringSmall(Example1),
  1369. X                LoadFarStringSmall2(Example2),
  1370. X                LoadFarStringSmall2(Example2));
  1371. X
  1372. X    }
  1373. X
  1374. X    if (error)
  1375. X        return PK_PARAM;
  1376. X    else
  1377. X        return PK_COOL;     /* just wanted usage screen: no error */
  1378. X
  1379. X} /* end function usage() */
  1380. X
  1381. X#endif /* !VMSCLI */
  1382. X#endif /* ?SFX */
  1383. X#endif /* ?MSWIN */
  1384. X
  1385. X
  1386. X
  1387. X
  1388. X/*******************************/
  1389. X/* Function process_zipfiles() */
  1390. X/*******************************/
  1391. X
  1392. Xint process_zipfiles()    /* return PK-type error code */
  1393. X{
  1394. X#ifndef SFX
  1395. X    char *lastzipfn = (char *)NULL;
  1396. X    int NumWinFiles, NumLoseFiles, NumWarnFiles;
  1397. X    int NumMissDirs, NumMissFiles;
  1398. X#endif
  1399. X    int error=0, error_in_archive=0;
  1400. X
  1401. X
  1402. X/*---------------------------------------------------------------------------
  1403. X    Start by constructing the various PK signature strings.
  1404. X  ---------------------------------------------------------------------------*/
  1405. X
  1406. X    local_hdr_sig[0]  /* = extd_local_sig[0] */  = '\120';   /* ASCII 'P', */
  1407. X    central_hdr_sig[0] = end_central_sig[0] = '\120';        /* not EBCDIC */
  1408. X
  1409. X    strcpy(local_hdr_sig+1, LOCAL_HDR_SIG);
  1410. X    strcpy(central_hdr_sig+1, CENTRAL_HDR_SIG);
  1411. X    strcpy(end_central_sig+1, END_CENTRAL_SIG);
  1412. X/*  strcpy(extd_local_sig+1, EXTD_LOCAL_SIG);   still to be used in multi? */
  1413. X
  1414. X/*---------------------------------------------------------------------------
  1415. X    Match (possible) wildcard zipfile specification with existing files and
  1416. X    attempt to process each.  If no hits, try again after appending ".zip"
  1417. X    suffix.  If still no luck, give up.
  1418. X  ---------------------------------------------------------------------------*/
  1419. X
  1420. X#ifdef SFX
  1421. X    if ((error = do_seekable(0)) == PK_NOZIP) {
  1422. X#ifdef EXE_EXTENSION
  1423. X        int len=strlen(argv0);
  1424. X
  1425. X        /* append .exe if appropriate; also .sfx? */
  1426. X        if ((zipfn = (char *)malloc(len+5)) != (char *)NULL) {
  1427. X            strcpy(zipfn, argv0);
  1428. X            strcpy(zipfn+len, EXE_EXTENSION);
  1429. X            error = do_seekable(0);
  1430. X            free(zipfn);
  1431. X            zipfn = argv0;  /* for "can't find myself" message only */
  1432. X        }
  1433. X#endif /* EXE_EXTENSION */
  1434. X#ifdef NT
  1435. X        zipfn = argv0;  /* for "can't find myself" message only */
  1436. X#endif
  1437. X    }
  1438. X    if (error) {
  1439. X        if (error == IZ_DIR)
  1440. X            error_in_archive = PK_NOZIP;
  1441. X        else
  1442. X            error_in_archive = error;
  1443. X        if (error == PK_NOZIP)
  1444. X            FPRINTF(stderr, LoadFarString(CantFindMyself), zipfn);
  1445. X    }
  1446. X
  1447. X#else /* !SFX */
  1448. X    NumWinFiles = NumLoseFiles = NumWarnFiles = 0;
  1449. X    NumMissDirs = NumMissFiles = 0;
  1450. X
  1451. X    while ((zipfn = do_wild(wildzipfn)) != (char *)NULL) {
  1452. X        Trace((stderr, "do_wild( %s ) returns %s\n", wildzipfn, zipfn));
  1453. X
  1454. X        lastzipfn = zipfn;
  1455. X
  1456. X        /* print a blank line between the output of different zipfiles */
  1457. X        if (!qflag  &&  error != PK_NOZIP  &&  error != IZ_DIR  &&
  1458. X            (NumWinFiles+NumLoseFiles+NumWarnFiles+NumMissFiles) > 0)
  1459. X            PRINTF("\n");
  1460. X        FFLUSH(stdout);
  1461. X
  1462. X        if ((error = do_seekable(0)) == PK_WARN)
  1463. X            ++NumWarnFiles;
  1464. X        else if (error == IZ_DIR)
  1465. X            ++NumMissDirs;
  1466. X        else if (error == PK_NOZIP)
  1467. X            ++NumMissFiles;
  1468. X        else if (error)
  1469. X            ++NumLoseFiles;
  1470. X        else
  1471. X            ++NumWinFiles;
  1472. X
  1473. X        if (error != IZ_DIR && error > error_in_archive)
  1474. X            error_in_archive = error;
  1475. X        Trace((stderr, "do_seekable(0) returns %d\n", error));
  1476. X
  1477. X    } /* end while-loop (wildcard zipfiles) */
  1478. X
  1479. X    if ((NumWinFiles + NumWarnFiles + NumLoseFiles) == 0  &&
  1480. X        (NumMissDirs + NumMissFiles) == 1  &&  lastzipfn != (char *)NULL)
  1481. X    {
  1482. X        char *p = lastzipfn + strlen(lastzipfn);
  1483. X
  1484. X        NumMissDirs = NumMissFiles = 0;
  1485. X        if (error_in_archive == PK_NOZIP)
  1486. X            error_in_archive = PK_COOL;
  1487. X        zipfn = lastzipfn;
  1488. X        strcpy(p, ".zip");
  1489. X
  1490. X#ifdef UNIX
  1491. X        if ((error = do_seekable(0)) == PK_NOZIP || error == IZ_DIR) {
  1492. X            if (error == IZ_DIR)
  1493. X                ++NumMissDirs;
  1494. X            strcpy(p, ".ZIP");
  1495. X            error = do_seekable(1);
  1496. X        }
  1497. X#else
  1498. X        error = do_seekable(1);
  1499. X#endif
  1500. X        if (error == PK_WARN)
  1501. X            ++NumWarnFiles;
  1502. X        else if (error == IZ_DIR)
  1503. X            ++NumMissDirs;
  1504. X        else if (error == PK_NOZIP)
  1505. X            /* if increment again => bug: "1 file had no zipfile directory." */
  1506. X            /* ++NumMissFiles */ ;
  1507. X        else if (error)
  1508. X            ++NumLoseFiles;
  1509. X        else
  1510. X            ++NumWinFiles;
  1511. X
  1512. X        if (error > error_in_archive)
  1513. X            error_in_archive = error;
  1514. X        Trace((stderr, "do_seekable(1) returns %d\n", error));
  1515. X    }
  1516. X#endif /* ?SFX */
  1517. X
  1518. X    FFLUSH(stdout);
  1519. X    FFLUSH(stderr);
  1520. X
  1521. X/*---------------------------------------------------------------------------
  1522. X    Print summary of all zipfiles, assuming zipfile spec was a wildcard (no
  1523. X    need for a summary if just one zipfile).
  1524. X  ---------------------------------------------------------------------------*/
  1525. X
  1526. X#ifndef SFX
  1527. X    if (iswild(wildzipfn)) {
  1528. X        if (NumMissFiles + NumLoseFiles + NumWarnFiles > 0 || NumWinFiles != 1)
  1529. X            FPRINTF(stderr, "\n");
  1530. X        if ((NumWinFiles > 1) || (NumWinFiles == 1 &&
  1531. X            NumMissDirs + NumMissFiles + NumLoseFiles + NumWarnFiles > 0))
  1532. X            FPRINTF(stderr, LoadFarString(FilesProcessOK),
  1533. X              NumWinFiles, (NumWinFiles == 1)? " was" : "s were");
  1534. X        if (NumWarnFiles > 0)
  1535. X            FPRINTF(stderr, LoadFarString(ArchiveWarning),
  1536. X              NumWarnFiles, (NumWarnFiles == 1)? "" : "s");
  1537. X        if (NumLoseFiles > 0)
  1538. X            FPRINTF(stderr, LoadFarString(ArchiveFatalError),
  1539. X              NumLoseFiles, (NumLoseFiles == 1)? "" : "s");
  1540. X        if (NumMissFiles > 0)
  1541. X            FPRINTF(stderr, LoadFarString(FileHadNoZipfileDir),
  1542. X              NumMissFiles, (NumMissFiles == 1)? "" : "s");
  1543. X        if (NumMissDirs == 1)
  1544. X            FPRINTF(stderr, LoadFarString(ZipfileWasDir));
  1545. X        else if (NumMissDirs > 0)
  1546. X            FPRINTF(stderr, LoadFarString(ManyZipfilesWereDir), NumMissDirs);
  1547. X        if (NumWinFiles + NumLoseFiles + NumWarnFiles == 0)
  1548. X            FPRINTF(stderr, LoadFarString(NoZipfileFound));
  1549. X    }
  1550. X#endif /* !SFX */
  1551. X
  1552. X    /* free allocated memory */
  1553. X    inflate_free();
  1554. X    checkdir((char *)NULL, END);
  1555. X#ifndef SMALL_MEM
  1556. X    if (outbuf2)
  1557. X        free(outbuf2);   /* malloc'd ONLY if unshrink and -a */
  1558. X#endif
  1559. X    free(outbuf);
  1560. X    free(inbuf);
  1561. X
  1562. X    return error_in_archive;
  1563. X
  1564. X} /* end function process_zipfiles() */
  1565. X
  1566. X
  1567. X
  1568. X
  1569. X
  1570. X/**************************/
  1571. X/* Function do_seekable() */
  1572. X/**************************/
  1573. X
  1574. Xint do_seekable(lastchance)    /* return PK-type error code */
  1575. X    int lastchance;
  1576. X{
  1577. X#ifndef SFX
  1578. X    static int no_ecrec = FALSE;
  1579. X    int maybe_exe=FALSE;
  1580. X#endif
  1581. X    int error=0, error_in_archive;
  1582. X
  1583. X
  1584. X/*---------------------------------------------------------------------------
  1585. X    Open the zipfile for reading in BINARY mode to prevent CR/LF translation,
  1586. X    which would corrupt the bit streams.
  1587. X  ---------------------------------------------------------------------------*/
  1588. X
  1589. X    if (SSTAT(zipfn, &statbuf) || (error = S_ISDIR(statbuf.st_mode)) != 0) {
  1590. X#ifndef SFX
  1591. X        if (lastchance)
  1592. X            if (no_ecrec)
  1593. X                FPRINTF(stderr, LoadFarString(CantFindZipfileDirMsg),
  1594. X                  zipinfo_mode? "zipinfo" : "unzip",
  1595. X                  wildzipfn, zipinfo_mode? "  " : "",
  1596. X#ifdef UNIX
  1597. X                                                     wildzipfn,
  1598. X#endif
  1599. X                                                               zipfn);
  1600. X            else
  1601. X                FPRINTF(stderr,
  1602. X                  LoadFarString(CantFindEitherZipfile),
  1603. X                  zipinfo_mode? "zipinfo" : "unzip", wildzipfn,
  1604. X#ifdef UNIX
  1605. X                                                               wildzipfn,
  1606. X#endif
  1607. X                                                                         zipfn);
  1608. X#endif /* !SFX */
  1609. X        return error? IZ_DIR : PK_NOZIP;
  1610. X    }
  1611. X    ziplen = statbuf.st_size;
  1612. X
  1613. X#ifndef SFX
  1614. X#if defined(UNIX) || defined(DOS_NT_OS2)
  1615. X    if (statbuf.st_mode & S_IEXEC)   /* no extension on Unix exec's:  might */
  1616. X        maybe_exe = TRUE;            /*  find unzip, not unzip.zip; etc. */
  1617. X#endif
  1618. X#endif /* !SFX */
  1619. X
  1620. X#ifdef VMS
  1621. X    if (check_format())      /* check for variable-length format */
  1622. X        return PK_ERR;
  1623. X#endif
  1624. X
  1625. X    if (open_input_file())   /* this should never happen, given */
  1626. X        return PK_NOZIP;     /*  the stat() test above, but... */
  1627. X
  1628. X/*---------------------------------------------------------------------------
  1629. X    Find and process the end-of-central-directory header.  UnZip need only
  1630. X    check last 65557 bytes of zipfile:  comment may be up to 65535, end-of-
  1631. X    central-directory record is 18 bytes, and signature itself is 4 bytes;
  1632. X    add some to allow for appended garbage.  Since ZipInfo is often used as
  1633. X    a debugging tool, search the whole zipfile if zipinfo_mode is true.
  1634. X  ---------------------------------------------------------------------------*/
  1635. X
  1636. X    cur_zipfile_bufstart = 0;
  1637. X    inptr = inbuf;
  1638. X
  1639. X    if (!qflag && !zipinfo_mode)
  1640. X        PRINTF("Archive:  %s\n", zipfn);
  1641. X
  1642. X    if ((
  1643. X#ifndef NO_ZIPINFO
  1644. X         zipinfo_mode &&
  1645. X          ((error_in_archive = find_ecrec(ziplen)) != 0 ||
  1646. X          (error_in_archive = zi_end_central()) > PK_WARN))
  1647. X        || (!zipinfo_mode &&
  1648. X#endif
  1649. X          ((error_in_archive = find_ecrec(MIN(ziplen,66000L))) != 0 ||
  1650. X          (error_in_archive = uz_end_central()) > PK_WARN)))
  1651. X    {
  1652. X        close(zipfd);
  1653. X#ifdef SFX
  1654. X        ++lastchance;   /* avoid picky compiler warnings */
  1655. X        return error_in_archive;
  1656. X#else
  1657. X        if (maybe_exe)
  1658. X            FPRINTF(stderr, LoadFarString(MaybeExe), zipfn);
  1659. X        if (lastchance)
  1660. X            return error_in_archive;
  1661. X        else {
  1662. X            no_ecrec = TRUE;    /* assume we found wrong file:  e.g., */
  1663. X            return PK_NOZIP;    /*  unzip instead of unzip.zip */
  1664. X        }
  1665. X#endif /* ?SFX */
  1666. X    }
  1667. X
  1668. X    if ((zflag > 0) && !zipinfo_mode) {   /* in unzip, zflag = comment ONLY */
  1669. X        close(zipfd);
  1670. X        return error_in_archive;
  1671. X    }
  1672. X
  1673. X/*---------------------------------------------------------------------------
  1674. X    Test the end-of-central-directory info for incompatibilities (multi-disk
  1675. X    archives) or inconsistencies (missing or extra bytes in zipfile).
  1676. X  ---------------------------------------------------------------------------*/
  1677. X
  1678. X#ifdef NO_MULTIPART
  1679. X    error = !zipinfo_mode && (ecrec.number_this_disk == 1) &&
  1680. X            (ecrec.num_disk_with_start_central_dir == 1);
  1681. X#else
  1682. X    error = !zipinfo_mode && (ecrec.number_this_disk != 0);
  1683. X#endif
  1684. X
  1685. X#ifndef SFX
  1686. X    if (zipinfo_mode &&
  1687. X        ecrec.number_this_disk != ecrec.num_disk_with_start_central_dir)
  1688. X    {
  1689. X        FPRINTF(stderr, LoadFarString(CentDirNotInZipMsg));
  1690. X        error_in_archive = PK_FIND;
  1691. X#ifdef NO_MULTIPART   /* concatenation of multiple parts works in some cases */
  1692. X    } else if (!zipinfo_mode && !error && ecrec.number_this_disk != 0) {
  1693. X        FPRINTF(stderr, LoadFarString(NoMultiDiskArcSupport), zipfn);
  1694. X        error_in_archive = PK_FIND;
  1695. X#endif
  1696. X    } else {   /* this is a (relatively) normal zipfile:  process normally */
  1697. X        if (error) {
  1698. X            FPRINTF(stderr, LoadFarString(MaybePakBug), zipfn);
  1699. X            error_in_archive = PK_WARN;
  1700. X        }
  1701. X#endif
  1702. X        if ((extra_bytes = real_ecrec_offset-expect_ecrec_offset) < (LONGINT)0)
  1703. X        {
  1704. X            FPRINTF(stderr, LoadFarString(MissingBytes), zipfn,
  1705. X              (long)(-extra_bytes));
  1706. X            error_in_archive = PK_ERR;
  1707. X        } else if (extra_bytes > 0) {
  1708. X            if ((ecrec.offset_start_central_directory == 0) &&
  1709. X                (ecrec.size_central_directory != 0))   /* zip 1.5 -go bug */
  1710. X            {
  1711. X                FPRINTF(stderr, LoadFarString(NullCentDirOffset), zipfn);
  1712. X                ecrec.offset_start_central_directory = extra_bytes;
  1713. X                extra_bytes = 0;
  1714. X                error_in_archive = PK_ERR;
  1715. X            }
  1716. X#ifndef SFX
  1717. X            else {
  1718. X                FPRINTF(stderr, LoadFarString(ExtraBytesAtStart), zipfn,
  1719. X                  (long)extra_bytes);
  1720. X                error_in_archive = PK_WARN;
  1721. X            }
  1722. X#endif
  1723. X        }
  1724. X
  1725. X    /*-----------------------------------------------------------------------
  1726. X        Check for empty zipfile and exit now if so.
  1727. X      -----------------------------------------------------------------------*/
  1728. X
  1729. X        if (expect_ecrec_offset == 0L  &&  ecrec.size_central_directory == 0) {
  1730. X            if (zipinfo_mode)
  1731. X                PRINTF("%sEmpty zipfile.\n", lflag>9 ? "\n  " : "");
  1732. X            else
  1733. X                FPRINTF(stderr, LoadFarString(ZipfileEmpty), zipfn);
  1734. X            close(zipfd);
  1735. X            return (error_in_archive > PK_WARN)? error_in_archive : PK_WARN;
  1736. X        }
  1737. X
  1738. X    /*-----------------------------------------------------------------------
  1739. X        Compensate for missing or extra bytes, and seek to where the start
  1740. X        of central directory should be.  If header not found, uncompensate
  1741. X        and try again (necessary for at least some Atari archives created
  1742. X        with STZip, as well as archives created by J.H. Holm's ZIPSPLIT 1.1).
  1743. X      -----------------------------------------------------------------------*/
  1744. X
  1745. X        LSEEK( ecrec.offset_start_central_directory )
  1746. X#ifdef OLD_SEEK_TEST
  1747. X        if (readbuf(sig, 4) == 0) {
  1748. X            close(zipfd);
  1749. X            return PK_ERR;  /* file may be locked, or possibly disk error(?) */
  1750. X        }
  1751. X        if (strncmp(sig, central_hdr_sig, 4))
  1752. X#else
  1753. X        if ((readbuf(sig, 4) == 0) || strncmp(sig, central_hdr_sig, 4))
  1754. X#endif
  1755. X        {
  1756. X            long tmp = extra_bytes;
  1757. X
  1758. X            extra_bytes = 0;
  1759. X            LSEEK( ecrec.offset_start_central_directory )
  1760. X            if ((readbuf(sig, 4) == 0) || strncmp(sig, central_hdr_sig, 4)) {
  1761. X                FPRINTF(stderr, LoadFarString(CentDirStartNotFound), zipfn,
  1762. X                  LoadFarStringSmall(ReportMsg));
  1763. X                close(zipfd);
  1764. X                return PK_BADERR;
  1765. X            }
  1766. X            FPRINTF(stderr, LoadFarString(CentDirTooLong), zipfn, -tmp);
  1767. X            error_in_archive = PK_ERR;
  1768. X        }
  1769. X
  1770. X    /*-----------------------------------------------------------------------
  1771. X        Seek to the start of the central directory one last time, since we
  1772. X        have just read the first entry's signature bytes; then list, extract
  1773. X        or test member files as instructed, and close the zipfile.
  1774. X      -----------------------------------------------------------------------*/
  1775. X
  1776. X        Trace((stderr, "about to extract/list files (error = %d)\n",
  1777. X          error_in_archive));
  1778. X
  1779. X        LSEEK( ecrec.offset_start_central_directory )
  1780. X
  1781. X#ifndef NO_ZIPINFO
  1782. X        if (zipinfo_mode) {
  1783. X            error = zipinfo();                     /* ZIPINFO 'EM */
  1784. X            if (lflag > 9)
  1785. X                PRINTF("\n");
  1786. X        } else
  1787. X#endif
  1788. X#ifndef SFX
  1789. X            if (vflag && !tflag && !cflag)
  1790. X                error = list_files();              /* LIST 'EM */
  1791. X            else
  1792. X#endif
  1793. X                error = extract_or_test_files();   /* EXTRACT OR TEST 'EM */
  1794. X
  1795. X        Trace((stderr, "done with extract/list files (error = %d)\n", error));
  1796. X
  1797. X        if (error > error_in_archive)   /* don't overwrite stronger error */
  1798. X            error_in_archive = error;   /*  with (for example) a warning */
  1799. X#ifndef SFX
  1800. X    }
  1801. X#endif
  1802. X
  1803. X    close(zipfd);
  1804. X    return error_in_archive;
  1805. X
  1806. X} /* end function do_seekable() */
  1807. X
  1808. X
  1809. X
  1810. X
  1811. X
  1812. X/*****************************/
  1813. X/* Function uz_end_central() */
  1814. X/*****************************/
  1815. X
  1816. Xint uz_end_central()    /* return PK-type error code */
  1817. X{
  1818. X    int error = PK_COOL;
  1819. X
  1820. X
  1821. X/*---------------------------------------------------------------------------
  1822. X    Get the zipfile comment (up to 64KB long), if any, and print it out.
  1823. X    Then position the file pointer to the beginning of the central directory
  1824. X    and fill buffer.
  1825. X  ---------------------------------------------------------------------------*/
  1826. X
  1827. X#ifdef MSWIN
  1828. X    cchComment = ecrec.zipfile_comment_length; /* save for comment button */
  1829. X    if (ecrec.zipfile_comment_length && (zflag > 0))
  1830. X#else
  1831. X    if (ecrec.zipfile_comment_length && (zflag > 0 || (zflag == 0 && !qflag)))
  1832. X#endif
  1833. X    {
  1834. X#if 0
  1835. X#ifndef MSWIN
  1836. X        if (zflag == 0)       (add "&& single_zipfile" perhaps; unnecessary with
  1837. X            PRINTF("[%s] comment:\n", zipfn);  multiple zipfiles: "Archive:...")
  1838. X#endif /* !MSWIN */
  1839. X#endif /* 0 */
  1840. X        if (do_string(ecrec.zipfile_comment_length,DISPLAY)) {
  1841. X            FPRINTF(stderr, LoadFarString(ZipfileCommTrunc1));
  1842. X            error = PK_WARN;
  1843. X        }
  1844. X    }
  1845. X    return error;
  1846. X
  1847. X} /* end function uz_end_central() */
  1848. X
  1849. X
  1850. X
  1851. X
  1852. X
  1853. X/************************************/
  1854. X/* Function process_cdir_file_hdr() */
  1855. X/************************************/
  1856. X
  1857. Xint process_cdir_file_hdr()    /* return PK-type error code */
  1858. X{
  1859. X    int error;
  1860. X
  1861. X
  1862. X/*---------------------------------------------------------------------------
  1863. X    Get central directory info, save host and method numbers, and set flag
  1864. X    for lowercase conversion of filename, depending on the OS from which the
  1865. X    file is coming.
  1866. X  ---------------------------------------------------------------------------*/
  1867. X
  1868. X    if ((error = get_cdir_ent()) != 0)
  1869. X        return error;
  1870. X
  1871. X    pInfo->hostnum = MIN(crec.version_made_by[1], NUM_HOSTS);
  1872. X/*  extnum = MIN(crec.version_needed_to_extract[1], NUM_HOSTS); */
  1873. X
  1874. X    pInfo->lcflag = 0;
  1875. X    if (L_flag)               /* user specified case-conversion */
  1876. X        switch (pInfo->hostnum) {
  1877. X            case FS_FAT_:     /* PKZIP and zip -k store in uppercase */
  1878. X            case ATARI_:      /* MS-DOS filesystem */
  1879. X            case CPM_:        /* like MS-DOS, right? */
  1880. X            case VM_CMS_:     /* all caps? */
  1881. X            case TOPS20_:
  1882. X            case VMS_:        /* our Zip uses lowercase, but ASi's doesn't */
  1883. X        /*  case Z_SYSTEM_:   ? */
  1884. X        /*  case QDOS_:       ? */
  1885. X                pInfo->lcflag = 1;   /* convert filename to lowercase */
  1886. X                break;
  1887. X
  1888. X            default:     /* AMIGA_, FS_HPFS_, FS_NTFS_, MAC_, UNIX_, */
  1889. X                break;   /*  (Z_SYSTEM_):  no conversion */
  1890. X        }
  1891. X
  1892. X    /* do Amigas (AMIGA_) also have volume labels? */
  1893. X    if (IS_VOLID(crec.external_file_attributes) &&
  1894. X        (pInfo->hostnum == FS_FAT_ || pInfo->hostnum == FS_HPFS_ ||
  1895. X         pInfo->hostnum == FS_NTFS_ || pInfo->hostnum == ATARI_))
  1896. X    {
  1897. X        pInfo->vollabel = TRUE;
  1898. X        pInfo->lcflag = 0;        /* preserve case of volume labels */
  1899. X    } else
  1900. X        pInfo->vollabel = FALSE;
  1901. X
  1902. X    return PK_COOL;
  1903. X
  1904. X} /* end function process_cdir_file_hdr() */
  1905. X
  1906. X
  1907. X
  1908. X
  1909. X
  1910. X/*************************************/
  1911. X/* Function process_local_file_hdr() */
  1912. X/*************************************/
  1913. X
  1914. Xint process_local_file_hdr()    /* return PK-type error code */
  1915. X{
  1916. X    local_byte_hdr byterec;
  1917. X
  1918. X
  1919. X/*---------------------------------------------------------------------------
  1920. X    Read the next local file header and do any necessary machine-type con-
  1921. X    versions (byte ordering, structure padding compensation--do so by copy-
  1922. X    ing the data from the array into which it was read (byterec) to the
  1923. X    usable struct (lrec)).
  1924. X  ---------------------------------------------------------------------------*/
  1925. X
  1926. X    if (readbuf((char *)byterec, LREC_SIZE) == 0)
  1927. X        return PK_EOF;
  1928. X
  1929. X    lrec.version_needed_to_extract[0] = byterec[L_VERSION_NEEDED_TO_EXTRACT_0];
  1930. X    lrec.version_needed_to_extract[1] = byterec[L_VERSION_NEEDED_TO_EXTRACT_1];
  1931. X
  1932. X    lrec.general_purpose_bit_flag = makeword(&byterec[L_GENERAL_PURPOSE_BIT_FLAG]);
  1933. X    lrec.compression_method = makeword(&byterec[L_COMPRESSION_METHOD]);
  1934. X    lrec.last_mod_file_time = makeword(&byterec[L_LAST_MOD_FILE_TIME]);
  1935. X    lrec.last_mod_file_date = makeword(&byterec[L_LAST_MOD_FILE_DATE]);
  1936. X    lrec.crc32 = makelong(&byterec[L_CRC32]);
  1937. X    lrec.csize = makelong(&byterec[L_COMPRESSED_SIZE]);
  1938. X    lrec.ucsize = makelong(&byterec[L_UNCOMPRESSED_SIZE]);
  1939. X    lrec.filename_length = makeword(&byterec[L_FILENAME_LENGTH]);
  1940. X    lrec.extra_field_length = makeword(&byterec[L_EXTRA_FIELD_LENGTH]);
  1941. X
  1942. X    csize = (long) lrec.csize;
  1943. X    ucsize = (long) lrec.ucsize;
  1944. X
  1945. X    if ((lrec.general_purpose_bit_flag & 8) != 0) {
  1946. X        /* can't trust local header, use central directory: */
  1947. X        lrec.crc32 = pInfo->crc;
  1948. X        csize = (long)(lrec.csize = pInfo->compr_size);
  1949. X    }
  1950. X
  1951. X    return PK_COOL;
  1952. X
  1953. X} /* end function process_local_file_hdr() */
  1954. END_OF_FILE
  1955.   if test 66790 -ne `wc -c <'unzip-5.12/unzip.c'`; then
  1956.     echo shar: \"'unzip-5.12/unzip.c'\" unpacked with wrong size!
  1957.   fi
  1958.   # end of 'unzip-5.12/unzip.c'
  1959. fi
  1960. echo shar: End of archive 2 \(of 20\).
  1961. cp /dev/null ark2isdone
  1962. MISSING=""
  1963. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ; do
  1964.     if test ! -f ark${I}isdone ; then
  1965.     MISSING="${MISSING} ${I}"
  1966.     fi
  1967. done
  1968. if test "${MISSING}" = "" ; then
  1969.     echo You have unpacked all 20 archives.
  1970.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1971. else
  1972.     echo You still must unpack the following archives:
  1973.     echo "        " ${MISSING}
  1974. fi
  1975. exit 0
  1976. exit 0 # Just in case...
  1977.