1diff -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+} 2981diff -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 */ 3074diff -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 3135diff -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