Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. diff -ru2 unz60e03/unzip.c u6e3_np/unzip.c
  2. --- unz60e03/unzip.c    Wed Mar 19 13:08:38 2008
  3. +++ u6e3_np/unzip.c     Mon Mar 24 14:16:58 2008
  4. @@ -128,4 +128,6 @@
  5.      "error:  command line parameter #%d exceeds internal size limit\n";
  6.  #endif /* !SFX */
  7. +static ZCONST char Far NoMemArgsList[] =
  8. +  "error:  no memory for arguments list";
  9.  
  10.  #if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
  11. @@ -245,5 +247,5 @@
  12.     static ZCONST char Far local3[] = "\
  13.    -Y  treat \".nnn\" as \";nnn\" version         -2  force ODS2 names\n\
  14. -  --D restore dir (-D: no) timestamps        -M  pipe through \"more\" pager\n\
  15. +  -D- restore dir (-D: no) timestamps        -M  pipe through \"more\" pager\n\
  16.    (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
  17.  \n\n";
  18. @@ -251,5 +253,5 @@
  19.     static ZCONST char Far local3[] = "\n\
  20.    -Y  treat \".nnn\" as \";nnn\" version         -2  force ODS2 names\n\
  21. -  --D restore dir (-D: no) timestamps\n\
  22. +  -D- restore dir (-D: no) timestamps\n\
  23.    (Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
  24.  \n\n";
  25. @@ -694,5 +696,5 @@
  26.      char *p;
  27.  #endif
  28. -#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))
  29. +#if ((defined(WIN32) && defined(__RSXNT__)) || !defined(SFX))
  30.      int i;
  31.  #endif
  32. @@ -1053,4 +1055,45 @@
  33.       * 'forward slashes' for user's convenience (include zipfile name itself)
  34.       */
  35. +    {
  36. +        /* pfnames */
  37. +
  38. +        char **names;
  39. +
  40. +        for (names = G.pfnames; *names; names++) {
  41. +#ifdef __human68k__
  42. +            extern char *_toslash(char *);
  43. +            _toslash(*names);
  44. +#else /* !__human68k__ */
  45. +            char *q = *names;
  46. +
  47. +            while (*q != '\0') {
  48. +                if (*q == '\\')
  49. +                    *q = '/';
  50. +                INCSTR(q);
  51. +            }
  52. +#endif /* ?__human68k__ */
  53. +        }
  54. +    }
  55. +    {
  56. +        /* G.wildzipfn */
  57. +
  58. +#ifdef __human68k__
  59. +        extern char *_toslash(char *);
  60. +        _toslash(*G.wildzipfn);
  61. +#else /* !__human68k__ */
  62. +        char *q = G.wildzipfn;
  63. +
  64. +        while (*q != '\0') {
  65. +            if (*q == '\\')
  66. +                *q = '/';
  67. +            INCSTR(q);
  68. +        }
  69. +#endif /* ?__human68k__ */
  70. +    }
  71. +#endif /* DOS_FLX_H68_NLM_OS2_W32 */
  72. +
  73. +
  74. +#if 0
  75. +#ifdef DOS_FLX_H68_NLM_OS2_W32
  76.  #ifdef SFX
  77.      for (G.pfnames = argv, i = argc;  i > 0;  --i) {
  78. @@ -1074,11 +1117,18 @@
  79.      }
  80.  #endif /* DOS_FLX_H68_NLM_OS2_W32 */
  81. +#endif /* 0 */
  82.  
  83. +/*
  84.  #ifndef SFX
  85.      G.wildzipfn = *argv++;
  86.  #endif
  87. +*/
  88.  
  89.  #if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
  90.  
  91. +# if 0
  92. +    /* all this should be done in the options call now */
  93. +
  94. +
  95.      G.filespecs = argc;
  96.      G.xfilespecs = 0;
  97. @@ -1104,7 +1154,10 @@
  98.      } else
  99.          G.process_all_files = TRUE;      /* for speed */
  100. +# endif
  101.  
  102.  #else /* !SFX || SFX_EXDIR */             /* check for -x or -d */
  103.  
  104. +# if 0
  105. +
  106.      G.filespecs = argc;
  107.      G.xfilespecs = 0;
  108. @@ -1118,9 +1171,9 @@
  109.          while (*++pp) {
  110.              Trace((stderr, "pp - argv = %d\n", pp-argv));
  111. -#ifdef CMS_MVS
  112. +# ifdef CMS_MVS
  113.              if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
  114. -#else
  115. +# else
  116.              if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
  117. -#endif
  118. +# endif
  119.                  int firstarg = (pp == argv);
  120.  
  121. @@ -1177,4 +1230,5 @@
  122.      } else
  123.          G.process_all_files = TRUE;      /* for speed */
  124. +# endif
  125.  
  126.      if (uO.exdir != (char *)NULL && !G.extract_flag)    /* -d ignored */
  127. @@ -1260,4 +1314,269 @@
  128.  
  129.  
  130. +/*
  131. +  -------------------------------------------------------
  132. +  Command Line Options
  133. +  -------------------------------------------------------
  134. +
  135. +  Valid command line options.
  136. +
  137. +  The function get_option() uses this table to check if an
  138. +  option is valid and if it takes a value (also called an
  139. +  option parameter).  To add an option to unzip just add it
  140. +  to this table and add a case in the main switch to handle
  141. +  it.  If either shortopt or longopt not used set to "".
  142. +
  143. +   The fields:
  144. +       option_group - UZO for UnZip option, ZIO for ZipInfo option
  145. +       shortopt     - short option name (1 or 2 chars)
  146. +       longopt      - long option name
  147. +       value_type   - see zip.h for constants
  148. +       negatable    - option is negatable with trailing -
  149. +       ID           - unsigned long int returned for option
  150. +       name         - short description of option which is
  151. +                        returned on some errors and when options
  152. +                        are listed with -so option, can be NULL
  153. +*/
  154. +
  155. +/* Most option IDs are set to the shortopt char.  For
  156. +   multichar short options set to arbitrary unused constant. */
  157. +#define o_so            0x101
  158. +
  159. +
  160. +/* The below is from the old main command line code with a few changes.
  161. +   Note that UnZip and ZipInfo filter out their own options based on the
  162. +   option_group value, so the same option letter can be used for both. */
  163. +
  164. +static struct option_struct far options[] = {
  165. +
  166. +  /* UnZip options */
  167. +
  168. +  /* short longopt                      value_type        negatable
  169. +       ID    name */
  170. +#ifdef RISCOS
  171. +    {UZO, "/",  "",                     o_REQUIRED_VALUE, o_NEGATABLE,
  172. +       '/',  "override Unzip$Exts"},
  173. +#endif
  174. +    {UZO, "a",  "",                     o_NO_VALUE,       o_NEGATABLE,
  175. +       'a',  "text conv (EOL char, ASCII->EBCDIC"},
  176. +#if (defined(DLL) && defined(API_DOC))
  177. +    {UZO, "A",  "",                     o_NO_VALUE,       o_NEGATABLE,
  178. +       'A',  "extended help for API"},
  179. +#endif
  180. +    {UZO, "b",  "",                     o_NO_VALUE,       o_NEGATABLE,
  181. +       'b',  "binary, no ASCII conversions"},
  182. +#ifdef UNIXBACKUP
  183. +    {UZO, "B",  "",                     o_NO_VALUE,       o_NEGATABLE,
  184. +       'B',  "back up existing files"},
  185. +#endif
  186. +#ifdef CMS_MVS
  187. +    {UZO, "B",  "",                     o_NO_VALUE,       o_NEGATABLE,
  188. +       'b',  "CMS/MVS binary"},
  189. +#endif
  190. +    {UZO, "c",  "",                     o_NO_VALUE,       o_NEGATABLE,
  191. +       'c',  "output to stdout"},
  192. +#ifdef CMS_MVS
  193. +    /* for CMS_MVS map to lower case */
  194. +    {UZO, "C",  "",                     o_NO_VALUE,       o_NEGATABLE,
  195. +       'C',  "CMS/MVS lower case"},
  196. +#endif
  197. +#if (!defined(SFX) || defined(SFX_EXDIR))
  198. +    {UZO, "d",  "",                     o_REQUIRED_VALUE, o_NEGATABLE,
  199. +       'd',  "extraction root directory"},
  200. +#endif
  201. +#if (!defined(NO_TIMESTAMPS))
  202. +    {UZO, "D",  "",                     o_NO_VALUE,       o_NEGATABLE,
  203. +       'D',  "don't restore dir (-DD: any) timestamps"},
  204. +#endif
  205. +    {UZO, "e",  "",                     o_NO_VALUE,       o_NEGATABLE,
  206. +       'e',  "extract (not used?)"},
  207. +#ifdef MACOS
  208. +    {UZO, "E",  "",                     o_NO_VALUE,       o_NEGATABLE,
  209. +       'E',  "display Mac e.f. when restoring"},
  210. +#endif
  211. +    {UZO, "f",  "",                     o_NO_VALUE,       o_NEGATABLE,
  212. +       'f',  "freshen (extract only newer files)"},
  213. +#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
  214. +    {UZO, "F",  "",                     o_NO_VALUE,       o_NEGATABLE,
  215. +       'F',  "Acorn filetype & NFS extension handling"},
  216. +#endif
  217. +    {UZO, "h",  "",                     o_NO_VALUE,       o_NOT_NEGATABLE,
  218. +       'h',  "help"},
  219. +#ifdef MACOS
  220. +    {UZO, "i",  "",                     o_NO_VALUE,       o_NEGATABLE,
  221. +       'i',  "ignore filenames stored in Mac ef"},
  222. +#endif
  223. +    {UZO, "j",  "",                     o_NO_VALUE,       o_NEGATABLE,
  224. +       'j',  "junk directories, extract names only"},
  225. +#if (defined(ATH_BEO) || defined(MACOS))
  226. +    {UZO, "J",  "",                     o_NO_VALUE,       o_NEGATABLE,
  227. +       'J',  "Junk AtheOS, BeOS or MacOS file attrs"},
  228. +#endif
  229. +#ifdef ATH_BEO_UNX
  230. +    {UZO, "K",  "",                     o_NO_VALUE,       o_NEGATABLE,
  231. +       'K',  "retain SUID/SGID/Tacky attrs"},
  232. +#endif
  233. +#ifndef SFX
  234. +    {UZO, "l",  "",                     o_NO_VALUE,       o_NEGATABLE,
  235. +        'l',  "listing verbosity"},
  236. +#endif
  237. +#ifndef CMS_MVS
  238. +    {UZO, "L",  "",                     o_NO_VALUE,       o_NEGATABLE,
  239. +       'L',  "convert (some) names to lower"},
  240. +#endif
  241. +#ifdef MORE
  242. +# ifdef CMS_MVS
  243. +    {UZO, "m",  "",                     o_NO_VALUE,       o_NEGATABLE,
  244. +       'm',  "pipe output through more"},
  245. +# endif
  246. +    {UZO, "M",  "",                     o_NO_VALUE,       o_NEGATABLE,
  247. +       'M',  "pipe output through more"},
  248. +#endif /* MORE */
  249. +    {UZO, "n",  "",                     o_NO_VALUE,       o_NEGATABLE,
  250. +       'n',  "never overwrite files (no prompting)"},
  251. +#ifdef AMIGA
  252. +    {UZO, "N",  "",                     o_NO_VALUE,       o_NEGATABLE,
  253. +       'N',  "restore comments as filenotes"},
  254. +#endif
  255. +    {UZO, "o",  "",                     o_NO_VALUE,       o_NEGATABLE,
  256. +       'o',  "overwrite files without prompting"},
  257. +    {UZO, "p",  "",                     o_NO_VALUE,       o_NEGATABLE,
  258. +       'p',  "pipe extraction to stdout, no messages"},
  259. +#if CRYPT
  260. +    {UZO, "P",  "",                     o_REQUIRED_VALUE, o_NEGATABLE,
  261. +       'P',  "password"},
  262. +#endif
  263. +    {UZO, "q",  "",                     o_NO_VALUE,       o_NEGATABLE,
  264. +       'q',  "quiet"},
  265. +#ifdef QDOS
  266. +    {UZO, "Q",  "",                     o_NO_VALUE,       o_NEGATABLE,
  267. +       'Q',  "QDOS flags"},
  268. +#endif
  269. +#ifdef TANDEM
  270. +    {UZO, "r",  "",                     o_NO_VALUE,       o_NEGATABLE,
  271. +       'r',  "remove file extensions"},
  272. +#endif
  273. +#ifdef DOS_FLX_NLM_OS2_W32
  274. +    {UZO, "s",  "",                     o_NO_VALUE,       o_NEGATABLE,
  275. +       's',  "spaces to underscores"},
  276. +#endif
  277. +#ifdef VMS
  278. +    {UZO, "S",  "",                     o_NO_VALUE,       o_NEGATABLE,
  279. +       'S',  "VMS extract text as Stream LF"},
  280. +#endif
  281. +    {UZO, "t",  "",                     o_NO_VALUE,       o_NEGATABLE,
  282. +       't',  "test"},
  283. +#ifdef TIMESTAMP
  284. +    {UZO, "T",  "",                     o_NO_VALUE,       o_NEGATABLE,
  285. +       'T',  "timestamps"},
  286. +#endif
  287. +    {UZO, "u",  "",                     o_NO_VALUE,       o_NEGATABLE,
  288. +       'u',  "update (extract only new/newer files)"},
  289. +#ifdef UNICODE_SUPPORT
  290. +    {UZO, "U",  "",                     o_NO_VALUE,       o_NEGATABLE,
  291. +       'U',  "escape non-ASCII Unicode, disable Unicode"},
  292. +#else /* !UNICODE_SUPPORT */
  293. +# ifndef CMS_MVS
  294. +    {UZO, "U",  "",                     o_NO_VALUE,       o_NEGATABLE,
  295. +       'U',  "names to lower case"},
  296. +# endif /* !CMS_MVS */
  297. +#endif /* ?UNICODE_SUPPORT */
  298. +#ifndef SFX
  299. +    {UZO, "v",  "",                     o_NO_VALUE,       o_NEGATABLE,
  300. +       'v',  "verbose"},
  301. +#endif
  302. +#ifndef CMS_MVS
  303. +    {UZO, "V",  "",                     o_NO_VALUE,       o_NEGATABLE,
  304. +       'V',  "don't strip VMS version numbers"},
  305. +#endif
  306. +#ifdef WILD_STOP_AT_DIR
  307. +    {UZO, "W",  "",                     o_NO_VALUE,       o_NEGATABLE,
  308. +       'W',  "wildcard * doesn't span /"},
  309. +#endif
  310. +    {UZO, "x",  "",                     o_VALUE_LIST,     o_NOT_NEGATABLE,
  311. +       'x',  "exclude this list of files"},
  312. +#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
  313. +    {UZO, "X",  "",                     o_NO_VALUE,       o_NEGATABLE,
  314. +       'X',  "restore owner/prot or UID/GID or ACLs"},
  315. +#endif
  316. +#ifdef VMS
  317. +    {UZO, "Y",  "",                     o_NO_VALUE,       o_NEGATABLE,
  318. +       'Y',  "VMS treat .nnn as ;nnn version"},
  319. +#endif
  320. +    {UZO, "z",  "",                     o_NO_VALUE,       o_NEGATABLE,
  321. +       'z',  "display zipfile comment"},
  322. +#ifndef SFX
  323. +    {UZO, "Z",  "",                     o_NO_VALUE,       o_NOT_NEGATABLE,
  324. +       'Z',  "ZipInfo mode"},
  325. +#endif
  326. +#ifdef VMS
  327. +    {UZO, "2",  "",                     o_NO_VALUE,       o_NEGATABLE,
  328. +       '2',  "Force ODS2-compliant names."},
  329. +#endif
  330. +#ifdef DOS_H68_OS2_W32
  331. +    {UZO, "$",  "",                     o_NO_VALUE,       o_NEGATABLE,
  332. +       '$',  "extract volume labels"},
  333. +#endif
  334. +#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
  335. +    {UZO, ":",  "",                     o_NO_VALUE,       o_NEGATABLE,
  336. +       ':',  "don't skip ../ path elements"},
  337. +#endif
  338. +#ifdef UNIX
  339. +    {UZO, "^",  "",                     o_NO_VALUE,       o_NEGATABLE,
  340. +       '^',  "allow control chars in filenames"},
  341. +#endif
  342. +
  343. +#ifndef NO_ZIPINFO
  344. +  /* ZipInfo options */
  345. +
  346. +  /* short longopt                      value_type        negatable
  347. +       ID    name (help text) */
  348. +    {ZIO, "1",  "",                     o_NO_VALUE,       o_NEGATABLE,
  349. +       '1',  "shortest list"},
  350. +    {ZIO, "2",  "",                     o_NO_VALUE,       o_NEGATABLE,
  351. +       '2',  "names and headers"},
  352. +#ifndef CMS_MVS
  353. +    {ZIO, "C",  "",                     o_NO_VALUE,       o_NEGATABLE,
  354. +       'C',  "ignore case"},
  355. +#endif
  356. +    {ZIO, "h",  "",                     o_NO_VALUE,       o_NEGATABLE,
  357. +       'h',  "header line"},
  358. +    {ZIO, "l",  "",                     o_NO_VALUE,       o_NEGATABLE,
  359. +       'l',  "longer listing"},
  360. +    {ZIO, "m",  "",                     o_NO_VALUE,       o_NEGATABLE,
  361. +       'm',  "medium listing"},
  362. +#ifdef MORE
  363. +    {ZIO, "M",  "",                     o_NO_VALUE,       o_NEGATABLE,
  364. +       'M',  "output like more"},
  365. +#endif
  366. +    {ZIO, "s",  "",                     o_NO_VALUE,       o_NEGATABLE,
  367. +       's',  "shorter list"},
  368. +    {ZIO, "t",  "",                     o_NO_VALUE,       o_NEGATABLE,
  369. +       't',  "totals line"},
  370. +    {ZIO, "T",  "",                     o_NO_VALUE,       o_NEGATABLE,
  371. +       'T',  "decimal time format"},
  372. +#ifdef UNICODE_SUPPORT
  373. +    {ZIO, "U",  "",                     o_NO_VALUE,       o_NEGATABLE,
  374. +       'U',  "escape non-ASCII Unicode, disable Unicode"},
  375. +#endif
  376. +    {ZIO, "v",  "",                     o_NO_VALUE,       o_NEGATABLE,
  377. +       'v',  "turbo-verbose listing"},
  378. +#ifdef WILD_STOP_AT_DIR
  379. +    {ZIO, "W",  "",                     o_NO_VALUE,       o_NEGATABLE,
  380. +       'W',  "wild stop at /"},
  381. +#endif
  382. +    {ZIO, "x",  "",                     o_VALUE_LIST,     o_NOT_NEGATABLE,
  383. +       'x',  "exclude this list of files"},
  384. +    {ZIO, "z",  "",                     o_NO_VALUE,       o_NEGATABLE,
  385. +       'z',  "print zipfile comment"},
  386. +    {ZIO, "Z",  "",                     o_NO_VALUE,       o_NEGATABLE,
  387. +       'Z',  "ZipInfo mode"},
  388. +#endif /* !NO_ZIPINFO */
  389. +
  390. +    /* the end of the list */
  391. +    {0,   NULL, NULL,                   o_NO_VALUE,       o_NOT_NEGATABLE,
  392. +       0,    NULL} /* end has option_ID = 0 */
  393. +  };
  394. +
  395.  
  396.  
  397. @@ -1271,502 +1590,649 @@
  398.      char ***pargv;
  399.  {
  400. -    char **argv, *s;
  401. -    int argc, c, error=FALSE, negative=0;
  402. +    char **args;
  403. +    int argc, error=FALSE;
  404.  
  405. +    /* used by get_option */
  406. +    unsigned long option; /* option ID returned by get_option */
  407. +    int argcnt = 0;       /* current argcnt in args */
  408. +    int argnum = 0;       /* arg number */
  409. +    int optchar = 0;      /* option state */
  410. +    char *value = NULL;   /* non-option arg, option value or NULL */
  411. +    int negative = 0;     /* 1 = option negated */
  412. +    int fna = 0;          /* current first non-opt arg */
  413. +    int optnum = 0;       /* index in table */
  414.  
  415. -    argc = *pargc;
  416. -    argv = *pargv;
  417.  
  418. -    while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
  419. -        s = *argv + 1;
  420. -        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  421. -#ifdef CMS_MVS
  422. -            switch (tolower(c))
  423. -#else
  424. -            switch (c)
  425. -#endif
  426. -            {
  427. -                case ('-'):
  428. -                    ++negative;
  429. -                    break;
  430. +    /* since get_option() returns xfiles and files one at a time, store them
  431. +       in linked lists until have them all */
  432. +
  433. +    int file_count = 0;
  434. +    struct file_list *next_file;
  435. +
  436. +    /* files to extract */
  437. +    int in_files_count = 0;
  438. +    struct file_list *in_files = NULL;
  439. +    struct file_list *next_in_files = NULL;
  440. +
  441. +    /* files to exclude in -x list */
  442. +    int in_xfiles_count = 0;
  443. +    struct file_list *in_xfiles = NULL;
  444. +    struct file_list *next_in_xfiles = NULL;
  445. +
  446. +    G.wildzipfn = NULL;
  447. +
  448. +    /* make copy of args that can use with insert_arg() used by get_option() */
  449. +    args = copy_args(*pargv, 0);
  450. +
  451. +
  452. +    /* Initialize lists */
  453. +    G.filespecs = 0;
  454. +    G.xfilespecs = 0;
  455. +
  456. +
  457. +    /*
  458. +    -------------------------------------------
  459. +    Process command line using get_option
  460. +    -------------------------------------------
  461. +
  462. +    Each call to get_option() returns either a command
  463. +    line option and possible value or a non-option argument.
  464. +    Arguments are permuted so that all options (-r, -b temp)
  465. +    are returned before non-option arguments (zipfile).
  466. +    Returns 0 when nothing left to read.
  467. +    */
  468. +
  469. +    /* set argnum = 0 on first call to init get_option */
  470. +    argnum = 0;
  471. +
  472. +    /* get_option returns the option ID and updates parameters:
  473. +           args    - usually same as argv if no argument file support
  474. +           argcnt  - current argc for args
  475. +           value   - char* to value (free() when done with it) or NULL if none
  476. +           negated - option was negated with trailing -
  477. +    */
  478. +
  479. +    while ((option = get_option(UZO, &args, &argcnt, &argnum,
  480. +                                &optchar, &value, &negative,
  481. +                                &fna, &optnum, 0)))
  482. +    {
  483. +        if(option == o_BAD_ERR) {
  484. +          return(PK_PARAM);
  485. +        }
  486. +
  487. +        switch (option)
  488. +        {
  489.  #ifdef RISCOS
  490. -                case ('/'):
  491. -                    if (negative) {   /* negative not allowed with -/ swap */
  492. -                        Info(slide, 0x401, ((char *)slide,
  493. -                          "error:  must give extensions list"));
  494. -                        return(PK_PARAM);  /* don't extract here by accident */
  495. -                    }
  496. -                    exts2swap = s; /* override Unzip$Exts */
  497. -                    s += strlen(s);
  498. -                    break;
  499. -#endif
  500. -                case ('a'):
  501. -                    if (negative) {
  502. -                        uO.aflag = MAX(uO.aflag-negative,0);
  503. -                        negative = 0;
  504. -                    } else
  505. -                        ++uO.aflag;
  506. -                    break;
  507. +            case ('/'):
  508. +                if (negative) {   /* negative not allowed with -/ swap */
  509. +                    Info(slide, 0x401, ((char *)slide,
  510. +                      "error:  must give extensions list"));
  511. +                    return(PK_PARAM);  /* don't extract here by accident */
  512. +                }
  513. +                exts2swap = value; /* override Unzip$Exts */
  514. +                break;
  515. +#endif
  516. +            case ('a'):
  517. +                if (negative) {
  518. +                    uO.aflag = MAX(uO.aflag-negative,0);
  519. +                    negative = 0;
  520. +                } else
  521. +                    ++uO.aflag;
  522. +                break;
  523.  #if (defined(DLL) && defined(API_DOC))
  524. -                case ('A'):    /* extended help for API */
  525. -                    APIhelp(__G__ argc, argv);
  526. -                    *pargc = -1;  /* signal to exit successfully */
  527. -                    return 0;
  528. +            case ('A'):    /* extended help for API */
  529. +                APIhelp(__G__ argc, args);
  530. +                *pargc = -1;  /* signal to exit successfully */
  531. +                return 0;
  532.  #endif
  533. -                case ('b'):
  534. -                    if (negative) {
  535. +            case ('b'):
  536. +                if (negative) {
  537.  #if (defined(TANDEM) || defined(VMS))
  538. -                        uO.bflag = MAX(uO.bflag-negative,0);
  539. +                    uO.bflag = MAX(uO.bflag-negative,0);
  540.  #endif
  541. -                        negative = 0;   /* do nothing:  "-b" is default */
  542. -                    } else {
  543. +                    negative = 0;   /* do nothing:  "-b" is default */
  544. +                } else {
  545.  #ifdef VMS
  546. -                        if (uO.aflag == 0)
  547. -                           ++uO.bflag;
  548. +                    if (uO.aflag == 0)
  549. +                       ++uO.bflag;
  550.  #endif
  551.  #ifdef TANDEM
  552. -                        ++uO.bflag;
  553. +                    ++uO.bflag;
  554.  #endif
  555. -                        uO.aflag = 0;
  556. -                    }
  557. -                    break;
  558. +                    uO.aflag = 0;
  559. +                }
  560. +                break;
  561.  #ifdef UNIXBACKUP
  562. -                case ('B'): /* -B: back up existing files */
  563. -                    if (negative)
  564. -                        uO.B_flag = FALSE, negative = 0;
  565. -                    else
  566. -                        uO.B_flag = TRUE;
  567. -                    break;
  568. -#endif
  569. -                case ('c'):
  570. -                    if (negative) {
  571. -                        uO.cflag = FALSE, negative = 0;
  572. +            case ('B'): /* -B: back up existing files */
  573. +                if (negative)
  574. +                    uO.B_flag = FALSE, negative = 0;
  575. +                else
  576. +                    uO.B_flag = TRUE;
  577. +                break;
  578. +#endif
  579. +            case ('c'):
  580. +                if (negative) {
  581. +                    uO.cflag = FALSE, negative = 0;
  582.  #ifdef NATIVE
  583. -                        uO.aflag = 0;
  584. +                    uO.aflag = 0;
  585.  #endif
  586. -                    } else {
  587. -                        uO.cflag = TRUE;
  588. +                } else {
  589. +                    uO.cflag = TRUE;
  590.  #ifdef NATIVE
  591. -                        uO.aflag = 2;   /* so you can read it on the screen */
  592. +                    uO.aflag = 2;   /* so you can read it on the screen */
  593.  #endif
  594.  #ifdef DLL
  595. -                        if (G.redirect_text)
  596. -                            G.redirect_data = 2;
  597. +                    if (G.redirect_text)
  598. +                        G.redirect_data = 2;
  599.  #endif
  600. -                    }
  601. -                    break;
  602. +                }
  603. +                break;
  604.  #ifndef CMS_MVS
  605. -                case ('C'):    /* -C:  match filenames case-insensitively */
  606. -                    if (negative)
  607. -                        uO.C_flag = FALSE, negative = 0;
  608. -                    else
  609. -                        uO.C_flag = TRUE;
  610. -                    break;
  611. +            case ('C'):    /* -C:  match filenames case-insensitively */
  612. +                if (negative)
  613. +                    uO.C_flag = FALSE, negative = 0;
  614. +                else
  615. +                    uO.C_flag = TRUE;
  616. +                break;
  617.  #endif /* !CMS_MVS */
  618.  #if (!defined(SFX) || defined(SFX_EXDIR))
  619. -                case ('d'):
  620. -                    if (negative) {   /* negative not allowed with -d exdir */
  621. +            case ('d'):
  622. +                if (negative) {   /* negative not allowed with -d exdir */
  623. +                    Info(slide, 0x401, ((char *)slide,
  624. +                      LoadFarString(MustGiveExdir)));
  625. +                    return(PK_PARAM);  /* don't extract here by accident */
  626. +                }
  627. +                if (uO.exdir != (char *)NULL) {
  628. +                    Info(slide, 0x401, ((char *)slide,
  629. +                      LoadFarString(OnlyOneExdir)));
  630. +                    return(PK_PARAM);    /* GRR:  stupid restriction? */
  631. +                } else {
  632. +                    /* first check for "-dexdir", then for "-d exdir" */
  633. +                    uO.exdir = value;
  634. +                    if (uO.exdir == NULL || *uO.exdir == '\0') {
  635.                          Info(slide, 0x401, ((char *)slide,
  636.                            LoadFarString(MustGiveExdir)));
  637. -                        return(PK_PARAM);  /* don't extract here by accident */
  638. -                    }
  639. -                    if (uO.exdir != (char *)NULL) {
  640. -                        Info(slide, 0x401, ((char *)slide,
  641. -                          LoadFarString(OnlyOneExdir)));
  642. -                        return(PK_PARAM);    /* GRR:  stupid restriction? */
  643. -                    } else {
  644. -                        /* first check for "-dexdir", then for "-d exdir" */
  645. -                        uO.exdir = s;
  646. -                        if (*uO.exdir == '\0') {
  647. -                            if (argc > 1) {
  648. -                                --argc;
  649. -                                uO.exdir = *++argv;
  650. -                                if (*uO.exdir == '-') {
  651. -                                    Info(slide, 0x401, ((char *)slide,
  652. -                                      LoadFarString(MustGiveExdir)));
  653. -                                    return(PK_PARAM);
  654. -                                }
  655. -                                /* else uO.exdir points at extraction dir */
  656. -                            } else {
  657. -                                Info(slide, 0x401, ((char *)slide,
  658. -                                  LoadFarString(MustGiveExdir)));
  659. -                                return(PK_PARAM);
  660. -                            }
  661. -                        }
  662. -                        /* uO.exdir now points at extraction dir (-dexdir or
  663. -                         *  -d exdir); point s at end of exdir to avoid mis-
  664. -                         *  interpretation of exdir characters as more options
  665. -                         */
  666. -                        if (*s != 0)
  667. -                            while (*++s != 0)
  668. -                                ;
  669. +                        return(PK_PARAM);
  670.                      }
  671. -                    break;
  672. +                    /* else uO.exdir points at extraction dir */
  673. +                }
  674. +                break;
  675.  #endif /* !SFX || SFX_EXDIR */
  676.  #if (!defined(NO_TIMESTAMPS))
  677. -                case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */
  678. -                    if (negative) {
  679. -                        uO.D_flag = MAX(uO.D_flag-negative,0);
  680. -                        negative = 0;
  681. -                    } else
  682. -                        uO.D_flag++;
  683. -                    break;
  684. +            case ('D'):    /* -D: Skip restoring dir (or any) timestamp. */
  685. +                if (negative) {
  686. +                    uO.D_flag = MAX(uO.D_flag-negative,0);
  687. +                    negative = 0;
  688. +                } else
  689. +                    uO.D_flag++;
  690. +                break;
  691.  #endif /* (!NO_TIMESTAMPS) */
  692. -                case ('e'):    /* just ignore -e, -x options (extract) */
  693. -                    break;
  694. +            case ('e'):    /* just ignore -e, -x options (extract) */
  695. +                break;
  696.  #ifdef MACOS
  697. -                case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
  698. -                    if( negative ) {
  699. -                        uO.E_flag = FALSE, negative = 0;
  700. -                    } else {
  701. -                        uO.E_flag = TRUE;
  702. -                    }
  703. -                    break;
  704. +            case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
  705. +                if( negative ) {
  706. +                    uO.E_flag = FALSE, negative = 0;
  707. +                } else {
  708. +                    uO.E_flag = TRUE;
  709. +                }
  710. +                break;
  711.  #endif /* MACOS */
  712. -                case ('f'):    /* "freshen" (extract only newer files) */
  713. -                    if (negative)
  714. -                        uO.fflag = uO.uflag = FALSE, negative = 0;
  715. -                    else
  716. -                        uO.fflag = uO.uflag = TRUE;
  717. -                    break;
  718. +            case ('f'):    /* "freshen" (extract only newer files) */
  719. +                if (negative)
  720. +                    uO.fflag = uO.uflag = FALSE, negative = 0;
  721. +                else
  722. +                    uO.fflag = uO.uflag = TRUE;
  723. +                break;
  724.  #if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
  725. -                case ('F'):    /* Acorn filetype & NFS extension handling */
  726. -                    if (negative)
  727. -                        uO.acorn_nfs_ext = FALSE, negative = 0;
  728. -                    else
  729. -                        uO.acorn_nfs_ext = TRUE;
  730. -                    break;
  731. +            case ('F'):    /* Acorn filetype & NFS extension handling */
  732. +                if (negative)
  733. +                    uO.acorn_nfs_ext = FALSE, negative = 0;
  734. +                else
  735. +                    uO.acorn_nfs_ext = TRUE;
  736. +                break;
  737.  #endif /* RISCOS || ACORN_FTYPE_NFS */
  738. -                case ('h'):    /* just print help message and quit */
  739. -                    *pargc = -1;
  740. -                    return USAGE(PK_OK);
  741. +            case ('h'):    /* just print help message and quit */
  742. +                *pargc = -1;
  743. +                return USAGE(PK_OK);
  744.  #ifdef MACOS
  745. -                case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
  746. -                    if( negative ) {
  747. -                        uO.i_flag = FALSE, negative = 0;
  748. -                    } else {
  749. -                        uO.i_flag = TRUE;
  750. -                    }
  751. -                    break;
  752. +            case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
  753. +                if( negative ) {
  754. +                    uO.i_flag = FALSE, negative = 0;
  755. +                } else {
  756. +                    uO.i_flag = TRUE;
  757. +                }
  758. +                break;
  759.  #endif  /* MACOS */
  760. -                case ('j'):    /* junk pathnames/directory structure */
  761. -                    if (negative)
  762. -                        uO.jflag = FALSE, negative = 0;
  763. -                    else
  764. -                        uO.jflag = TRUE;
  765. -                    break;
  766. +            case ('j'):    /* junk pathnames/directory structure */
  767. +                if (negative)
  768. +                    uO.jflag = FALSE, negative = 0;
  769. +                else
  770. +                    uO.jflag = TRUE;
  771. +                break;
  772.  #if (defined(ATH_BEO) || defined(MACOS))
  773. -                case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */
  774. -                    if( negative ) {
  775. -                        uO.J_flag = FALSE, negative = 0;
  776. -                    } else {
  777. -                        uO.J_flag = TRUE;
  778. -                    }
  779. -                    break;
  780. +            case ('J'):    /* Junk AtheOS, BeOS or MacOS file attributes */
  781. +                if( negative ) {
  782. +                    uO.J_flag = FALSE, negative = 0;
  783. +                } else {
  784. +                    uO.J_flag = TRUE;
  785. +                }
  786. +                break;
  787.  #endif /* ATH_BEO || MACOS */
  788.  #ifdef ATH_BEO_UNX
  789. -                case ('K'):
  790. -                    if (negative) {
  791. -                        uO.K_flag = FALSE, negative = 0;
  792. -                    } else {
  793. -                        uO.K_flag = TRUE;
  794. -                    }
  795. -                    break;
  796. +            case ('K'):
  797. +                if (negative) {
  798. +                    uO.K_flag = FALSE, negative = 0;
  799. +                } else {
  800. +                    uO.K_flag = TRUE;
  801. +                }
  802. +                break;
  803.  #endif /* ATH_BEO_UNX */
  804.  #ifndef SFX
  805. -                case ('l'):
  806. -                    if (negative) {
  807. -                        uO.vflag = MAX(uO.vflag-negative,0);
  808. -                        negative = 0;
  809. -                    } else
  810. -                        ++uO.vflag;
  811. -                    break;
  812. +            case ('l'):
  813. +                if (negative) {
  814. +                    uO.vflag = MAX(uO.vflag-negative,0);
  815. +                    negative = 0;
  816. +                } else
  817. +                    ++uO.vflag;
  818. +                break;
  819.  #endif /* !SFX */
  820.  #ifndef CMS_MVS
  821. -                case ('L'):    /* convert (some) filenames to lowercase */
  822. -                    if (negative) {
  823. -                        uO.L_flag = MAX(uO.L_flag-negative,0);
  824. -                        negative = 0;
  825. -                    } else
  826. -                        ++uO.L_flag;
  827. -                    break;
  828. +            case ('L'):    /* convert (some) filenames to lowercase */
  829. +                if (negative) {
  830. +                    uO.L_flag = MAX(uO.L_flag-negative,0);
  831. +                    negative = 0;
  832. +                } else
  833. +                    ++uO.L_flag;
  834. +                break;
  835.  #endif /* !CMS_MVS */
  836.  #ifdef MORE
  837.  #ifdef CMS_MVS
  838. -                case ('m'):
  839. +            case ('m'):
  840.  #endif
  841. -                case ('M'):    /* send all screen output through "more" fn. */
  842. +            case ('M'):    /* send all screen output through "more" fn. */
  843.  /* GRR:  eventually check for numerical argument => height */
  844. -                    if (negative)
  845. -                        G.M_flag = FALSE, negative = 0;
  846. -                    else
  847. -                        G.M_flag = TRUE;
  848. -                    break;
  849. +                if (negative)
  850. +                    G.M_flag = FALSE, negative = 0;
  851. +                else
  852. +                    G.M_flag = TRUE;
  853. +                break;
  854.  #endif /* MORE */
  855. -                case ('n'):    /* don't overwrite any files */
  856. -                    if (negative)
  857. -                        uO.overwrite_none = FALSE, negative = 0;
  858. -                    else
  859. -                        uO.overwrite_none = TRUE;
  860. -                    break;
  861. +            case ('n'):    /* don't overwrite any files */
  862. +                if (negative)
  863. +                    uO.overwrite_none = FALSE, negative = 0;
  864. +                else
  865. +                    uO.overwrite_none = TRUE;
  866. +                break;
  867.  #ifdef AMIGA
  868. -                case ('N'):    /* restore comments as filenotes */
  869. -                    if (negative)
  870. -                        uO.N_flag = FALSE, negative = 0;
  871. -                    else
  872. -                        uO.N_flag = TRUE;
  873. -                    break;
  874. +            case ('N'):    /* restore comments as filenotes */
  875. +                if (negative)
  876. +                    uO.N_flag = FALSE, negative = 0;
  877. +                else
  878. +                    uO.N_flag = TRUE;
  879. +                break;
  880.  #endif /* AMIGA */
  881. -                case ('o'):    /* OK to overwrite files without prompting */
  882. -                    if (negative) {
  883. -                        uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
  884. -                        negative = 0;
  885. -                    } else
  886. -                        ++uO.overwrite_all;
  887. -                    break;
  888. -                case ('p'):    /* pipes:  extract to stdout, no messages */
  889. -                    if (negative) {
  890. -                        uO.cflag = FALSE;
  891. -                        uO.qflag = MAX(uO.qflag-999,0);
  892. -                        negative = 0;
  893. -                    } else {
  894. -                        uO.cflag = TRUE;
  895. -                        uO.qflag += 999;
  896. -                    }
  897. -                    break;
  898. +            case ('o'):    /* OK to overwrite files without prompting */
  899. +                if (negative) {
  900. +                    uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
  901. +                    negative = 0;
  902. +                } else
  903. +                    ++uO.overwrite_all;
  904. +                break;
  905. +            case ('p'):    /* pipes:  extract to stdout, no messages */
  906. +                if (negative) {
  907. +                    uO.cflag = FALSE;
  908. +                    uO.qflag = MAX(uO.qflag-999,0);
  909. +                    negative = 0;
  910. +                } else {
  911. +                    uO.cflag = TRUE;
  912. +                    uO.qflag += 999;
  913. +                }
  914. +                break;
  915.  #if CRYPT
  916. -                /* GRR:  yes, this is highly insecure, but dozens of people
  917. -                 * have pestered us for this, so here we go... */
  918. -                case ('P'):
  919. -                    if (negative) {   /* negative not allowed with -P passwd */
  920. -                        Info(slide, 0x401, ((char *)slide,
  921. -                          LoadFarString(MustGivePasswd)));
  922. -                        return(PK_PARAM);  /* don't extract here by accident */
  923. -                    }
  924. -                    if (uO.pwdarg != (char *)NULL) {
  925. +            /* GRR:  yes, this is highly insecure, but dozens of people
  926. +             * have pestered us for this, so here we go... */
  927. +            case ('P'):
  928. +                if (negative) {   /* negative not allowed with -P passwd */
  929. +                    Info(slide, 0x401, ((char *)slide,
  930. +                      LoadFarString(MustGivePasswd)));
  931. +                    return(PK_PARAM);  /* don't extract here by accident */
  932. +                }
  933. +                if (uO.pwdarg != (char *)NULL) {
  934.  /*
  935. -                        GRR:  eventually support multiple passwords?
  936. +                    GRR:  eventually support multiple passwords?
  937. +                    Info(slide, 0x401, ((char *)slide,
  938. +                      LoadFarString(OnlyOnePasswd)));
  939. +                    return(PK_PARAM);
  940. +*/
  941. +                } else {
  942. +                    /* first check for "-Ppasswd", then for "-P passwd" */
  943. +                    uO.pwdarg = value;
  944. +                    if (uO.pwdarg == NULL || *uO.pwdarg == '\0') {
  945.                          Info(slide, 0x401, ((char *)slide,
  946. -                          LoadFarString(OnlyOnePasswd)));
  947. +                          LoadFarString(MustGivePasswd)));
  948.                          return(PK_PARAM);
  949. - */
  950. -                    } else {
  951. -                        /* first check for "-Ppasswd", then for "-P passwd" */
  952. -                        uO.pwdarg = s;
  953. -                        if (*uO.pwdarg == '\0') {
  954. -                            if (argc > 1) {
  955. -                                --argc;
  956. -                                uO.pwdarg = *++argv;
  957. -                                if (*uO.pwdarg == '-') {
  958. -                                    Info(slide, 0x401, ((char *)slide,
  959. -                                      LoadFarString(MustGivePasswd)));
  960. -                                    return(PK_PARAM);
  961. -                                }
  962. -                                /* else pwdarg points at decryption password */
  963. -                            } else {
  964. -                                Info(slide, 0x401, ((char *)slide,
  965. -                                  LoadFarString(MustGivePasswd)));
  966. -                                return(PK_PARAM);
  967. -                            }
  968. -                        }
  969. -                        /* pwdarg now points at decryption password (-Ppasswd or
  970. -                         *  -P passwd); point s at end of passwd to avoid mis-
  971. -                         *  interpretation of passwd characters as more options
  972. -                         */
  973. -                        if (*s != 0)
  974. -                            while (*++s != 0)
  975. -                                ;
  976. +                        /* else pwdarg points at decryption password */
  977.                      }
  978. -                    break;
  979. +                }
  980. +                break;
  981.  #endif /* CRYPT */
  982. -                case ('q'):    /* quiet:  fewer comments/messages */
  983. -                    if (negative) {
  984. -                        uO.qflag = MAX(uO.qflag-negative,0);
  985. -                        negative = 0;
  986. -                    } else
  987. -                        ++uO.qflag;
  988. -                    break;
  989. +            case ('q'):    /* quiet:  fewer comments/messages */
  990. +                if (negative) {
  991. +                    uO.qflag = MAX(uO.qflag-negative,0);
  992. +                    negative = 0;
  993. +                } else
  994. +                    ++uO.qflag;
  995. +                break;
  996.  #ifdef QDOS
  997. -                case ('Q'):   /* QDOS flags */
  998. -                    qlflag ^= strtol(s, &s, 10);
  999. -                    break;    /* we XOR this as we can config qlflags */
  1000. +            case ('Q'):   /* QDOS flags */
  1001. +                qlflag ^= strtol(value, &value, 10);
  1002. +                break;    /* we XOR this as we can config qlflags */
  1003.  #endif
  1004.  #ifdef TANDEM
  1005. -                case ('r'):    /* remove file extensions */
  1006. -                    if (negative)
  1007. -                        uO.rflag = FALSE, negative = 0;
  1008. -                    else
  1009. -                        uO.rflag = TRUE;
  1010. -                    break;
  1011. +            case ('r'):    /* remove file extensions */
  1012. +                if (negative)
  1013. +                    uO.rflag = FALSE, negative = 0;
  1014. +                else
  1015. +                    uO.rflag = TRUE;
  1016. +                break;
  1017.  #endif /* TANDEM */
  1018.  #ifdef DOS_FLX_NLM_OS2_W32
  1019. -                case ('s'):    /* spaces in filenames:  allow by default */
  1020. -                    if (negative)
  1021. -                        uO.sflag = FALSE, negative = 0;
  1022. -                    else
  1023. -                        uO.sflag = TRUE;
  1024. -                    break;
  1025. +            case ('s'):    /* spaces in filenames:  allow by default */
  1026. +                if (negative)
  1027. +                    uO.sflag = FALSE, negative = 0;
  1028. +                else
  1029. +                    uO.sflag = TRUE;
  1030. +                break;
  1031.  #endif /* DOS_FLX_NLM_OS2_W32 */
  1032.  #ifdef VMS
  1033. -                /* VMS:  extract "text" files in Stream_LF format (-a[a]) */
  1034. -                case ('S'):
  1035. -                    if (negative)
  1036. -                        uO.S_flag = FALSE, negative = 0;
  1037. -                    else
  1038. -                        uO.S_flag = TRUE;
  1039. -                    break;
  1040. +            /* VMS:  extract "text" files in Stream_LF format (-a[a]) */
  1041. +            case ('S'):
  1042. +                if (negative)
  1043. +                    uO.S_flag = FALSE, negative = 0;
  1044. +                else
  1045. +                    uO.S_flag = TRUE;
  1046. +                break;
  1047.  #endif /* VMS */
  1048. -                case ('t'):
  1049. -                    if (negative)
  1050. -                        uO.tflag = FALSE, negative = 0;
  1051. -                    else
  1052. -                        uO.tflag = TRUE;
  1053. -                    break;
  1054. +            case ('t'):
  1055. +                if (negative)
  1056. +                    uO.tflag = FALSE, negative = 0;
  1057. +                else
  1058. +                    uO.tflag = TRUE;
  1059. +                break;
  1060.  #ifdef TIMESTAMP
  1061. -                case ('T'):
  1062. -                    if (negative)
  1063. -                        uO.T_flag = FALSE, negative = 0;
  1064. -                    else
  1065. -                        uO.T_flag = TRUE;
  1066. -                    break;
  1067. -#endif
  1068. -                case ('u'):    /* update (extract only new and newer files) */
  1069. -                    if (negative)
  1070. -                        uO.uflag = FALSE, negative = 0;
  1071. -                    else
  1072. -                        uO.uflag = TRUE;
  1073. -                    break;
  1074. +            case ('T'):
  1075. +                if (negative)
  1076. +                    uO.T_flag = FALSE, negative = 0;
  1077. +                else
  1078. +                    uO.T_flag = TRUE;
  1079. +                break;
  1080. +#endif
  1081. +            case ('u'):    /* update (extract only new and newer files) */
  1082. +                if (negative)
  1083. +                    uO.uflag = FALSE, negative = 0;
  1084. +                else
  1085. +                    uO.uflag = TRUE;
  1086. +                break;
  1087.  #ifdef UNICODE_SUPPORT
  1088. -                case ('U'):    /* escape UTF-8, or disable UTF-8 support */
  1089. -                    if (negative) {
  1090. -                        uO.U_flag = MAX(uO.U_flag-negative,0);
  1091. -                        negative = 0;
  1092. -                    } else
  1093. -                        uO.U_flag++;
  1094. -                    break;
  1095. +            case ('U'):    /* escape UTF-8, or disable UTF-8 support */
  1096. +                if (negative)
  1097. +                    uO.U_flag = MAX(uO.U_flag - 1, 0);
  1098. +                else
  1099. +                    uO.U_flag++;
  1100. +                break;
  1101.  #else /* !UNICODE_SUPPORT */
  1102.  #ifndef CMS_MVS
  1103. -                case ('U'):    /* obsolete; to be removed in version 6.0 */
  1104. -                    if (negative)
  1105. -                        uO.L_flag = TRUE, negative = 0;
  1106. -                    else
  1107. -                        uO.L_flag = FALSE;
  1108. -                    break;
  1109. +            case ('U'):    /* obsolete; to be removed in version 6.0 */
  1110. +                if (negative)
  1111. +                    uO.L_flag = TRUE, negative = 0;
  1112. +                else
  1113. +                    uO.L_flag = FALSE;
  1114. +                break;
  1115.  #endif /* !CMS_MVS */
  1116.  #endif /* ?UNICODE_SUPPORT */
  1117.  #ifndef SFX
  1118. -                case ('v'):    /* verbose */
  1119. -                    if (negative) {
  1120. -                        uO.vflag = MAX(uO.vflag-negative,0);
  1121. -                        negative = 0;
  1122. -                    } else if (uO.vflag)
  1123. -                        ++uO.vflag;
  1124. -                    else
  1125. -                        uO.vflag = 2;
  1126. -                    break;
  1127. +            case ('v'):    /* verbose */
  1128. +                if (negative) {
  1129. +                    uO.vflag = MAX(uO.vflag-negative,0);
  1130. +                    negative = 0;
  1131. +                } else if (uO.vflag)
  1132. +                    ++uO.vflag;
  1133. +                else
  1134. +                    uO.vflag = 2;
  1135. +                break;
  1136.  #endif /* !SFX */
  1137.  #ifndef CMS_MVS
  1138. -                case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
  1139. -                    if (negative)
  1140. -                        uO.V_flag = FALSE, negative = 0;
  1141. -                    else
  1142. -                        uO.V_flag = TRUE;
  1143. -                    break;
  1144. +            case ('V'):    /* Version (retain VMS/DEC-20 file versions) */
  1145. +                if (negative)
  1146. +                    uO.V_flag = FALSE, negative = 0;
  1147. +                else
  1148. +                    uO.V_flag = TRUE;
  1149. +                break;
  1150.  #endif /* !CMS_MVS */
  1151.  #ifdef WILD_STOP_AT_DIR
  1152. -                case ('W'):    /* Wildcard interpretation (stop at '/'?) */
  1153. -                    if (negative)
  1154. -                        uO.W_flag = FALSE, negative = 0;
  1155. -                    else
  1156. -                        uO.W_flag = TRUE;
  1157. -                    break;
  1158. +            case ('W'):    /* Wildcard interpretation (stop at '/'?) */
  1159. +                if (negative)
  1160. +                    uO.W_flag = FALSE, negative = 0;
  1161. +                else
  1162. +                    uO.W_flag = TRUE;
  1163. +                break;
  1164.  #endif /* WILD_STOP_AT_DIR */
  1165. -                case ('x'):    /* extract:  default */
  1166. -#ifdef SFX
  1167. -                    /* when 'x' is the only option in this argument, and the
  1168. -                     * next arg is not an option, assume this initiates an
  1169. -                     * exclusion list (-x xlist):  terminate option-scanning
  1170. -                     * and leave uz_opts with argv still pointing to "-x";
  1171. -                     * the xlist is processed later
  1172. -                     */
  1173. -                    if (s - argv[0] == 2 && *s == '\0' &&
  1174. -                        argc > 1 && argv[1][0] != '-') {
  1175. -                        /* break out of nested loops without "++argv;--argc" */
  1176. -                        goto opts_done;
  1177. +            case ('x'):    /* extract:  default */
  1178. +                /* add -x file to linked list */
  1179. +
  1180. +                if (in_xfiles_count == 0) {
  1181. +                    /* first entry */
  1182. +                    if ((in_xfiles = (struct file_list *)
  1183. +                                     malloc(sizeof(struct file_list))
  1184. +                        ) == NULL) {
  1185. +                        Info(slide, 0x401, ((char *)slide,
  1186. +                          LoadFarString(NoMemArgsList)));
  1187. +                        return PK_MEM;
  1188. +                    }
  1189. +                    in_xfiles->name = value;
  1190. +                    in_xfiles->next = NULL;
  1191. +                    next_in_xfiles = in_xfiles;
  1192. +                } else {
  1193. +                    /* add next entry */
  1194. +                    if ((next_file = (struct file_list *)
  1195. +                                     malloc(sizeof(struct file_list))
  1196. +                        ) == NULL) {
  1197. +                        Info(slide, 0x401, ((char *)slide,
  1198. +                          LoadFarString(NoMemArgsList)));
  1199. +                        return PK_MEM;
  1200.                      }
  1201. +                    next_in_xfiles->next = next_file;
  1202. +                    next_file->name = value;
  1203. +                    next_file->next = NULL;
  1204. +                    next_in_xfiles = next_file;
  1205. +                }
  1206. +                in_xfiles_count++;
  1207. +
  1208. +#if 0
  1209. +#ifdef SFX
  1210. +                /* now get -x list one entry at a time */
  1211. +
  1212. +
  1213. +
  1214. +                /* when 'x' is the only option in this argument, and the
  1215. +                 * next arg is not an option, assume this initiates an
  1216. +                 * exclusion list (-x xlist):  terminate option-scanning
  1217. +                 * and leave uz_opts with argv still pointing to "-x";
  1218. +                 * the xlist is processed later
  1219. +                 */
  1220. +                if (s - argv[0] == 2 && *s == '\0' &&
  1221. +                    argc > 1 && argv[1][0] != '-') {
  1222. +                    /* break out of nested loops without "++argv;--argc" */
  1223. +                    goto opts_done;
  1224. +                }
  1225.  #endif /* SFX */
  1226. -                    break;
  1227. +#endif
  1228. +                break;
  1229.  #if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
  1230. -                case ('X'):   /* restore owner/protection info (need privs?) */
  1231. -                    if (negative) {
  1232. -                        uO.X_flag = MAX(uO.X_flag-negative,0);
  1233. -                        negative = 0;
  1234. -                    } else
  1235. -                        ++uO.X_flag;
  1236. -                    break;
  1237. +            case ('X'):   /* restore owner/protection info (need privs?) */
  1238. +                if (negative) {
  1239. +                    uO.X_flag = MAX(uO.X_flag-negative,0);
  1240. +                    negative = 0;
  1241. +                } else
  1242. +                    ++uO.X_flag;
  1243. +                break;
  1244.  #endif /* RESTORE_UIDGID || RESTORE_ACL */
  1245.  #ifdef VMS
  1246. -                case ('Y'):    /* Treat ".nnn" as ";nnn" version. */
  1247. -                    if (negative)
  1248. -                        uO.Y_flag = FALSE, negative = 0;
  1249. -                    else
  1250. -                        uO.Y_flag = TRUE;
  1251. -                    break;
  1252. +            case ('Y'):    /* Treat ".nnn" as ";nnn" version. */
  1253. +                if (negative)
  1254. +                    uO.Y_flag = FALSE, negative = 0;
  1255. +                else
  1256. +                    uO.Y_flag = TRUE;
  1257. +                break;
  1258.  #endif /* VMS */
  1259. -                case ('z'):    /* display only the archive comment */
  1260. -                    if (negative) {
  1261. -                        uO.zflag = MAX(uO.zflag-negative,0);
  1262. -                        negative = 0;
  1263. -                    } else
  1264. -                        ++uO.zflag;
  1265. -                    break;
  1266. +            case ('z'):    /* display only the archive comment */
  1267. +                if (negative) {
  1268. +                    uO.zflag = MAX(uO.zflag-negative,0);
  1269. +                    negative = 0;
  1270. +                } else
  1271. +                    ++uO.zflag;
  1272. +                break;
  1273.  #ifndef SFX
  1274. -                case ('Z'):    /* should have been first option (ZipInfo) */
  1275. -                    Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
  1276. -                    error = TRUE;
  1277. -                    break;
  1278. +            case ('Z'):    /* should have been first option (ZipInfo) */
  1279. +                Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
  1280. +                error = TRUE;
  1281. +                break;
  1282.  #endif /* !SFX */
  1283.  #ifdef VMS
  1284. -                case ('2'):    /* Force ODS2-compliant names. */
  1285. -                    if (negative)
  1286. -                        uO.ods2_flag = FALSE, negative = 0;
  1287. -                    else
  1288. -                        uO.ods2_flag = TRUE;
  1289. -                    break;
  1290. +            case ('2'):    /* Force ODS2-compliant names. */
  1291. +                if (negative)
  1292. +                    uO.ods2_flag = FALSE, negative = 0;
  1293. +                else
  1294. +                    uO.ods2_flag = TRUE;
  1295. +                break;
  1296.  #endif /* VMS */
  1297.  #ifdef DOS_H68_OS2_W32
  1298. -                case ('$'):
  1299. -                    if (negative) {
  1300. -                        uO.volflag = MAX(uO.volflag-negative,0);
  1301. -                        negative = 0;
  1302. -                    } else
  1303. -                        ++uO.volflag;
  1304. -                    break;
  1305. +            case ('$'):
  1306. +                if (negative) {
  1307. +                    uO.volflag = MAX(uO.volflag-negative,0);
  1308. +                    negative = 0;
  1309. +                } else
  1310. +                    ++uO.volflag;
  1311. +                break;
  1312.  #endif /* DOS_H68_OS2_W32 */
  1313.  #if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
  1314. -                case (':'):    /* allow "parent dir" path components */
  1315. -                    if (negative) {
  1316. -                        uO.ddotflag = MAX(uO.ddotflag-negative,0);
  1317. -                        negative = 0;
  1318. -                    } else
  1319. -                        ++uO.ddotflag;
  1320. -                    break;
  1321. +            case (':'):    /* allow "parent dir" path components */
  1322. +                if (negative) {
  1323. +                    uO.ddotflag = MAX(uO.ddotflag-negative,0);
  1324. +                    negative = 0;
  1325. +                } else
  1326. +                    ++uO.ddotflag;
  1327. +                break;
  1328.  #endif /* !RISCOS && !CMS_MVS && !TANDEM */
  1329.  #ifdef UNIX
  1330. -                case ('^'):    /* allow control chars in filenames */
  1331. -                    if (negative) {
  1332. -                        uO.cflxflag = MAX(uO.cflxflag-negative,0);
  1333. -                        negative = 0;
  1334. -                    } else
  1335. -                        ++uO.cflxflag;
  1336. -                    break;
  1337. +            case ('^'):    /* allow control chars in filenames */
  1338. +                if (negative) {
  1339. +                    uO.cflxflag = MAX(uO.cflxflag-negative,0);
  1340. +                    negative = 0;
  1341. +                } else
  1342. +                    ++uO.cflxflag;
  1343. +                break;
  1344.  #endif /* UNIX */
  1345. -                default:
  1346. -                    error = TRUE;
  1347. -                    break;
  1348. -
  1349. -            } /* end switch */
  1350. -        } /* end while (not end of argument string) */
  1351. -    } /* end while (not done with switches) */
  1352. +            case o_NON_OPTION_ARG:
  1353. +                /* not an option */
  1354. +                /* no more options as permuting */
  1355. +
  1356. +
  1357. +                if (G.wildzipfn == NULL) {
  1358. +                    /* first non-option argument is zip file */
  1359. +                    G.wildzipfn = value;
  1360. +
  1361. +                } else {
  1362. +                    /* add include file to list */
  1363. +                    if (in_files_count == 0) {
  1364. +                        /* first entry */
  1365. +                        if ((next_file = (struct file_list *)
  1366. +                                         malloc(sizeof(struct file_list))
  1367. +                            ) == NULL) {
  1368. +                            Info(slide, 0x401, ((char *)slide,
  1369. +                              LoadFarString(NoMemArgsList)));
  1370. +                            return PK_MEM;
  1371. +                        }
  1372. +                        next_file->name = value;
  1373. +                        next_file->next = NULL;
  1374. +                        in_files = next_file;
  1375. +                        next_in_files = next_file;
  1376. +                    } else {
  1377. +                        /* add next entry */
  1378. +                        if ((next_file = (struct file_list *)
  1379. +                                         malloc(sizeof(struct file_list))
  1380. +                            ) == NULL) {
  1381. +                            Info(slide, 0x401, ((char *)slide,
  1382. +                              LoadFarString(NoMemArgsList)));
  1383. +                            return PK_MEM;
  1384. +                        }
  1385. +                        next_in_files->next = next_file;
  1386. +                        next_file->name = value;
  1387. +                        next_file->next = NULL;
  1388. +                        next_in_files = next_file;
  1389. +                    }
  1390. +                    in_files_count++;
  1391. +                }
  1392. +                break;
  1393. +            default:
  1394. +                error = TRUE;
  1395. +                break;
  1396. +
  1397. +        } /* end switch */
  1398. +    } /* get_option() */
  1399. +
  1400. +
  1401. +    /* convert files and xfiles lists to arrays */
  1402. +
  1403. +    /* convert files list to array */
  1404. +    if (in_files_count) {
  1405. +      if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))
  1406. +          ) == NULL) {
  1407. +          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));
  1408. +          return PK_MEM;
  1409. +      }
  1410. +      file_count = 0;
  1411. +      for (next_file = in_files; next_file;) {
  1412. +          G.pfnames[file_count] = next_file->name;
  1413. +          in_files = next_file;
  1414. +          next_file = next_file->next;
  1415. +          free(in_files);
  1416. +          file_count++;
  1417. +      }
  1418. +      G.pfnames[file_count] = NULL;
  1419. +      G.filespecs = in_files_count;
  1420. +    }
  1421. +
  1422. +    /* convert xfiles list to array */
  1423. +    if (in_xfiles_count) {
  1424. +      if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))
  1425. +          ) == NULL) {
  1426. +          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));
  1427. +          return PK_MEM;
  1428. +      }
  1429. +      file_count = 0;
  1430. +      for (next_file = in_xfiles; next_file;) {
  1431. +          G.pxnames[file_count] = next_file->name;
  1432. +          in_xfiles = next_file;
  1433. +          next_file = next_file->next;
  1434. +          free(in_xfiles);
  1435. +          file_count++;
  1436. +      }
  1437. +      G.pxnames[file_count] = NULL;
  1438. +      G.xfilespecs = in_xfiles_count;
  1439. +    }
  1440. +
  1441. +    if (in_files_count || in_xfiles_count) {
  1442. +        G.process_all_files = FALSE;
  1443. +    } else {
  1444. +        G.process_all_files = TRUE;      /* for speed */
  1445. +    }
  1446. +
  1447. +
  1448. +    /* it's possible the arg count could have been changed by get_option() */
  1449. +    argc = arg_count(args);
  1450. +
  1451. +
  1452.  
  1453.  /*---------------------------------------------------------------------------
  1454. @@ -1774,7 +2240,77 @@
  1455.    ---------------------------------------------------------------------------*/
  1456.  
  1457. +    if ((uO.cflag && (uO.tflag || uO.uflag)) ||
  1458. +        (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
  1459. +    {
  1460. +        Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
  1461. +        error = TRUE;
  1462. +    }
  1463. +    if (uO.aflag > 2)
  1464. +        uO.aflag = 2;
  1465. +#ifdef VMS
  1466. +    if (uO.bflag > 2)
  1467. +        uO.bflag = 2;
  1468. +    /* Clear -s flag when converting text files. */
  1469. +    if (uO.aflag <= 0)
  1470. +        uO.S_flag = 0;
  1471. +#endif /* VMS */
  1472. +    if (uO.overwrite_all && uO.overwrite_none) {
  1473. +        Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
  1474. +        uO.overwrite_all = FALSE;
  1475. +    }
  1476. +#ifdef MORE
  1477. +    if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
  1478. +        G.M_flag = 0;
  1479. +#endif
  1480. +
  1481. +#ifdef SFX
  1482. +    if (error)
  1483. +#else
  1484. +    if ((G.wildzipfn == NULL) || error)
  1485. +#endif
  1486. +    {
  1487. +        /* tell caller to exit */
  1488. +        if (argc <= 2)
  1489. +            argc = -1;
  1490. +
  1491. +        *pargc = argc;
  1492. +        *pargv = args;
  1493. +#ifndef SFX
  1494. +        if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
  1495. +            show_version_info(__G);
  1496. +            return PK_OK;
  1497. +        }
  1498. +        if (!G.noargs && !error)
  1499. +            error = TRUE;       /* had options (not -h or -v) but no zipfile */
  1500. +#endif /* !SFX */
  1501. +        return USAGE(error);
  1502. +    }
  1503. +
  1504.  #ifdef SFX
  1505. -opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
  1506. +    /* print our banner unless we're being fairly quiet */
  1507. +    if (uO.qflag < 2)
  1508. +        Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
  1509. +          UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
  1510. +          LoadFarStringSmall(VersionDate)));
  1511. +#ifdef BETA
  1512. +    /* always print the beta warning:  no unauthorized distribution!! */
  1513. +    Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
  1514. +      "SFX"));
  1515. +#endif
  1516. +#endif /* SFX */
  1517. +
  1518. +    if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
  1519. +#ifdef TIMESTAMP
  1520. +                                                     || uO.T_flag
  1521.  #endif
  1522. +                                                                 )
  1523. +        G.extract_flag = FALSE;
  1524. +    else
  1525. +        G.extract_flag = TRUE;
  1526. +
  1527. +#if 0
  1528. +# ifdef SFX
  1529. +opts_done:  /* yes, very ugly...but only used by UnZipSFX with -x xlist */
  1530. +# endif
  1531.  
  1532.      if ((uO.cflag && (uO.tflag || uO.uflag)) ||
  1533. @@ -1786,5 +2322,5 @@
  1534.      if (uO.aflag > 2)
  1535.          uO.aflag = 2;
  1536. -#ifdef VMS
  1537. +# ifdef VMS
  1538.      if (uO.bflag > 2)
  1539.          uO.bflag = 2;
  1540. @@ -1792,23 +2328,23 @@
  1541.      if (uO.aflag <= 0)
  1542.          uO.S_flag = 0;
  1543. -#endif /* VMS */
  1544. +# endif /* VMS */
  1545.      if (uO.overwrite_all && uO.overwrite_none) {
  1546.          Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
  1547.          uO.overwrite_all = FALSE;
  1548.      }
  1549. -#ifdef MORE
  1550. +# ifdef MORE
  1551.      if (G.M_flag && !isatty(1))  /* stdout redirected: "more" func. useless */
  1552.          G.M_flag = 0;
  1553. -#endif
  1554. +# endif
  1555.  
  1556. -#ifdef SFX
  1557. +# ifdef SFX
  1558.      if (error)
  1559. -#else
  1560. +# else
  1561.      if ((argc-- == 0) || error)
  1562. -#endif
  1563. +# endif
  1564.      {
  1565.          *pargc = argc;
  1566. -        *pargv = argv;
  1567. -#ifndef SFX
  1568. +        *pargv = args;
  1569. +# ifndef SFX
  1570.          if (uO.vflag >= 2 && argc == -1) {              /* "unzip -v" */
  1571.              show_version_info(__G);
  1572. @@ -1817,9 +2353,9 @@
  1573.          if (!G.noargs && !error)
  1574.              error = TRUE;       /* had options (not -h or -v) but no zipfile */
  1575. -#endif /* !SFX */
  1576. +# endif /* !SFX */
  1577.          return USAGE(error);
  1578.      }
  1579.  
  1580. -#ifdef SFX
  1581. +# ifdef SFX
  1582.      /* print our banner unless we're being fairly quiet */
  1583.      if (uO.qflag < 2)
  1584. @@ -1827,22 +2363,23 @@
  1585.            UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
  1586.            LoadFarStringSmall(VersionDate)));
  1587. -#ifdef BETA
  1588. +# ifdef BETA
  1589.      /* always print the beta warning:  no unauthorized distribution!! */
  1590.      Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
  1591.        "SFX"));
  1592. -#endif
  1593. -#endif /* SFX */
  1594. +# endif
  1595. +# endif /* SFX */
  1596.  
  1597.      if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
  1598. -#ifdef TIMESTAMP
  1599. +# ifdef TIMESTAMP
  1600.                                                       || uO.T_flag
  1601. -#endif
  1602. +# endif
  1603.                                                                   )
  1604.          G.extract_flag = FALSE;
  1605.      else
  1606.          G.extract_flag = TRUE;
  1607. +#endif
  1608.  
  1609.      *pargc = argc;
  1610. -    *pargv = argv;
  1611. +    *pargv = args;
  1612.      return PK_OK;
  1613.  
  1614. @@ -2314,2 +2851,1366 @@
  1615.  #endif /* !SFX */
  1616.  #endif /* !WINDLL */
  1617. +
  1618. +
  1619. +
  1620. +
  1621. +
  1622. +
  1623. +/*---------------------------------------------------------------
  1624. + *  Long option support
  1625. + *  8/23/2003
  1626. + *  Updated 3/1/2008 to support UnZip
  1627. + *
  1628. + *  Defines function get_option() to get and process the command
  1629. + *  line options and arguments from argv[].  The caller calls
  1630. + *  get_option() in a loop to get either one option and possible
  1631. + *  value or a non-option argument each loop.
  1632. + *
  1633. + *  This version has been modified to work with UnZip and ZipInfo.
  1634. + *  the major changes are removing the error returns, instead
  1635. + *  passing back error codes for errors, and supporting separate
  1636. + *  groups of options for UnZip and ZipInfo and selecting the option
  1637. + *  group by an argument.
  1638. + *
  1639. + *  This version does not include argument file support and can
  1640. + *  work directly on argv.  The argument file code complicates things and
  1641. + *  it seemed best to leave it out for now.  If argument file support
  1642. + *  (reading in command line arguments stored in a file and inserting into
  1643. + *  command line where @filename is found) is added later the arguments
  1644. + *  can change and a freeable copy of argv will be needed and can be
  1645. + *  created using copy_args in the left out code.
  1646. + *
  1647. + *  Supports short and long options as defined in the array options[]
  1648. + *  in zip.c, multiple short options in an argument (like -jlv), long
  1649. + *  option abbreviation (like --te for --temp-file if --te unique),
  1650. + *  short and long option values (like -b filename or --temp-file filename
  1651. + *  or --temp-file=filename), optional and required values, option negation
  1652. + *  by trailing - (like -S- to not include hidden and system files in MSDOS),
  1653. + *  value lists (like -x a b c), argument permuting (returning all options
  1654. + *  and values before any non-option arguments), and argument files (where
  1655. + *  any non-option non-value argument in form @path gets substituted with
  1656. + *  the white space separated arguments in the text file at path).  In this
  1657. + *  version argument file support has been removed to simplify development
  1658. + *  but may be added later.
  1659. + *
  1660. + *  E. Gordon
  1661. + */
  1662. +
  1663. +
  1664. +/* message output - char casts are needed to handle constants */
  1665. +#define oWARN(message) Info(slide, 0x401, ((char *)slide, (char *)message))
  1666. +
  1667. +
  1668. +
  1669. +/* Although the below provides some support for multibyte characters
  1670. +   the proper thing to do may be to use wide characters and support
  1671. +   Unicode.  May get to it soon.  Wide support would likely require
  1672. +   the ability to convert the command line to wide strings, which most
  1673. +   modern OS should support now.  EG
  1674. + */
  1675. +
  1676. +/* For now stay with multi-byte characters.  May support wide characters
  1677. +   in Zip 3.1 and UnZip 6.1.
  1678. + */
  1679. +
  1680. +/* multibyte character set support
  1681. +   Multibyte characters use typically two or more sequential bytes
  1682. +   to represent additional characters than can fit in a single byte
  1683. +   character set.  The code used here is based on the ANSI mblen function. */
  1684. +#define MB_CLEN(ptr) CLEN(ptr)
  1685. +#define MB_NEXTCHAR(ptr) PREINCSTR(ptr)
  1686. +
  1687. +
  1688. +/* constants */
  1689. +
  1690. +/* function get_args_from_arg_file() can return this in depth parameter */
  1691. +#define ARG_FILE_ERR -1
  1692. +
  1693. +/* internal settings for optchar */
  1694. +#define SKIP_VALUE_ARG   -1
  1695. +#define THIS_ARG_DONE    -2
  1696. +#define START_VALUE_LIST -3
  1697. +#define IN_VALUE_LIST    -4
  1698. +#define NON_OPTION_ARG   -5
  1699. +#define STOP_VALUE_LIST  -6
  1700. +/* 7/25/04 EG */
  1701. +#define READ_REST_ARGS_VERBATIM -7
  1702. +
  1703. +
  1704. +/* global veriables */
  1705. +
  1706. +int enable_permute = 1;                     /* yes - return options first */
  1707. +/* 7/25/04 EG */
  1708. +int doubledash_ends_options = 1;            /* when -- what follows are not options */
  1709. +
  1710. +/* buffer for error messages (this sizing is a guess but must hold 2 paths) */
  1711. +#define OPTIONERR_BUF_SIZE (80+ 2*FILENAME_MAX)
  1712. +char optionerrbuf[OPTIONERR_BUF_SIZE + 1];
  1713. +
  1714. +/* error messages */
  1715. +static ZCONST char Far op_not_neg_err[] =
  1716. +   "option %s not negatable";
  1717. +static ZCONST char Far op_req_val_err[] =
  1718. +   "option %s requires a value";
  1719. +static ZCONST char Far op_no_allow_val_err[] =
  1720. +   "option %s does not allow a value";
  1721. +static ZCONST char Far sh_op_not_sup_err[] =
  1722. +   "short option '%c' not supported";
  1723. +static ZCONST char Far oco_req_val_err[] =
  1724. +   "option %s requires one character value";
  1725. +static ZCONST char Far oco_no_mbc_err[] =
  1726. +   "option %s does not support multibyte values";
  1727. +static ZCONST char Far num_req_val_err[] =
  1728. +   "option %s requires number value";
  1729. +static ZCONST char Far long_op_ambig_err[] =
  1730. +   "long option '%s' ambiguous";
  1731. +static ZCONST char Far long_op_not_sup_err[] =
  1732. +   "long option '%s' not supported";
  1733. +
  1734. +static ZCONST char Far no_arg_files_err[] = "argument files not enabled\n";
  1735. +
  1736. +
  1737. +/* below removed as only used for processing argument files */
  1738. +
  1739. +/* get_nextarg */
  1740. +/* get_args_from_string */
  1741. +/* get_args_from_arg_file */
  1742. +
  1743. +
  1744. +/* copy error, option name, and option description if any to buf */
  1745. +static int optionerr(options, buf, err, optind, islong)
  1746. +  struct option_struct *options;
  1747. +  char *buf;
  1748. +  ZCONST char Far *err;
  1749. +  int optind;
  1750. +  int islong;
  1751. +{
  1752. +  char optname[50];
  1753. +
  1754. +  if (options[optind].name && options[optind].name[0] != '\0') {
  1755. +    sprintf(optname, "'%s' (%s)",
  1756. +            LoadFarStringSmall2(islong ? options[optind].longopt
  1757. +                                       : options[optind].shortopt),
  1758. +            LoadFarStringSmall(options[optind].name));
  1759. +  } else {
  1760. +    sprintf(optname, "'%s'",
  1761. +            LoadFarStringSmall2(islong ? options[optind].longopt
  1762. +                                       : options[optind].shortopt));
  1763. +  }
  1764. +  sprintf(buf, LoadFarStringSmall(err), optname);
  1765. +  return 0;
  1766. +}
  1767. +
  1768. +
  1769. +/* copy_args
  1770. + *
  1771. + * Copy arguments in args, allocating storage with malloc.
  1772. + * Copies until a NULL argument is found or until max_args args
  1773. + * including args[0] are copied.  Set max_args to 0 to copy
  1774. + * until NULL.  Always terminates returned args[] with NULL arg.
  1775. + *
  1776. + * Any argument in the returned args can be freed with free().  Any
  1777. + * freed argument should be replaced with either another string
  1778. + * allocated with malloc or by NULL if last argument so that free_args
  1779. + * will properly work.
  1780. + */
  1781. +char **copy_args(args, max_args)
  1782. +  char **args;
  1783. +  int max_args;
  1784. +{
  1785. +  int j;
  1786. +  char **new_args;
  1787. +
  1788. +  if (args == NULL) {
  1789. +    return NULL;
  1790. +  }
  1791. +
  1792. +  /* count args */
  1793. +  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ;
  1794. +
  1795. +  if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) {
  1796. +    oWARN("memory - ca");
  1797. +    return NULL;
  1798. +  }
  1799. +
  1800. +  for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) {
  1801. +    if (args[j] == NULL) {
  1802. +      /* null argument is end of args */
  1803. +      new_args[j] = NULL;
  1804. +      break;
  1805. +    }
  1806. +    if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) {
  1807. +      free_args(new_args);
  1808. +      oWARN("memory - ca");
  1809. +      return NULL;
  1810. +    }
  1811. +    strcpy(new_args[j], args[j]);
  1812. +  }
  1813. +  new_args[j] = NULL;
  1814. +
  1815. +  return new_args;
  1816. +}
  1817. +
  1818. +
  1819. +/* count args - count args in argv like array */
  1820. +int arg_count(args)
  1821. +  char **args;
  1822. +{
  1823. +  int i;
  1824. +
  1825. +  if (args == NULL) {
  1826. +    return 0;
  1827. +  }
  1828. +
  1829. +  for (i = 0; args[i]; i++) {
  1830. +  }
  1831. +  return i;
  1832. +}
  1833. +
  1834. +
  1835. +/* free args - free args created with one of these functions */
  1836. +int free_args(args)
  1837. +  char **args;
  1838. +{
  1839. +  int i;
  1840. +
  1841. +  if (args == NULL) {
  1842. +    return 0;
  1843. +  }
  1844. +
  1845. +  for (i = 0; args[i]; i++) {
  1846. +    free(args[i]);
  1847. +  }
  1848. +  free(args);
  1849. +  return i;
  1850. +}
  1851. +
  1852. +
  1853. +/* insert_arg
  1854. + *
  1855. + * Insert the argument arg into the array args before argument at_arg.
  1856. + * If at_arg = -1 then append to end.
  1857. + * Return the new count of arguments (argc).
  1858. + *
  1859. + * If free_args is true, this function frees the old args array
  1860. + * (but not the component strings).  DO NOT set free_args on original
  1861. + * argv but only on args allocated with malloc.
  1862. + */
  1863. +
  1864. +int insert_arg(pargs, arg, at_arg, free_args)
  1865. +   char ***pargs;
  1866. +   ZCONST char *arg;
  1867. +   int at_arg;
  1868. +   int free_args;
  1869. +{
  1870. +   char *newarg = NULL;
  1871. +   char **args;
  1872. +   char **newargs = NULL;
  1873. +   int argnum;
  1874. +   int newargnum;
  1875. +   int argcnt;
  1876. +   int newargcnt;
  1877. +
  1878. +   if (pargs == NULL) {
  1879. +     return 0;
  1880. +   }
  1881. +   args = *pargs;
  1882. +
  1883. +   /* count args */
  1884. +   if (args == NULL) {
  1885. +     argcnt = 0;
  1886. +   } else {
  1887. +     for (argcnt = 0; args[argcnt]; argcnt++) ;
  1888. +   }
  1889. +   if (arg == NULL) {
  1890. +     /* done */
  1891. +     return argcnt;
  1892. +   }
  1893. +   if (at_arg == -1) {
  1894. +     at_arg = argcnt;
  1895. +   }
  1896. +   newargcnt = argcnt + 1;
  1897. +
  1898. +   /* get storage for new args */
  1899. +   if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL)
  1900. +   {
  1901. +     oWARN("memory - ia");
  1902. +     return 0;
  1903. +   }
  1904. +
  1905. +   /* copy argument pointers from args to position at_arg, copy the new arg,
  1906. +      then copy the rest of the args */
  1907. +   argnum = 0;
  1908. +   newargnum = 0;
  1909. +   if (args) {
  1910. +     for (; args[argnum] && argnum < at_arg; argnum++) {
  1911. +       newargs[newargnum++] = args[argnum];
  1912. +     }
  1913. +   }
  1914. +   /* copy new arg */
  1915. +   if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) {
  1916. +     oWARN("memory - ia");
  1917. +     return 0;
  1918. +   }
  1919. +   strcpy(newarg, arg);
  1920. +
  1921. +   newargs[newargnum++] = newarg;
  1922. +   if (args) {
  1923. +     for ( ; args[argnum]; argnum++) {
  1924. +       newargs[newargnum++] = args[argnum];
  1925. +     }
  1926. +   }
  1927. +   newargs[newargnum] = NULL;
  1928. +
  1929. +   /* free old args array but not component strings - this assumes that
  1930. +      args was allocated with malloc as copy_args does.  DO NOT DO THIS
  1931. +      on the original argv.
  1932. +    */
  1933. +   if (free_args)
  1934. +     free(args);
  1935. +
  1936. +   *pargs = newargs;
  1937. +
  1938. +   return newargnum;
  1939. +}
  1940. +
  1941. +/* ------------------------------------- */
  1942. +
  1943. +/* get_shortopt
  1944. + *
  1945. + * Get next short option from arg.  The state is stored in argnum, optchar, and
  1946. + * option_num so no static storage is used.  Returns the option_ID.
  1947. + *
  1948. + * parameters:
  1949. + *    option_group - either UZO for UnZip options or ZIO for ZipInfo options
  1950. + *    args         - argv array of arguments
  1951. + *    argnum       - index of current arg in args
  1952. + *    optchar      - pointer to index of next char to process.  Can be 0 or
  1953. + *                   const defined at top of this file like THIS_ARG_DONE
  1954. + *    negated      - on return pointer to int set to 1 if option negated
  1955. + *                   or 0 otherwise
  1956. + *    value        - on return pointer to string set to value of option if any
  1957. + *                   or NULL if none.  If value is returned then the caller
  1958. + *                   should free() it when not needed anymore.
  1959. + *    option_num   - pointer to index in options[] of returned option or
  1960. + *                   o_NO_OPTION_MATCH if none.  Do not change as used by
  1961. + *                   value lists.
  1962. + *    depth        - recursion depth (0 at top level, 1 or more in arg files)
  1963. + */
  1964. +static unsigned long get_shortopt(option_group, args, argnum, optchar, negated,
  1965. +                                  value, option_num, depth)
  1966. +  int option_group;
  1967. +  ZCONST char **args;
  1968. +  int argnum;
  1969. +  int *optchar;
  1970. +  int *negated;
  1971. +  char **value;
  1972. +  int *option_num;
  1973. +  int depth;
  1974. +{
  1975. +  ZCONST char *shortopt;
  1976. +  int clen;
  1977. +  ZCONST char *nextchar;
  1978. +  ZCONST char *s;
  1979. +  ZCONST char *start;
  1980. +  int op;
  1981. +  ZCONST char *arg;
  1982. +  int match = -1;
  1983. +
  1984. +
  1985. +  /* get arg */
  1986. +  arg = args[argnum];
  1987. +  /* current char in arg */
  1988. +  nextchar = arg + (*optchar);
  1989. +  clen = MB_CLEN(nextchar);
  1990. +  /* next char in arg */
  1991. +  (*optchar) +=  clen;
  1992. +  /* get first char of short option */
  1993. +  shortopt = arg + (*optchar);
  1994. +  /* no value */
  1995. +  *value = NULL;
  1996. +
  1997. +  if (*shortopt == '\0') {
  1998. +    /* no more options in arg */
  1999. +    *optchar = 0;
  2000. +    *option_num = o_NO_OPTION_MATCH;
  2001. +    return 0;
  2002. +  }
  2003. +
  2004. +  /* look for match in options */
  2005. +  clen = MB_CLEN(shortopt);
  2006. +  for (op = 0; options[op].option_ID; op++) {
  2007. +    /* Only look at options in this option group */
  2008. +    if (options[op].option_group == option_group) {
  2009. +      s = options[op].shortopt;
  2010. +      if (s && s[0] == shortopt[0]) {
  2011. +        if (s[1] == '\0' && clen == 1) {
  2012. +          /* single char match */
  2013. +          match = op;
  2014. +        } else {
  2015. +          /* 2 wide short opt.  Could support more chars but should use long opts instead */
  2016. +          if (s[1] == shortopt[1]) {
  2017. +            /* match 2 char short opt or 2 byte char */
  2018. +            match = op;
  2019. +            if (clen == 1) (*optchar)++;
  2020. +            break;
  2021. +          }
  2022. +        }
  2023. +      }
  2024. +    }
  2025. +  }
  2026. +
  2027. +  if (match > -1) {
  2028. +    /* match */
  2029. +    clen = MB_CLEN(shortopt);
  2030. +    nextchar = arg + (*optchar) + clen;
  2031. +    /* check for trailing dash negating option */
  2032. +    if (*nextchar == '-') {
  2033. +      /* negated */
  2034. +      if (options[match].negatable == o_NOT_NEGATABLE) {
  2035. +        if (options[match].value_type == o_NO_VALUE) {
  2036. +          optionerr(options, optionerrbuf, op_not_neg_err, match, 0);
  2037. +          if (depth > 0) {
  2038. +            /* unwind */
  2039. +            oWARN(optionerrbuf);
  2040. +            return o_ARG_FILE_ERR;
  2041. +          } else {
  2042. +            oWARN(optionerrbuf);
  2043. +            return o_BAD_ERR;
  2044. +          }
  2045. +        }
  2046. +      } else {
  2047. +        *negated = 1;
  2048. +        /* set up to skip negating dash */
  2049. +        (*optchar) += clen;
  2050. +        clen = 1;
  2051. +      }
  2052. +    }
  2053. +
  2054. +    /* value */
  2055. +    clen = MB_CLEN(arg + (*optchar));
  2056. +    /* optional value, one char value, and number value must follow option */
  2057. +    if (options[match].value_type == o_ONE_CHAR_VALUE) {
  2058. +      /* one char value */
  2059. +      if (arg[(*optchar) + clen]) {
  2060. +        /* has value */
  2061. +        if (MB_CLEN(arg + (*optchar) + clen) > 1) {
  2062. +          /* multibyte value not allowed for now */
  2063. +          optionerr(options, optionerrbuf, oco_no_mbc_err, match, 0);
  2064. +          if (depth > 0) {
  2065. +            /* unwind */
  2066. +            oWARN(optionerrbuf);
  2067. +            return o_ARG_FILE_ERR;
  2068. +          } else {
  2069. +            oWARN(optionerrbuf);
  2070. +            return o_BAD_ERR;
  2071. +          }
  2072. +        }
  2073. +        if ((*value = (char *) malloc(2)) == NULL) {
  2074. +          oWARN("memory - gso");
  2075. +          return o_BAD_ERR;
  2076. +        }
  2077. +        (*value)[0] = *(arg + (*optchar) + clen);
  2078. +        (*value)[1] = '\0';
  2079. +        *optchar += clen;
  2080. +        clen = 1;
  2081. +      } else {
  2082. +        /* one char values require a value */
  2083. +        optionerr(options, optionerrbuf, oco_req_val_err, match, 0);
  2084. +        if (depth > 0) {
  2085. +          oWARN(optionerrbuf);
  2086. +          return o_ARG_FILE_ERR;
  2087. +        } else {
  2088. +          oWARN(optionerrbuf);
  2089. +          return o_BAD_ERR;
  2090. +        }
  2091. +      }
  2092. +    } else if (options[match].value_type == o_NUMBER_VALUE) {
  2093. +      /* read chars until end of number */
  2094. +      start = arg + (*optchar) + clen;
  2095. +      if (*start == '+' || *start == '-') {
  2096. +        start++;
  2097. +      }
  2098. +      s = start;
  2099. +      for (; isdigit(*s); MB_NEXTCHAR(s)) ;
  2100. +      if (s == start) {
  2101. +        /* no digits */
  2102. +        optionerr(options, optionerrbuf, num_req_val_err, match, 0);
  2103. +        if (depth > 0) {
  2104. +          oWARN(optionerrbuf);
  2105. +          return o_ARG_FILE_ERR;
  2106. +        } else {
  2107. +          oWARN(optionerrbuf);
  2108. +          return o_BAD_ERR;
  2109. +        }
  2110. +      }
  2111. +      start = arg + (*optchar) + clen;
  2112. +      if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) {
  2113. +        oWARN("memory - gso");
  2114. +        return o_BAD_ERR;
  2115. +      }
  2116. +      *optchar += (int)(s - start);
  2117. +      strncpy(*value, start, (int)(s - start));
  2118. +      (*value)[(int)(s - start)] = '\0';
  2119. +      clen = MB_CLEN(s);
  2120. +    } else if (options[match].value_type == o_OPTIONAL_VALUE) {
  2121. +      /* optional value */
  2122. +      /* This seemed inconsistent so now if no value attached to argument look
  2123. +         to the next argument if that argument is not an option for option
  2124. +         value - 11/12/04 EG */
  2125. +      if (arg[(*optchar) + clen]) {
  2126. +        /* has value */
  2127. +        /* add support for optional = - 2/6/05 EG */
  2128. +        if (arg[(*optchar) + clen] == '=') {
  2129. +          /* skip = */
  2130. +          clen++;
  2131. +        }
  2132. +        if (arg[(*optchar) + clen]) {
  2133. +          if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))
  2134. +              == NULL) {
  2135. +            oWARN("memory - gso");
  2136. +            return o_BAD_ERR;
  2137. +          }
  2138. +          strcpy(*value, arg + (*optchar) + clen);
  2139. +        }
  2140. +        *optchar = THIS_ARG_DONE;
  2141. +      } else if (args[argnum + 1] && args[argnum + 1][0] != '-') {
  2142. +        /* use next arg for value */
  2143. +        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {
  2144. +          oWARN("memory - gso");
  2145. +          return o_BAD_ERR;
  2146. +        }
  2147. +        /* using next arg as value */
  2148. +        strcpy(*value, args[argnum + 1]);
  2149. +        *optchar = SKIP_VALUE_ARG;
  2150. +      }
  2151. +    } else if (options[match].value_type == o_REQUIRED_VALUE ||
  2152. +               options[match].value_type == o_VALUE_LIST) {
  2153. +      /* see if follows option */
  2154. +      if (arg[(*optchar) + clen]) {
  2155. +        /* has value following option as -ovalue */
  2156. +        /* add support for optional = - 6/5/05 EG */
  2157. +        if (arg[(*optchar) + clen] == '=') {
  2158. +          /* skip = */
  2159. +          clen++;
  2160. +        }
  2161. +        if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))
  2162. +            == NULL) {
  2163. +          oWARN("memory - gso");
  2164. +          return o_BAD_ERR;
  2165. +        }
  2166. +        strcpy(*value, arg + (*optchar) + clen);
  2167. +        *optchar = THIS_ARG_DONE;
  2168. +      } else {
  2169. +        /* use next arg for value */
  2170. +        if (args[argnum + 1]) {
  2171. +          if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1))
  2172. +              == NULL) {
  2173. +            oWARN("memory - gso");
  2174. +            return o_BAD_ERR;
  2175. +          }
  2176. +          strcpy(*value, args[argnum + 1]);
  2177. +          if (options[match].value_type == o_VALUE_LIST) {
  2178. +            *optchar = START_VALUE_LIST;
  2179. +          } else {
  2180. +            *optchar = SKIP_VALUE_ARG;
  2181. +          }
  2182. +        } else {
  2183. +          /* no value found */
  2184. +          optionerr(options, optionerrbuf, op_req_val_err, match, 0);
  2185. +          if (depth > 0) {
  2186. +            oWARN(optionerrbuf);
  2187. +            return o_ARG_FILE_ERR;
  2188. +          } else {
  2189. +            oWARN(optionerrbuf);
  2190. +            return o_BAD_ERR;
  2191. +          }
  2192. +        }
  2193. +      }
  2194. +    }
  2195. +
  2196. +    *option_num = match;
  2197. +    return options[match].option_ID;
  2198. +  }
  2199. +  sprintf(optionerrbuf, LoadFarStringSmall(sh_op_not_sup_err), *shortopt);
  2200. +  if (depth > 0) {
  2201. +    /* unwind */
  2202. +    oWARN(optionerrbuf);
  2203. +    return o_ARG_FILE_ERR;
  2204. +  } else {
  2205. +    oWARN(optionerrbuf);
  2206. +    return o_BAD_ERR;
  2207. +  }
  2208. +  return 0;
  2209. +}
  2210. +
  2211. +
  2212. +/* get_longopt
  2213. + *
  2214. + * Get the long option in args array at argnum.
  2215. + * Parameters same as for get_shortopt.
  2216. + */
  2217. +
  2218. +static unsigned long get_longopt(option_group, args, argnum, optchar, negated,
  2219. +                                 value, option_num, depth)
  2220. +  int option_group;
  2221. +  ZCONST char **args;
  2222. +  int argnum;
  2223. +  int *optchar;
  2224. +  int *negated;
  2225. +  char **value;
  2226. +  int *option_num;
  2227. +  int depth;
  2228. +{
  2229. +  char *longopt;
  2230. +  char *lastchr;
  2231. +  char *valuestart;
  2232. +  int op;
  2233. +  char *arg;
  2234. +  int match = -1;
  2235. +  *value = NULL;
  2236. +
  2237. +  if (args == NULL) {
  2238. +    *option_num = o_NO_OPTION_MATCH;
  2239. +    return 0;
  2240. +  }
  2241. +  if (args[argnum] == NULL) {
  2242. +    *option_num = o_NO_OPTION_MATCH;
  2243. +    return 0;
  2244. +  }
  2245. +  /* copy arg so can chop end if value */
  2246. +  if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) {
  2247. +    oWARN("memory - glo");
  2248. +    return o_BAD_ERR;
  2249. +  }
  2250. +  strcpy(arg, args[argnum]);
  2251. +
  2252. +  /* get option */
  2253. +  longopt = arg + 2;
  2254. +  /* no value */
  2255. +  *value = NULL;
  2256. +
  2257. +  /* find = */
  2258. +  for (lastchr = longopt, valuestart = longopt;
  2259. +       *valuestart && *valuestart != '=';
  2260. +       lastchr = valuestart, MB_NEXTCHAR(valuestart)) ;
  2261. +  if (*valuestart) {
  2262. +    /* found =value */
  2263. +    *valuestart = '\0';
  2264. +    valuestart++;
  2265. +  } else {
  2266. +    valuestart = NULL;
  2267. +  }
  2268. +
  2269. +  if (*lastchr == '-') {
  2270. +    /* option negated */
  2271. +    *negated = 1;
  2272. +    *lastchr = '\0';
  2273. +  } else {
  2274. +    *negated = 0;
  2275. +  }
  2276. +
  2277. +  /* look for long option match */
  2278. +  for (op = 0; options[op].option_ID; op++) {
  2279. +    /* Only look at options in the option group */
  2280. +    if (options[op].option_group == option_group) {
  2281. +      if (options[op].longopt &&
  2282. +          strcmp(LoadFarStringSmall(options[op].longopt), longopt) == 0) {
  2283. +        /* exact match */
  2284. +        match = op;
  2285. +        break;
  2286. +      }
  2287. +      if (options[op].longopt &&
  2288. +          strncmp(LoadFarStringSmall(options[op].longopt),
  2289. +                  longopt, strlen(longopt)) == 0) {
  2290. +        if (match > -1) {
  2291. +          sprintf(optionerrbuf, LoadFarStringSmall(long_op_ambig_err),
  2292. +                  longopt);
  2293. +          free(arg);
  2294. +          if (depth > 0) {
  2295. +            /* unwind */
  2296. +            oWARN(optionerrbuf);
  2297. +            return o_ARG_FILE_ERR;
  2298. +          } else {
  2299. +            oWARN(optionerrbuf);
  2300. +            return o_BAD_ERR;
  2301. +          }
  2302. +        }
  2303. +        match = op;
  2304. +      }
  2305. +    }
  2306. +  }
  2307. +
  2308. +  if (match == -1) {
  2309. +    sprintf(optionerrbuf, LoadFarStringSmall(long_op_not_sup_err), longopt);
  2310. +    free(arg);
  2311. +    if (depth > 0) {
  2312. +      oWARN(optionerrbuf);
  2313. +      return o_ARG_FILE_ERR;
  2314. +    } else {
  2315. +      oWARN(optionerrbuf);
  2316. +      return o_BAD_ERR;
  2317. +    }
  2318. +  }
  2319. +
  2320. +  /* one long option an arg */
  2321. +  *optchar = THIS_ARG_DONE;
  2322. +
  2323. +  /* if negated then see if allowed */
  2324. +  if (*negated && options[match].negatable == o_NOT_NEGATABLE) {
  2325. +    optionerr(options, optionerrbuf, op_not_neg_err, match, 1);
  2326. +    free(arg);
  2327. +    if (depth > 0) {
  2328. +      /* unwind */
  2329. +      oWARN(optionerrbuf);
  2330. +      return o_ARG_FILE_ERR;
  2331. +    } else {
  2332. +      oWARN(optionerrbuf);
  2333. +      return o_BAD_ERR;
  2334. +    }
  2335. +  }
  2336. +  /* get value */
  2337. +  if (options[match].value_type == o_OPTIONAL_VALUE) {
  2338. +    /* optional value in form option=value */
  2339. +    if (valuestart) {
  2340. +      /* option=value */
  2341. +      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {
  2342. +        free(arg);
  2343. +        oWARN("memory - glo");
  2344. +        return o_BAD_ERR;
  2345. +      }
  2346. +      strcpy(*value, valuestart);
  2347. +    }
  2348. +  } else if (options[match].value_type == o_REQUIRED_VALUE ||
  2349. +             options[match].value_type == o_NUMBER_VALUE ||
  2350. +             options[match].value_type == o_ONE_CHAR_VALUE ||
  2351. +             options[match].value_type == o_VALUE_LIST) {
  2352. +    /* handle long option one char and number value as required value */
  2353. +    if (valuestart) {
  2354. +      /* option=value */
  2355. +      if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {
  2356. +        free(arg);
  2357. +        oWARN("memory - glo");
  2358. +        return o_BAD_ERR;
  2359. +      }
  2360. +      strcpy(*value, valuestart);
  2361. +    } else {
  2362. +      /* use next arg */
  2363. +      if (args[argnum + 1]) {
  2364. +        if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {
  2365. +          free(arg);
  2366. +          oWARN("memory - glo");
  2367. +          return o_BAD_ERR;
  2368. +        }
  2369. +        /* using next arg as value */
  2370. +        strcpy(*value, args[argnum + 1]);
  2371. +        if (options[match].value_type == o_VALUE_LIST) {
  2372. +          *optchar = START_VALUE_LIST;
  2373. +        } else {
  2374. +          *optchar = SKIP_VALUE_ARG;
  2375. +        }
  2376. +      } else {
  2377. +        /* no value found */
  2378. +        optionerr(options, optionerrbuf, op_req_val_err, match, 1);
  2379. +        free(arg);
  2380. +        if (depth > 0) {
  2381. +          /* unwind */
  2382. +          oWARN(optionerrbuf);
  2383. +          return o_ARG_FILE_ERR;
  2384. +        } else {
  2385. +          oWARN(optionerrbuf);
  2386. +          return o_BAD_ERR;
  2387. +        }
  2388. +      }
  2389. +    }
  2390. +  } else if (options[match].value_type == o_NO_VALUE) {
  2391. +    /* this option does not accept a value */
  2392. +    if (valuestart) {
  2393. +      /* --option=value */
  2394. +      optionerr(options, optionerrbuf, op_no_allow_val_err, match, 1);
  2395. +      free(arg);
  2396. +      if (depth > 0) {
  2397. +        oWARN(optionerrbuf);
  2398. +        return o_ARG_FILE_ERR;
  2399. +      } else {
  2400. +        oWARN(optionerrbuf);
  2401. +        return o_BAD_ERR;
  2402. +      }
  2403. +    }
  2404. +  }
  2405. +  free(arg);
  2406. +
  2407. +  *option_num = match;
  2408. +  return options[match].option_ID;
  2409. +}
  2410. +
  2411. +
  2412. +
  2413. +/* get_option
  2414. + *
  2415. + * Main interface for user.  Use this function to get options, values and
  2416. + * non-option arguments from a command line provided in argv form.
  2417. + *
  2418. + * To use get_option() first define valid options by setting
  2419. + * the global variable options[] to an array of option_struct.  Also
  2420. + * either change defaults below or make variables global and set elsewhere.
  2421. + * Zip uses below defaults.
  2422. + *
  2423. + * Call get_option() to get an option (like -b or --temp-file) and any
  2424. + * value for that option (like filename for -b) or a non-option argument
  2425. + * (like archive name) each call.  If *value* is not NULL after calling
  2426. + * get_option() it is a returned value and the caller should either store
  2427. + * the char pointer or free() it before calling get_option() again to avoid
  2428. + * leaking memory.  If a non-option non-value argument is returned get_option()
  2429. + * returns o_NON_OPTION_ARG and value is set to the entire argument.
  2430. + * When there are no more arguments get_option() returns 0.
  2431. + *
  2432. + * The parameters argnum (after set to 0 on initial call),
  2433. + * optchar, first_nonopt_arg, option_num, and depth (after initial
  2434. + * call) are set and maintained by get_option() and should not be
  2435. + * changed.  The parameters argc, negated, and value are outputs and
  2436. + * can be used by the calling program.  get_option() returns either the
  2437. + * option_ID for the current option, a special value defined in
  2438. + * zip.h, or 0 when no more arguments.
  2439. + *
  2440. + * The value returned by get_option() is the ID value in the options
  2441. + * table.  This value can be duplicated in the table if different
  2442. + * options are really the same option.  The index into the options[]
  2443. + * table is given by option_num, though the ID should be used as
  2444. + * option numbers change when the table is changed.  The ID must
  2445. + * not be 0 for any option as this ends the table.  If get_option()
  2446. + * finds an option not in the table it calls oERR to post an
  2447. + * error and exit.  Errors also result if the option requires a
  2448. + * value that is missing, a value is present but the option does
  2449. + * not take one, and an option is negated but is not
  2450. + * negatable.  Non-option arguments return o_NON_OPTION_ARG
  2451. + * with the entire argument in value.
  2452. + *
  2453. + * For Zip and UnZip, permuting is on and all options and their values
  2454. + * are returned before any non-option arguments like archive name.
  2455. + *
  2456. + * The arguments "-" alone and "--" alone return as non-option arguments.
  2457. + * Note that "-" should not be used as part of a short option
  2458. + * entry in the table but can be used in the middle of long
  2459. + * options such as in the long option "a-long-option".  Now "--" alone
  2460. + * stops option processing, returning any arguments following "--" as
  2461. + * non-option arguments instead of options.
  2462. + *
  2463. + * Argument file support is removed from this version. It may be added later.
  2464. + *
  2465. + * After each call:
  2466. + *   argc       is set to the current size of args[] but should not change
  2467. + *                with argument file support removed,
  2468. + *   argnum     is the index of the current arg,
  2469. + *   value      is either the value of the returned option or non-option
  2470. + *                argument or NULL if option with no value,
  2471. + *   negated    is set if the option was negated by a trailing dash (-)
  2472. + *   option_num is set to either the index in options[] for the option or
  2473. + *                o_NO_OPTION_MATCH if no match.
  2474. + * Negation is checked before the value is read if the option is negatable so
  2475. + * that the - is not included in the value.  If the option is not negatable
  2476. + * but takes a value then the - will start the value.  If permuting then
  2477. + * argnum and first_nonopt_arg are unreliable and should not be used.
  2478. + *
  2479. + * Command line is read from left to right.  As get_option() finds non-option
  2480. + * arguments (arguments not starting with - and that are not values to options)
  2481. + * it moves later options and values in front of the non-option arguments.
  2482. + * This permuting is turned off by setting enable_permute to 0.  Then
  2483. + * get_option() will return options and non-option arguments in the order
  2484. + * found.  Currently permuting is only done after an argument is completely
  2485. + * processed so that any value can be moved with options they go with.  All
  2486. + * state information is stored in the parameters argnum, optchar,
  2487. + * first_nonopt_arg and option_num.  You should not change these after the
  2488. + * first call to get_option().  If you need to back up to a previous arg then
  2489. + * set argnum to that arg (remembering that args may have been permuted) and
  2490. + * set optchar = 0 and first_nonopt_arg to the first non-option argument if
  2491. + * permuting.  After all arguments are returned the next call to get_option()
  2492. + * returns 0.  The caller can then call free_args(args) if appropriate.
  2493. + *
  2494. + * get_option() accepts arguments in the following forms:
  2495. + *  short options
  2496. + *       of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single
  2497. + *       leading -, as in -abccdba.  In this example if 'b' is followed by 'a'
  2498. + *       it matches short option 'ba' else it is interpreted as short option
  2499. + *       b followed by another option.  The character - is not legal as a
  2500. + *       short option or as part of a 2 character short option.
  2501. + *
  2502. + *       If a short option has a value it immediately follows the option or
  2503. + *       if that option is the end of the arg then the next arg is used as
  2504. + *       the value.  So if short option e has a value, it can be given as
  2505. + *             -evalue
  2506. + *       or
  2507. + *             -e value
  2508. + *       and now
  2509. + *             -e=value
  2510. + *       but now that = is optional a leading = is stripped for the first.
  2511. + *       This change allows optional short option values to be defaulted as
  2512. + *             -e=
  2513. + *       Either optional or required values can be specified.  Optional values
  2514. + *       now use both forms as ignoring the later got confusing.  Any
  2515. + *       non-value short options can preceed a valued short option as in
  2516. + *             -abevalue
  2517. + *       Some value types (one_char and number) allow options after the value
  2518. + *       so if oc is an option that takes a character and n takes a number
  2519. + *       then
  2520. + *             -abocVccn42evalue
  2521. + *       returns value V for oc and value 42 for n.  All values are strings
  2522. + *       so programs may have to convert the "42" to a number.  See long
  2523. + *       options below for how value lists are handled.
  2524. + *
  2525. + *       Any short option can be negated by following it with -.  Any - is
  2526. + *       handled and skipped over before any value is read unless the option
  2527. + *       is not negatable but takes a value and then - starts the value.
  2528. + *
  2529. + *       If the value for an optional value is just =, then treated as no
  2530. + *       value.
  2531. + *
  2532. + *  long options
  2533. + *       of arbitrary length are assumed if an arg starts with -- but is not
  2534. + *       exactly --.  Long options are given one per arg and can be abbreviated
  2535. + *       if the abbreviation uniquely matches one of the long options.
  2536. + *       Exact matches always match before partial matches.  If ambiguous an
  2537. + *       error is generated.
  2538. + *
  2539. + *       Values are specified either in the form
  2540. + *             --longoption=value
  2541. + *       or can be the following arg if the value is required as in
  2542. + *             --longoption value
  2543. + *       Optional values to long options must be in the first form.
  2544. + *
  2545. + *       Value lists are specified by o_VALUE_LIST and consist of an option
  2546. + *       that takes a value followed by one or more value arguments.
  2547. + *       The two forms are
  2548. + *             --option=value
  2549. + *       or
  2550. + *             -ovalue
  2551. + *       for a single value or
  2552. + *             --option value1 value2 value3 ... --option2
  2553. + *       or
  2554. + *             -o value1 value2 value3 ...
  2555. + *       for a list of values.  The list ends at the next option, the
  2556. + *       end of the command line, or at a single "@" argument.
  2557. + *       Each value is treated as if it was preceeded by the option, so
  2558. + *             --option1 val1 val2
  2559. + *       with option1 value_type set to o_VALUE_LIST is the same as
  2560. + *             --option1=val1 --option1=val2
  2561. + *
  2562. + *       Long options can be negated by following the option with - as in
  2563. + *             --longoption-
  2564. + *       Long options with values can also be negated if this makes sense for
  2565. + *       the caller as:
  2566. + *             --longoption-=value
  2567. + *       If = is not followed by anything it is treated as no value.
  2568. + *
  2569. + *  @path
  2570. + *       Argument files support removed from this version.  It may be added
  2571. + *       back later.
  2572. + *
  2573. + *  non-option argument
  2574. + *       is any argument not given above.  If enable_permute is 1 then
  2575. + *       these are returned after all options, otherwise all options and
  2576. + *       args are returned in order.  Returns option ID o_NON_OPTION_ARG
  2577. + *       and sets value to the argument.
  2578. + *
  2579. + *
  2580. + * Arguments to get_option:
  2581. + *  int option_group       - either UZO for UnZip or ZIO for ZipInfo
  2582. + *  char ***pargs          - pointer to arg array in the argv form
  2583. + *  int *argc              - returns the current argc for args incl. args[0]
  2584. + *  int *argnum            - the index of the current argument (caller
  2585. + *                            should set = 0 on first call and not change
  2586. + *                            after that)
  2587. + *  int *optchar           - index of next short opt in arg or special
  2588. + *  int *first_nonopt_arg  - used by get_option to permute args
  2589. + *  int *negated           - option was negated (had trailing -)
  2590. + *  char *value            - value of option if any (free when done with it)
  2591. + *                            or NULL
  2592. + *  int *option_num        - the index in options of the last option returned
  2593. + *                            (can be o_NO_OPTION_MATCH)
  2594. + *  int recursion_depth    - current depth of recursion
  2595. + *                            (always set to 0 by caller)
  2596. + *                            (always 0 with argument files support removed)
  2597. + *
  2598. + *  Caller should only read the returned option ID and the value, negated,
  2599. + *  and option_num (if required) parameters after each call.
  2600. + *
  2601. + *  Ed Gordon
  2602. + *  8/24/2003 (last updated 3/1/2008 EG)
  2603. + *
  2604. + */
  2605. +
  2606. +unsigned long get_option(option_group, pargs, argc, argnum, optchar, value,
  2607. +                         negated, first_nonopt_arg, option_num, recursion_depth)
  2608. +  int option_group;
  2609. +  char ***pargs;
  2610. +  int *argc;
  2611. +  int *argnum;
  2612. +  int *optchar;
  2613. +  char **value;
  2614. +  int *negated;
  2615. +  int *first_nonopt_arg;
  2616. +  int *option_num;
  2617. +  int recursion_depth;
  2618. +{
  2619. +  char **args;
  2620. +  unsigned long option_ID;
  2621. +
  2622. +  int argcnt;
  2623. +  int first_nonoption_arg;
  2624. +  char *arg = NULL;
  2625. +  int h;
  2626. +  int optc;
  2627. +  int argn;
  2628. +  int j;
  2629. +  int v;
  2630. +  int read_rest_args_verbatim = 0;  /* 7/25/04 - ignore options and arg files for rest args */
  2631. +
  2632. +  /* caller should free value or assign it to another
  2633. +     variable before calling get_option again. */
  2634. +  *value = NULL;
  2635. +
  2636. +  /* if args is NULL then done */
  2637. +  if (pargs == NULL) {
  2638. +    *argc = 0;
  2639. +    return 0;
  2640. +  }
  2641. +  args = *pargs;
  2642. +  if (args == NULL) {
  2643. +    *argc = 0;
  2644. +    return 0;
  2645. +  }
  2646. +
  2647. +  /* count args */
  2648. +  for (argcnt = 0; args[argcnt]; argcnt++) ;
  2649. +
  2650. +  /* if no provided args then nothing to do */
  2651. +  if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) {
  2652. +    *argc = argcnt;
  2653. +    /* return 0 to note that no args are left */
  2654. +    return 0;
  2655. +  }
  2656. +
  2657. +  *negated = 0;
  2658. +  first_nonoption_arg = *first_nonopt_arg;
  2659. +  argn = *argnum;
  2660. +  optc = *optchar;
  2661. +
  2662. +  if (optc == READ_REST_ARGS_VERBATIM) {
  2663. +    read_rest_args_verbatim = 1;
  2664. +  }
  2665. +
  2666. +  if (argn == -1 || (recursion_depth == 0 && argn == 0)) {
  2667. +    /* first call */
  2668. +    /* if depth = 0 then args[0] is argv[0] so skip */
  2669. +    *option_num = o_NO_OPTION_MATCH;
  2670. +    optc = THIS_ARG_DONE;
  2671. +    first_nonoption_arg = -1;
  2672. +  }
  2673. +
  2674. +  /* if option_num is set then restore last option_ID in case continuing
  2675. +     value list */
  2676. +  option_ID = 0;
  2677. +  if (*option_num != o_NO_OPTION_MATCH) {
  2678. +    option_ID = options[*option_num].option_ID;
  2679. +  }
  2680. +
  2681. +  /* get next option if any */
  2682. +  for (;;)  {
  2683. +    if (read_rest_args_verbatim) {
  2684. +      /* rest of args after "--" are non-option args if doubledash_ends_options
  2685. +         set */
  2686. +      argn++;
  2687. +      if (argn > argcnt || args[argn] == NULL) {
  2688. +        /* done */
  2689. +        option_ID = 0;
  2690. +        break;
  2691. +      }
  2692. +      arg = args[argn];
  2693. +      if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
  2694. +        oWARN("memory - go");
  2695. +        return o_BAD_ERR;
  2696. +      }
  2697. +      strcpy(*value, arg);
  2698. +      *option_num = o_NO_OPTION_MATCH;
  2699. +      option_ID = o_NON_OPTION_ARG;
  2700. +      break;
  2701. +
  2702. +    /* permute non-option args after option args so options are returned
  2703. +       first */
  2704. +    } else if (enable_permute) {
  2705. +      if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE ||
  2706. +          optc == START_VALUE_LIST || optc == IN_VALUE_LIST ||
  2707. +          optc == STOP_VALUE_LIST) {
  2708. +        /* moved to new arg */
  2709. +        if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {
  2710. +          /* do the permuting - move non-options after this option */
  2711. +          /* if option and value separate args or starting list skip option */
  2712. +          if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) {
  2713. +            v = 1;
  2714. +          } else {
  2715. +            v = 0;
  2716. +          }
  2717. +          for (h = first_nonoption_arg; h < argn; h++) {
  2718. +            arg = args[first_nonoption_arg];
  2719. +            for (j = first_nonoption_arg; j < argn + v; j++) {
  2720. +              args[j] = args[j + 1];
  2721. +            }
  2722. +            args[j] = arg;
  2723. +          }
  2724. +          first_nonoption_arg += 1 + v;
  2725. +        }
  2726. +      }
  2727. +    } else if (optc == NON_OPTION_ARG) {
  2728. +      /* if not permuting then already returned arg */
  2729. +      optc = THIS_ARG_DONE;
  2730. +    }
  2731. +
  2732. +    /* value lists */
  2733. +    if (optc == STOP_VALUE_LIST) {
  2734. +      optc = THIS_ARG_DONE;
  2735. +    }
  2736. +
  2737. +    if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) {
  2738. +      if (optc == START_VALUE_LIST) {
  2739. +        /* already returned first value */
  2740. +        argn++;
  2741. +        optc = IN_VALUE_LIST;
  2742. +      }
  2743. +      argn++;
  2744. +      arg = args[argn];
  2745. +      /* if end of args and still in list and there are non-option args then
  2746. +         terminate list */
  2747. +      if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST)
  2748. +          && first_nonoption_arg > -1) {
  2749. +        /* terminate value list with @ */
  2750. +        /* this is only needed for argument files */
  2751. +        /* but is also good for show command line so command lines with lists
  2752. +           can always be read back in */
  2753. +        argcnt = insert_arg(&args, "@", first_nonoption_arg, 1);
  2754. +        argn++;
  2755. +        if (first_nonoption_arg > -1) {
  2756. +          first_nonoption_arg++;
  2757. +        }
  2758. +      }
  2759. +
  2760. +      arg = args[argn];
  2761. +      if (arg && arg[0] == '@' && arg[1] == '\0') {
  2762. +          /* inserted arguments terminator */
  2763. +          optc = STOP_VALUE_LIST;
  2764. +          continue;
  2765. +      } else if (arg && arg[0] != '-') {  /* not option */
  2766. +        /* - and -- are not allowed in value lists unless escaped */
  2767. +        /* another value in value list */
  2768. +        if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {
  2769. +          oWARN("memory - go");
  2770. +          return o_BAD_ERR;
  2771. +        }
  2772. +        strcpy(*value, args[argn]);
  2773. +        break;
  2774. +
  2775. +      } else {
  2776. +        argn--;
  2777. +        optc = THIS_ARG_DONE;
  2778. +      }
  2779. +    }
  2780. +
  2781. +    /* move to next arg */
  2782. +    if (optc == SKIP_VALUE_ARG) {
  2783. +      argn += 2;
  2784. +      optc = 0;
  2785. +    } else if (optc == THIS_ARG_DONE) {
  2786. +      argn++;
  2787. +      optc = 0;
  2788. +    }
  2789. +    if (argn > argcnt) {
  2790. +      break;
  2791. +    }
  2792. +    if (args[argn] == NULL) {
  2793. +      /* done unless permuting and non-option args */
  2794. +      if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {
  2795. +        /* return non-option arguments at end */
  2796. +        if (optc == NON_OPTION_ARG) {
  2797. +          first_nonoption_arg++;
  2798. +        }
  2799. +        /* after first pass args are permuted but skipped over non-option
  2800. +           args */
  2801. +        /* swap so argn points to first non-option arg */
  2802. +        j = argn;
  2803. +        argn = first_nonoption_arg;
  2804. +        first_nonoption_arg = j;
  2805. +      }
  2806. +      if (argn > argcnt || args[argn] == NULL) {
  2807. +        /* done */
  2808. +        option_ID = 0;
  2809. +        break;
  2810. +      }
  2811. +    }
  2812. +
  2813. +    /* after swap first_nonoption_arg points to end which is NULL */
  2814. +    if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) {
  2815. +      /* only non-option args left */
  2816. +      if (optc == NON_OPTION_ARG) {
  2817. +        argn++;
  2818. +      }
  2819. +      if (argn > argcnt || args[argn] == NULL) {
  2820. +        /* done */
  2821. +        option_ID = 0;
  2822. +        break;
  2823. +      }
  2824. +      if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {
  2825. +        oWARN("memory - go");
  2826. +        return o_BAD_ERR;
  2827. +      }
  2828. +      strcpy(*value, args[argn]);
  2829. +      optc = NON_OPTION_ARG;
  2830. +      option_ID = o_NON_OPTION_ARG;
  2831. +      break;
  2832. +    }
  2833. +
  2834. +    arg = args[argn];
  2835. +
  2836. +    /* is it an option */
  2837. +    if (arg[0] == '-') {
  2838. +      /* option */
  2839. +      if (arg[1] == '\0') {
  2840. +        /* arg = - */
  2841. +        /* treat like non-option arg */
  2842. +        *option_num = o_NO_OPTION_MATCH;
  2843. +        if (enable_permute) {
  2844. +          /* permute args to move all non-option args to end */
  2845. +          if (first_nonoption_arg < 0) {
  2846. +            first_nonoption_arg = argn;
  2847. +          }
  2848. +          argn++;
  2849. +        } else {
  2850. +          /* not permute args so return non-option args when found */
  2851. +          if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
  2852. +            oWARN("memory - go");
  2853. +            return o_BAD_ERR;
  2854. +          }
  2855. +          strcpy(*value, arg);
  2856. +          optc = NON_OPTION_ARG;
  2857. +          option_ID = o_NON_OPTION_ARG;
  2858. +          break;
  2859. +        }
  2860. +
  2861. +      } else if (arg[1] == '-') {
  2862. +        /* long option */
  2863. +        if (arg[2] == '\0') {
  2864. +          /* arg = -- */
  2865. +          if (doubledash_ends_options) {
  2866. +            /* Now -- stops permuting and forces the rest of
  2867. +               the command line to be read verbatim - 7/25/04 EG */
  2868. +
  2869. +            /* never permute args after -- and return as non-option args */
  2870. +            if (first_nonoption_arg < 1) {
  2871. +              /* -- is first non-option argument - 8/7/04 EG */
  2872. +              argn--;
  2873. +            } else {
  2874. +              /* go back to start of non-option args - 8/7/04 EG */
  2875. +              argn = first_nonoption_arg - 1;
  2876. +            }
  2877. +
  2878. +            /* disable permuting and treat remaining arguments as not
  2879. +               options */
  2880. +            read_rest_args_verbatim = 1;
  2881. +            optc = READ_REST_ARGS_VERBATIM;
  2882. +
  2883. +          } else {
  2884. +            /* treat like non-option arg */
  2885. +            *option_num = o_NO_OPTION_MATCH;
  2886. +            if (enable_permute) {
  2887. +              /* permute args to move all non-option args to end */
  2888. +              if (first_nonoption_arg < 0) {
  2889. +                first_nonoption_arg = argn;
  2890. +              }
  2891. +              argn++;
  2892. +            } else {
  2893. +              /* not permute args so return non-option args when found */
  2894. +              if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
  2895. +                oWARN("memory - go");
  2896. +                return o_BAD_ERR;
  2897. +              }
  2898. +              strcpy(*value, arg);
  2899. +              optc = NON_OPTION_ARG;
  2900. +              option_ID = o_NON_OPTION_ARG;
  2901. +              break;
  2902. +            }
  2903. +          }
  2904. +
  2905. +        } else {
  2906. +          option_ID = get_longopt(option_group, (ZCONST char **)args, argn,
  2907. +                                  &optc, negated,
  2908. +                                  value, option_num, recursion_depth);
  2909. +          if (option_ID == o_BAD_ERR) {
  2910. +            return o_BAD_ERR;
  2911. +          } else if (option_ID == o_ARG_FILE_ERR) {
  2912. +            /* unwind as only get this if recursion_depth > 0 */
  2913. +            return option_ID;
  2914. +          }
  2915. +          break;
  2916. +        }
  2917. +
  2918. +      } else {
  2919. +        /* short option */
  2920. +        option_ID = get_shortopt(option_group, (ZCONST char **)args, argn,
  2921. +                                 &optc, negated,
  2922. +                                 value, option_num, recursion_depth);
  2923. +
  2924. +        if (option_ID == o_BAD_ERR) {
  2925. +          return o_BAD_ERR;
  2926. +        } else if (option_ID == o_ARG_FILE_ERR) {
  2927. +          /* unwind as only get this if recursion_depth > 0 */
  2928. +          return option_ID;
  2929. +        }
  2930. +
  2931. +        if (optc == 0) {
  2932. +          /* if optc = 0 then ran out of short opts this arg */
  2933. +          optc = THIS_ARG_DONE;
  2934. +        } else {
  2935. +          break;
  2936. +        }
  2937. +      }
  2938. +
  2939. +#if 0
  2940. +    /* argument file code left out
  2941. +       so for now let filenames start with @
  2942. +    */
  2943. +
  2944. +    } else if (allow_arg_files && arg[0] == '@') {
  2945. +      /* arg file */
  2946. +      oERR(PK_PARMS, no_arg_files_err);
  2947. +#endif
  2948. +
  2949. +    } else {
  2950. +      /* non-option */
  2951. +      if (enable_permute) {
  2952. +        /* permute args to move all non-option args to end */
  2953. +        if (first_nonoption_arg < 0) {
  2954. +          first_nonoption_arg = argn;
  2955. +        }
  2956. +        argn++;
  2957. +      } else {
  2958. +        /* no permute args so return non-option args when found */
  2959. +        if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
  2960. +          oWARN("memory - go");
  2961. +          return o_BAD_ERR;
  2962. +        }
  2963. +        strcpy(*value, arg);
  2964. +        *option_num = o_NO_OPTION_MATCH;
  2965. +        optc = NON_OPTION_ARG;
  2966. +        option_ID = o_NON_OPTION_ARG;
  2967. +        break;
  2968. +      }
  2969. +
  2970. +    }
  2971. +  }
  2972. +
  2973. +  *pargs = args;
  2974. +  *argc = argcnt;
  2975. +  *first_nonopt_arg = first_nonoption_arg;
  2976. +  *argnum = argn;
  2977. +  *optchar = optc;
  2978. +
  2979. +  return option_ID;
  2980. +}
  2981. diff -ru2 unz60e03/unzpriv.h u6e3_np/unzpriv.h
  2982. --- unz60e03/unzpriv.h  Mon Mar 24 11:53:24 2008
  2983. +++ u6e3_np/unzpriv.h   Mon Mar 24 14:13:02 2008
  2984. @@ -1271,4 +1271,89 @@
  2985.  #endif
  2986.  
  2987. +
  2988. +/*--------------------------------------------------------------------
  2989. +    Long option support
  2990. +    23 August 2003
  2991. +    Updated for UnZip 1 March 2008
  2992. +    See unzip.c
  2993. +  --------------------------------------------------------------------*/
  2994. +
  2995. +/* The below is for use in the caller-provided options table */
  2996. +
  2997. +/* option groups */
  2998. +#define UZO 1   /* UnZip option */
  2999. +#define ZIO 2   /* ZipInfo option */
  3000. +
  3001. +
  3002. +/* value_type - value is always returned as a string. */
  3003. +#define o_NO_VALUE        0   /* this option does not take a value */
  3004. +#define o_REQUIRED_VALUE  1   /* this option requires a value */
  3005. +#define o_OPTIONAL_VALUE  2   /* value is optional (see get_option() for details) */
  3006. +#define o_VALUE_LIST      3   /* this option takes a list of values */
  3007. +#define o_ONE_CHAR_VALUE  4   /* next char is value (does not end short opt string) */
  3008. +#define o_NUMBER_VALUE    5   /* value is integer (does not end short opt string) */
  3009. +
  3010. +
  3011. +/* negatable - a dash following the option (but before any value) sets negated. */
  3012. +#define o_NOT_NEGATABLE   0   /* trailing '-' to negate either starts value or generates error */
  3013. +#define o_NEGATABLE       1   /* trailing '-' sets negated to TRUE */
  3014. +
  3015. +
  3016. +/* option_num can be this when option not in options table */
  3017. +#define o_NO_OPTION_MATCH     -1
  3018. +
  3019. +/* special values returned by get_option - do not use these as option IDs */
  3020. +#define o_NON_OPTION_ARG      ((unsigned long) 0xFFFF)    /* returned for non-option
  3021. +                                                             args */
  3022. +#define o_ARG_FILE_ERR        ((unsigned long) 0xFFFE)    /* internal recursion
  3023. +                                                             return (user never sees) */
  3024. +#define o_BAD_ERR             ((unsigned long) 0xFFFD)    /* bad error */
  3025. +
  3026. +/* options array is set in unzip.c */
  3027. +struct option_struct {
  3028. +  int option_group;         /* either UZO for UnZip or ZIO for ZipInfo syntax */
  3029. +  char Far *shortopt;       /* pointer to short option string */
  3030. +  char Far *longopt;        /* pointer to long option string */
  3031. +  int  value_type;          /* from above */
  3032. +  int  negatable;           /* from above */
  3033. +  unsigned long option_ID;  /* value returned by get_option when this option
  3034. +                               is found */
  3035. +  char Far *name;           /* optional string for option returned on some
  3036. +                               errors */
  3037. +};
  3038. +
  3039. +/* structure used to create -x and include file lists */
  3040. +struct file_list {
  3041. +  char *name;
  3042. +  struct file_list *next;
  3043. +};
  3044. +
  3045. +
  3046. +/* function prototypes */
  3047. +
  3048. +/* get the next option from args */
  3049. +unsigned long get_option OF((int option_group,
  3050. +                             char ***pargs, int *argc, int *argnum,
  3051. +                             int *optchar,
  3052. +                             char **value, int *negated, int *first_nonopt_arg,
  3053. +                             int *option_num, int recursion_depth));
  3054. +
  3055. +/* copy args - copy an args array, allocating space as needed */
  3056. +char **copy_args OF((char **args, int max_args));
  3057. +
  3058. +/* arg count - count args in argv like array */
  3059. +int arg_count OF((char **args));
  3060. +
  3061. +/* free args - free args created with one of these functions */
  3062. +int free_args OF((char **args));
  3063. +
  3064. +/* insert arg - copy an arg into args */
  3065. +int insert_arg OF((char ***args, ZCONST char *arg, int insert_at,
  3066. +                   int free_args));
  3067. +
  3068. +/*--------------------------------------------------------------------
  3069. +    End of Long option support
  3070. +  --------------------------------------------------------------------*/
  3071. +
  3072.  /***********************************/
  3073.  /*  LARGE_FILE_SUPPORT             */
  3074. diff -ru2 unz60e03/vms/cmdline.c u6e3_np/vms/cmdline.c
  3075. --- unz60e03/vms/cmdline.c      Tue Feb 12 01:37:42 2008
  3076. +++ u6e3_np/vms/cmdline.c       Mon Mar 24 14:13:10 2008
  3077. @@ -34,4 +34,6 @@
  3078.  **  Modified by:
  3079.  **
  3080. +**      02-014          E. Gordon               10-Mar-2008 03:12
  3081. +**              Modified to work with get_options().
  3082.  **      02-013          S. Schweda, C. Spieler  29-Dec-2007 03:34
  3083.  **              Extended /RESTORE qualifier to support timestamp restoration
  3084. @@ -172,10 +174,10 @@
  3085.  $DESCRIPTOR(cli_text_auto,      "TEXT.AUTO");           /* -a */
  3086.  $DESCRIPTOR(cli_text_all,       "TEXT.ALL");            /* -aa */
  3087. -$DESCRIPTOR(cli_text_none,      "TEXT.NONE");           /* ---a */
  3088. +$DESCRIPTOR(cli_text_none,      "TEXT.NONE");           /* -a- */
  3089.  $DESCRIPTOR(cli_text_stmlf,     "TEXT.STMLF");          /* -S */
  3090.  $DESCRIPTOR(cli_binary,         "BINARY");              /* -b[b] */
  3091.  $DESCRIPTOR(cli_binary_auto,    "BINARY.AUTO");         /* -b */
  3092.  $DESCRIPTOR(cli_binary_all,     "BINARY.ALL");          /* -bb */
  3093. -$DESCRIPTOR(cli_binary_none,    "BINARY.NONE");         /* ---b */
  3094. +$DESCRIPTOR(cli_binary_none,    "BINARY.NONE");         /* -b- */
  3095.  $DESCRIPTOR(cli_case_insensitive,"CASE_INSENSITIVE");   /* -C */
  3096.  $DESCRIPTOR(cli_screen,         "SCREEN");              /* -c */
  3097. @@ -202,5 +204,5 @@
  3098.  $DESCRIPTOR(cli_restore_own,    "RESTORE.OWNER_PROT");  /* -X */
  3099.  $DESCRIPTOR(cli_restore_date,   "RESTORE.DATE");        /* -DD */
  3100. -$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL");  /* --D */
  3101. +$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL");  /* -D- */
  3102.  $DESCRIPTOR(cli_restore_date_files, "RESTORE.DATE.FILES"); /* -D */
  3103.  $DESCRIPTOR(cli_dot_version,    "DOT_VERSION");         /* -Y */
  3104. @@ -299,4 +301,6 @@
  3105.  **      SS$_ABORT       - Bad time value
  3106.  **
  3107. +**  Modified to work with the get_option() command line parser.  10 March 2008
  3108. +**
  3109.  */
  3110.      register unsigned long status;
  3111. @@ -419,5 +423,4 @@
  3112.          if (status != CLI$_ABSENT) {
  3113.              *ptr++ = '-';
  3114. -            *ptr++ = '-';
  3115.              *ptr++ = 'b';
  3116.              if ((status & 1) &&
  3117. @@ -427,4 +430,5 @@
  3118.                      *ptr++ = 'b';
  3119.              }
  3120. +            *ptr++ = '-';
  3121.          }
  3122.  
  3123. @@ -436,5 +440,4 @@
  3124.          if (status != CLI$_ABSENT) {
  3125.              *ptr++ = '-';
  3126. -            *ptr++ = '-';
  3127.              *ptr++ = 'a';
  3128.              if ((status & 1) &&
  3129. @@ -446,4 +449,5 @@
  3130.                      *ptr++ = 'S';
  3131.              }
  3132. +            *ptr++ = '-';
  3133.          }
  3134.  
  3135. diff -ru2 unz60e03/zipinfo.c u6e3_np/zipinfo.c
  3136. --- unz60e03/zipinfo.c  Mon Mar 24 14:23:54 2008
  3137. +++ u6e3_np/zipinfo.c   Mon Mar 24 14:25:24 2008
  3138. @@ -171,4 +171,6 @@
  3139.  static ZCONST char Far ZipfileCommTruncMsg[] =
  3140.    "\ncaution:  zipfile comment truncated\n";
  3141. +static ZCONST char Far NoMemArguments[] =
  3142. +  "envargs:  cannot get memory for arguments";
  3143.  
  3144.  static ZCONST char Far CentralDirEntry[] =
  3145. @@ -459,10 +461,48 @@
  3146.      __GDEF
  3147.  {
  3148. -    char   **argv, *s;
  3149. -    int    argc, c, error=FALSE, negative=0;
  3150. +    int    argc, error=FALSE;
  3151.      int    hflag_slmv=TRUE, hflag_2=FALSE;  /* diff options => diff defaults */
  3152.      int    tflag_slm=TRUE, tflag_2v=FALSE;
  3153.      int    explicit_h=FALSE, explicit_t=FALSE;
  3154.  
  3155. +    char **args;
  3156. +
  3157. +
  3158. +    /* used by get_option */
  3159. +    unsigned long option; /* option ID returned by get_option */
  3160. +    int argcnt = 0;       /* current argcnt in args */
  3161. +    int argnum = 0;       /* arg number */
  3162. +    int optchar = 0;      /* option state */
  3163. +    char *value = NULL;   /* non-option arg, option value or NULL */
  3164. +    int negative = 0;     /* 1 = option negated */
  3165. +    int fna = 0;          /* current first non-opt arg */
  3166. +    int optnum = 0;       /* index in table */
  3167. +
  3168. +
  3169. +    /* since get_option() returns xfiles and files one at a time, store them in
  3170. +       linked lists until have them all */
  3171. +
  3172. +    int file_count;
  3173. +    struct file_list *next_file;
  3174. +
  3175. +    /* files to extract */
  3176. +    int in_files_count = 0;
  3177. +    struct file_list *in_files = NULL;
  3178. +    struct file_list *next_in_files = NULL;
  3179. +
  3180. +    /* files to exclude in -x list */
  3181. +    int in_xfiles_count = 0;
  3182. +    struct file_list *in_xfiles = NULL;
  3183. +    struct file_list *next_in_xfiles = NULL;
  3184. +
  3185. +    G.wildzipfn = NULL;
  3186. +
  3187. +    /* make copy of args that can use with insert_arg() used by get_option() */
  3188. +    args = copy_args(*pargv, 0);
  3189. +
  3190. +
  3191. +    /* Initialize lists */
  3192. +    G.filespecs = 0;
  3193. +    G.xfilespecs = 0;
  3194.  
  3195.  #ifdef MACOS
  3196. @@ -470,17 +510,41 @@
  3197.  #endif
  3198.      G.extract_flag = FALSE;   /* zipinfo does not extract to disk */
  3199. -    argc = *pargc;
  3200. -    argv = *pargv;
  3201.  
  3202. -    while (--argc > 0 && (*++argv)[0] == '-') {
  3203. -        s = argv[0] + 1;
  3204. -        while ((c = *s++) != 0) {    /* "!= 0":  prevent Turbo C warning */
  3205. -            switch (c) {
  3206. -                case '-':
  3207. -                    ++negative;
  3208. -                    break;
  3209. +
  3210. +    /*
  3211. +    -------------------------------------------
  3212. +    Process command line using get_option
  3213. +    -------------------------------------------
  3214. +
  3215. +    Each call to get_option() returns either a command
  3216. +    line option and possible value or a non-option argument.
  3217. +    Arguments are permuted so that all options (-r, -b temp)
  3218. +    are returned before non-option arguments (zipfile).
  3219. +    Returns 0 when nothing left to read.
  3220. +    */
  3221. +
  3222. +    /* set argnum = 0 on first call to init get_option */
  3223. +    argnum = 0;
  3224. +
  3225. +    /* get_option returns the option ID and updates parameters:
  3226. +           args    - usually same as argv if no argument file support
  3227. +           argcnt  - current argc for args
  3228. +           value   - char* to value (free() when done with it) or NULL if no value
  3229. +           negated - option was negated with trailing -
  3230. +    */
  3231. +
  3232. +    while ((option = get_option(ZIO, &args, &argcnt, &argnum,
  3233. +                                &optchar, &value, &negative,
  3234. +                                &fna, &optnum, 0)))
  3235. +    {
  3236. +        if(option == o_BAD_ERR) {
  3237. +          return(PK_PARAM);
  3238. +        }
  3239. +
  3240. +        switch (option)
  3241. +        {
  3242.                  case '1':      /* shortest listing:  JUST filenames */
  3243.                      if (negative)
  3244. -                        uO.lflag = -2, negative = 0;
  3245. +                        uO.lflag = -2;
  3246.                      else
  3247.                          uO.lflag = 1;
  3248. @@ -488,5 +552,5 @@
  3249.                  case '2':      /* just filenames, plus headers if specified */
  3250.                      if (negative)
  3251. -                        uO.lflag = -2, negative = 0;
  3252. +                        uO.lflag = -2;
  3253.                      else
  3254.                          uO.lflag = 2;
  3255. @@ -495,5 +559,5 @@
  3256.                  case ('C'):    /* -C:  match filenames case-insensitively */
  3257.                      if (negative)
  3258. -                        uO.C_flag = FALSE, negative = 0;
  3259. +                        uO.C_flag = FALSE;
  3260.                      else
  3261.                          uO.C_flag = TRUE;
  3262. @@ -502,5 +566,5 @@
  3263.                  case 'h':      /* header line */
  3264.                      if (negative)
  3265. -                        hflag_2 = hflag_slmv = FALSE, negative = 0;
  3266. +                        hflag_2 = hflag_slmv = FALSE;
  3267.                      else {
  3268.                          hflag_2 = hflag_slmv = explicit_h = TRUE;
  3269. @@ -511,5 +575,5 @@
  3270.                  case 'l':      /* longer form of "ls -l" type listing */
  3271.                      if (negative)
  3272. -                        uO.lflag = -2, negative = 0;
  3273. +                        uO.lflag = -2;
  3274.                      else
  3275.                          uO.lflag = 5;
  3276. @@ -517,5 +581,5 @@
  3277.                  case 'm':      /* medium form of "ls -l" type listing */
  3278.                      if (negative)
  3279. -                        uO.lflag = -2, negative = 0;
  3280. +                        uO.lflag = -2;
  3281.                      else
  3282.                          uO.lflag = 4;
  3283. @@ -524,5 +588,5 @@
  3284.                  case 'M':      /* send output through built-in "more" */
  3285.                      if (negative)
  3286. -                        G.M_flag = FALSE, negative = 0;
  3287. +                        G.M_flag = FALSE;
  3288.                      else
  3289.                          G.M_flag = TRUE;
  3290. @@ -531,5 +595,5 @@
  3291.                  case 's':      /* default:  shorter "ls -l" type listing */
  3292.                      if (negative)
  3293. -                        uO.lflag = -2, negative = 0;
  3294. +                        uO.lflag = -2;
  3295.                      else
  3296.                          uO.lflag = 3;
  3297. @@ -537,5 +601,5 @@
  3298.                  case 't':      /* totals line */
  3299.                      if (negative)
  3300. -                        tflag_2v = tflag_slm = FALSE, negative = 0;
  3301. +                        tflag_2v = tflag_slm = FALSE;
  3302.                      else {
  3303.                          tflag_2v = tflag_slm = explicit_t = TRUE;
  3304. @@ -546,5 +610,5 @@
  3305.                  case ('T'):    /* use (sortable) decimal time format */
  3306.                      if (negative)
  3307. -                        uO.T_flag = FALSE, negative = 0;
  3308. +                        uO.T_flag = FALSE;
  3309.                      else
  3310.                          uO.T_flag = TRUE;
  3311. @@ -552,8 +616,7 @@
  3312.  #ifdef UNICODE_SUPPORT
  3313.                  case ('U'):    /* escape UTF-8, or disable UTF-8 support */
  3314. -                    if (negative) {
  3315. -                        uO.U_flag = MAX(uO.U_flag-negative,0);
  3316. -                        negative = 0;
  3317. -                    } else
  3318. +                    if (negative)
  3319. +                        uO.U_flag = MAX(uO.U_flag - 1, 0);
  3320. +                    else
  3321.                          uO.U_flag++;
  3322.                      break;
  3323. @@ -561,5 +624,5 @@
  3324.                  case 'v':      /* turbo-verbose listing */
  3325.                      if (negative)
  3326. -                        uO.lflag = -2, negative = 0;
  3327. +                        uO.lflag = -2;
  3328.                      else
  3329.                          uO.lflag = 10;
  3330. @@ -568,12 +631,36 @@
  3331.                  case ('W'):    /* Wildcard interpretation (stop at '/'?) */
  3332.                      if (negative)
  3333. -                        uO.W_flag = FALSE, negative = 0;
  3334. +                        uO.W_flag = FALSE;
  3335.                      else
  3336.                          uO.W_flag = TRUE;
  3337.                      break;
  3338.  #endif /* WILD_STOP_AT_DIR */
  3339. +                case ('x'):    /* extract:  default */
  3340. +                    /* add -x file to linked list */
  3341. +
  3342. +                    if (in_xfiles_count == 0) {
  3343. +                        /* first entry */
  3344. +                        if ((in_xfiles = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
  3345. +                            Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3346. +                            return PK_MEM;
  3347. +                        }
  3348. +                        in_xfiles->name = value;
  3349. +                        in_xfiles->next = NULL;
  3350. +                        next_in_xfiles = in_xfiles;
  3351. +                    } else {
  3352. +                        /* add next entry */
  3353. +                        if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
  3354. +                            Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3355. +                            return PK_MEM;
  3356. +                        }
  3357. +                        next_in_xfiles->next = next_file;
  3358. +                        next_file->name = value;
  3359. +                        next_file->next = NULL;
  3360. +                        next_in_xfiles = next_file;
  3361. +                    }
  3362. +                    in_xfiles_count++;
  3363.                  case 'z':      /* print zipfile comment */
  3364.                      if (negative)
  3365. -                        uO.zflag = negative = 0;
  3366. +                        uO.zflag = 0;
  3367.                      else
  3368.                          uO.zflag = 1;
  3369. @@ -581,13 +668,96 @@
  3370.                  case 'Z':      /* ZipInfo mode:  ignore */
  3371.                      break;
  3372. +                case o_NON_OPTION_ARG:
  3373. +                    /* not an option */
  3374. +                    /* no more options as permuting */
  3375. +
  3376. +
  3377. +                    if (G.wildzipfn == NULL) {
  3378. +                        /* first non-option argument is zip file */
  3379. +                        G.wildzipfn = value;
  3380. +
  3381. +                    } else {
  3382. +                        /* add include file to list */
  3383. +                        if (in_files_count == 0) {
  3384. +                            /* first entry */
  3385. +                            if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
  3386. +                                Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3387. +                                return PK_MEM;
  3388. +                            }
  3389. +                            next_file->name = value;
  3390. +                            next_file->next = NULL;
  3391. +                            in_files = next_file;
  3392. +                            next_in_files = next_file;
  3393. +                        } else {
  3394. +                            /* add next entry */
  3395. +                            if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
  3396. +                                Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3397. +                                return PK_MEM;
  3398. +                            }
  3399. +                            next_in_files->next = next_file;
  3400. +                            next_file->name = value;
  3401. +                            next_file->next = NULL;
  3402. +                            next_in_files = next_file;
  3403. +                        }
  3404. +                        in_files_count++;
  3405. +                    }
  3406. +                    break;
  3407.                  default:
  3408.                      error = TRUE;
  3409.                      break;
  3410. -            }
  3411. -        }
  3412. +        } /* switch */
  3413. +    } /* get_option() */
  3414. +
  3415. +    /* convert files and xfiles lists to arrays */
  3416. +
  3417. +    /* convert files list to array */
  3418. +    if (in_files_count) {
  3419. +      if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))) == NULL) {
  3420. +          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3421. +          return PK_MEM;
  3422. +      }
  3423. +      file_count = 0;
  3424. +      for (next_file = in_files; next_file;) {
  3425. +          G.pfnames[file_count] = next_file->name;
  3426. +          in_files = next_file;
  3427. +          next_file = next_file->next;
  3428. +          free(in_files);
  3429. +          file_count++;
  3430. +      }
  3431. +      G.pfnames[file_count] = NULL;
  3432. +      G.filespecs = in_files_count;
  3433. +    }
  3434. +
  3435. +    /* convert xfiles list to array */
  3436. +    if (in_xfiles_count) {
  3437. +      if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))) == NULL) {
  3438. +          Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
  3439. +          return PK_MEM;
  3440. +      }
  3441. +      file_count = 0;
  3442. +      for (next_file = in_xfiles; next_file;) {
  3443. +          G.pxnames[file_count] = next_file->name;
  3444. +          in_xfiles = next_file;
  3445. +          next_file = next_file->next;
  3446. +          free(in_xfiles);
  3447. +          file_count++;
  3448. +      }
  3449. +      G.pxnames[file_count] = NULL;
  3450. +      G.xfilespecs = in_xfiles_count;
  3451.      }
  3452. -    if ((argc-- == 0) || error) {
  3453. +
  3454. +    if (in_files_count || in_xfiles_count) {
  3455. +        G.process_all_files = FALSE;
  3456. +    } else {
  3457. +        G.process_all_files = TRUE;      /* for speed */
  3458. +    }
  3459. +
  3460. +    /* it's possible the arg count could have been changed by get_option() */
  3461. +    argc = arg_count(args);
  3462. +
  3463. +    if ((G.wildzipfn == NULL) || error) {
  3464. +        argc = -1;      /* tell the caller to stop processing */
  3465.          *pargc = argc;
  3466. -        *pargv = argv;
  3467. +        *pargv = args;
  3468.          return USAGE(error);
  3469.      }
  3470. @@ -628,5 +798,5 @@
  3471.  
  3472.      *pargc = argc;
  3473. -    *pargv = argv;
  3474. +    *pargv = args;
  3475.      return 0;
  3476.  
  3477.