1/*
2  Copyright (c) 1990-2002 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2000-Apr-09 or later
5  (the contents of which are also included in unzip.h) for terms of use.
6  If, for some reason, all these files are missing, the Info-ZIP license
7  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
8*/
9/*---------------------------------------------------------------------------
10
11  unzip.c
12
13  UnZip - a zipfile extraction utility.  See below for make instructions, or
14  read the comments in Makefile and the various Contents files for more de-
15  tailed explanations.  To report a bug, send a *complete* description to
16  Zip-Bugs@lists.wku.edu; include machine type, operating system and ver-
17  sion, compiler and version, and reasonably detailed error messages or prob-
18  lem report.  To join Info-ZIP, see the instructions in README.
19
20  UnZip 5.x is a greatly expanded and partially rewritten successor to 4.x,
21  which in turn was almost a complete rewrite of version 3.x.  For a detailed
22  revision history, see UnzpHist.zip at quest.jpl.nasa.gov.  For a list of
23  the many (near infinite) contributors, see "CONTRIBS" in the UnZip source
24  distribution.
25
26  ---------------------------------------------------------------------------
27
28  [from original zipinfo.c]
29
30  This program reads great gobs of totally nifty information, including the
31  central directory stuff, from ZIP archives ("zipfiles" for short).  It
32  started as just a testbed for fooling with zipfiles, but at this point it
33  is actually a useful utility.  It also became the basis for the rewrite of
34  UnZip (3.16 -> 4.0), using the central directory for processing rather than
35  the individual (local) file headers.
36
37  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
38  If the executable is named "unzip" (or "unzip.exe", depending), it behaves
39  like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
40  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
41  option; for example, "unzip -Z [zipinfo_options] archive.zip".
42
43  Another dandy product from your buddies at Newtware!
44
45  Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
46           23 August 1990 -> April 1997
47
48  ---------------------------------------------------------------------------
49
50  Version:  unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
51              Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
52              BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos and
53              TOPS-20.
54
55  Copyrights:  see accompanying file "LICENSE" in UnZip source distribution.
56               (This software is free but NOT IN THE PUBLIC DOMAIN.)
57
58  ---------------------------------------------------------------------------*/
59
60
61
62#define __UNZIP_C       /* identifies this source module */
63#define UNZIP_INTERNAL
64#include "unzip.h"      /* includes, typedefs, macros, prototypes, etc. */
65#include "crypt.h"
66#include "unzvers.h"
67
68#ifndef WINDLL          /* The WINDLL port uses windll/windll.c instead... */
69
70/***************************/
71/* Local type declarations */
72/***************************/
73
74#ifdef REENTRANT
75typedef struct _sign_info
76    {
77        struct _sign_info *previous;
78        void (*sighandler)(int);
79        int sigtype;
80    } savsigs_info;
81#endif
82
83/*******************/
84/* Local Functions */
85/*******************/
86
87#ifdef REENTRANT
88static int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain,
89                                int signal_type, void (*newhandler)(int)));
90#endif
91#ifndef SFX
92static void  show_version_info  OF((__GPRO));
93#endif
94
95
96/*************/
97/* Constants */
98/*************/
99
100#include "consts.h"  /* all constant global variables are in here */
101                     /* (non-constant globals were moved to globals.c) */
102
103/* constant local variables: */
104
105#ifndef SFX
106   static ZCONST char Far EnvUnZip[] = ENV_UNZIP;
107   static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;
108   static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;
109   static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;
110#ifdef RISCOS
111   static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
112#endif /* RISCOS */
113  static ZCONST char Far NoMemArguments[] =
114    "envargs:  cannot get memory for arguments";
115#endif
116
117#ifdef REENTRANT
118  static ZCONST char Far CantSaveSigHandler[] =
119    "error:  cannot save signal handler settings\n";
120#endif
121
122#if (!defined(SFX) || defined(SFX_EXDIR))
123   static ZCONST char Far NotExtracting[] =
124     "caution:  not extracting; -d ignored\n";
125   static ZCONST char Far MustGiveExdir[] =
126     "error:  must specify directory to which to extract with -d option\n";
127   static ZCONST char Far OnlyOneExdir[] =
128     "error:  -d option used more than once (only one exdir allowed)\n";
129#endif
130
131#if CRYPT
132   static ZCONST char Far MustGivePasswd[] =
133     "error:  must give decryption password with -P option\n";
134#endif
135
136#ifndef SFX
137   static ZCONST char Far Zfirst[] =
138   "error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
139#endif
140static ZCONST char Far InvalidOptionsMsg[] = "error:\
141  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
142static ZCONST char Far IgnoreOOptionMsg[] =
143  "caution:  both -n and -o specified; ignoring -o\n";
144
145/* usage() strings */
146#ifndef SFX
147#ifdef VMS
148   static ZCONST char Far Example3[] = "vms.c";
149   static ZCONST char Far Example2[] = "  unzip\
150 \"-V\" foo \"Bar\" => must quote uppercase options and filenames in VMS\n";
151#else /* !VMS */
152   static ZCONST char Far Example3[] = "ReadMe";
153#ifdef RISCOS
154   static ZCONST char Far Example2[] =
155"  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\n";
156#else /* !RISCOS */
157#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))
158   static ZCONST char Far Example2[] =
159     "";                /* no room:  too many local3[] items */
160#else /* !OS2 */
161#ifdef MACOS
162   static ZCONST char Far Example2[] = ""; /* not needed */
163#else /* !MACOS */
164   static ZCONST char Far Example2[] = " \
165 unzip -p foo | more  => send contents of foo.zip via pipe into program more\n";
166#endif /* ?MACOS */
167#endif /* ?OS2 */
168#endif /* ?RISCOS */
169#endif /* ?VMS */
170
171/* local1[]:  command options */
172#if (defined(DLL) && defined(API_DOC))
173   static ZCONST char Far local1[] =
174     "  -A  print extended help for API functions";
175#else /* !(DLL && API_DOC) */
176   static ZCONST char Far local1[] = "";
177#endif /* ?(DLL && API_DOC) */
178
179/* local2[] and local3[]:  modifier options */
180#ifdef DOS_FLX_H68_OS2_W32
181#ifdef FLEXOS
182   static ZCONST char Far local2[] = "";
183#else
184   static ZCONST char Far local2[] =
185     " -$  label removables (-$$ => fixed disks)";
186#endif
187#ifdef OS2
188#ifdef MORE
189   static ZCONST char Far local3[] = "\
190  -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\
191                                             -M  pipe through \"more\" pager\n";
192#else
193   static ZCONST char Far local3[] = " \
194 -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\n";
195#endif /* ?MORE */
196#else /* !OS2 */
197#ifdef WIN32
198#ifdef NTSD_EAS
199#ifdef MORE
200   static ZCONST char Far local3[] = "\
201  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\
202                                             -M  pipe through \"more\" pager\n";
203#else
204   static ZCONST char Far local3[] = " \
205 -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\n";
206#endif /* ?MORE */
207#else /* !NTSD_EAS */
208#ifdef MORE
209   static ZCONST char Far local3[] = "\
210  -M  pipe through \"more\" pager            \
211  -s  spaces in filenames => '_'\n\n";
212#else
213   static ZCONST char Far local3[] = " \
214                                            -s  spaces in filenames => '_'\n\n";
215#endif /* ?MORE */
216#endif /* ?NTSD_EAS */
217#else /* !WIN32 */
218#ifdef MORE
219   static ZCONST char Far local3[] = "  -\
220M  pipe through \"more\" pager              -s  spaces in filenames => '_'\n\n";
221#else
222   static ZCONST char Far local3[] = "\
223                                             -s  spaces in filenames => '_'\n";
224#endif
225#endif /* ?WIN32 */
226#endif /* ?OS2 || ?WIN32 */
227#else /* !DOS_FLX_OS2_W32 */
228#ifdef VMS
229   static ZCONST char Far local2[] = "\"-X\" restore owner/protection info";
230#ifdef MORE
231   static ZCONST char Far local3[] = "  \
232                                          \"-M\" pipe through \"more\" pager\n";
233#else
234   static ZCONST char Far local3[] = "\n";
235#endif
236#else /* !VMS */
237#ifdef BEO_UNX
238   static ZCONST char Far local2[] = " -X  restore UID/GID info";
239#ifdef MORE
240   static ZCONST char Far local3[] = "\
241                                             -M  pipe through \"more\" pager\n";
242#else
243   static ZCONST char Far local3[] = "\n";
244#endif
245#else /* !BEO_UNX */
246#ifdef TANDEM
247   static ZCONST char Far local2[] = " -X  restore Tandem User ID";
248#ifdef MORE
249   static ZCONST char Far local3[] = "\
250  -b  create 'C' (180) text files            -M  pipe through \"more\" pager\n";
251#else
252   static ZCONST char Far local3[] = " -b  create 'C' (180) text files\n";
253#endif
254#else /* !TANDEM */
255#ifdef AMIGA
256   static ZCONST char Far local2[] = " -N  restore comments as filenotes";
257#ifdef MORE
258   static ZCONST char Far local3[] = " \
259                                            -M  pipe through \"more\" pager\n";
260#else
261   static ZCONST char Far local3[] = "\n";
262#endif
263#else /* !AMIGA */
264#ifdef MACOS
265   static ZCONST char Far local2[] = " -E  show Mac info during extraction";
266   static ZCONST char Far local3[] = " \
267 -i  ignore filenames in mac extra info     -J  junk (ignore) Mac extra info\n\
268\n";
269#else /* !MACOS */
270#ifdef MORE
271   static ZCONST char Far local2[] = " -M  pipe through \"more\" pager";
272   static ZCONST char Far local3[] = "\n";
273#else
274   static ZCONST char Far local2[] = "";   /* Atari, Mac, CMS/MVS etc. */
275   static ZCONST char Far local3[] = "";
276#endif
277#endif /* ?MACOS */
278#endif /* ?AMIGA */
279#endif /* ?TANDEM */
280#endif /* ?BEO_UNX */
281#endif /* ?VMS */
282#endif /* ?DOS_FLX_OS2_W32 */
283#endif /* !SFX */
284
285#ifndef NO_ZIPINFO
286#ifdef VMS
287   static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
288#else
289   static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
290#endif
291
292static ZCONST char Far ZipInfoUsageLine1[] = "\
293ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\
294\n\
295List name, date/time, attribute, size, compression method, etc., about files\n\
296in list (excluding those in xlist) contained in the specified .zip archive(s).\
297\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
298   usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
299      or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
300
301static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\
302 listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
303  -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
304  -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
305                                         -v  verbose, multi-page format\n";
306
307static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
308  -h  print header line       -t  print totals for listed files or for all\n\
309  -z  print zipfile comment  %c-T%c print file times in sortable decimal format\
310\n %c-C%c be case-insensitive   %s\
311  -x  exclude filenames that follow from listing\n";
312#ifdef MORE
313#ifdef VMS
314   static ZCONST char Far ZipInfoUsageLine4[] =
315     " \"-M\" page output through built-in \"more\"\n";
316#else
317   static ZCONST char Far ZipInfoUsageLine4[] =
318     "  -M  page output through built-in \"more\"\n";
319#endif
320#else /* !MORE */
321   static ZCONST char Far ZipInfoUsageLine4[] = "";
322#endif /* ?MORE */
323#endif /* !NO_ZIPINFO */
324
325#ifdef BETA
326#  ifdef VMSCLI
327   /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */
328     ZCONST char Far BetaVersion[] = "%s\
329        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
330#  else
331     static ZCONST char Far BetaVersion[] = "%s\
332        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
333#  endif
334#endif
335
336#ifdef SFX
337#  ifdef VMSCLI
338   /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */
339     ZCONST char Far UnzipSFXBanner[] =
340#  else
341     static ZCONST char Far UnzipSFXBanner[] =
342#  endif
343     "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (Zip-Bugs@lists.wku.edu).\n";
344#  ifdef SFX_EXDIR
345     static ZCONST char Far UnzipSFXOpts[] =
346    "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
347#  else
348     static ZCONST char Far UnzipSFXOpts[] =
349       "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
350#  endif
351#else /* !SFX */
352   static ZCONST char Far CompileOptions[] =
353     "UnZip special compilation options:\n";
354   static ZCONST char Far CompileOptFormat[] = "\t%s\n";
355   static ZCONST char Far EnvOptions[] =
356     "\nUnZip and ZipInfo environment options:\n";
357   static ZCONST char Far EnvOptFormat[] = "%16s:  %s\n";
358   static ZCONST char Far None[] = "[none]";
359#  ifdef ACORN_FTYPE_NFS
360     static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS";
361#  endif
362#  ifdef ASM_CRC
363     static ZCONST char Far AsmCRC[] = "ASM_CRC";
364#  endif
365#  ifdef ASM_INFLATECODES
366     static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES";
367#  endif
368#  ifdef CHECK_VERSIONS
369     static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS";
370#  endif
371#  ifdef COPYRIGHT_CLEAN
372     static ZCONST char Far Copyright_Clean[] =
373     "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
374#  endif
375#  ifdef DEBUG
376     static ZCONST char Far UDebug[] = "DEBUG";
377#  endif
378#  ifdef DEBUG_TIME
379     static ZCONST char Far DebugTime[] = "DEBUG_TIME";
380#  endif
381#  ifdef DLL
382     static ZCONST char Far Dll[] = "DLL";
383#  endif
384#  ifdef DOSWILD
385     static ZCONST char Far DosWild[] = "DOSWILD";
386#  endif
387#  ifdef LZW_CLEAN
388     static ZCONST char Far LZW_Clean[] =
389     "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
390#  endif
391#  ifndef MORE
392     static ZCONST char Far No_More[] = "NO_MORE";
393#  endif
394#  ifdef NO_ZIPINFO
395     static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO";
396#  endif
397#  ifdef NTSD_EAS
398     static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS";
399#  endif
400#  ifdef OLD_THEOS_EXTRA
401     static ZCONST char Far OldTheosExtra[] =
402     "OLD_THEOS_EXTRA (handle also old Theos port extra field)";
403#  endif
404#  ifdef OS2_EAS
405     static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS";
406#  endif
407#  ifdef QLZIP
408     static ZCONST char Far SMSExFldOnUnix[] = "QLZIP";
409#  endif
410#  ifdef REENTRANT
411     static ZCONST char Far Reentrant[] = "REENTRANT";
412#  endif
413#  ifdef REGARGS
414     static ZCONST char Far RegArgs[] = "REGARGS";
415#  endif
416#  ifdef RETURN_CODES
417     static ZCONST char Far Return_Codes[] = "RETURN_CODES";
418#  endif
419#  ifdef SET_DIR_ATTRIB
420     static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB";
421#  endif
422#  ifdef TIMESTAMP
423     static ZCONST char Far TimeStamp[] = "TIMESTAMP";
424#  endif
425#  ifdef UNIXBACKUP
426     static ZCONST char Far UnixBackup[] = "UNIXBACKUP";
427#  endif
428#  ifdef USE_EF_UT_TIME
429     static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
430#  endif
431#  ifndef LZW_CLEAN
432     static ZCONST char Far Use_Unshrink[] =
433     "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
434#  endif
435#  ifndef COPYRIGHT_CLEAN
436     static ZCONST char Far Use_Smith_Code[] =
437     "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
438#  endif
439#  ifdef USE_DEFLATE64
440     static ZCONST char Far Use_Deflate64[] =
441     "USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)";
442#  endif
443#  ifdef MULT_VOLUME
444     static ZCONST char Far Use_MultiVol[] =
445     "MULT_VOLUME (multi-volume archives supported)";
446#  endif
447#  if (defined(__DJGPP__) && (__DJGPP__ >= 2))
448#    ifdef USE_DJGPP_ENV
449       static ZCONST char Far Use_DJGPP_Env[] = "USE_DJGPP_ENV";
450#    endif
451#    ifdef USE_DJGPP_GLOB
452       static ZCONST char Far Use_DJGPP_Glob[] = "USE_DJGPP_GLOB";
453#    endif
454#  endif /* __DJGPP__ && (__DJGPP__ >= 2) */
455#  ifdef USE_VFAT
456     static ZCONST char Far Use_VFAT_support[] = "USE_VFAT";
457#  endif
458#  ifdef USE_ZLIB
459     static ZCONST char Far UseZlib[] =
460     "USE_ZLIB (compiled with version %s; using version %s)";
461#  endif
462#  ifdef VMS_TEXT_CONV
463     static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV";
464#  endif
465#  ifdef VMSCLI
466     static ZCONST char Far VmsCLI[] = "VMSCLI";
467#  endif
468#  ifdef VMSWILD
469     static ZCONST char Far VmsWild[] = "VMSWILD";
470#  endif
471#  ifdef WILD_STOP_AT_DIR
472     static ZCONST char Far WildStopAtDir[] = "WILD_STOP_AT_DIR";
473#  endif
474#  if CRYPT
475#    ifdef PASSWD_FROM_STDIN
476       static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
477#    endif
478     static ZCONST char Far Decryption[] =
479       "\t[decryption, version %d.%d%s of %s]\n";
480     static ZCONST char Far CryptDate[] = CR_VERSION_DATE;
481#  endif
482#  ifndef __RSXNT__
483#    ifdef __EMX__
484       static ZCONST char Far EnvEMX[] = "EMX";
485       static ZCONST char Far EnvEMXOPT[] = "EMXOPT";
486#    endif
487#    if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
488       static ZCONST char Far EnvGO32[] = "GO32";
489       static ZCONST char Far EnvGO32TMP[] = "GO32TMP";
490#    endif
491#  endif /* !__RSXNT__ */
492
493#ifdef VMS
494/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
495   ZCONST char Far UnzipUsageLine1[] = "\
496UnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\n\n";
497#ifdef COPYRIGHT_CLEAN
498   static ZCONST char Far UnzipUsageLine1v[] = "\
499UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
500bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
501\n\n";
502#else
503   static ZCONST char Far UnzipUsageLine1v[] = "\
504UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
505Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
506\n\n";
507#endif /* ?COPYRIGHT_CLEAN */
508#else /* !VMS */
509#ifdef COPYRIGHT_CLEAN
510   static ZCONST char Far UnzipUsageLine1[] = "\
511UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
512bug reports to the authors at Zip-Bugs@lists.wku.edu; see README for details.\
513\n\n";
514#else
515   static ZCONST char Far UnzipUsageLine1[] = "\
516UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
517Send bug reports to authors at Zip-Bugs@lists.wku.edu; see README for details.\
518\n\n";
519#endif /* ?COPYRIGHT_CLEAN */
520#define UnzipUsageLine1v        UnzipUsageLine1
521#endif /* ?VMS */
522
523static ZCONST char Far UnzipUsageLine2v[] = "\
524Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\
525\nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\
526\n\n";
527
528#ifdef MACOS
529static ZCONST char Far UnzipUsageLine2[] = "\
530Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \
531 Default action is to extract files in list, to exdir;\n\
532  file[.zip] may be a wildcard.  %s\n";
533#else /* !MACOS */
534#ifdef VM_CMS
535static ZCONST char Far UnzipUsageLine2[] = "\
536Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \
537 Default action is to extract files in list, except those in xlist, to disk fm;\
538\n  file[.zip] may be a wildcard.  %s\n";
539#else /* !VM_CMS */
540static ZCONST char Far UnzipUsageLine2[] = "\
541Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
542 Default action is to extract files in list, except those in xlist, to exdir;\n\
543  file[.zip] may be a wildcard.  %s\n";
544#endif /* ?VM_CMS */
545#endif /* ?MACOS */
546
547#ifdef NO_ZIPINFO
548#  define ZIPINFO_MODE_OPTION  ""
549   static ZCONST char Far ZipInfoMode[] =
550     "(ZipInfo mode is disabled in this version.)";
551#else
552#  define ZIPINFO_MODE_OPTION  "[-Z] "
553#  ifdef VMS
554     static ZCONST char Far ZipInfoMode[] =
555       "\"-Z\" => ZipInfo mode (`unzip \"-Z\"' for usage).";
556#  else
557     static ZCONST char Far ZipInfoMode[] =
558       "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
559#  endif
560#endif /* ?NO_ZIPINFO */
561
562#ifdef VMS
563   static ZCONST char Far VMSusageLine2b[] = "\
564=> define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\
565\n";
566#endif
567
568#ifdef MACOS
569static ZCONST char Far UnzipUsageLine3[] = "\n\
570  -d  extract files into exdir               -l  list files (short format)\n\
571  -f  freshen existing files, create none    -t  test compressed archive data\n\
572  -u  update files, create if necessary      -z  display archive comment\n\
573%s\n";
574#else /* !MACOS */
575#ifdef VM_CMS
576static ZCONST char Far UnzipUsageLine3[] = "\n\
577  -p  extract files to pipe, no messages     -l  list files (short format)\n\
578  -f  freshen existing files, create none    -t  test compressed archive data\n\
579  -u  update files, create if necessary      -z  display archive comment\n\
580  -x  exclude files that follow (in xlist)   -d  extract files onto disk fm\n\
581%s\n";
582#else /* !VM_CMS */
583static ZCONST char Far UnzipUsageLine3[] = "\n\
584  -p  extract files to pipe, no messages     -l  list files (short format)\n\
585  -f  freshen existing files, create none    -t  test compressed archive data\n\
586  -u  update files, create if necessary      -z  display archive comment\n\
587  -x  exclude files that follow (in xlist)   -d  extract files into exdir\n\
588%s\n";
589#endif /* ?VM_CMS */
590#endif /* ?MACOS */
591
592static ZCONST char Far UnzipUsageLine4[] = "\
593modifiers:                                   -q  quiet mode (-qq => quieter)\n\
594  -n  never overwrite existing files         -a  auto-convert any text files\n\
595  -o  overwrite files WITHOUT prompting      -aa treat ALL files as text\n \
596 -j  junk paths (do not make directories)   -v  be verbose/print version info\n\
597 %c-C%c match filenames case-insensitively    %c-L%c make (some) names \
598lowercase\n %-42s %c-V%c retain VMS version numbers\n%s";
599
600static ZCONST char Far UnzipUsageLine5[] = "\
601Examples (see unzip.txt for more info):\n\
602  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
603%s\
604  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
605#endif /* ?SFX */
606
607
608
609
610
611/*****************************/
612/*  main() / UzpMain() stub  */
613/*****************************/
614
615int MAIN(argc, argv)   /* return PK-type error code (except under VMS) */
616    int argc;
617    char *argv[];
618{
619    int r;
620
621    CONSTRUCTGLOBALS();
622    r = unzip(__G__ argc, argv);
623    DESTROYGLOBALS();
624    RETURN(r);
625}
626
627
628
629
630/*******************************/
631/*  Primary UnZip entry point  */
632/*******************************/
633
634int unzip(__G__ argc, argv)
635    __GDEF
636    int argc;
637    char *argv[];
638{
639#ifndef NO_ZIPINFO
640    char *p;
641#endif
642#ifdef DOS_FLX_H68_NLM_OS2_W32
643    int i;
644#endif
645    int retcode, error=FALSE;
646#ifdef REENTRANT
647    savsigs_info *oldsighandlers = NULL;
648#   define SET_SIGHANDLER(sigtype, newsighandler) \
649      if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \
650                                      (newsighandler))) > PK_WARN) \
651          goto cleanup_and_exit
652#else
653#   define SET_SIGHANDLER(sigtype, newsighandler) \
654      signal((sigtype), (newsighandler))
655#endif
656
657    SETLOCALE(LC_CTYPE,"");
658
659#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
660    extern void DebugMalloc(void);
661
662    atexit(DebugMalloc);
663#endif
664
665#ifdef MALLOC_WORK
666    /* The following (rather complex) expression determines the allocation
667       size of the decompression work area.  It simulates what the
668       combined "union" and "struct" declaration of the "static" work
669       area reservation achieves automatically at compile time.
670       Any decent compiler should evaluate this expression completely at
671       compile time and provide constants to the zcalloc() call.
672       (For better readability, some subexpressions are encapsulated
673       in temporarly defined macros.)
674     */
675#   define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))
676#   define UZ_NUMOF_CHUNKS \
677      (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \
678                 (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE)
679    G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);
680#   undef UZ_SLIDE_CHUNK
681#   undef UZ_NUMOF_CHUNKS
682    G.area.shrink.Parent = (shrint *)G.area.Slide;
683    G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE));
684    G.area.shrink.Stack = G.area.Slide +
685                           (sizeof(shrint) + sizeof(uch))*(HSIZE);
686#endif
687
688/*---------------------------------------------------------------------------
689    Set signal handler for restoring echo, warn of zipfile corruption, etc.
690  ---------------------------------------------------------------------------*/
691
692#ifdef SIGINT
693    SET_SIGHANDLER(SIGINT, handler);
694#endif
695#ifdef SIGTERM                 /* some systems really have no SIGTERM */
696    SET_SIGHANDLER(SIGTERM, handler);
697#endif
698#ifdef SIGBUS
699    SET_SIGHANDLER(SIGBUS, handler);
700#endif
701#ifdef SIGSEGV
702    SET_SIGHANDLER(SIGSEGV, handler);
703#endif
704
705#if (defined(WIN32) && defined(__RSXNT__))
706    for (i = 0 ; i < argc; i++) {
707       _ISO_INTERN(argv[i]);
708    }
709#endif
710
711/*---------------------------------------------------------------------------
712    Macintosh initialization code.
713  ---------------------------------------------------------------------------*/
714
715#ifdef MACOS
716    {
717        int a;
718
719        for (a = 0;  a < 4;  ++a)
720            G.rghCursor[a] = GetCursor(a+128);
721        G.giCursor = 0;
722    }
723#endif
724
725/*---------------------------------------------------------------------------
726    NetWare initialization code.
727  ---------------------------------------------------------------------------*/
728
729#ifdef NLM
730    InitUnZipConsole();
731#endif
732
733/*---------------------------------------------------------------------------
734    Acorn RISC OS initialization code.
735  ---------------------------------------------------------------------------*/
736
737#ifdef RISCOS
738    set_prefix();
739#endif
740
741/*---------------------------------------------------------------------------
742    Theos initialization code.
743  ---------------------------------------------------------------------------*/
744
745#ifdef THEOS
746    /* The easiest way found to force creation of libraries when selected
747     * members are to be unzipped. Explicitely add libraries names to the
748     * arguments list before the first member of the library.
749     */
750    if (! _setargv(&argc, &argv)) {
751        Info(slide, 0x401, ((char *)slide, "cannot process argv\n"));
752        retcode = PK_MEM;
753        goto cleanup_and_exit;
754    }
755#endif
756
757/*---------------------------------------------------------------------------
758    First figure out if we're running in UnZip mode or ZipInfo mode, and put
759    the appropriate environment-variable options into the queue.  Then rip
760    through any command-line options lurking about...
761  ---------------------------------------------------------------------------*/
762
763#ifdef SFX
764    G.argv0 = argv[0];
765#if (defined(OS2) || defined(WIN32))
766    G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
767#else
768    G.zipfn = G.argv0;
769#endif
770
771#ifdef VMSCLI
772    {
773        ulg status = vms_unzip_cmdline(&argc, &argv);
774        if (!(status & 1)) {
775            retcode = (int)status;
776            goto cleanup_and_exit;
777        }
778    }
779#endif /* VMSCLI */
780
781    uO.zipinfo_mode = FALSE;
782    error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */
783
784#else /* !SFX */
785
786#ifdef RISCOS
787    /* get the extensions to swap from environment */
788    getRISCOSexts(ENV_UNZIPEXTS);
789#endif
790
791#ifdef MSDOS
792    /* extract MKS extended argument list from environment (before envargs!) */
793    mksargs(&argc, &argv);
794#endif
795
796#ifdef VMSCLI
797    {
798        ulg status = vms_unzip_cmdline(&argc, &argv);
799        if (!(status & 1)) {
800            retcode = (int)status;
801            goto cleanup_and_exit;
802        }
803    }
804#endif /* VMSCLI */
805
806    G.noargs = (argc == 1);   /* no options, no zipfile, no anything */
807
808#ifndef NO_ZIPINFO
809    for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {
810        if (*p == DIR_END
811#ifdef DIR_END2
812            || *p == DIR_END2
813#endif
814           )
815            break;
816    }
817    ++p;
818
819#ifdef THEOS
820    if (strncmp(p, "ZIPINFO.",8) == 0 || strstr(p, ".ZIPINFO:") != NULL ||
821        strncmp(p, "II.",3) == 0 || strstr(p, ".II:") != NULL ||
822#else
823    if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
824        STRNICMP(p, "ii", 2) == 0 ||
825#endif
826        (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
827    {
828        uO.zipinfo_mode = TRUE;
829        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),
830                             LoadFarStringSmall2(EnvZipInfo2))) != PK_OK)
831            perror(LoadFarString(NoMemArguments));
832        else
833            error = zi_opts(__G__ &argc, &argv);
834    } else
835#endif /* NO_ZIPINFO */
836    {
837        uO.zipinfo_mode = FALSE;
838        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),
839                             LoadFarStringSmall2(EnvUnZip2))) != PK_OK)
840            perror(LoadFarString(NoMemArguments));
841        else
842            error = uz_opts(__G__ &argc, &argv);
843    }
844
845#endif /* ?SFX */
846
847    if ((argc < 0) || error) {
848        retcode = error;
849        goto cleanup_and_exit;
850    }
851
852/*---------------------------------------------------------------------------
853    Now get the zipfile name from the command line and then process any re-
854    maining options and file specifications.
855  ---------------------------------------------------------------------------*/
856
857#ifdef DOS_FLX_H68_NLM_OS2_W32
858    /* convert MSDOS-style 'backward slash' directory separators to Unix-style
859     * 'forward slashes' for user's convenience (include zipfile name itself)
860     */
861#ifdef SFX
862    for (G.pfnames = argv, i = argc;  i > 0;  --i) {
863#else
864    /* argc does not include the zipfile specification */
865    for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {
866#endif
867#ifdef __human68k__
868        extern char *_toslash(char *);
869        _toslash(*G.pfnames);
870#else /* !__human68k__ */
871        char *q;
872
873        for (q = *G.pfnames;  *q;  ++q)
874            if (*q == '\\')
875                *q = '/';
876        ++G.pfnames;
877#endif /* ?__human68k__ */
878    }
879#endif /* DOS_FLX_H68_NLM_OS2_W32 */
880
881#ifndef SFX
882    G.wildzipfn = *argv++;
883#endif
884
885#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
886
887    G.filespecs = argc;
888    G.xfilespecs = 0;
889
890    if (argc > 0) {
891        char **pp = argv-1;
892
893        G.pfnames = argv;
894        while (*++pp)
895            if (strcmp(*pp, "-x") == 0) {
896                if (pp > argv) {
897                    *pp = 0;              /* terminate G.pfnames */
898                    G.filespecs = pp - G.pfnames;
899                } else {
900                    G.pfnames = (char **)fnames;  /* defaults */
901                    G.filespecs = 0;
902                }
903                G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */
904                G.xfilespecs = argc - G.filespecs - 1;
905                break;                    /* skip rest of args */
906            }
907        G.process_all_files = FALSE;
908    } else
909        G.process_all_files = TRUE;      /* for speed */
910
911#else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
912
913    G.filespecs = argc;
914    G.xfilespecs = 0;
915
916    if (argc > 0) {
917        int in_files=FALSE, in_xfiles=FALSE;
918        char **pp = argv-1;
919
920        G.process_all_files = FALSE;
921        G.pfnames = argv;
922        while (*++pp) {
923            Trace((stderr, "pp - argv = %d\n", pp-argv));
924#ifdef CMS_MVS
925            if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
926#else
927            if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
928#endif
929                int firstarg = (pp == argv);
930
931                uO.exdir = (*pp) + 2;
932                if (in_files) {      /* ... zipfile ... -d exdir ... */
933                    *pp = (char *)NULL;         /* terminate G.pfnames */
934                    G.filespecs = pp - G.pfnames;
935                    in_files = FALSE;
936                } else if (in_xfiles) {
937                    *pp = (char *)NULL;         /* terminate G.pxnames */
938                    G.xfilespecs = pp - G.pxnames;
939                    /* "... -x xlist -d exdir":  nothing left */
940                }
941                /* first check for "-dexdir", then for "-d exdir" */
942                if (*uO.exdir == '\0') {
943                    if (*++pp)
944                        uO.exdir = *pp;
945                    else {
946                        Info(slide, 0x401, ((char *)slide,
947                          LoadFarString(MustGiveExdir)));
948                        /* don't extract here by accident */
949                        retcode = PK_PARAM;
950                        goto cleanup_and_exit;
951                    }
952                }
953                if (firstarg) { /* ... zipfile -d exdir ... */
954                    if (pp[1]) {
955                        G.pfnames = pp + 1;  /* argv+2 */
956                        G.filespecs = argc - (G.pfnames-argv);  /* for now... */
957                    } else {
958                        G.process_all_files = TRUE;
959                        G.pfnames = (char **)fnames;  /* GRR: necessary? */
960                        G.filespecs = 0;     /* GRR: necessary? */
961                        break;
962                    }
963                }
964            } else if (!in_xfiles) {
965                if (strcmp(*pp, "-x") == 0) {
966                    in_xfiles = TRUE;
967                    if (pp == G.pfnames) {
968                        G.pfnames = (char **)fnames;  /* defaults */
969                        G.filespecs = 0;
970                    } else if (in_files) {
971                        *pp = 0;                   /* terminate G.pfnames */
972                        G.filespecs = pp - G.pfnames;  /* adjust count */
973                        in_files = FALSE;
974                    }
975                    G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
976                    G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */
977                } else
978                    in_files = TRUE;
979            }
980        }
981    } else
982        G.process_all_files = TRUE;      /* for speed */
983
984    if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */
985        Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
986#endif /* ?(SFX && !SFX_EXDIR) */
987
988/*---------------------------------------------------------------------------
989    Okey dokey, we have everything we need to get started.  Let's roll.
990  ---------------------------------------------------------------------------*/
991
992    retcode = process_zipfiles(__G);
993
994cleanup_and_exit:
995#ifdef REENTRANT
996    /* restore all signal handlers back to their state at function entry */
997    while (oldsighandlers != NULL) {
998        savsigs_info *thissigsav = oldsighandlers;
999
1000        signal(thissigsav->sigtype, thissigsav->sighandler);
1001        oldsighandlers = thissigsav->previous;
1002        free(thissigsav);
1003    }
1004#endif
1005#if (defined(MALLOC_WORK) && !defined(REENTRANT))
1006    if (G.area.Slide != (uch *)NULL) {
1007        free(G.area.Slide);
1008        G.area.Slide = (uch *)NULL;
1009    }
1010#endif
1011    return(retcode);
1012
1013} /* end main()/unzip() */
1014
1015
1016
1017
1018
1019#ifdef REENTRANT
1020/*******************************/
1021/* Function setsignalhandler() */
1022/*******************************/
1023
1024static int setsignalhandler(__G__ p_savedhandler_chain, signal_type,
1025                            newhandler)
1026    __GDEF
1027    savsigs_info **p_savedhandler_chain;
1028    int signal_type;
1029    void (*newhandler)(int);
1030{
1031    savsigs_info *savsig;
1032
1033    savsig = malloc(sizeof(savsigs_info));
1034    if (savsig == NULL) {
1035        /* error message and break */
1036        Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler)));
1037        return PK_MEM;
1038    }
1039    savsig->sigtype = signal_type;
1040    savsig->sighandler = signal(SIGINT, newhandler);
1041    if (savsig->sighandler == SIG_ERR) {
1042        free(savsig);
1043    } else {
1044        savsig->previous = *p_savedhandler_chain;
1045        *p_savedhandler_chain = savsig;
1046    }
1047    return PK_OK;
1048
1049} /* end function setsignalhandler() */
1050
1051#endif /* REENTRANT */
1052
1053
1054
1055
1056
1057/**********************/
1058/* Function uz_opts() */
1059/**********************/
1060
1061int uz_opts(__G__ pargc, pargv)
1062    __GDEF
1063    int *pargc;
1064    char ***pargv;
1065{
1066    char **argv, *s;
1067    int argc, c, error=FALSE, negative=0;
1068
1069
1070    argc = *pargc;
1071    argv = *pargv;
1072
1073    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
1074        s = *argv + 1;
1075        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
1076#ifdef CMS_MVS
1077            switch (tolower(c))
1078#else
1079            switch (c)
1080#endif
1081            {
1082                case ('-'):
1083                    ++negative;
1084                    break;
1085#ifdef RISCOS
1086                case ('/'):
1087                    if (negative) {   /* negative not allowed with -/ swap */
1088                        Info(slide, 0x401, ((char *)slide,
1089                          "error:  must give extensions list"));
1090                        return(PK_PARAM);  /* don't extract here by accident */
1091                    }
1092                    exts2swap = s; /* override Unzip$Exts */
1093                    s += strlen(s);
1094                    break;
1095#endif
1096                case ('a'):
1097                    if (negative) {
1098                        uO.aflag = MAX(uO.aflag-negative,0);
1099                        negative = 0;
1100                    } else
1101                        ++uO.aflag;
1102                    break;
1103#if (defined(DLL) && defined(API_DOC))
1104                case ('A'):    /* extended help for API */
1105                    APIhelp(__G__ argc, argv);
1106                    *pargc = -1;  /* signal to exit successfully */
1107                    return 0;
1108#endif
1109                case ('b'):
1110                    if (negative) {
1111#if (defined(TANDEM) || defined(VMS))
1112                        uO.bflag = MAX(uO.bflag-negative,0);
1113#endif
1114                        negative = 0;   /* do nothing:  "-b" is default */
1115                    } else {
1116#ifdef VMS
1117                        if (uO.aflag == 0)
1118                           ++uO.bflag;
1119#endif
1120#ifdef TANDEM
1121                        ++uO.bflag;
1122#endif
1123                        uO.aflag = 0;
1124                    }
1125                    break;
1126#ifdef UNIXBACKUP
1127                case ('B'): /* -B: back up existing files */
1128                    if (negative)
1129                        uO.B_flag = FALSE, negative = 0;
1130                    else
1131                        uO.B_flag = TRUE;
1132                    break;
1133#endif
1134                case ('c'):
1135                    if (negative) {
1136                        uO.cflag = FALSE, negative = 0;
1137#ifdef NATIVE
1138                        uO.aflag = 0;
1139#endif
1140                    } else {
1141                        uO.cflag = TRUE;
1142#ifdef NATIVE
1143                        uO.aflag = 2;   /* so you can read it on the screen */
1144#endif
1145#ifdef DLL
1146                        if (G.redirect_text)
1147                            G.redirect_data = 2;
1148#endif
1149                    }
1150                    break;
1151#ifndef CMS_MVS
1152                case ('C'):    /* -C:  match filenames case-insensitively */
1153                    if (negative)
1154                        uO.C_flag = FALSE, negative = 0;
1155                    else
1156                        uO.C_flag = TRUE;
1157                    break;
1158#endif /* !CMS_MVS */
1159#if (!defined(SFX) || defined(SFX_EXDIR))
1160                case ('d'):
1161                    if (negative) {   /* negative not allowed with -d exdir */
1162                        Info(slide, 0x401, ((char *)slide,
1163                          LoadFarString(MustGiveExdir)));
1164                        return(PK_PARAM);  /* don't extract here by accident */
1165                    }
1166                    if (uO.exdir != (char *)NULL) {
1167                        Info(slide, 0x401, ((char *)slide,
1168                          LoadFarString(OnlyOneExdir)));
1169                        return(PK_PARAM);    /* GRR:  stupid restriction? */
1170                    } else {
1171                        /* first check for "-dexdir", then for "-d exdir" */
1172                        uO.exdir = s;
1173                        if (*uO.exdir == '\0') {
1174                            if (argc > 1) {
1175                                --argc;
1176                                uO.exdir = *++argv;
1177                                if (*uO.exdir == '-') {
1178                                    Info(slide, 0x401, ((char *)slide,
1179                                      LoadFarString(MustGiveExdir)));
1180                                    return(PK_PARAM);
1181                                }
1182                                /* else uO.exdir points at extraction dir */
1183                            } else {
1184                                Info(slide, 0x401, ((char *)slide,
1185                                  LoadFarString(MustGiveExdir)));
1186                                return(PK_PARAM);
1187                            }
1188                        }
1189                        /* uO.exdir now points at extraction dir (-dexdir or
1190                         *  -d exdir); point s at end of exdir to avoid mis-
1191                         *  interpretation of exdir characters as more options
1192                         */
1193                        if (*s != 0)
1194                            while (*++s != 0)
1195                                ;
1196                    }
1197                    break;
1198#endif /* !SFX || SFX_EXDIR */
1199                case ('e'):    /* just ignore -e, -x options (extract) */
1200                    break;
1201#ifdef MACOS
1202                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
1203                    if( negative ) {
1204                        uO.E_flag = FALSE, negative = 0;
1205                    } else {
1206                        uO.E_flag = TRUE;
1207                    }
1208                    break;
1209#endif /* MACOS */
1210                case ('f'):    /* "freshen" (extract only newer files) */
1211                    if (negative)
1212                        uO.fflag = uO.uflag = FALSE, negative = 0;
1213                    else
1214                        uO.fflag = uO.uflag = TRUE;
1215                    break;
1216#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
1217                case ('F'):    /* Acorn filetype & NFS extension handling */
1218                    if (negative)
1219                        uO.acorn_nfs_ext = FALSE, negative = 0;
1220                    else
1221                        uO.acorn_nfs_ext = TRUE;
1222                    break;
1223#endif /* RISCOS || ACORN_FTYPE_NFS */
1224                case ('h'):    /* just print help message and quit */
1225                    *pargc = -1;
1226                    return USAGE(PK_OK);
1227#ifdef MACOS
1228                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
1229                    if( negative ) {
1230                        uO.i_flag = FALSE, negative = 0;
1231                    } else {
1232                        uO.i_flag = TRUE;
1233                    }
1234                    break;
1235#endif  /* MACOS */
1236                case ('j'):    /* junk pathnames/directory structure */
1237                    if (negative)
1238                        uO.jflag = FALSE, negative = 0;
1239                    else
1240                        uO.jflag = TRUE;
1241                    break;
1242#if ((defined(__BEOS__) || defined(__HAIKU__)) || defined(MACOS) || defined(HAS_JUNK_EXTRA_FIELD_OPTION))
1243                case ('J'):    /* Junk BeOS or MacOS file attributes */
1244                    if( negative ) {
1245                        uO.J_flag = FALSE, negative = 0;
1246                    } else {
1247                        uO.J_flag = TRUE;
1248                    }
1249                    break;
1250#endif /* __BEOS__ || MACOS */
1251#ifndef SFX
1252                case ('l'):
1253                    if (negative) {
1254                        uO.vflag = MAX(uO.vflag-negative,0);
1255                        negative = 0;
1256                    } else
1257                        ++uO.vflag;
1258                    break;
1259#endif /* !SFX */
1260#ifndef CMS_MVS
1261                case ('L'):    /* convert (some) filenames to lowercase */
1262                    if (negative) {
1263                        uO.L_flag = MAX(uO.L_flag-negative,0);
1264                        negative = 0;
1265                    } else
1266                        ++uO.L_flag;
1267                    break;
1268#endif /* !CMS_MVS */
1269#ifdef MORE
1270#ifdef CMS_MVS
1271                case ('m'):
1272#endif
1273                case ('M'):    /* send all screen output through "more" fn. */
1274/* GRR:  eventually check for numerical argument => height */
1275                    if (negative)
1276                        G.M_flag = FALSE, negative = 0;
1277                    else
1278                        G.M_flag = TRUE;
1279                    break;
1280#endif /* MORE */
1281                case ('n'):    /* don't overwrite any files */
1282                    if (negative)
1283                        uO.overwrite_none = FALSE, negative = 0;
1284                    else
1285                        uO.overwrite_none = TRUE;
1286                    break;
1287#ifdef AMIGA
1288                case ('N'):    /* restore comments as filenotes */
1289                    if (negative)
1290                        uO.N_flag = FALSE, negative = 0;
1291                    else
1292                        uO.N_flag = TRUE;
1293                    break;
1294#endif /* AMIGA */
1295                case ('o'):    /* OK to overwrite files without prompting */
1296                    if (negative) {
1297                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
1298                        negative = 0;
1299                    } else
1300                        ++uO.overwrite_all;
1301                    break;
1302                case ('p'):    /* pipes:  extract to stdout, no messages */
1303                    if (negative) {
1304                        uO.cflag = FALSE;
1305                        uO.qflag = MAX(uO.qflag-999,0);
1306                        negative = 0;
1307                    } else {
1308                        uO.cflag = TRUE;
1309                        uO.qflag += 999;
1310                    }
1311                    break;
1312#if CRYPT
1313                /* GRR:  yes, this is highly insecure, but dozens of people
1314                 * have pestered us for this, so here we go... */
1315                case ('P'):
1316                    if (negative) {   /* negative not allowed with -P passwd */
1317                        Info(slide, 0x401, ((char *)slide,
1318                          LoadFarString(MustGivePasswd)));
1319                        return(PK_PARAM);  /* don't extract here by accident */
1320                    }
1321                    if (uO.pwdarg != (char *)NULL) {
1322/*
1323                        GRR:  eventually support multiple passwords?
1324                        Info(slide, 0x401, ((char *)slide,
1325                          LoadFarString(OnlyOnePasswd)));
1326                        return(PK_PARAM);
1327 */
1328                    } else {
1329                        /* first check for "-Ppasswd", then for "-P passwd" */
1330                        uO.pwdarg = s;
1331                        if (*uO.pwdarg == '\0') {
1332                            if (argc > 1) {
1333                                --argc;
1334                                uO.pwdarg = *++argv;
1335                                if (*uO.pwdarg == '-') {
1336                                    Info(slide, 0x401, ((char *)slide,
1337                                      LoadFarString(MustGivePasswd)));
1338                                    return(PK_PARAM);
1339                                }
1340                                /* else pwdarg points at decryption password */
1341                            } else {
1342                                Info(slide, 0x401, ((char *)slide,
1343                                  LoadFarString(MustGivePasswd)));
1344                                return(PK_PARAM);
1345                            }
1346                        }
1347                        /* pwdarg now points at decryption password (-Ppasswd or
1348                         *  -P passwd); point s at end of passwd to avoid mis-
1349                         *  interpretation of passwd characters as more options
1350                         */
1351                        if (*s != 0)
1352                            while (*++s != 0)
1353                                ;
1354                    }
1355                    break;
1356#endif /* CRYPT */
1357                case ('q'):    /* quiet:  fewer comments/messages */
1358                    if (negative) {
1359                        uO.qflag = MAX(uO.qflag-negative,0);
1360                        negative = 0;
1361                    } else
1362                        ++uO.qflag;
1363                    break;
1364#ifdef QDOS
1365                case ('Q'):   /* QDOS flags */
1366                    qlflag ^= strtol(s, &s, 10);
1367                    break;    /* we XOR this as we can config qlflags */
1368#endif
1369#ifdef DOS_FLX_NLM_OS2_W32
1370                case ('s'):    /* spaces in filenames:  allow by default */
1371                    if (negative)
1372                        uO.sflag = FALSE, negative = 0;
1373                    else
1374                        uO.sflag = TRUE;
1375                    break;
1376#endif /* DOS_FLX_NLM_OS2_W32 */
1377                case ('t'):
1378                    if (negative)
1379                        uO.tflag = FALSE, negative = 0;
1380                    else
1381                        uO.tflag = TRUE;
1382                    break;
1383#ifdef TIMESTAMP
1384                case ('T'):
1385                    if (negative)
1386                        uO.T_flag = FALSE, negative = 0;
1387                    else
1388                        uO.T_flag = TRUE;
1389                    break;
1390#endif
1391                case ('u'):    /* update (extract only new and newer files) */
1392                    if (negative)
1393                        uO.uflag = FALSE, negative = 0;
1394                    else
1395                        uO.uflag = TRUE;
1396                    break;
1397#ifndef CMS_MVS
1398                case ('U'):    /* obsolete; to be removed in version 6.0 */
1399                    if (negative)
1400                        uO.L_flag = TRUE, negative = 0;
1401                    else
1402                        uO.L_flag = FALSE;
1403                    break;
1404#endif /* !CMS_MVS */
1405#ifndef SFX
1406                case ('v'):    /* verbose */
1407                    if (negative) {
1408                        uO.vflag = MAX(uO.vflag-negative,0);
1409                        negative = 0;
1410                    } else if (uO.vflag)
1411                        ++uO.vflag;
1412                    else
1413                        uO.vflag = 2;
1414                    break;
1415#endif /* !SFX */
1416#ifndef CMS_MVS
1417                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
1418                    if (negative)
1419                        uO.V_flag = FALSE, negative = 0;
1420                    else
1421                        uO.V_flag = TRUE;
1422                    break;
1423#endif /* !CMS_MVS */
1424                case ('x'):    /* extract:  default */
1425#ifdef SFX
1426                    /* when 'x' is the only option in this argument, and the
1427                     * next arg is not an option, assume this initiates an
1428                     * exclusion list (-x xlist):  terminate option-scanning
1429                     * and leave uz_opts with argv still pointing to "-x";
1430                     * the xlist is processed later
1431                     */
1432                    if (s - argv[0] == 2 && *s == '\0' &&
1433                        argc > 1 && argv[1][0] != '-') {
1434                        /* break out of nested loops without "++argv;--argc" */
1435                        goto opts_done;
1436                    }
1437#endif /* SFX */
1438                    break;
1439#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
1440                case ('X'):   /* restore owner/protection info (need privs?) */
1441                    if (negative) {
1442                        uO.X_flag = MAX(uO.X_flag-negative,0);
1443                        negative = 0;
1444                    } else
1445                        ++uO.X_flag;
1446                    break;
1447#endif /* RESTORE_UIDGID || RESTORE_ACL */
1448                case ('z'):    /* display only the archive comment */
1449                    if (negative) {
1450                        uO.zflag = MAX(uO.zflag-negative,0);
1451                        negative = 0;
1452                    } else
1453                        ++uO.zflag;
1454                    break;
1455#ifndef SFX
1456                case ('Z'):    /* should have been first option (ZipInfo) */
1457                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
1458                    error = TRUE;
1459                    break;
1460#endif /* !SFX */
1461#ifdef DOS_H68_OS2_W32
1462                case ('$'):
1463                    if (negative) {
1464                        uO.volflag = MAX(uO.volflag-negative,0);
1465                        negative = 0;
1466                    } else
1467                        ++uO.volflag;
1468                    break;
1469#endif /* DOS_H68_OS2_W32 */
1470#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
1471                case (':'):
1472                    if (negative) {
1473                        uO.ddotflag = MAX(uO.ddotflag-negative,0);
1474                        negative = 0;
1475                    } else
1476                        ++uO.ddotflag;
1477                    break;
1478#endif /* !RISCOS && !CMS_MVS && !TANDEM */
1479                default:
1480                    error = TRUE;
1481                    break;
1482
1483            } /* end switch */
1484        } /* end while (not end of argument string) */
1485    } /* end while (not done with switches) */
1486
1487/*---------------------------------------------------------------------------
1488    Check for nonsensical combinations of options.
1489  ---------------------------------------------------------------------------*/
1490
1491#ifdef SFX
1492opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
1493#endif
1494
1495    if ((uO.cflag && uO.tflag) || (uO.cflag && uO.uflag) ||
1496        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
1497    {
1498        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
1499        error = TRUE;
1500    }
1501    if (uO.aflag > 2)
1502        uO.aflag = 2;
1503#ifdef VMS
1504    if (uO.bflag > 2)
1505        uO.bflag = 2;
1506#endif
1507    if (uO.overwrite_all && uO.overwrite_none) {
1508        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
1509        uO.overwrite_all = FALSE;
1510    }
1511#ifdef MORE
1512    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
1513        G.M_flag = 0;
1514#endif
1515
1516#ifdef SFX
1517    if (error)
1518#else
1519    if ((argc-- == 0) || error)
1520#endif
1521    {
1522        *pargc = argc;
1523        *pargv = argv;
1524#ifndef SFX
1525        if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
1526            show_version_info(__G);
1527            return PK_OK;
1528        }
1529        if (!G.noargs && !error)
1530            error = PK_PARAM;   /* had options (not -h or -v) but no zipfile */
1531#endif /* !SFX */
1532        return USAGE(error);
1533    }
1534
1535#ifdef SFX
1536    /* print our banner unless we're being fairly quiet */
1537    if (uO.qflag < 2)
1538        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
1539          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1540          LoadFarStringSmall(VersionDate)));
1541#ifdef BETA
1542    /* always print the beta warning:  no unauthorized distribution!! */
1543    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
1544      "SFX"));
1545#endif
1546#endif /* SFX */
1547
1548    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
1549#ifdef TIMESTAMP
1550                                                     || uO.T_flag
1551#endif
1552                                                                 )
1553        G.extract_flag = FALSE;
1554    else
1555        G.extract_flag = TRUE;
1556
1557    *pargc = argc;
1558    *pargv = argv;
1559    return PK_OK;
1560
1561} /* end function uz_opts() */
1562
1563
1564
1565
1566/********************/
1567/* Function usage() */
1568/********************/
1569
1570#ifdef SFX
1571#  ifdef VMS
1572#    define LOCAL "X.  Quote uppercase options"
1573#  endif
1574#  ifdef UNIX
1575#    define LOCAL "X"
1576#  endif
1577#  ifdef DOS_OS2_W32
1578#    define LOCAL "s$"
1579#  endif
1580#  if (defined(FLEXOS) || defined(NLM))
1581#    define LOCAL "s"
1582#  endif
1583#  ifdef AMIGA
1584#    define LOCAL "N"
1585#  endif
1586   /* Default for all other systems: */
1587#  ifndef LOCAL
1588#    define LOCAL ""
1589#  endif
1590
1591#  ifdef MORE
1592#    define SFXOPT1 "M"
1593#  else
1594#    define SFXOPT1 ""
1595#  endif
1596
1597int usage(__G__ error)   /* return PK-type error code */
1598    __GDEF
1599    int error;
1600{
1601    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
1602      UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1603      LoadFarStringSmall(VersionDate)));
1604    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
1605      SFXOPT1, LOCAL));
1606#ifdef BETA
1607    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
1608      "SFX"));
1609#endif
1610
1611    if (error)
1612        return PK_PARAM;
1613    else
1614        return PK_COOL;     /* just wanted usage screen: no error */
1615
1616} /* end function usage() */
1617
1618
1619
1620
1621
1622#else /* !SFX */
1623#  ifdef VMS
1624#    define QUOT '\"'
1625#    define QUOTS "\""
1626#  else
1627#    define QUOT ' '
1628#    define QUOTS ""
1629#  endif
1630
1631int usage(__G__ error)   /* return PK-type error code */
1632    __GDEF
1633    int error;
1634{
1635    int flag = (error? 1 : 0);
1636
1637
1638/*---------------------------------------------------------------------------
1639    Print either ZipInfo usage or UnZip usage, depending on incantation.
1640    (Strings must be no longer than 512 bytes for Turbo C, apparently.)
1641  ---------------------------------------------------------------------------*/
1642
1643    if (uO.zipinfo_mode) {
1644
1645#ifndef NO_ZIPINFO
1646
1647        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
1648          ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1649          LoadFarStringSmall(VersionDate),
1650          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
1651        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
1652        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
1653          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(ZipInfoUsageLine4)));
1654#ifdef VMS
1655        Info(slide, flag, ((char *)slide, "\nRemember that non-lowercase\
1656 filespecs must be quoted in VMS (e.g., \"Makefile\").\n"));
1657#endif
1658
1659#endif /* !NO_ZIPINFO */
1660
1661    } else {   /* UnZip mode */
1662
1663        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
1664          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1665          LoadFarStringSmall(VersionDate)));
1666#ifdef BETA
1667        Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
1668#endif
1669
1670        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
1671          ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
1672#ifdef VMS
1673        if (!error)  /* maybe no command-line tail found; show extra help */
1674            Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
1675#endif
1676
1677        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
1678          LoadFarStringSmall(local1)));
1679
1680        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
1681          QUOT,QUOT, QUOT,QUOT, LoadFarStringSmall(local2), QUOT,QUOT,
1682          LoadFarStringSmall2(local3)));
1683
1684        /* This is extra work for SMALL_MEM, but it will work since
1685         * LoadFarStringSmall2 uses the same buffer.  Remember, this
1686         * is a hack. */
1687        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
1688          LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
1689          LoadFarStringSmall2(Example3)));
1690
1691    } /* end if (uO.zipinfo_mode) */
1692
1693    if (error)
1694        return PK_PARAM;
1695    else
1696        return PK_COOL;     /* just wanted usage screen: no error */
1697
1698} /* end function usage() */
1699
1700#endif /* ?SFX */
1701
1702
1703
1704
1705#ifndef SFX
1706
1707/********************************/
1708/* Function show_version_info() */
1709/********************************/
1710
1711static void show_version_info(__G)
1712    __GDEF
1713{
1714    if (uO.qflag > 3)                           /* "unzip -vqqqq" */
1715        Info(slide, 0, ((char *)slide, "%d\n",
1716          (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL)));
1717    else {
1718        char *envptr, *getenv();
1719        int numopts = 0;
1720
1721        Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
1722          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1723          LoadFarStringSmall(VersionDate)));
1724        Info(slide, 0, ((char *)slide,
1725          LoadFarString(UnzipUsageLine2v)));
1726        version(__G);
1727        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
1728#ifdef ACORN_FTYPE_NFS
1729        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1730          LoadFarStringSmall(AcornFtypeNFS)));
1731        ++numopts;
1732#endif
1733#ifdef ASM_CRC
1734        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1735          LoadFarStringSmall(AsmCRC)));
1736        ++numopts;
1737#endif
1738#ifdef ASM_INFLATECODES
1739        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1740          LoadFarStringSmall(AsmInflateCodes)));
1741        ++numopts;
1742#endif
1743#ifdef CHECK_VERSIONS
1744        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1745          LoadFarStringSmall(Check_Versions)));
1746        ++numopts;
1747#endif
1748#ifdef COPYRIGHT_CLEAN
1749        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1750          LoadFarStringSmall(Copyright_Clean)));
1751        ++numopts;
1752#endif
1753#ifdef DEBUG
1754        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1755          LoadFarStringSmall(UDebug)));
1756        ++numopts;
1757#endif
1758#ifdef DEBUG_TIME
1759        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1760          LoadFarStringSmall(DebugTime)));
1761        ++numopts;
1762#endif
1763#ifdef DLL
1764        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1765          LoadFarStringSmall(Dll)));
1766        ++numopts;
1767#endif
1768#ifdef DOSWILD
1769        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1770          LoadFarStringSmall(DosWild)));
1771        ++numopts;
1772#endif
1773#ifdef LZW_CLEAN
1774        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1775          LoadFarStringSmall(LZW_Clean)));
1776        ++numopts;
1777#endif
1778#ifndef MORE
1779        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1780          LoadFarStringSmall(No_More)));
1781        ++numopts;
1782#endif
1783#ifdef NO_ZIPINFO
1784        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1785          LoadFarStringSmall(No_ZipInfo)));
1786        ++numopts;
1787#endif
1788#ifdef NTSD_EAS
1789        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1790          LoadFarStringSmall(NTSDExtAttrib)));
1791        ++numopts;
1792#endif
1793#ifdef OLD_THEOS_EXTRA
1794        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1795          LoadFarStringSmall(OldTheosExtra)));
1796        ++numopts;
1797#endif
1798#ifdef OS2_EAS
1799        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1800          LoadFarStringSmall(OS2ExtAttrib)));
1801        ++numopts;
1802#endif
1803#ifdef QLZIP
1804        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1805          LoadFarStringSmall(SMSExFldOnUnix)));
1806        ++numopts;
1807#endif
1808#ifdef REENTRANT
1809        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1810          LoadFarStringSmall(Reentrant)));
1811        ++numopts;
1812#endif
1813#ifdef REGARGS
1814        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1815          LoadFarStringSmall(RegArgs)));
1816        ++numopts;
1817#endif
1818#ifdef RETURN_CODES
1819        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1820          LoadFarStringSmall(Return_Codes)));
1821        ++numopts;
1822#endif
1823#ifdef SET_DIR_ATTRIB
1824        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1825          LoadFarStringSmall(SetDirAttrib)));
1826        ++numopts;
1827#endif
1828#ifdef TIMESTAMP
1829        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1830          LoadFarStringSmall(TimeStamp)));
1831        ++numopts;
1832#endif
1833#ifdef UNIXBACKUP
1834        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1835          LoadFarStringSmall(UnixBackup)));
1836        ++numopts;
1837#endif
1838#ifdef USE_EF_UT_TIME
1839        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1840          LoadFarStringSmall(Use_EF_UT_time)));
1841        ++numopts;
1842#endif
1843#ifndef COPYRIGHT_CLEAN
1844        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1845          LoadFarStringSmall(Use_Smith_Code)));
1846        ++numopts;
1847#endif
1848#ifndef LZW_CLEAN
1849        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1850          LoadFarStringSmall(Use_Unshrink)));
1851        ++numopts;
1852#endif
1853#ifdef USE_DEFLATE64
1854        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1855          LoadFarStringSmall(Use_Deflate64)));
1856        ++numopts;
1857#endif
1858#ifdef MULT_VOLUME
1859        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1860          LoadFarStringSmall(Use_MultiVol)));
1861        ++numopts;
1862#endif
1863#  if (defined(__DJGPP__) && (__DJGPP__ >= 2))
1864#    ifdef USE_DJGPP_ENV
1865        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1866          LoadFarStringSmall(Use_DJGPP_Env)));
1867        ++numopts;
1868#    endif
1869#    ifdef USE_DJGPP_GLOB
1870        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1871          LoadFarStringSmall(Use_DJGPP_Glob)));
1872        ++numopts;
1873#    endif
1874#  endif /* __DJGPP__ && (__DJGPP__ >= 2) */
1875#ifdef USE_VFAT
1876        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1877          LoadFarStringSmall(Use_VFAT_support)));
1878        ++numopts;
1879#endif
1880#ifdef USE_ZLIB
1881        sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
1882          ZLIB_VERSION, zlib_version);
1883        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1884          (char *)(slide+256)));
1885        ++numopts;
1886#endif
1887#ifdef VMS_TEXT_CONV
1888        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1889          LoadFarStringSmall(VmsTextConv)));
1890        ++numopts;
1891#endif
1892#ifdef VMSCLI
1893        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1894          LoadFarStringSmall(VmsCLI)));
1895        ++numopts;
1896#endif
1897#ifdef VMSWILD
1898        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1899          LoadFarStringSmall(VmsWild)));
1900        ++numopts;
1901#endif
1902#ifdef WILD_STOP_AT_DIR
1903        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1904          LoadFarStringSmall(WildStopAtDir)));
1905        ++numopts;
1906#endif
1907#if CRYPT
1908# ifdef PASSWD_FROM_STDIN
1909        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
1910          LoadFarStringSmall(PasswdStdin)));
1911# endif
1912        Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
1913          CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
1914          LoadFarStringSmall(CryptDate)));
1915        ++numopts;
1916#endif /* CRYPT */
1917        if (numopts == 0)
1918            Info(slide, 0, ((char *)slide,
1919              LoadFarString(CompileOptFormat),
1920              LoadFarStringSmall(None)));
1921
1922        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
1923        envptr = getenv(LoadFarStringSmall(EnvUnZip));
1924        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1925          LoadFarStringSmall(EnvUnZip),
1926          (envptr == (char *)NULL || *envptr == 0)?
1927          LoadFarStringSmall2(None) : envptr));
1928        envptr = getenv(LoadFarStringSmall(EnvUnZip2));
1929        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1930          LoadFarStringSmall(EnvUnZip2),
1931          (envptr == (char *)NULL || *envptr == 0)?
1932          LoadFarStringSmall2(None) : envptr));
1933        envptr = getenv(LoadFarStringSmall(EnvZipInfo));
1934        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1935          LoadFarStringSmall(EnvZipInfo),
1936          (envptr == (char *)NULL || *envptr == 0)?
1937          LoadFarStringSmall2(None) : envptr));
1938        envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
1939        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1940          LoadFarStringSmall(EnvZipInfo2),
1941          (envptr == (char *)NULL || *envptr == 0)?
1942          LoadFarStringSmall2(None) : envptr));
1943#ifndef __RSXNT__
1944#ifdef __EMX__
1945        envptr = getenv(LoadFarStringSmall(EnvEMX));
1946        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1947          LoadFarStringSmall(EnvEMX),
1948          (envptr == (char *)NULL || *envptr == 0)?
1949          LoadFarStringSmall2(None) : envptr));
1950        envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
1951        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1952          LoadFarStringSmall(EnvEMXOPT),
1953          (envptr == (char *)NULL || *envptr == 0)?
1954          LoadFarStringSmall2(None) : envptr));
1955#endif /* __EMX__ */
1956#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
1957        envptr = getenv(LoadFarStringSmall(EnvGO32));
1958        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1959          LoadFarStringSmall(EnvGO32),
1960          (envptr == (char *)NULL || *envptr == 0)?
1961          LoadFarStringSmall2(None) : envptr));
1962        envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
1963        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1964          LoadFarStringSmall(EnvGO32TMP),
1965          (envptr == (char *)NULL || *envptr == 0)?
1966          LoadFarStringSmall2(None) : envptr));
1967#endif /* __GO32__ && !(__DJGPP__ >= 2) */
1968#endif /* !__RSXNT__ */
1969#ifdef RISCOS
1970        envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
1971        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
1972          LoadFarStringSmall(EnvUnZipExts),
1973          (envptr == (char *)NULL || *envptr == 0)?
1974          LoadFarStringSmall2(None) : envptr));
1975#endif /* RISCOS */
1976    }
1977} /* end function show_version() */
1978
1979#endif /* !SFX */
1980#endif /* !WINDLL */
1981