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