home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip532.zip / unzip.c < prev    next >
C/C++ Source or Header  |  1997-10-18  |  57KB  |  1,619 lines

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