1/*
2  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
3
4  See the accompanying file LICENSE, version 2009-Jan-02 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, submit a *complete* description via
16  //www.info-zip.org/zip-bug.html; include machine type, operating system and
17  version, compiler and version, and reasonably detailed error messages or
18  problem 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  UnZip 6.0 adds support for archives larger than 4 GiB using the Zip64
27  extensions as well as support for Unicode information embedded per the
28  latest zip standard additions.
29
30  ---------------------------------------------------------------------------
31
32  [from original zipinfo.c]
33
34  This program reads great gobs of totally nifty information, including the
35  central directory stuff, from ZIP archives ("zipfiles" for short).  It
36  started as just a testbed for fooling with zipfiles, but at this point it
37  is actually a useful utility.  It also became the basis for the rewrite of
38  UnZip (3.16 -> 4.0), using the central directory for processing rather than
39  the individual (local) file headers.
40
41  As of ZipInfo v2.0 and UnZip v5.1, the two programs are combined into one.
42  If the executable is named "unzip" (or "unzip.exe", depending), it behaves
43  like UnZip by default; if it is named "zipinfo" or "ii", it behaves like
44  ZipInfo.  The ZipInfo behavior may also be triggered by use of unzip's -Z
45  option; for example, "unzip -Z [zipinfo_options] archive.zip".
46
47  Another dandy product from your buddies at Newtware!
48
49  Author:  Greg Roelofs, newt@pobox.com, http://pobox.com/~newt/
50           23 August 1990 -> April 1997
51
52  ---------------------------------------------------------------------------
53
54  Version:  unzip5??.{tar.Z | tar.gz | zip} for Unix, VMS, OS/2, MS-DOS, Amiga,
55              Atari, Windows 3.x/95/NT/CE, Macintosh, Human68K, Acorn RISC OS,
56              AtheOS, BeOS, SMS/QDOS, VM/CMS, MVS, AOS/VS, Tandem NSK, Theos
57              and TOPS-20.
58
59  Copyrights:  see accompanying file "LICENSE" in UnZip source distribution.
60               (This software is free but NOT IN THE PUBLIC DOMAIN.)
61
62  ---------------------------------------------------------------------------*/
63
64
65
66#define __UNZIP_C       /* identifies this source module */
67#define UNZIP_INTERNAL
68#include "unzip.h"      /* includes, typedefs, macros, prototypes, etc. */
69#include "crypt.h"
70#include "unzvers.h"
71
72#ifndef WINDLL          /* The WINDLL port uses windll/windll.c instead... */
73
74/***************************/
75/* Local type declarations */
76/***************************/
77
78#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
79typedef struct _sign_info
80    {
81        struct _sign_info *previous;
82        void (*sighandler)(int);
83        int sigtype;
84    } savsigs_info;
85#endif
86
87/*******************/
88/* Local Functions */
89/*******************/
90
91#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
92static int setsignalhandler OF((__GPRO__ savsigs_info **p_savedhandler_chain,
93                                int signal_type, void (*newhandler)(int)));
94#endif
95#ifndef SFX
96static void  help_extended      OF((__GPRO));
97static void  show_version_info  OF((__GPRO));
98#endif
99
100
101/*************/
102/* Constants */
103/*************/
104
105#include "consts.h"  /* all constant global variables are in here */
106                     /* (non-constant globals were moved to globals.c) */
107
108/* constant local variables: */
109
110#ifndef SFX
111#ifndef _WIN32_WCE /* Win CE does not support environment variables */
112   static ZCONST char Far EnvUnZip[] = ENV_UNZIP;
113   static ZCONST char Far EnvUnZip2[] = ENV_UNZIP2;
114   static ZCONST char Far EnvZipInfo[] = ENV_ZIPINFO;
115   static ZCONST char Far EnvZipInfo2[] = ENV_ZIPINFO2;
116#ifdef RISCOS
117   static ZCONST char Far EnvUnZipExts[] = ENV_UNZIPEXTS;
118#endif /* RISCOS */
119  static ZCONST char Far NoMemEnvArguments[] =
120    "envargs:  cannot get memory for arguments";
121#endif /* !_WIN32_WCE */
122  static ZCONST char Far CmdLineParamTooLong[] =
123    "error:  command line parameter #%d exceeds internal size limit\n";
124#endif /* !SFX */
125
126#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
127  static ZCONST char Far CantSaveSigHandler[] =
128    "error:  cannot save signal handler settings\n";
129#endif
130
131#if (!defined(SFX) || defined(SFX_EXDIR))
132   static ZCONST char Far NotExtracting[] =
133     "caution:  not extracting; -d ignored\n";
134   static ZCONST char Far MustGiveExdir[] =
135     "error:  must specify directory to which to extract with -d option\n";
136   static ZCONST char Far OnlyOneExdir[] =
137     "error:  -d option used more than once (only one exdir allowed)\n";
138#endif
139#if (defined(UNICODE_SUPPORT) && !defined(UNICODE_WCHAR))
140  static ZCONST char Far UTF8EscapeUnSupp[] =
141    "warning:  -U \"escape all non-ASCII UTF-8 chars\" is not supported\n";
142#endif
143
144#if CRYPT
145   static ZCONST char Far MustGivePasswd[] =
146     "error:  must give decryption password with -P option\n";
147#endif
148
149#ifndef SFX
150   static ZCONST char Far Zfirst[] =
151   "error:  -Z must be first option for ZipInfo mode (check UNZIP variable?)\n";
152#endif
153static ZCONST char Far InvalidOptionsMsg[] = "error:\
154  -fn or any combination of -c, -l, -p, -t, -u and -v options invalid\n";
155static ZCONST char Far IgnoreOOptionMsg[] =
156  "caution:  both -n and -o specified; ignoring -o\n";
157
158/* usage() strings */
159#ifndef SFX
160#ifdef VMS
161   static ZCONST char Far Example3[] = "vms.c";
162   static ZCONST char Far Example2[] = "  unzip \"-V\" foo \"Bar\"\
163 (Quote names to preserve case, unless SET PROC/PARS=EXT)\n";
164#else /* !VMS */
165   static ZCONST char Far Example3[] = "ReadMe";
166#ifdef RISCOS
167   static ZCONST char Far Example2[] =
168"  unzip foo -d RAM:$   => extract all files from foo into RAMDisc\n";
169#else /* !RISCOS */
170#if (defined(OS2) || (defined(DOS_FLX_OS2_W32) && defined(MORE)))
171   static ZCONST char Far Example2[] =
172     "";                /* no room:  too many local3[] items */
173#else /* !OS2 */
174#ifdef MACOS
175   static ZCONST char Far Example2[] = ""; /* not needed */
176#else /* !MACOS */
177   static ZCONST char Far Example2[] = " \
178 unzip -p foo | more  => send contents of foo.zip via pipe into program more\n";
179#endif /* ?MACOS */
180#endif /* ?OS2 */
181#endif /* ?RISCOS */
182#endif /* ?VMS */
183
184/* local1[]:  command options */
185#if defined(TIMESTAMP)
186   static ZCONST char Far local1[] =
187     "  -T  timestamp archive to latest";
188#else /* !TIMESTAMP */
189   static ZCONST char Far local1[] = "";
190#endif /* ?TIMESTAMP */
191
192/* local2[] and local3[]:  modifier options */
193#ifdef DOS_FLX_H68_OS2_W32
194#ifdef FLEXOS
195   static ZCONST char Far local2[] = "";
196#else
197   static ZCONST char Far local2[] =
198     " -$  label removables (-$$ => fixed disks)";
199#endif
200#ifdef OS2
201#ifdef MORE
202   static ZCONST char Far local3[] = "\
203  -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\
204                                             -M  pipe through \"more\" pager\n";
205#else
206   static ZCONST char Far local3[] = " \
207 -X  restore ACLs if supported              -s  spaces in filenames => '_'\n\n";
208#endif /* ?MORE */
209#else /* !OS2 */
210#ifdef WIN32
211#ifdef NTSD_EAS
212#ifdef MORE
213   static ZCONST char Far local3[] = "\
214  -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\
215                                             -M  pipe through \"more\" pager\n";
216#else
217   static ZCONST char Far local3[] = " \
218 -X  restore ACLs (-XX => use privileges)   -s  spaces in filenames => '_'\n\n";
219#endif /* ?MORE */
220#else /* !NTSD_EAS */
221#ifdef MORE
222   static ZCONST char Far local3[] = "\
223  -M  pipe through \"more\" pager            \
224  -s  spaces in filenames => '_'\n\n";
225#else
226   static ZCONST char Far local3[] = " \
227                                            -s  spaces in filenames => '_'\n\n";
228#endif /* ?MORE */
229#endif /* ?NTSD_EAS */
230#else /* !WIN32 */
231#ifdef MORE
232   static ZCONST char Far local3[] = "  -\
233M  pipe through \"more\" pager              -s  spaces in filenames => '_'\n\n";
234#else
235   static ZCONST char Far local3[] = "\
236                                             -s  spaces in filenames => '_'\n";
237#endif
238#endif /* ?WIN32 */
239#endif /* ?OS2 || ?WIN32 */
240#else /* !DOS_FLX_OS2_W32 */
241#ifdef VMS
242   static ZCONST char Far local2[] = " -X  restore owner/ACL protection info";
243#ifdef MORE
244   static ZCONST char Far local3[] = "\
245  -Y  treat \".nnn\" as \";nnn\" version         -2  force ODS2 names\n\
246  --D restore dir (-D: no) timestamps        -M  pipe through \"more\" pager\n\
247  (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
248\n\n";
249#else
250   static ZCONST char Far local3[] = "\n\
251  -Y  treat \".nnn\" as \";nnn\" version         -2  force ODS2 names\n\
252  --D restore dir (-D: no) timestamps\n\
253  (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
254\n\n";
255#endif
256#else /* !VMS */
257#ifdef ATH_BEO_UNX
258   static ZCONST char Far local2[] = " -X  restore UID/GID info";
259#ifdef MORE
260   static ZCONST char Far local3[] = "\
261  -K  keep setuid/setgid/tacky permissions   -M  pipe through \"more\" pager\n";
262#else
263   static ZCONST char Far local3[] = "\
264  -K  keep setuid/setgid/tacky permissions\n";
265#endif
266#else /* !ATH_BEO_UNX */
267#ifdef TANDEM
268   static ZCONST char Far local2[] = "\
269 -X  restore Tandem User ID                 -r  remove file extensions\n\
270  -b  create 'C' (180) text files          ";
271#ifdef MORE
272   static ZCONST char Far local3[] = " \
273                                            -M  pipe through \"more\" pager\n";
274#else
275   static ZCONST char Far local3[] = "\n";
276#endif
277#else /* !TANDEM */
278#ifdef AMIGA
279   static ZCONST char Far local2[] = " -N  restore comments as filenotes";
280#ifdef MORE
281   static ZCONST char Far local3[] = " \
282                                            -M  pipe through \"more\" pager\n";
283#else
284   static ZCONST char Far local3[] = "\n";
285#endif
286#else /* !AMIGA */
287#ifdef MACOS
288   static ZCONST char Far local2[] = " -E  show Mac info during extraction";
289   static ZCONST char Far local3[] = " \
290 -i  ignore filenames in mac extra info     -J  junk (ignore) Mac extra info\n\
291\n";
292#else /* !MACOS */
293#ifdef MORE
294   static ZCONST char Far local2[] = " -M  pipe through \"more\" pager";
295   static ZCONST char Far local3[] = "\n";
296#else
297   static ZCONST char Far local2[] = "";   /* Atari, Mac, CMS/MVS etc. */
298   static ZCONST char Far local3[] = "";
299#endif
300#endif /* ?MACOS */
301#endif /* ?AMIGA */
302#endif /* ?TANDEM */
303#endif /* ?ATH_BEO_UNX */
304#endif /* ?VMS */
305#endif /* ?DOS_FLX_OS2_W32 */
306#endif /* !SFX */
307
308#ifndef NO_ZIPINFO
309#ifdef VMS
310   static ZCONST char Far ZipInfoExample[] = "* or % (e.g., \"*font-%.zip\")";
311#else
312   static ZCONST char Far ZipInfoExample[] = "*, ?, [] (e.g., \"[a-j]*.zip\")";
313#endif
314
315static ZCONST char Far ZipInfoUsageLine1[] = "\
316ZipInfo %d.%d%d%s of %s, by Greg Roelofs and the Info-ZIP group.\n\
317\n\
318List name, date/time, attribute, size, compression method, etc., about files\n\
319in list (excluding those in xlist) contained in the specified .zip archive(s).\
320\n\"file[.zip]\" may be a wildcard name containing %s.\n\n\
321   usage:  zipinfo [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n\
322      or:  unzip %s-Z%s [-12smlvChMtTz] file[.zip] [list...] [-x xlist...]\n";
323
324static ZCONST char Far ZipInfoUsageLine2[] = "\nmain\
325 listing-format options:             -s  short Unix \"ls -l\" format (def.)\n\
326  -1  filenames ONLY, one per line       -m  medium Unix \"ls -l\" format\n\
327  -2  just filenames but allow -h/-t/-z  -l  long Unix \"ls -l\" format\n\
328                                         -v  verbose, multi-page format\n";
329
330static ZCONST char Far ZipInfoUsageLine3[] = "miscellaneous options:\n\
331  -h  print header line       -t  print totals for listed files or for all\n\
332  -z  print zipfile comment   -T  print file times in sortable decimal format\
333\n  -C  be case-insensitive   %s\
334  -x  exclude filenames that follow from listing\n";
335#ifdef MORE
336   static ZCONST char Far ZipInfoUsageLine4[] =
337     "  -M  page output through built-in \"more\"\n";
338#else /* !MORE */
339   static ZCONST char Far ZipInfoUsageLine4[] = "";
340#endif /* ?MORE */
341#endif /* !NO_ZIPINFO */
342
343#ifdef BETA
344#  ifdef VMSCLI
345   /* BetaVersion[] is also used in vms/cmdline.c:  do not make it static */
346     ZCONST char Far BetaVersion[] = "%s\
347        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
348#  else
349     static ZCONST char Far BetaVersion[] = "%s\
350        THIS IS STILL A BETA VERSION OF UNZIP%s -- DO NOT DISTRIBUTE.\n\n";
351#  endif
352#endif
353
354#ifdef SFX
355#  ifdef VMSCLI
356   /* UnzipSFXBanner[] is also used in vms/cmdline.c:  do not make it static */
357     ZCONST char Far UnzipSFXBanner[] =
358#  else
359     static ZCONST char Far UnzipSFXBanner[] =
360#  endif
361     "UnZipSFX %d.%d%d%s of %s, by Info-ZIP (http://www.info-zip.org).\n";
362#  ifdef SFX_EXDIR
363     static ZCONST char Far UnzipSFXOpts[] =
364    "Valid options are -tfupcz and -d <exdir>; modifiers are -abjnoqCL%sV%s.\n";
365#  else
366     static ZCONST char Far UnzipSFXOpts[] =
367       "Valid options are -tfupcz; modifiers are -abjnoqCL%sV%s.\n";
368#  endif
369#else /* !SFX */
370   static ZCONST char Far CompileOptions[] =
371     "UnZip special compilation options:\n";
372   static ZCONST char Far CompileOptFormat[] = "        %s\n";
373#ifndef _WIN32_WCE /* Win CE does not support environment variables */
374   static ZCONST char Far EnvOptions[] =
375     "\nUnZip and ZipInfo environment options:\n";
376   static ZCONST char Far EnvOptFormat[] = "%16s:  %.1024s\n";
377#endif
378   static ZCONST char Far None[] = "[none]";
379#  ifdef ACORN_FTYPE_NFS
380     static ZCONST char Far AcornFtypeNFS[] = "ACORN_FTYPE_NFS";
381#  endif
382#  ifdef ASM_CRC
383     static ZCONST char Far AsmCRC[] = "ASM_CRC";
384#  endif
385#  ifdef ASM_INFLATECODES
386     static ZCONST char Far AsmInflateCodes[] = "ASM_INFLATECODES";
387#  endif
388#  ifdef CHECK_VERSIONS
389     static ZCONST char Far Check_Versions[] = "CHECK_VERSIONS";
390#  endif
391#  ifdef COPYRIGHT_CLEAN
392     static ZCONST char Far Copyright_Clean[] =
393     "COPYRIGHT_CLEAN (PKZIP 0.9x unreducing method not supported)";
394#  endif
395#  ifdef DEBUG
396     static ZCONST char Far UDebug[] = "DEBUG";
397#  endif
398#  ifdef DEBUG_TIME
399     static ZCONST char Far DebugTime[] = "DEBUG_TIME";
400#  endif
401#  ifdef DLL
402     static ZCONST char Far Dll[] = "DLL";
403#  endif
404#  ifdef DOSWILD
405     static ZCONST char Far DosWild[] = "DOSWILD";
406#  endif
407#  ifdef LZW_CLEAN
408     static ZCONST char Far LZW_Clean[] =
409     "LZW_CLEAN (PKZIP/Zip 1.x unshrinking method not supported)";
410#  endif
411#  ifndef MORE
412     static ZCONST char Far No_More[] = "NO_MORE";
413#  endif
414#  ifdef NO_ZIPINFO
415     static ZCONST char Far No_ZipInfo[] = "NO_ZIPINFO";
416#  endif
417#  ifdef NTSD_EAS
418     static ZCONST char Far NTSDExtAttrib[] = "NTSD_EAS";
419#  endif
420#  if defined(WIN32) && defined(NO_W32TIMES_IZFIX)
421     static ZCONST char Far W32NoIZTimeFix[] = "NO_W32TIMES_IZFIX";
422#  endif
423#  ifdef OLD_THEOS_EXTRA
424     static ZCONST char Far OldTheosExtra[] =
425     "OLD_THEOS_EXTRA (handle also old Theos port extra field)";
426#  endif
427#  ifdef OS2_EAS
428     static ZCONST char Far OS2ExtAttrib[] = "OS2_EAS";
429#  endif
430#  ifdef QLZIP
431     static ZCONST char Far SMSExFldOnUnix[] = "QLZIP";
432#  endif
433#  ifdef REENTRANT
434     static ZCONST char Far Reentrant[] = "REENTRANT";
435#  endif
436#  ifdef REGARGS
437     static ZCONST char Far RegArgs[] = "REGARGS";
438#  endif
439#  ifdef RETURN_CODES
440     static ZCONST char Far Return_Codes[] = "RETURN_CODES";
441#  endif
442#  ifdef SET_DIR_ATTRIB
443     static ZCONST char Far SetDirAttrib[] = "SET_DIR_ATTRIB";
444#  endif
445#  ifdef SYMLINKS
446     static ZCONST char Far SymLinkSupport[] =
447     "SYMLINKS (symbolic links supported, if RTL and file system permit)";
448#  endif
449#  ifdef TIMESTAMP
450     static ZCONST char Far TimeStamp[] = "TIMESTAMP";
451#  endif
452#  ifdef UNIXBACKUP
453     static ZCONST char Far UnixBackup[] = "UNIXBACKUP";
454#  endif
455#  ifdef USE_EF_UT_TIME
456     static ZCONST char Far Use_EF_UT_time[] = "USE_EF_UT_TIME";
457#  endif
458#  ifndef LZW_CLEAN
459     static ZCONST char Far Use_Unshrink[] =
460     "USE_UNSHRINK (PKZIP/Zip 1.x unshrinking method supported)";
461#  endif
462#  ifndef COPYRIGHT_CLEAN
463     static ZCONST char Far Use_Smith_Code[] =
464     "USE_SMITH_CODE (PKZIP 0.9x unreducing method supported)";
465#  endif
466#  ifdef USE_DEFLATE64
467     static ZCONST char Far Use_Deflate64[] =
468     "USE_DEFLATE64 (PKZIP 4.x Deflate64(tm) supported)";
469#  endif
470#  ifdef UNICODE_SUPPORT
471#   ifdef UTF8_MAYBE_NATIVE
472#    ifdef UNICODE_WCHAR
473       /* direct native UTF-8 check AND charset transform via wchar_t */
474       static ZCONST char Far Use_Unicode[] =
475       "UNICODE_SUPPORT [wide-chars, char coding: %s] (handle UTF-8 paths)";
476#    else
477       /* direct native UTF-8 check, only */
478       static ZCONST char Far Use_Unicode[] =
479       "UNICODE_SUPPORT [char coding: %s] (handle UTF-8 paths)";
480#    endif
481       static ZCONST char Far SysChUTF8[] = "UTF-8";
482       static ZCONST char Far SysChOther[] = "other";
483#   else /* !UTF8_MAYBE_NATIVE */
484       /* charset transform via wchar_t, no native UTF-8 support */
485       static ZCONST char Far Use_Unicode[] =
486       "UNICODE_SUPPORT [wide-chars] (handle UTF-8 paths)";
487#   endif /* ?UTF8_MAYBE_NATIVE */
488#  endif /* UNICODE_SUPPORT */
489#  ifdef _MBCS
490     static ZCONST char Far Have_MBCS_Support[] =
491     "MBCS-support (multibyte character support, MB_CUR_MAX = %u)";
492#  endif
493#  ifdef MULT_VOLUME
494     static ZCONST char Far Use_MultiVol[] =
495     "MULT_VOLUME (multi-volume archives supported)";
496#  endif
497#  ifdef LARGE_FILE_SUPPORT
498     static ZCONST char Far Use_LFS[] =
499     "LARGE_FILE_SUPPORT (large files over 2 GiB supported)";
500#  endif
501#  ifdef ZIP64_SUPPORT
502     static ZCONST char Far Use_Zip64[] =
503     "ZIP64_SUPPORT (archives using Zip64 for large files supported)";
504#  endif
505#  if (defined(__DJGPP__) && (__DJGPP__ >= 2))
506#    ifdef USE_DJGPP_ENV
507       static ZCONST char Far Use_DJGPP_Env[] = "USE_DJGPP_ENV";
508#    endif
509#    ifdef USE_DJGPP_GLOB
510       static ZCONST char Far Use_DJGPP_Glob[] = "USE_DJGPP_GLOB";
511#    endif
512#  endif /* __DJGPP__ && (__DJGPP__ >= 2) */
513#  ifdef USE_VFAT
514     static ZCONST char Far Use_VFAT_support[] = "USE_VFAT";
515#  endif
516#  ifdef USE_ZLIB
517     static ZCONST char Far UseZlib[] =
518     "USE_ZLIB (compiled with version %s; using version %s)";
519#  endif
520#  ifdef USE_BZIP2
521     static ZCONST char Far UseBZip2[] =
522     "USE_BZIP2 (PKZIP 4.6+, using bzip2 lib version %s)";
523#  endif
524#  ifdef VMS_TEXT_CONV
525     static ZCONST char Far VmsTextConv[] = "VMS_TEXT_CONV";
526#  endif
527#  ifdef VMSCLI
528     static ZCONST char Far VmsCLI[] = "VMSCLI";
529#  endif
530#  ifdef VMSWILD
531     static ZCONST char Far VmsWild[] = "VMSWILD";
532#  endif
533#  ifdef WILD_STOP_AT_DIR
534     static ZCONST char Far WildStopAtDir[] = "WILD_STOP_AT_DIR";
535#  endif
536#  if CRYPT
537#    ifdef PASSWD_FROM_STDIN
538       static ZCONST char Far PasswdStdin[] = "PASSWD_FROM_STDIN";
539#    endif
540     static ZCONST char Far Decryption[] =
541       "        [decryption, version %d.%d%s of %s]\n";
542     static ZCONST char Far CryptDate[] = CR_VERSION_DATE;
543#  endif
544#  ifndef __RSXNT__
545#    ifdef __EMX__
546       static ZCONST char Far EnvEMX[] = "EMX";
547       static ZCONST char Far EnvEMXOPT[] = "EMXOPT";
548#    endif
549#    if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
550       static ZCONST char Far EnvGO32[] = "GO32";
551       static ZCONST char Far EnvGO32TMP[] = "GO32TMP";
552#    endif
553#  endif /* !__RSXNT__ */
554
555#ifdef VMS
556/* UnzipUsageLine1[] is also used in vms/cmdline.c:  do not make it static */
557   ZCONST char Far UnzipUsageLine1[] = "\
558UnZip %d.%d%d%s of %s, by Info-ZIP.  For more details see: unzip -v.\n\n";
559# ifdef COPYRIGHT_CLEAN
560   static ZCONST char Far UnzipUsageLine1v[] = "\
561UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
562bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\
563\n\n";
564# else
565   static ZCONST char Far UnzipUsageLine1v[] = "\
566UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
567Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\
568\n\n";
569# endif /* ?COPYRIGHT_CLEAN */
570#else /* !VMS */
571# ifdef COPYRIGHT_CLEAN
572   static ZCONST char Far UnzipUsageLine1[] = "\
573UnZip %d.%d%d%s of %s, by Info-ZIP.  Maintained by C. Spieler.  Send\n\
574bug reports using http://www.info-zip.org/zip-bug.html; see README for details.\
575\n\n";
576# else
577   static ZCONST char Far UnzipUsageLine1[] = "\
578UnZip %d.%d%d%s of %s, by Info-ZIP.  UnReduce (c) 1989 by S. H. Smith.\n\
579Send bug reports using //www.info-zip.org/zip-bug.html; see README for details.\
580\n\n";
581# endif /* ?COPYRIGHT_CLEAN */
582# define UnzipUsageLine1v       UnzipUsageLine1
583#endif /* ?VMS */
584
585static ZCONST char Far UnzipUsageLine2v[] = "\
586Latest sources and executables are at ftp://ftp.info-zip.org/pub/infozip/ ;\
587\nsee ftp://ftp.info-zip.org/pub/infozip/UnZip.html for other sites.\
588\n\n";
589
590#ifdef MACOS
591static ZCONST char Far UnzipUsageLine2[] = "\
592Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-d exdir]\n \
593 Default action is to extract files in list, to exdir;\n\
594  file[.zip] may be a wildcard.  %s\n";
595#else /* !MACOS */
596#ifdef VM_CMS
597static ZCONST char Far UnzipUsageLine2[] = "\
598Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d fm]\n \
599 Default action is to extract files in list, except those in xlist, to disk fm;\
600\n  file[.zip] may be a wildcard.  %s\n";
601#else /* !VM_CMS */
602static ZCONST char Far UnzipUsageLine2[] = "\
603Usage: unzip %s[-opts[modifiers]] file[.zip] [list] [-x xlist] [-d exdir]\n \
604 Default action is to extract files in list, except those in xlist, to exdir;\n\
605  file[.zip] may be a wildcard.  %s\n";
606#endif /* ?VM_CMS */
607#endif /* ?MACOS */
608
609#ifdef NO_ZIPINFO
610#  define ZIPINFO_MODE_OPTION  ""
611   static ZCONST char Far ZipInfoMode[] =
612     "(ZipInfo mode is disabled in this version.)";
613#else
614#  define ZIPINFO_MODE_OPTION  "[-Z] "
615   static ZCONST char Far ZipInfoMode[] =
616     "-Z => ZipInfo mode (\"unzip -Z\" for usage).";
617#endif /* ?NO_ZIPINFO */
618
619#ifdef VMS
620   static ZCONST char Far VMSusageLine2b[] = "\
621=> define foreign command symbol in LOGIN.COM:  $ unzip :== $dev:[dir]unzip.exe\
622\n";
623#endif
624
625#ifdef MACOS
626static ZCONST char Far UnzipUsageLine3[] = "\n\
627  -d  extract files into exdir               -l  list files (short format)\n\
628  -f  freshen existing files, create none    -t  test compressed archive data\n\
629  -u  update files, create if necessary      -z  display archive comment only\n\
630  -v  list verbosely/show version info     %s\n";
631#else /* !MACOS */
632#ifdef VM_CMS
633static ZCONST char Far UnzipUsageLine3[] = "\n\
634  -p  extract files to pipe, no messages     -l  list files (short format)\n\
635  -f  freshen existing files, create none    -t  test compressed archive data\n\
636  -u  update files, create if necessary      -z  display archive comment only\n\
637  -v  list verbosely/show version info     %s\n\
638  -x  exclude files that follow (in xlist)   -d  extract files onto disk fm\n";
639#else /* !VM_CMS */
640static ZCONST char Far UnzipUsageLine3[] = "\n\
641  -p  extract files to pipe, no messages     -l  list files (short format)\n\
642  -f  freshen existing files, create none    -t  test compressed archive data\n\
643  -u  update files, create if necessary      -z  display archive comment only\n\
644  -v  list verbosely/show version info     %s\n\
645  -x  exclude files that follow (in xlist)   -d  extract files into exdir\n";
646#endif /* ?VM_CMS */
647#endif /* ?MACOS */
648
649/* There is not enough space on a standard 80x25 Windows console screen for
650 * the additional line advertising the UTF-8 debugging options. This may
651 * eventually also be the case for other ports. Probably, the -U option need
652 * not be shown on the introductory screen at all. [Chr. Spieler, 2008-02-09]
653 *
654 * Likely, other advanced options should be moved to an extended help page and
655 * the option to list that page put here.  [E. Gordon, 2008-3-16]
656 */
657#if (defined(UNICODE_SUPPORT) && !defined(WIN32))
658#ifdef VMS
659static ZCONST char Far UnzipUsageLine4[] = "\
660modifiers:\n\
661  -n  never overwrite or make a new version of an existing file\n\
662  -o  always make a new version (-oo: overwrite original) of an existing file\n\
663  -q  quiet mode (-qq => quieter)            -a  auto-convert any text files\n\
664  -j  junk paths (do not make directories)   -aa treat ALL files as text\n\
665  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\n\
666  -C  match filenames case-insensitively     -L  make (some) names \
667lowercase\n %-42s  -V  retain VMS version numbers\n%s";
668#else /* !VMS */
669static ZCONST char Far UnzipUsageLine4[] = "\
670modifiers:\n\
671  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)\n\
672  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files\n\
673  -j  junk paths (do not make directories)   -aa treat ALL files as text\n\
674  -U  use escapes for all non-ASCII Unicode  -UU ignore any Unicode fields\n\
675  -C  match filenames case-insensitively     -L  make (some) names \
676lowercase\n %-42s  -V  retain VMS version numbers\n%s";
677#endif /* ?VMS */
678#else /* !UNICODE_SUPPORT */
679#ifdef VMS
680static ZCONST char Far UnzipUsageLine4[] = "\
681modifiers:\n\
682  -n  never overwrite or make a new version of an existing file\n\
683  -o  always make a new version (-oo: overwrite original) of an existing file\n\
684  -q  quiet mode (-qq => quieter)            -a  auto-convert any text files\n\
685  -j  junk paths (do not make directories)   -aa treat ALL files as text\n\
686  -C  match filenames case-insensitively     -L  make (some) names \
687lowercase\n %-42s  -V  retain VMS version numbers\n%s";
688#else /* !VMS */
689static ZCONST char Far UnzipUsageLine4[] = "\
690modifiers:\n\
691  -n  never overwrite existing files         -q  quiet mode (-qq => quieter)\n\
692  -o  overwrite files WITHOUT prompting      -a  auto-convert any text files\n\
693  -j  junk paths (do not make directories)   -aa treat ALL files as text\n\
694  -C  match filenames case-insensitively     -L  make (some) names \
695lowercase\n %-42s  -V  retain VMS version numbers\n%s";
696#endif /* ?VMS */
697#endif /* ?UNICODE_SUPPORT */
698
699static ZCONST char Far UnzipUsageLine5[] = "\
700See \"unzip -hh\" or unzip.txt for more help.  Examples:\n\
701  unzip data1 -x joe   => extract all files except joe from zipfile data1.zip\n\
702%s\
703  unzip -fo foo %-6s => quietly replace existing %s if archive file newer\n";
704#endif /* ?SFX */
705
706
707
708
709
710/*****************************/
711/*  main() / UzpMain() stub  */
712/*****************************/
713
714int MAIN(argc, argv)   /* return PK-type error code (except under VMS) */
715    int argc;
716    char *argv[];
717{
718    int r;
719
720    CONSTRUCTGLOBALS();
721    r = unzip(__G__ argc, argv);
722    DESTROYGLOBALS();
723    RETURN(r);
724}
725
726
727
728
729/*******************************/
730/*  Primary UnZip entry point  */
731/*******************************/
732
733int unzip(__G__ argc, argv)
734    __GDEF
735    int argc;
736    char *argv[];
737{
738#ifndef NO_ZIPINFO
739    char *p;
740#endif
741#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))
742    int i;
743#endif
744    int retcode, error=FALSE;
745#ifndef NO_EXCEPT_SIGNALS
746#ifdef REENTRANT
747    savsigs_info *oldsighandlers = NULL;
748#   define SET_SIGHANDLER(sigtype, newsighandler) \
749      if ((retcode = setsignalhandler(__G__ &oldsighandlers, (sigtype), \
750                                      (newsighandler))) > PK_WARN) \
751          goto cleanup_and_exit
752#else
753#   define SET_SIGHANDLER(sigtype, newsighandler) \
754      signal((sigtype), (newsighandler))
755#endif
756#endif /* NO_EXCEPT_SIGNALS */
757
758    /* initialize international char support to the current environment */
759    SETLOCALE(LC_CTYPE, "");
760
761#ifdef UNICODE_SUPPORT
762    /* see if can use UTF-8 Unicode locale */
763# ifdef UTF8_MAYBE_NATIVE
764    {
765        char *codeset;
766#  if !(defined(NO_NL_LANGINFO) || defined(NO_LANGINFO_H))
767        /* get the codeset (character set encoding) currently used */
768#       include <langinfo.h>
769
770        codeset = nl_langinfo(CODESET);
771#  else /* NO_NL_LANGINFO || NO_LANGINFO_H */
772        /* query the current locale setting for character classification */
773        codeset = setlocale(LC_CTYPE, NULL);
774        if (codeset != NULL) {
775            /* extract the codeset portion of the locale name */
776            codeset = strchr(codeset, '.');
777            if (codeset != NULL) ++codeset;
778        }
779#  endif /* ?(NO_NL_LANGINFO || NO_LANGINFO_H) */
780        /* is the current codeset UTF-8 ? */
781        if ((codeset != NULL) && (strcmp(codeset, "UTF-8") == 0)) {
782            /* successfully found UTF-8 char coding */
783            G.native_is_utf8 = TRUE;
784        } else {
785            /* Current codeset is not UTF-8 or cannot be determined. */
786            G.native_is_utf8 = FALSE;
787        }
788        /* Note: At least for UnZip, trying to change the process codeset to
789         *       UTF-8 does not work.  For the example Linux setup of the
790         *       UnZip maintainer, a successful switch to "en-US.UTF-8"
791         *       resulted in garbage display of all non-basic ASCII characters.
792         */
793    }
794# endif /* UTF8_MAYBE_NATIVE */
795
796    /* initialize Unicode */
797    G.unicode_escape_all = 0;
798    G.unicode_mismatch = 0;
799
800    G.unipath_version = 0;
801    G.unipath_checksum = 0;
802    G.unipath_filename = NULL;
803#endif /* UNICODE_SUPPORT */
804
805
806#if (defined(__IBMC__) && defined(__DEBUG_ALLOC__))
807    extern void DebugMalloc(void);
808
809    atexit(DebugMalloc);
810#endif
811
812#ifdef MALLOC_WORK
813    /* The following (rather complex) expression determines the allocation
814       size of the decompression work area.  It simulates what the
815       combined "union" and "struct" declaration of the "static" work
816       area reservation achieves automatically at compile time.
817       Any decent compiler should evaluate this expression completely at
818       compile time and provide constants to the zcalloc() call.
819       (For better readability, some subexpressions are encapsulated
820       in temporarly defined macros.)
821     */
822#   define UZ_SLIDE_CHUNK (sizeof(shrint)+sizeof(uch)+sizeof(uch))
823#   define UZ_NUMOF_CHUNKS \
824      (unsigned)(((WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK > HSIZE) ? \
825                 (WSIZE+UZ_SLIDE_CHUNK-1)/UZ_SLIDE_CHUNK : HSIZE)
826    G.area.Slide = (uch *)zcalloc(UZ_NUMOF_CHUNKS, UZ_SLIDE_CHUNK);
827#   undef UZ_SLIDE_CHUNK
828#   undef UZ_NUMOF_CHUNKS
829    G.area.shrink.Parent = (shrint *)G.area.Slide;
830    G.area.shrink.value = G.area.Slide + (sizeof(shrint)*(HSIZE));
831    G.area.shrink.Stack = G.area.Slide +
832                           (sizeof(shrint) + sizeof(uch))*(HSIZE);
833#endif
834
835/*---------------------------------------------------------------------------
836    Set signal handler for restoring echo, warn of zipfile corruption, etc.
837  ---------------------------------------------------------------------------*/
838#ifndef NO_EXCEPT_SIGNALS
839#ifdef SIGINT
840    SET_SIGHANDLER(SIGINT, handler);
841#endif
842#ifdef SIGTERM                 /* some systems really have no SIGTERM */
843    SET_SIGHANDLER(SIGTERM, handler);
844#endif
845#if defined(SIGABRT) && !(defined(AMIGA) && defined(__SASC))
846    SET_SIGHANDLER(SIGABRT, handler);
847#endif
848#ifdef SIGBREAK
849    SET_SIGHANDLER(SIGBREAK, handler);
850#endif
851#ifdef SIGBUS
852    SET_SIGHANDLER(SIGBUS, handler);
853#endif
854#ifdef SIGILL
855    SET_SIGHANDLER(SIGILL, handler);
856#endif
857#ifdef SIGSEGV
858    SET_SIGHANDLER(SIGSEGV, handler);
859#endif
860#endif /* NO_EXCEPT_SIGNALS */
861
862#if (defined(WIN32) && defined(__RSXNT__))
863    for (i = 0 ; i < argc; i++) {
864        _ISO_INTERN(argv[i]);
865    }
866#endif
867
868/*---------------------------------------------------------------------------
869    Macintosh initialization code.
870  ---------------------------------------------------------------------------*/
871
872#ifdef MACOS
873    {
874        int a;
875
876        for (a = 0;  a < 4;  ++a)
877            G.rghCursor[a] = GetCursor(a+128);
878        G.giCursor = 0;
879    }
880#endif
881
882/*---------------------------------------------------------------------------
883    NetWare initialization code.
884  ---------------------------------------------------------------------------*/
885
886#ifdef NLM
887    InitUnZipConsole();
888#endif
889
890/*---------------------------------------------------------------------------
891    Acorn RISC OS initialization code.
892  ---------------------------------------------------------------------------*/
893
894#ifdef RISCOS
895    set_prefix();
896#endif
897
898/*---------------------------------------------------------------------------
899    Theos initialization code.
900  ---------------------------------------------------------------------------*/
901
902#ifdef THEOS
903    /* The easiest way found to force creation of libraries when selected
904     * members are to be unzipped. Explicitly add libraries names to the
905     * arguments list before the first member of the library.
906     */
907    if (! _setargv(&argc, &argv)) {
908        Info(slide, 0x401, ((char *)slide, "cannot process argv\n"));
909        retcode = PK_MEM;
910        goto cleanup_and_exit;
911    }
912#endif
913
914/*---------------------------------------------------------------------------
915    Sanity checks.  Commentary by Otis B. Driftwood and Fiorello:
916
917    D:  It's all right.  That's in every contract.  That's what they
918        call a sanity clause.
919
920    F:  Ha-ha-ha-ha-ha.  You can't fool me.  There ain't no Sanity
921        Claus.
922  ---------------------------------------------------------------------------*/
923
924#ifdef DEBUG
925# ifdef LARGE_FILE_SUPPORT
926  /* test if we can support large files - 10/6/04 EG */
927    if (sizeof(zoff_t) < 8) {
928        Info(slide, 0x401, ((char *)slide, "LARGE_FILE_SUPPORT set but not supported\n"));
929        retcode = PK_BADERR;
930        goto cleanup_and_exit;
931    }
932    /* test if we can show 64-bit values */
933    {
934        zoff_t z = ~(zoff_t)0;  /* z should be all 1s now */
935        char *sz;
936
937        sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X");
938        if ((sz[0] != 'F') || (strlen(sz) != 16))
939        {
940            z = 0;
941        }
942
943        /* shift z so only MSB is set */
944        z <<= 63;
945        sz = FmZofft(z, FZOFFT_HEX_DOT_WID, "X");
946        if ((sz[0] != '8') || (strlen(sz) != 16))
947        {
948            Info(slide, 0x401, ((char *)slide,
949              "Can't show 64-bit values correctly\n"));
950            retcode = PK_BADERR;
951            goto cleanup_and_exit;
952        }
953    }
954# endif /* LARGE_FILE_SUPPORT */
955
956    /* 2004-11-30 SMS.
957       Test the NEXTBYTE macro for proper operation.
958    */
959    {
960        int test_char;
961        static uch test_buf[2] = { 'a', 'b' };
962
963        G.inptr = test_buf;
964        G.incnt = 1;
965
966        test_char = NEXTBYTE;           /* Should get 'a'. */
967        if (test_char == 'a')
968        {
969            test_char = NEXTBYTE;       /* Should get EOF, not 'b'. */
970        }
971        if (test_char != EOF)
972        {
973            Info(slide, 0x401, ((char *)slide,
974 "NEXTBYTE macro failed.  Try compiling with ALT_NEXTBYTE defined?"));
975
976            retcode = PK_BADERR;
977            goto cleanup_and_exit;
978        }
979    }
980#endif /* DEBUG */
981
982/*---------------------------------------------------------------------------
983    First figure out if we're running in UnZip mode or ZipInfo mode, and put
984    the appropriate environment-variable options into the queue.  Then rip
985    through any command-line options lurking about...
986  ---------------------------------------------------------------------------*/
987
988#ifdef SFX
989    G.argv0 = argv[0];
990#if (defined(OS2) || defined(WIN32))
991    G.zipfn = GetLoadPath(__G);/* non-MSC NT puts path into G.filename[] */
992#else
993    G.zipfn = G.argv0;
994#endif
995
996#ifdef VMSCLI
997    {
998        ulg status = vms_unzip_cmdline(&argc, &argv);
999        if (!(status & 1)) {
1000            retcode = (int)status;
1001            goto cleanup_and_exit;
1002        }
1003    }
1004#endif /* VMSCLI */
1005
1006    uO.zipinfo_mode = FALSE;
1007    error = uz_opts(__G__ &argc, &argv);   /* UnZipSFX call only */
1008
1009#else /* !SFX */
1010
1011#ifdef RISCOS
1012    /* get the extensions to swap from environment */
1013    getRISCOSexts(ENV_UNZIPEXTS);
1014#endif
1015
1016#ifdef MSDOS
1017    /* extract MKS extended argument list from environment (before envargs!) */
1018    mksargs(&argc, &argv);
1019#endif
1020
1021#ifdef VMSCLI
1022    {
1023        ulg status = vms_unzip_cmdline(&argc, &argv);
1024        if (!(status & 1)) {
1025            retcode = (int)status;
1026            goto cleanup_and_exit;
1027        }
1028    }
1029#endif /* VMSCLI */
1030
1031    G.noargs = (argc == 1);   /* no options, no zipfile, no anything */
1032
1033#ifndef NO_ZIPINFO
1034    for (p = argv[0] + strlen(argv[0]); p >= argv[0]; --p) {
1035        if (*p == DIR_END
1036#ifdef DIR_END2
1037            || *p == DIR_END2
1038#endif
1039           )
1040            break;
1041    }
1042    ++p;
1043
1044#ifdef THEOS
1045    if (strncmp(p, "ZIPINFO.",8) == 0 || strstr(p, ".ZIPINFO:") != NULL ||
1046        strncmp(p, "II.",3) == 0 || strstr(p, ".II:") != NULL ||
1047#else
1048    if (STRNICMP(p, LoadFarStringSmall(Zipnfo), 7) == 0 ||
1049        STRNICMP(p, "ii", 2) == 0 ||
1050#endif
1051        (argc > 1 && strncmp(argv[1], "-Z", 2) == 0))
1052    {
1053        uO.zipinfo_mode = TRUE;
1054#ifndef _WIN32_WCE /* Win CE does not support environment variables */
1055        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvZipInfo),
1056                             LoadFarStringSmall2(EnvZipInfo2))) != PK_OK)
1057            perror(LoadFarString(NoMemEnvArguments));
1058#endif
1059    } else
1060#endif /* !NO_ZIPINFO */
1061    {
1062        uO.zipinfo_mode = FALSE;
1063#ifndef _WIN32_WCE /* Win CE does not support environment variables */
1064        if ((error = envargs(&argc, &argv, LoadFarStringSmall(EnvUnZip),
1065                             LoadFarStringSmall2(EnvUnZip2))) != PK_OK)
1066            perror(LoadFarString(NoMemEnvArguments));
1067#endif
1068    }
1069
1070    if (!error) {
1071        /* Check the length of all passed command line parameters.
1072         * Command arguments might get sent through the Info() message
1073         * system, which uses the sliding window area as string buffer.
1074         * As arguments may additionally get fed through one of the FnFilter
1075         * macros, we require all command line arguments to be shorter than
1076         * WSIZE/4 (and ca. 2 standard line widths for fixed message text).
1077         */
1078        for (i = 1 ; i < argc; i++) {
1079           if (strlen(argv[i]) > ((WSIZE>>2) - 160)) {
1080               Info(slide, 0x401, ((char *)slide,
1081                 LoadFarString(CmdLineParamTooLong), i));
1082               retcode = PK_PARAM;
1083               goto cleanup_and_exit;
1084           }
1085        }
1086#ifndef NO_ZIPINFO
1087        if (uO.zipinfo_mode)
1088            error = zi_opts(__G__ &argc, &argv);
1089        else
1090#endif /* !NO_ZIPINFO */
1091            error = uz_opts(__G__ &argc, &argv);
1092    }
1093
1094#endif /* ?SFX */
1095
1096    if ((argc < 0) || error) {
1097        retcode = error;
1098        goto cleanup_and_exit;
1099    }
1100
1101/*---------------------------------------------------------------------------
1102    Now get the zipfile name from the command line and then process any re-
1103    maining options and file specifications.
1104  ---------------------------------------------------------------------------*/
1105
1106#ifdef DOS_FLX_H68_NLM_OS2_W32
1107    /* convert MSDOS-style 'backward slash' directory separators to Unix-style
1108     * 'forward slashes' for user's convenience (include zipfile name itself)
1109     */
1110#ifdef SFX
1111    for (G.pfnames = argv, i = argc;  i > 0;  --i) {
1112#else
1113    /* argc does not include the zipfile specification */
1114    for (G.pfnames = argv, i = argc+1;  i > 0;  --i) {
1115#endif
1116#ifdef __human68k__
1117        extern char *_toslash(char *);
1118        _toslash(*G.pfnames);
1119#else /* !__human68k__ */
1120        char *q = *G.pfnames;
1121
1122        while (*q != '\0') {
1123            if (*q == '\\')
1124                *q = '/';
1125            INCSTR(q);
1126        }
1127#endif /* ?__human68k__ */
1128        ++G.pfnames;
1129    }
1130#endif /* DOS_FLX_H68_NLM_OS2_W32 */
1131
1132#ifndef SFX
1133    G.wildzipfn = *argv++;
1134#endif
1135
1136#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
1137
1138    G.filespecs = argc;
1139    G.xfilespecs = 0;
1140
1141    if (argc > 0) {
1142        char **pp = argv-1;
1143
1144        G.pfnames = argv;
1145        while (*++pp)
1146            if (strcmp(*pp, "-x") == 0) {
1147                if (pp > argv) {
1148                    *pp = 0;              /* terminate G.pfnames */
1149                    G.filespecs = pp - G.pfnames;
1150                } else {
1151                    G.pfnames = (char **)fnames;  /* defaults */
1152                    G.filespecs = 0;
1153                }
1154                G.pxnames = pp + 1;      /* excluded-names ptr: _after_ -x */
1155                G.xfilespecs = argc - G.filespecs - 1;
1156                break;                    /* skip rest of args */
1157            }
1158        G.process_all_files = FALSE;
1159    } else
1160        G.process_all_files = TRUE;      /* for speed */
1161
1162#else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
1163
1164    G.filespecs = argc;
1165    G.xfilespecs = 0;
1166
1167    if (argc > 0) {
1168        int in_files=FALSE, in_xfiles=FALSE;
1169        char **pp = argv-1;
1170
1171        G.process_all_files = FALSE;
1172        G.pfnames = argv;
1173        while (*++pp) {
1174            Trace((stderr, "pp - argv = %d\n", pp-argv));
1175#ifdef CMS_MVS
1176            if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
1177#else
1178            if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
1179#endif
1180                int firstarg = (pp == argv);
1181
1182                uO.exdir = (*pp) + 2;
1183                if (in_files) {      /* ... zipfile ... -d exdir ... */
1184                    *pp = (char *)NULL;         /* terminate G.pfnames */
1185                    G.filespecs = pp - G.pfnames;
1186                    in_files = FALSE;
1187                } else if (in_xfiles) {
1188                    *pp = (char *)NULL;         /* terminate G.pxnames */
1189                    G.xfilespecs = pp - G.pxnames;
1190                    /* "... -x xlist -d exdir":  nothing left */
1191                }
1192                /* first check for "-dexdir", then for "-d exdir" */
1193                if (*uO.exdir == '\0') {
1194                    if (*++pp)
1195                        uO.exdir = *pp;
1196                    else {
1197                        Info(slide, 0x401, ((char *)slide,
1198                          LoadFarString(MustGiveExdir)));
1199                        /* don't extract here by accident */
1200                        retcode = PK_PARAM;
1201                        goto cleanup_and_exit;
1202                    }
1203                }
1204                if (firstarg) { /* ... zipfile -d exdir ... */
1205                    if (pp[1]) {
1206                        G.pfnames = pp + 1;  /* argv+2 */
1207                        G.filespecs = argc - (G.pfnames-argv);  /* for now... */
1208                    } else {
1209                        G.process_all_files = TRUE;
1210                        G.pfnames = (char **)fnames;  /* GRR: necessary? */
1211                        G.filespecs = 0;     /* GRR: necessary? */
1212                        break;
1213                    }
1214                }
1215            } else if (!in_xfiles) {
1216                if (strcmp(*pp, "-x") == 0) {
1217                    in_xfiles = TRUE;
1218                    if (pp == G.pfnames) {
1219                        G.pfnames = (char **)fnames;  /* defaults */
1220                        G.filespecs = 0;
1221                    } else if (in_files) {
1222                        *pp = 0;                   /* terminate G.pfnames */
1223                        G.filespecs = pp - G.pfnames;  /* adjust count */
1224                        in_files = FALSE;
1225                    }
1226                    G.pxnames = pp + 1; /* excluded-names ptr starts after -x */
1227                    G.xfilespecs = argc - (G.pxnames-argv);  /* anything left */
1228                } else
1229                    in_files = TRUE;
1230            }
1231        }
1232    } else
1233        G.process_all_files = TRUE;      /* for speed */
1234
1235    if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */
1236        Info(slide, 0x401, ((char *)slide, LoadFarString(NotExtracting)));
1237#endif /* ?(SFX && !SFX_EXDIR) */
1238
1239#ifdef UNICODE_SUPPORT
1240    /* set Unicode-escape-all if option -U used */
1241    if (uO.U_flag == 1)
1242# ifdef UNICODE_WCHAR
1243        G.unicode_escape_all = TRUE;
1244# else
1245        Info(slide, 0x401, ((char *)slide, LoadFarString(UTF8EscapeUnSupp)));
1246# endif
1247#endif
1248
1249
1250/*---------------------------------------------------------------------------
1251    Okey dokey, we have everything we need to get started.  Let's roll.
1252  ---------------------------------------------------------------------------*/
1253
1254    retcode = process_zipfiles(__G);
1255
1256cleanup_and_exit:
1257#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
1258    /* restore all signal handlers back to their state at function entry */
1259    while (oldsighandlers != NULL) {
1260        savsigs_info *thissigsav = oldsighandlers;
1261
1262        signal(thissigsav->sigtype, thissigsav->sighandler);
1263        oldsighandlers = thissigsav->previous;
1264        free(thissigsav);
1265    }
1266#endif
1267#if (defined(MALLOC_WORK) && !defined(REENTRANT))
1268    if (G.area.Slide != (uch *)NULL) {
1269        free(G.area.Slide);
1270        G.area.Slide = (uch *)NULL;
1271    }
1272#endif
1273#if (defined(MSDOS) && !defined(SFX) && !defined(WINDLL))
1274    if (retcode != PK_OK)
1275        check_for_windows("UnZip");
1276#endif
1277    return(retcode);
1278
1279} /* end main()/unzip() */
1280
1281
1282
1283
1284
1285#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
1286/*******************************/
1287/* Function setsignalhandler() */
1288/*******************************/
1289
1290static int setsignalhandler(__G__ p_savedhandler_chain, signal_type,
1291                            newhandler)
1292    __GDEF
1293    savsigs_info **p_savedhandler_chain;
1294    int signal_type;
1295    void (*newhandler)(int);
1296{
1297    savsigs_info *savsig;
1298
1299    savsig = malloc(sizeof(savsigs_info));
1300    if (savsig == NULL) {
1301        /* error message and break */
1302        Info(slide, 0x401, ((char *)slide, LoadFarString(CantSaveSigHandler)));
1303        return PK_MEM;
1304    }
1305    savsig->sigtype = signal_type;
1306    savsig->sighandler = signal(SIGINT, newhandler);
1307    if (savsig->sighandler == SIG_ERR) {
1308        free(savsig);
1309    } else {
1310        savsig->previous = *p_savedhandler_chain;
1311        *p_savedhandler_chain = savsig;
1312    }
1313    return PK_OK;
1314
1315} /* end function setsignalhandler() */
1316
1317#endif /* REENTRANT && !NO_EXCEPT_SIGNALS */
1318
1319
1320
1321
1322
1323/**********************/
1324/* Function uz_opts() */
1325/**********************/
1326
1327int uz_opts(__G__ pargc, pargv)
1328    __GDEF
1329    int *pargc;
1330    char ***pargv;
1331{
1332    char **argv, *s;
1333    int argc, c, error=FALSE, negative=0, showhelp=0;
1334
1335
1336    argc = *pargc;
1337    argv = *pargv;
1338
1339    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
1340        s = *argv + 1;
1341        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
1342#ifdef CMS_MVS
1343            switch (tolower(c))
1344#else
1345            switch (c)
1346#endif
1347            {
1348                case ('-'):
1349                    ++negative;
1350                    break;
1351#ifdef RISCOS
1352                case ('/'):
1353                    if (negative) {   /* negative not allowed with -/ swap */
1354                        Info(slide, 0x401, ((char *)slide,
1355                          "error:  must give extensions list"));
1356                        return(PK_PARAM);  /* don't extract here by accident */
1357                    }
1358                    exts2swap = s; /* override Unzip$Exts */
1359                    s += strlen(s);
1360                    break;
1361#endif
1362                case ('a'):
1363                    if (negative) {
1364                        uO.aflag = MAX(uO.aflag-negative,0);
1365                        negative = 0;
1366                    } else
1367                        ++uO.aflag;
1368                    break;
1369#if (defined(DLL) && defined(API_DOC))
1370                case ('A'):    /* extended help for API */
1371                    APIhelp(__G__ argc, argv);
1372                    *pargc = -1;  /* signal to exit successfully */
1373                    return 0;
1374#endif
1375                case ('b'):
1376                    if (negative) {
1377#if (defined(TANDEM) || defined(VMS))
1378                        uO.bflag = MAX(uO.bflag-negative,0);
1379#endif
1380                        negative = 0;   /* do nothing:  "-b" is default */
1381                    } else {
1382#ifdef VMS
1383                        if (uO.aflag == 0)
1384                           ++uO.bflag;
1385#endif
1386#ifdef TANDEM
1387                        ++uO.bflag;
1388#endif
1389                        uO.aflag = 0;
1390                    }
1391                    break;
1392#ifdef UNIXBACKUP
1393                case ('B'): /* -B: back up existing files */
1394                    if (negative)
1395                        uO.B_flag = FALSE, negative = 0;
1396                    else
1397                        uO.B_flag = TRUE;
1398                    break;
1399#endif
1400                case ('c'):
1401                    if (negative) {
1402                        uO.cflag = FALSE, negative = 0;
1403#ifdef NATIVE
1404                        uO.aflag = 0;
1405#endif
1406                    } else {
1407                        uO.cflag = TRUE;
1408#ifdef NATIVE
1409                        uO.aflag = 2;   /* so you can read it on the screen */
1410#endif
1411#ifdef DLL
1412                        if (G.redirect_text)
1413                            G.redirect_data = 2;
1414#endif
1415                    }
1416                    break;
1417#ifndef CMS_MVS
1418                case ('C'):    /* -C:  match filenames case-insensitively */
1419                    if (negative)
1420                        uO.C_flag = FALSE, negative = 0;
1421                    else
1422                        uO.C_flag = TRUE;
1423                    break;
1424#endif /* !CMS_MVS */
1425#if (!defined(SFX) || defined(SFX_EXDIR))
1426                case ('d'):
1427                    if (negative) {   /* negative not allowed with -d exdir */
1428                        Info(slide, 0x401, ((char *)slide,
1429                          LoadFarString(MustGiveExdir)));
1430                        return(PK_PARAM);  /* don't extract here by accident */
1431                    }
1432                    if (uO.exdir != (char *)NULL) {
1433                        Info(slide, 0x401, ((char *)slide,
1434                          LoadFarString(OnlyOneExdir)));
1435                        return(PK_PARAM);    /* GRR:  stupid restriction? */
1436                    } else {
1437                        /* first check for "-dexdir", then for "-d exdir" */
1438                        uO.exdir = s;
1439                        if (*uO.exdir == '\0') {
1440                            if (argc > 1) {
1441                                --argc;
1442                                uO.exdir = *++argv;
1443                                if (*uO.exdir == '-') {
1444                                    Info(slide, 0x401, ((char *)slide,
1445                                      LoadFarString(MustGiveExdir)));
1446                                    return(PK_PARAM);
1447                                }
1448                                /* else uO.exdir points at extraction dir */
1449                            } else {
1450                                Info(slide, 0x401, ((char *)slide,
1451                                  LoadFarString(MustGiveExdir)));
1452                                return(PK_PARAM);
1453                            }
1454                        }
1455                        /* uO.exdir now points at extraction dir (-dexdir or
1456                         *  -d exdir); point s at end of exdir to avoid mis-
1457                         *  interpretation of exdir characters as more options
1458                         */
1459                        if (*s != 0)
1460                            while (*++s != 0)
1461                                ;
1462                    }
1463                    break;
1464#endif /* !SFX || SFX_EXDIR */
1465#if (!defined(NO_TIMESTAMPS))
1466                case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */
1467                    if (negative) {
1468                        uO.D_flag = MAX(uO.D_flag-negative,0);
1469                        negative = 0;
1470                    } else
1471                        uO.D_flag++;
1472                    break;
1473#endif /* (!NO_TIMESTAMPS) */
1474                case ('e'):    /* just ignore -e, -x options (extract) */
1475                    break;
1476#ifdef MACOS
1477                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
1478                    if( negative ) {
1479                        uO.E_flag = FALSE, negative = 0;
1480                    } else {
1481                        uO.E_flag = TRUE;
1482                    }
1483                    break;
1484#endif /* MACOS */
1485                case ('f'):    /* "freshen" (extract only newer files) */
1486                    if (negative)
1487                        uO.fflag = uO.uflag = FALSE, negative = 0;
1488                    else
1489                        uO.fflag = uO.uflag = TRUE;
1490                    break;
1491#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
1492                case ('F'):    /* Acorn filetype & NFS extension handling */
1493                    if (negative)
1494                        uO.acorn_nfs_ext = FALSE, negative = 0;
1495                    else
1496                        uO.acorn_nfs_ext = TRUE;
1497                    break;
1498#endif /* RISCOS || ACORN_FTYPE_NFS */
1499                case ('h'):    /* just print help message and quit */
1500                    if (showhelp == 0) {
1501#ifndef SFX
1502                        if (*s == 'h')
1503                            showhelp = 2;
1504                        else
1505#endif /* !SFX */
1506                        {
1507                            showhelp = 1;
1508                        }
1509                    }
1510                    break;
1511#ifdef MACOS
1512                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
1513                    if( negative ) {
1514                        uO.i_flag = FALSE, negative = 0;
1515                    } else {
1516                        uO.i_flag = TRUE;
1517                    }
1518                    break;
1519#endif  /* MACOS */
1520                case ('j'):    /* junk pathnames/directory structure */
1521                    if (negative)
1522                        uO.jflag = FALSE, negative = 0;
1523                    else
1524                        uO.jflag = TRUE;
1525                    break;
1526#if (defined(ATH_BEO) || defined(MACOS))
1527                case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */
1528                    if( negative ) {
1529                        uO.J_flag = FALSE, negative = 0;
1530                    } else {
1531                        uO.J_flag = TRUE;
1532                    }
1533                    break;
1534#endif /* ATH_BEO || MACOS */
1535#ifdef ATH_BEO_UNX
1536                case ('K'):
1537                    if (negative) {
1538                        uO.K_flag = FALSE, negative = 0;
1539                    } else {
1540                        uO.K_flag = TRUE;
1541                    }
1542                    break;
1543#endif /* ATH_BEO_UNX */
1544#ifndef SFX
1545                case ('l'):
1546                    if (negative) {
1547                        uO.vflag = MAX(uO.vflag-negative,0);
1548                        negative = 0;
1549                    } else
1550                        ++uO.vflag;
1551                    break;
1552#endif /* !SFX */
1553#ifndef CMS_MVS
1554                case ('L'):    /* convert (some) filenames to lowercase */
1555                    if (negative) {
1556                        uO.L_flag = MAX(uO.L_flag-negative,0);
1557                        negative = 0;
1558                    } else
1559                        ++uO.L_flag;
1560                    break;
1561#endif /* !CMS_MVS */
1562#ifdef MORE
1563#ifdef CMS_MVS
1564                case ('m'):
1565#endif
1566                case ('M'):    /* send all screen output through "more" fn. */
1567/* GRR:  eventually check for numerical argument => height */
1568                    if (negative)
1569                        G.M_flag = FALSE, negative = 0;
1570                    else
1571                        G.M_flag = TRUE;
1572                    break;
1573#endif /* MORE */
1574                case ('n'):    /* don't overwrite any files */
1575                    if (negative)
1576                        uO.overwrite_none = FALSE, negative = 0;
1577                    else
1578                        uO.overwrite_none = TRUE;
1579                    break;
1580#ifdef AMIGA
1581                case ('N'):    /* restore comments as filenotes */
1582                    if (negative)
1583                        uO.N_flag = FALSE, negative = 0;
1584                    else
1585                        uO.N_flag = TRUE;
1586                    break;
1587#endif /* AMIGA */
1588                case ('o'):    /* OK to overwrite files without prompting */
1589                    if (negative) {
1590                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
1591                        negative = 0;
1592                    } else
1593                        ++uO.overwrite_all;
1594                    break;
1595                case ('p'):    /* pipes:  extract to stdout, no messages */
1596                    if (negative) {
1597                        uO.cflag = FALSE;
1598                        uO.qflag = MAX(uO.qflag-999,0);
1599                        negative = 0;
1600                    } else {
1601                        uO.cflag = TRUE;
1602                        uO.qflag += 999;
1603                    }
1604                    break;
1605#if CRYPT
1606                /* GRR:  yes, this is highly insecure, but dozens of people
1607                 * have pestered us for this, so here we go... */
1608                case ('P'):
1609                    if (negative) {   /* negative not allowed with -P passwd */
1610                        Info(slide, 0x401, ((char *)slide,
1611                          LoadFarString(MustGivePasswd)));
1612                        return(PK_PARAM);  /* don't extract here by accident */
1613                    }
1614                    if (uO.pwdarg != (char *)NULL) {
1615/*
1616                        GRR:  eventually support multiple passwords?
1617                        Info(slide, 0x401, ((char *)slide,
1618                          LoadFarString(OnlyOnePasswd)));
1619                        return(PK_PARAM);
1620 */
1621                    } else {
1622                        /* first check for "-Ppasswd", then for "-P passwd" */
1623                        uO.pwdarg = s;
1624                        if (*uO.pwdarg == '\0') {
1625                            if (argc > 1) {
1626                                --argc;
1627                                uO.pwdarg = *++argv;
1628                                if (*uO.pwdarg == '-') {
1629                                    Info(slide, 0x401, ((char *)slide,
1630                                      LoadFarString(MustGivePasswd)));
1631                                    return(PK_PARAM);
1632                                }
1633                                /* else pwdarg points at decryption password */
1634                            } else {
1635                                Info(slide, 0x401, ((char *)slide,
1636                                  LoadFarString(MustGivePasswd)));
1637                                return(PK_PARAM);
1638                            }
1639                        }
1640                        /* pwdarg now points at decryption password (-Ppasswd or
1641                         *  -P passwd); point s at end of passwd to avoid mis-
1642                         *  interpretation of passwd characters as more options
1643                         */
1644                        if (*s != 0)
1645                            while (*++s != 0)
1646                                ;
1647                    }
1648                    break;
1649#endif /* CRYPT */
1650                case ('q'):    /* quiet:  fewer comments/messages */
1651                    if (negative) {
1652                        uO.qflag = MAX(uO.qflag-negative,0);
1653                        negative = 0;
1654                    } else
1655                        ++uO.qflag;
1656                    break;
1657#ifdef QDOS
1658                case ('Q'):   /* QDOS flags */
1659                    qlflag ^= strtol(s, &s, 10);
1660                    break;    /* we XOR this as we can config qlflags */
1661#endif
1662#ifdef TANDEM
1663                case ('r'):    /* remove file extensions */
1664                    if (negative)
1665                        uO.rflag = FALSE, negative = 0;
1666                    else
1667                        uO.rflag = TRUE;
1668                    break;
1669#endif /* TANDEM */
1670#ifdef DOS_FLX_NLM_OS2_W32
1671                case ('s'):    /* spaces in filenames:  allow by default */
1672                    if (negative)
1673                        uO.sflag = FALSE, negative = 0;
1674                    else
1675                        uO.sflag = TRUE;
1676                    break;
1677#endif /* DOS_FLX_NLM_OS2_W32 */
1678#ifdef VMS
1679                /* VMS:  extract "text" files in Stream_LF format (-a[a]) */
1680                case ('S'):
1681                    if (negative)
1682                        uO.S_flag = FALSE, negative = 0;
1683                    else
1684                        uO.S_flag = TRUE;
1685                    break;
1686#endif /* VMS */
1687                case ('t'):
1688                    if (negative)
1689                        uO.tflag = FALSE, negative = 0;
1690                    else
1691                        uO.tflag = TRUE;
1692                    break;
1693#ifdef TIMESTAMP
1694                case ('T'):
1695                    if (negative)
1696                        uO.T_flag = FALSE, negative = 0;
1697                    else
1698                        uO.T_flag = TRUE;
1699                    break;
1700#endif
1701                case ('u'):    /* update (extract only new and newer files) */
1702                    if (negative)
1703                        uO.uflag = FALSE, negative = 0;
1704                    else
1705                        uO.uflag = TRUE;
1706                    break;
1707#ifdef UNICODE_SUPPORT
1708                case ('U'):    /* escape UTF-8, or disable UTF-8 support */
1709                    if (negative) {
1710                        uO.U_flag = MAX(uO.U_flag-negative,0);
1711                        negative = 0;
1712                    } else
1713                        uO.U_flag++;
1714                    break;
1715#else /* !UNICODE_SUPPORT */
1716#ifndef CMS_MVS
1717                case ('U'):    /* obsolete; to be removed in version 6.0 */
1718                    if (negative)
1719                        uO.L_flag = TRUE, negative = 0;
1720                    else
1721                        uO.L_flag = FALSE;
1722                    break;
1723#endif /* !CMS_MVS */
1724#endif /* ?UNICODE_SUPPORT */
1725#ifndef SFX
1726                case ('v'):    /* verbose */
1727                    if (negative) {
1728                        uO.vflag = MAX(uO.vflag-negative,0);
1729                        negative = 0;
1730                    } else if (uO.vflag)
1731                        ++uO.vflag;
1732                    else
1733                        uO.vflag = 2;
1734                    break;
1735#endif /* !SFX */
1736#ifndef CMS_MVS
1737                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
1738                    if (negative)
1739                        uO.V_flag = FALSE, negative = 0;
1740                    else
1741                        uO.V_flag = TRUE;
1742                    break;
1743#endif /* !CMS_MVS */
1744#ifdef WILD_STOP_AT_DIR
1745                case ('W'):    /* Wildcard interpretation (stop at '/'?) */
1746                    if (negative)
1747                        uO.W_flag = FALSE, negative = 0;
1748                    else
1749                        uO.W_flag = TRUE;
1750                    break;
1751#endif /* WILD_STOP_AT_DIR */
1752                case ('x'):    /* extract:  default */
1753#ifdef SFX
1754                    /* when 'x' is the only option in this argument, and the
1755                     * next arg is not an option, assume this initiates an
1756                     * exclusion list (-x xlist):  terminate option-scanning
1757                     * and leave uz_opts with argv still pointing to "-x";
1758                     * the xlist is processed later
1759                     */
1760                    if (s - argv[0] == 2 && *s == '\0' &&
1761                        argc > 1 && argv[1][0] != '-') {
1762                        /* break out of nested loops without "++argv;--argc" */
1763                        goto opts_done;
1764                    }
1765#endif /* SFX */
1766                    break;
1767#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
1768                case ('X'):   /* restore owner/protection info (need privs?) */
1769                    if (negative) {
1770                        uO.X_flag = MAX(uO.X_flag-negative,0);
1771                        negative = 0;
1772                    } else
1773                        ++uO.X_flag;
1774                    break;
1775#endif /* RESTORE_UIDGID || RESTORE_ACL */
1776#ifdef VMS
1777                case ('Y'):    /* Treat ".nnn" as ";nnn" version. */
1778                    if (negative)
1779                        uO.Y_flag = FALSE, negative = 0;
1780                    else
1781                        uO.Y_flag = TRUE;
1782                    break;
1783#endif /* VMS */
1784                case ('z'):    /* display only the archive comment */
1785                    if (negative) {
1786                        uO.zflag = MAX(uO.zflag-negative,0);
1787                        negative = 0;
1788                    } else
1789                        ++uO.zflag;
1790                    break;
1791#ifndef SFX
1792                case ('Z'):    /* should have been first option (ZipInfo) */
1793                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
1794                    error = TRUE;
1795                    break;
1796#endif /* !SFX */
1797#ifdef VMS
1798                case ('2'):    /* Force ODS2-compliant names. */
1799                    if (negative)
1800                        uO.ods2_flag = FALSE, negative = 0;
1801                    else
1802                        uO.ods2_flag = TRUE;
1803                    break;
1804#endif /* VMS */
1805#ifdef DOS_H68_OS2_W32
1806                case ('$'):
1807                    if (negative) {
1808                        uO.volflag = MAX(uO.volflag-negative,0);
1809                        negative = 0;
1810                    } else
1811                        ++uO.volflag;
1812                    break;
1813#endif /* DOS_H68_OS2_W32 */
1814#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
1815                case (':'):    /* allow "parent dir" path components */
1816                    if (negative) {
1817                        uO.ddotflag = MAX(uO.ddotflag-negative,0);
1818                        negative = 0;
1819                    } else
1820                        ++uO.ddotflag;
1821                    break;
1822#endif /* !RISCOS && !CMS_MVS && !TANDEM */
1823#ifdef UNIX
1824                case ('^'):    /* allow control chars in filenames */
1825                    if (negative) {
1826                        uO.cflxflag = MAX(uO.cflxflag-negative,0);
1827                        negative = 0;
1828                    } else
1829                        ++uO.cflxflag;
1830                    break;
1831#endif /* UNIX */
1832                default:
1833                    error = TRUE;
1834                    break;
1835
1836            } /* end switch */
1837        } /* end while (not end of argument string) */
1838    } /* end while (not done with switches) */
1839
1840/*---------------------------------------------------------------------------
1841    Check for nonsensical combinations of options.
1842  ---------------------------------------------------------------------------*/
1843
1844#ifdef SFX
1845opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
1846#endif
1847
1848    if (showhelp > 0) {         /* just print help message and quit */
1849        *pargc = -1;
1850#ifndef SFX
1851        if (showhelp == 2) {
1852            help_extended(__G);
1853            return PK_OK;
1854        } else
1855#endif /* !SFX */
1856        {
1857            return USAGE(PK_OK);
1858        }
1859    }
1860
1861    if ((uO.cflag && (uO.tflag || uO.uflag)) ||
1862        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
1863    {
1864        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
1865        error = TRUE;
1866    }
1867    if (uO.aflag > 2)
1868        uO.aflag = 2;
1869#ifdef VMS
1870    if (uO.bflag > 2)
1871        uO.bflag = 2;
1872    /* Clear -s flag when converting text files. */
1873    if (uO.aflag <= 0)
1874        uO.S_flag = 0;
1875#endif /* VMS */
1876    if (uO.overwrite_all && uO.overwrite_none) {
1877        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
1878        uO.overwrite_all = FALSE;
1879    }
1880#ifdef MORE
1881    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
1882        G.M_flag = 0;
1883#endif
1884
1885#ifdef SFX
1886    if (error)
1887#else
1888    if ((argc-- == 0) || error)
1889#endif
1890    {
1891        *pargc = argc;
1892        *pargv = argv;
1893#ifndef SFX
1894        if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
1895            show_version_info(__G);
1896            return PK_OK;
1897        }
1898        if (!G.noargs && !error)
1899            error = TRUE;       /* had options (not -h or -v) but no zipfile */
1900#endif /* !SFX */
1901        return USAGE(error);
1902    }
1903
1904#ifdef SFX
1905    /* print our banner unless we're being fairly quiet */
1906    if (uO.qflag < 2)
1907        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
1908          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1909          LoadFarStringSmall(VersionDate)));
1910#ifdef BETA
1911    /* always print the beta warning:  no unauthorized distribution!! */
1912    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
1913      "SFX"));
1914#endif
1915#endif /* SFX */
1916
1917    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
1918#ifdef TIMESTAMP
1919                                                     || uO.T_flag
1920#endif
1921                                                                 )
1922        G.extract_flag = FALSE;
1923    else
1924        G.extract_flag = TRUE;
1925
1926    *pargc = argc;
1927    *pargv = argv;
1928    return PK_OK;
1929
1930} /* end function uz_opts() */
1931
1932
1933
1934
1935/********************/
1936/* Function usage() */
1937/********************/
1938
1939#ifdef SFX
1940#  ifdef VMS
1941#    define LOCAL "X.\n\
1942(Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)"
1943#  endif
1944#  ifdef UNIX
1945#    define LOCAL "X"
1946#  endif
1947#  ifdef DOS_OS2_W32
1948#    define LOCAL "s$"
1949#  endif
1950#  if (defined(FLEXOS) || defined(NLM))
1951#    define LOCAL "s"
1952#  endif
1953#  ifdef AMIGA
1954#    define LOCAL "N"
1955#  endif
1956   /* Default for all other systems: */
1957#  ifndef LOCAL
1958#    define LOCAL ""
1959#  endif
1960
1961#  ifndef NO_TIMESTAMP
1962#    ifdef MORE
1963#      define SFXOPT1 "DM"
1964#    else
1965#      define SFXOPT1 "D"
1966#    endif
1967#  else
1968#    ifdef MORE
1969#      define SFXOPT1 "M"
1970#    else
1971#      define SFXOPT1 ""
1972#    endif
1973#  endif
1974
1975int usage(__G__ error)   /* return PK-type error code */
1976    __GDEF
1977    int error;
1978{
1979    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
1980      UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
1981      LoadFarStringSmall(VersionDate)));
1982    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXOpts),
1983      SFXOPT1, LOCAL));
1984#ifdef BETA
1985    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
1986      "SFX"));
1987#endif
1988
1989    if (error)
1990        return PK_PARAM;
1991    else
1992        return PK_COOL;     /* just wanted usage screen: no error */
1993
1994} /* end function usage() */
1995
1996
1997
1998
1999
2000#else /* !SFX */
2001#  ifdef VMS
2002#    define QUOT '\"'
2003#    define QUOTS "\""
2004#  else
2005#    define QUOT ' '
2006#    define QUOTS ""
2007#  endif
2008
2009int usage(__G__ error)   /* return PK-type error code */
2010    __GDEF
2011    int error;
2012{
2013    int flag = (error? 1 : 0);
2014
2015
2016/*---------------------------------------------------------------------------
2017    Print either ZipInfo usage or UnZip usage, depending on incantation.
2018    (Strings must be no longer than 512 bytes for Turbo C, apparently.)
2019  ---------------------------------------------------------------------------*/
2020
2021    if (uO.zipinfo_mode) {
2022
2023#ifndef NO_ZIPINFO
2024
2025        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine1),
2026          ZI_MAJORVER, ZI_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
2027          LoadFarStringSmall(VersionDate),
2028          LoadFarStringSmall2(ZipInfoExample), QUOTS,QUOTS));
2029        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine2)));
2030        Info(slide, flag, ((char *)slide, LoadFarString(ZipInfoUsageLine3),
2031          LoadFarStringSmall(ZipInfoUsageLine4)));
2032#ifdef VMS
2033        Info(slide, flag, ((char *)slide, "\n\
2034You must quote non-lowercase options and filespecs, unless SET PROC/PARSE=EXT.\
2035\n"));
2036#endif
2037
2038#endif /* !NO_ZIPINFO */
2039
2040    } else {   /* UnZip mode */
2041
2042        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine1),
2043          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
2044          LoadFarStringSmall(VersionDate)));
2045#ifdef BETA
2046        Info(slide, flag, ((char *)slide, LoadFarString(BetaVersion), "", ""));
2047#endif
2048
2049        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine2),
2050          ZIPINFO_MODE_OPTION, LoadFarStringSmall(ZipInfoMode)));
2051#ifdef VMS
2052        if (!error)  /* maybe no command-line tail found; show extra help */
2053            Info(slide, flag, ((char *)slide, LoadFarString(VMSusageLine2b)));
2054#endif
2055
2056        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine3),
2057          LoadFarStringSmall(local1)));
2058
2059        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine4),
2060          LoadFarStringSmall(local2), LoadFarStringSmall2(local3)));
2061
2062        /* This is extra work for SMALL_MEM, but it will work since
2063         * LoadFarStringSmall2 uses the same buffer.  Remember, this
2064         * is a hack. */
2065        Info(slide, flag, ((char *)slide, LoadFarString(UnzipUsageLine5),
2066          LoadFarStringSmall(Example2), LoadFarStringSmall2(Example3),
2067          LoadFarStringSmall2(Example3)));
2068
2069    } /* end if (uO.zipinfo_mode) */
2070
2071    if (error)
2072        return PK_PARAM;
2073    else
2074        return PK_COOL;     /* just wanted usage screen: no error */
2075
2076} /* end function usage() */
2077
2078#endif /* ?SFX */
2079
2080
2081
2082
2083#ifndef SFX
2084
2085/* Print extended help to stdout. */
2086static void help_extended(__G)
2087    __GDEF
2088{
2089    extent i;             /* counter for help array */
2090
2091    /* help array */
2092    static ZCONST char *text[] = {
2093  "",
2094  "Extended Help for UnZip",
2095  "",
2096  "See the UnZip Manual for more detailed help",
2097  "",
2098  "",
2099  "UnZip lists and extracts files in zip archives.  The default action is to",
2100  "extract zipfile entries to the current directory, creating directories as",
2101  "needed.  With appropriate options, UnZip lists the contents of archives",
2102  "instead.",
2103  "",
2104  "Basic unzip command line:",
2105  "  unzip [-Z] options archive[.zip] [file ...] [-x xfile ...] [-d exdir]",
2106  "",
2107  "Some examples:",
2108  "  unzip -l foo.zip        - list files in short format in archive foo.zip",
2109  "",
2110  "  unzip -t foo            - test the files in archive foo",
2111  "",
2112  "  unzip -Z foo            - list files using more detailed zipinfo format",
2113  "",
2114  "  unzip foo               - unzip the contents of foo in current dir",
2115  "",
2116  "  unzip -a foo            - unzip foo and convert text files to local OS",
2117  "",
2118  "If unzip is run in zipinfo mode, a more detailed list of archive contents",
2119  "is provided.  The -Z option sets zipinfo mode and changes the available",
2120  "options.",
2121  "",
2122  "Basic zipinfo command line:",
2123  "  zipinfo options archive[.zip] [file ...] [-x xfile ...]",
2124  "  unzip -Z options archive[.zip] [file ...] [-x xfile ...]",
2125  "",
2126  "Below, Mac OS refers to Mac OS before Mac OS X.  Mac OS X is a Unix based",
2127  "port and is referred to as Unix Apple.",
2128  "",
2129  "",
2130  "unzip options:",
2131  "  -Z   Switch to zipinfo mode.  Must be first option.",
2132  "  -hh  Display extended help.",
2133  "  -A   [OS/2, Unix DLL] Print extended help for DLL.",
2134  "  -c   Extract files to stdout/screen.  As -p but include names.  Also,",
2135  "         -a allowed and EBCDIC conversions done if needed.",
2136  "  -f   Freshen by extracting only if older file on disk.",
2137  "  -l   List files using short form.",
2138  "  -p   Extract files to pipe (stdout).  Only file data is output and all",
2139  "         files extracted in binary mode (as stored).",
2140  "  -t   Test archive files.",
2141  "  -T   Set timestamp on archive(s) to that of newest file.  Similar to",
2142  "       zip -o but faster.",
2143  "  -u   Update existing older files on disk as -f and extract new files.",
2144  "  -v   Use verbose list format.  If given alone as unzip -v show version",
2145  "         information.  Also can be added to other list commands for more",
2146  "         verbose output.",
2147  "  -z   Display only archive comment.",
2148  "",
2149  "unzip modifiers:",
2150  "  -a   Convert text files to local OS format.  Convert line ends, EOF",
2151  "         marker, and from or to EBCDIC character set as needed.",
2152  "  -b   Treat all files as binary.  [Tandem] Force filecode 180 ('C').",
2153  "         [VMS] Autoconvert binary files.  -bb forces convert of all files.",
2154  "  -B   [UNIXBACKUP compile option enabled] Save a backup copy of each",
2155  "         overwritten file in foo~ or foo~99999 format.",
2156  "  -C   Use case-insensitive matching.",
2157  "  -D   Skip restoration of timestamps for extracted directories.  On VMS this",
2158  "         is on by default and -D essentially becames -DD.",
2159  "  -DD  Skip restoration of timestamps for all entries.",
2160  "  -E   [MacOS (not Unix Apple)]  Display contents of MacOS extra field during",
2161  "         restore.",
2162  "  -F   [Acorn] Suppress removal of NFS filetype extension.  [Non-Acorn if",
2163  "         ACORN_FTYPE_NFS] Translate filetype and append to name.",
2164  "  -i   [MacOS] Ignore filenames in MacOS extra field.  Instead, use name in",
2165  "         standard header.",
2166  "  -j   Junk paths and deposit all files in extraction directory.",
2167  "  -J   [BeOS] Junk file attributes.  [MacOS] Ignore MacOS specific info.",
2168  "  -K   [AtheOS, BeOS, Unix] Restore SUID/SGID/Tacky file attributes.",
2169  "  -L   Convert to lowercase any names from uppercase only file system.",
2170  "  -LL  Convert all files to lowercase.",
2171  "  -M   Pipe all output through internal pager similar to Unix more(1).",
2172  "  -n   Never overwrite existing files.  Skip extracting that file, no prompt.",
2173  "  -N   [Amiga] Extract file comments as Amiga filenotes.",
2174  "  -o   Overwrite existing files without prompting.  Useful with -f.  Use with",
2175  "         care.",
2176  "  -P p Use password p to decrypt files.  THIS IS INSECURE!  Some OS show",
2177  "         command line to other users.",
2178  "  -q   Perform operations quietly.  The more q (as in -qq) the quieter.",
2179  "  -s   [OS/2, NT, MS-DOS] Convert spaces in filenames to underscores.",
2180  "  -S   [VMS] Convert text files (-a, -aa) into Stream_LF format.",
2181  "  -U   [UNICODE enabled] Show non-local characters as #Uxxxx or #Lxxxxxx ASCII",
2182  "         text escapes where x is hex digit.  [Old] -U used to leave names",
2183  "         uppercase if created on MS-DOS, VMS, etc.  See -L.",
2184  "  -UU  [UNICODE enabled] Disable use of stored UTF-8 paths.  Note that UTF-8",
2185  "         paths stored as native local paths are still processed as Unicode.",
2186  "  -V   Retain VMS file version numbers.",
2187  "  -W   [Only if WILD_STOP_AT_DIR] Modify pattern matching so ? and * do not",
2188  "         match directory separator /, but ** does.  Allows matching at specific",
2189  "         directory levels.",
2190  "  -X   [VMS, Unix, OS/2, NT, Tandem] Restore UICs and ACL entries under VMS,",
2191  "         or UIDs/GIDs under Unix, or ACLs under certain network-enabled",
2192  "         versions of OS/2, or security ACLs under Windows NT.  Can require",
2193  "         user privileges.",
2194  "  -XX  [NT] Extract NT security ACLs after trying to enable additional",
2195  "         system privileges.",
2196  "  -Y   [VMS] Treat archived name endings of .nnn as VMS version numbers.",
2197  "  -$   [MS-DOS, OS/2, NT] Restore volume label if extraction medium is",
2198  "         removable.  -$$ allows fixed media (hard drives) to be labeled.",
2199  "  -/ e [Acorn] Use e as extension list.",
2200  "  -:   [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into",
2201  "         locations outside of current extraction root folder.  This allows",
2202  "         paths such as ../foo to be extracted above the current extraction",
2203  "         directory, which can be a security problem.",
2204  "  -^   [Unix] Allow control characters in names of extracted entries.  Usually",
2205  "         this is not a good thing and should be avoided.",
2206  "  -2   [VMS] Force unconditional conversion of names to ODS-compatible names.",
2207  "         Default is to exploit destination file system, preserving cases and",
2208  "         extended name characters on ODS5 and applying ODS2 filtering on ODS2.",
2209  "",
2210  "",
2211  "Wildcards:",
2212  "  Internally unzip supports the following wildcards:",
2213  "    ?       (or %% or #, depending on OS) matches any single character",
2214  "    *       matches any number of characters, including zero",
2215  "    [list]  matches char in list (regex), can do range [ac-f], all but [!bf]",
2216  "  If port supports [], must escape [ as [[]",
2217  "  For shells that expand wildcards, escape (\\* or \"*\") so unzip can recurse.",
2218  "",
2219  "Include and Exclude:",
2220  "  -i pattern pattern ...   include files that match a pattern",
2221  "  -x pattern pattern ...   exclude files that match a pattern",
2222  "  Patterns are paths with optional wildcards and match paths as stored in",
2223  "  archive.  Exclude and include lists end at next option or end of line.",
2224  "    unzip archive -x pattern pattern ...",
2225  "",
2226  "Multi-part (split) archives (archives created as a set of split files):",
2227  "  Currently split archives are not readable by unzip.  A workaround is",
2228  "  to use zip to convert the split archive to a single-file archive and",
2229  "  use unzip on that.  See the manual page for Zip 3.0 or later.",
2230  "",
2231  "Streaming (piping into unzip):",
2232  "  Currently unzip does not support streaming.  The funzip utility can be",
2233  "  used to process the first entry in a stream.",
2234  "    cat archive | funzip",
2235  "",
2236  "Testing archives:",
2237  "  -t        test contents of archive",
2238  "  This can be modified using -q for quieter operation, and -qq for even",
2239  "  quieter operation.",
2240  "",
2241  "Unicode:",
2242  "  If compiled with Unicode support, unzip automatically handles archives",
2243  "  with Unicode entries.  Currently Unicode on Win32 systems is limited.",
2244  "  Characters not in the current character set are shown as ASCII escapes",
2245  "  in the form #Uxxxx where the Unicode character number fits in 16 bits,",
2246  "  or #Lxxxxxx where it doesn't, where x is the ASCII character for a hex",
2247  "  digit.",
2248  "",
2249  "",
2250  "zipinfo options (these are used in zipinfo mode (unzip -Z ...)):",
2251  "  -1  List names only, one per line.  No headers/trailers.  Good for scripts.",
2252  "  -2  List names only as -1, but include headers, trailers, and comments.",
2253  "  -s  List archive entries in short Unix ls -l format.  Default list format.",
2254  "  -m  List in long Unix ls -l format.  As -s, but includes compression %.",
2255  "  -l  List in long Unix ls -l format.  As -m, but compression in bytes.",
2256  "  -v  List zipfile information in verbose, multi-page format.",
2257  "  -h  List header line.  Includes archive name, actual size, total files.",
2258  "  -M  Pipe all output through internal pager similar to Unix more(1) command.",
2259  "  -t  List totals for files listed or for all files.  Includes uncompressed",
2260  "        and compressed sizes, and compression factors.",
2261  "  -T  Print file dates and times in a sortable decimal format (yymmdd.hhmmss)",
2262  "        Default date and time format is a more human-readable version.",
2263  "  -U  [UNICODE] If entry has a UTF-8 Unicode path, display any characters",
2264  "        not in current character set as text #Uxxxx and #Lxxxxxx escapes",
2265  "        representing the Unicode character number of the character in hex.",
2266  "  -UU [UNICODE]  Disable use of any UTF-8 path information.",
2267  "  -z  Include archive comment if any in listing.",
2268  "",
2269  "",
2270  "funzip stream extractor:",
2271  "  funzip extracts the first member in an archive to stdout.  Typically",
2272  "  used to unzip the first member of a stream or pipe.  If a file argument",
2273  "  is given, read from that file instead of stdin.",
2274  "",
2275  "funzip command line:",
2276  "  funzip [-password] [input[.zip|.gz]]",
2277  "",
2278  "",
2279  "unzipsfx self extractor:",
2280  "  Self-extracting archives made with unzipsfx are no more (or less)",
2281  "  portable across different operating systems than unzip executables.",
2282  "  In general, a self-extracting archive made on a particular Unix system,",
2283  "  for example, will only self-extract under the same flavor of Unix.",
2284  "  Regular unzip may still be used to extract embedded archive however.",
2285  "",
2286  "unzipsfx command line:",
2287  "  <unzipsfx+archive_filename>  [-options] [file(s) ... [-x xfile(s) ...]]",
2288  "",
2289  "unzipsfx options:",
2290  "  -c, -p - Output to pipe.  (See above for unzip.)",
2291  "  -f, -u - Freshen and Update, as for unzip.",
2292  "  -t     - Test embedded archive.  (Can be used to list contents.)",
2293  "  -z     - Print archive comment.  (See unzip above.)",
2294  "",
2295  "unzipsfx modifiers:",
2296  "  Most unzip modifiers are supported.  These include",
2297  "  -a     - Convert text files.",
2298  "  -n     - Never overwrite.",
2299  "  -o     - Overwrite without prompting.",
2300  "  -q     - Quiet operation.",
2301  "  -C     - Match names case-insensitively.",
2302  "  -j     - Junk paths.",
2303  "  -V     - Keep version numbers.",
2304  "  -s     - Convert spaces to underscores.",
2305  "  -$     - Restore volume label.",
2306  "",
2307  "If unzipsfx compiled with SFX_EXDIR defined, -d option also available:",
2308  "  -d exd - Extract to directory exd.",
2309  "By default, all files extracted to current directory.  This option",
2310  "forces extraction to specified directory.",
2311  "",
2312  "See unzipsfx manual page for more information.",
2313  ""
2314    };
2315
2316    for (i = 0; i < sizeof(text)/sizeof(char *); i++)
2317    {
2318        Info(slide, 0, ((char *)slide, "%s\n", text[i]));
2319    }
2320} /* end function help_extended() */
2321
2322
2323
2324
2325#ifndef _WIN32_WCE /* Win CE does not support environment variables */
2326#if (!defined(MODERN) || defined(NO_STDLIB_H))
2327/* Declare getenv() to be sure (might be missing in some environments) */
2328extern char *getenv();
2329#endif
2330#endif
2331
2332/********************************/
2333/* Function show_version_info() */
2334/********************************/
2335
2336static void show_version_info(__G)
2337    __GDEF
2338{
2339    if (uO.qflag > 3)                           /* "unzip -vqqqq" */
2340        Info(slide, 0, ((char *)slide, "%d\n",
2341          (UZ_MAJORVER*100 + UZ_MINORVER*10 + UZ_PATCHLEVEL)));
2342    else {
2343#ifndef _WIN32_WCE /* Win CE does not support environment variables */
2344        char *envptr;
2345#endif
2346        int numopts = 0;
2347
2348        Info(slide, 0, ((char *)slide, LoadFarString(UnzipUsageLine1v),
2349          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
2350          LoadFarStringSmall(VersionDate)));
2351        Info(slide, 0, ((char *)slide,
2352          LoadFarString(UnzipUsageLine2v)));
2353        version(__G);
2354        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptions)));
2355#ifdef ACORN_FTYPE_NFS
2356        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2357          LoadFarStringSmall(AcornFtypeNFS)));
2358        ++numopts;
2359#endif
2360#ifdef ASM_CRC
2361        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2362          LoadFarStringSmall(AsmCRC)));
2363        ++numopts;
2364#endif
2365#ifdef ASM_INFLATECODES
2366        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2367          LoadFarStringSmall(AsmInflateCodes)));
2368        ++numopts;
2369#endif
2370#ifdef CHECK_VERSIONS
2371        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2372          LoadFarStringSmall(Check_Versions)));
2373        ++numopts;
2374#endif
2375#ifdef COPYRIGHT_CLEAN
2376        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2377          LoadFarStringSmall(Copyright_Clean)));
2378        ++numopts;
2379#endif
2380#ifdef DEBUG
2381        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2382          LoadFarStringSmall(UDebug)));
2383        ++numopts;
2384#endif
2385#ifdef DEBUG_TIME
2386        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2387          LoadFarStringSmall(DebugTime)));
2388        ++numopts;
2389#endif
2390#ifdef DLL
2391        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2392          LoadFarStringSmall(Dll)));
2393        ++numopts;
2394#endif
2395#ifdef DOSWILD
2396        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2397          LoadFarStringSmall(DosWild)));
2398        ++numopts;
2399#endif
2400#ifdef LZW_CLEAN
2401        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2402          LoadFarStringSmall(LZW_Clean)));
2403        ++numopts;
2404#endif
2405#ifndef MORE
2406        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2407          LoadFarStringSmall(No_More)));
2408        ++numopts;
2409#endif
2410#ifdef NO_ZIPINFO
2411        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2412          LoadFarStringSmall(No_ZipInfo)));
2413        ++numopts;
2414#endif
2415#ifdef NTSD_EAS
2416        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2417          LoadFarStringSmall(NTSDExtAttrib)));
2418        ++numopts;
2419#endif
2420#if defined(WIN32) && defined(NO_W32TIMES_IZFIX)
2421        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2422          LoadFarStringSmall(W32NoIZTimeFix)));
2423        ++numopts;
2424#endif
2425#ifdef OLD_THEOS_EXTRA
2426        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2427          LoadFarStringSmall(OldTheosExtra)));
2428        ++numopts;
2429#endif
2430#ifdef OS2_EAS
2431        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2432          LoadFarStringSmall(OS2ExtAttrib)));
2433        ++numopts;
2434#endif
2435#ifdef QLZIP
2436        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2437          LoadFarStringSmall(SMSExFldOnUnix)));
2438        ++numopts;
2439#endif
2440#ifdef REENTRANT
2441        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2442          LoadFarStringSmall(Reentrant)));
2443        ++numopts;
2444#endif
2445#ifdef REGARGS
2446        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2447          LoadFarStringSmall(RegArgs)));
2448        ++numopts;
2449#endif
2450#ifdef RETURN_CODES
2451        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2452          LoadFarStringSmall(Return_Codes)));
2453        ++numopts;
2454#endif
2455#ifdef SET_DIR_ATTRIB
2456        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2457          LoadFarStringSmall(SetDirAttrib)));
2458        ++numopts;
2459#endif
2460#ifdef SYMLINKS
2461        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2462          LoadFarStringSmall(SymLinkSupport)));
2463        ++numopts;
2464#endif
2465#ifdef TIMESTAMP
2466        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2467          LoadFarStringSmall(TimeStamp)));
2468        ++numopts;
2469#endif
2470#ifdef UNIXBACKUP
2471        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2472          LoadFarStringSmall(UnixBackup)));
2473        ++numopts;
2474#endif
2475#ifdef USE_EF_UT_TIME
2476        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2477          LoadFarStringSmall(Use_EF_UT_time)));
2478        ++numopts;
2479#endif
2480#ifndef COPYRIGHT_CLEAN
2481        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2482          LoadFarStringSmall(Use_Smith_Code)));
2483        ++numopts;
2484#endif
2485#ifndef LZW_CLEAN
2486        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2487          LoadFarStringSmall(Use_Unshrink)));
2488        ++numopts;
2489#endif
2490#ifdef USE_DEFLATE64
2491        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2492          LoadFarStringSmall(Use_Deflate64)));
2493        ++numopts;
2494#endif
2495#ifdef UNICODE_SUPPORT
2496# ifdef UTF8_MAYBE_NATIVE
2497        sprintf((char *)(slide+256), LoadFarStringSmall(Use_Unicode),
2498          LoadFarStringSmall2(G.native_is_utf8 ? SysChUTF8 : SysChOther));
2499        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2500          (char *)(slide+256)));
2501# else
2502        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2503          LoadFarStringSmall(Use_Unicode)));
2504# endif
2505        ++numopts;
2506#endif
2507#ifdef _MBCS
2508        sprintf((char *)(slide+256), LoadFarStringSmall(Have_MBCS_Support),
2509          (unsigned int)MB_CUR_MAX);
2510        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2511          (char *)(slide+256)));
2512        ++numopts;
2513#endif
2514#ifdef MULT_VOLUME
2515        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2516          LoadFarStringSmall(Use_MultiVol)));
2517        ++numopts;
2518#endif
2519#ifdef LARGE_FILE_SUPPORT
2520        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2521          LoadFarStringSmall(Use_LFS)));
2522        ++numopts;
2523#endif
2524#ifdef ZIP64_SUPPORT
2525        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2526          LoadFarStringSmall(Use_Zip64)));
2527        ++numopts;
2528#endif
2529#if (defined(__DJGPP__) && (__DJGPP__ >= 2))
2530#  ifdef USE_DJGPP_ENV
2531        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2532          LoadFarStringSmall(Use_DJGPP_Env)));
2533        ++numopts;
2534#  endif
2535#  ifdef USE_DJGPP_GLOB
2536        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2537          LoadFarStringSmall(Use_DJGPP_Glob)));
2538        ++numopts;
2539#  endif
2540#endif /* __DJGPP__ && (__DJGPP__ >= 2) */
2541#ifdef USE_VFAT
2542        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2543          LoadFarStringSmall(Use_VFAT_support)));
2544        ++numopts;
2545#endif
2546#ifdef USE_ZLIB
2547        sprintf((char *)(slide+256), LoadFarStringSmall(UseZlib),
2548          ZLIB_VERSION, zlibVersion());
2549        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2550          (char *)(slide+256)));
2551        ++numopts;
2552#endif
2553#ifdef USE_BZIP2
2554        sprintf((char *)(slide+256), LoadFarStringSmall(UseBZip2),
2555          BZ2_bzlibVersion());
2556        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2557          (char *)(slide+256)));
2558        ++numopts;
2559#endif
2560#ifdef VMS_TEXT_CONV
2561        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2562          LoadFarStringSmall(VmsTextConv)));
2563        ++numopts;
2564#endif
2565#ifdef VMSCLI
2566        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2567          LoadFarStringSmall(VmsCLI)));
2568        ++numopts;
2569#endif
2570#ifdef VMSWILD
2571        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2572          LoadFarStringSmall(VmsWild)));
2573        ++numopts;
2574#endif
2575#ifdef WILD_STOP_AT_DIR
2576        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2577          LoadFarStringSmall(WildStopAtDir)));
2578        ++numopts;
2579#endif
2580#if CRYPT
2581# ifdef PASSWD_FROM_STDIN
2582        Info(slide, 0, ((char *)slide, LoadFarString(CompileOptFormat),
2583          LoadFarStringSmall(PasswdStdin)));
2584# endif
2585        Info(slide, 0, ((char *)slide, LoadFarString(Decryption),
2586          CR_MAJORVER, CR_MINORVER, CR_BETA_VER,
2587          LoadFarStringSmall(CryptDate)));
2588        ++numopts;
2589#endif /* CRYPT */
2590        if (numopts == 0)
2591            Info(slide, 0, ((char *)slide,
2592              LoadFarString(CompileOptFormat),
2593              LoadFarStringSmall(None)));
2594
2595#ifndef _WIN32_WCE /* Win CE does not support environment variables */
2596        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptions)));
2597        envptr = getenv(LoadFarStringSmall(EnvUnZip));
2598        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2599          LoadFarStringSmall(EnvUnZip),
2600          (envptr == (char *)NULL || *envptr == 0)?
2601          LoadFarStringSmall2(None) : envptr));
2602        envptr = getenv(LoadFarStringSmall(EnvUnZip2));
2603        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2604          LoadFarStringSmall(EnvUnZip2),
2605          (envptr == (char *)NULL || *envptr == 0)?
2606          LoadFarStringSmall2(None) : envptr));
2607        envptr = getenv(LoadFarStringSmall(EnvZipInfo));
2608        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2609          LoadFarStringSmall(EnvZipInfo),
2610          (envptr == (char *)NULL || *envptr == 0)?
2611          LoadFarStringSmall2(None) : envptr));
2612        envptr = getenv(LoadFarStringSmall(EnvZipInfo2));
2613        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2614          LoadFarStringSmall(EnvZipInfo2),
2615          (envptr == (char *)NULL || *envptr == 0)?
2616          LoadFarStringSmall2(None) : envptr));
2617#ifndef __RSXNT__
2618#ifdef __EMX__
2619        envptr = getenv(LoadFarStringSmall(EnvEMX));
2620        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2621          LoadFarStringSmall(EnvEMX),
2622          (envptr == (char *)NULL || *envptr == 0)?
2623          LoadFarStringSmall2(None) : envptr));
2624        envptr = getenv(LoadFarStringSmall(EnvEMXOPT));
2625        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2626          LoadFarStringSmall(EnvEMXOPT),
2627          (envptr == (char *)NULL || *envptr == 0)?
2628          LoadFarStringSmall2(None) : envptr));
2629#endif /* __EMX__ */
2630#if (defined(__GO32__) && (!defined(__DJGPP__) || (__DJGPP__ < 2)))
2631        envptr = getenv(LoadFarStringSmall(EnvGO32));
2632        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2633          LoadFarStringSmall(EnvGO32),
2634          (envptr == (char *)NULL || *envptr == 0)?
2635          LoadFarStringSmall2(None) : envptr));
2636        envptr = getenv(LoadFarStringSmall(EnvGO32TMP));
2637        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2638          LoadFarStringSmall(EnvGO32TMP),
2639          (envptr == (char *)NULL || *envptr == 0)?
2640          LoadFarStringSmall2(None) : envptr));
2641#endif /* __GO32__ && !(__DJGPP__ >= 2) */
2642#endif /* !__RSXNT__ */
2643#ifdef RISCOS
2644        envptr = getenv(LoadFarStringSmall(EnvUnZipExts));
2645        Info(slide, 0, ((char *)slide, LoadFarString(EnvOptFormat),
2646          LoadFarStringSmall(EnvUnZipExts),
2647          (envptr == (char *)NULL || *envptr == 0)?
2648          LoadFarStringSmall2(None) : envptr));
2649#endif /* RISCOS */
2650#endif /* !_WIN32_WCE */
2651    }
2652} /* end function show_version() */
2653
2654#endif /* !SFX */
2655#endif /* !WINDLL */
2656