kolibrios/programs/fs/unzip60/new-cmdparser/unz6-newcmdparser-diffs.txt
siemargl e9b1c1bac6 unzip initial commit
git-svn-id: svn://kolibrios.org@6725 a494cfbc-eb01-0410-851d-a64ba20cac60
2016-11-18 13:40:05 +00:00

3477 lines
122 KiB
Plaintext

diff -ru2 unz60e03/unzip.c u6e3_np/unzip.c
--- unz60e03/unzip.c Wed Mar 19 13:08:38 2008
+++ u6e3_np/unzip.c Mon Mar 24 14:16:58 2008
@@ -128,4 +128,6 @@
"error: command line parameter #%d exceeds internal size limit\n";
#endif /* !SFX */
+static ZCONST char Far NoMemArgsList[] =
+ "error: no memory for arguments list";
#if (defined(REENTRANT) && !defined(NO_EXCEPT_SIGNALS))
@@ -245,5 +247,5 @@
static ZCONST char Far local3[] = "\
-Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\
- --D restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\
+ -D- restore dir (-D: no) timestamps -M pipe through \"more\" pager\n\
(Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
\n\n";
@@ -251,5 +253,5 @@
static ZCONST char Far local3[] = "\n\
-Y treat \".nnn\" as \";nnn\" version -2 force ODS2 names\n\
- --D restore dir (-D: no) timestamps\n\
+ -D- restore dir (-D: no) timestamps\n\
(Must quote upper-case options, like \"-V\", unless SET PROC/PARSE=EXTEND.)\
\n\n";
@@ -694,5 +696,5 @@
char *p;
#endif
-#if (defined(DOS_FLX_H68_NLM_OS2_W32) || !defined(SFX))
+#if ((defined(WIN32) && defined(__RSXNT__)) || !defined(SFX))
int i;
#endif
@@ -1053,4 +1055,45 @@
* 'forward slashes' for user's convenience (include zipfile name itself)
*/
+ {
+ /* pfnames */
+
+ char **names;
+
+ for (names = G.pfnames; *names; names++) {
+#ifdef __human68k__
+ extern char *_toslash(char *);
+ _toslash(*names);
+#else /* !__human68k__ */
+ char *q = *names;
+
+ while (*q != '\0') {
+ if (*q == '\\')
+ *q = '/';
+ INCSTR(q);
+ }
+#endif /* ?__human68k__ */
+ }
+ }
+ {
+ /* G.wildzipfn */
+
+#ifdef __human68k__
+ extern char *_toslash(char *);
+ _toslash(*G.wildzipfn);
+#else /* !__human68k__ */
+ char *q = G.wildzipfn;
+
+ while (*q != '\0') {
+ if (*q == '\\')
+ *q = '/';
+ INCSTR(q);
+ }
+#endif /* ?__human68k__ */
+ }
+#endif /* DOS_FLX_H68_NLM_OS2_W32 */
+
+
+#if 0
+#ifdef DOS_FLX_H68_NLM_OS2_W32
#ifdef SFX
for (G.pfnames = argv, i = argc; i > 0; --i) {
@@ -1074,11 +1117,18 @@
}
#endif /* DOS_FLX_H68_NLM_OS2_W32 */
+#endif /* 0 */
+/*
#ifndef SFX
G.wildzipfn = *argv++;
#endif
+*/
#if (defined(SFX) && !defined(SFX_EXDIR)) /* only check for -x */
+# if 0
+ /* all this should be done in the options call now */
+
+
G.filespecs = argc;
G.xfilespecs = 0;
@@ -1104,7 +1154,10 @@
} else
G.process_all_files = TRUE; /* for speed */
+# endif
#else /* !SFX || SFX_EXDIR */ /* check for -x or -d */
+# if 0
+
G.filespecs = argc;
G.xfilespecs = 0;
@@ -1118,9 +1171,9 @@
while (*++pp) {
Trace((stderr, "pp - argv = %d\n", pp-argv));
-#ifdef CMS_MVS
+# ifdef CMS_MVS
if (!uO.exdir && STRNICMP(*pp, "-d", 2) == 0) {
-#else
+# else
if (!uO.exdir && strncmp(*pp, "-d", 2) == 0) {
-#endif
+# endif
int firstarg = (pp == argv);
@@ -1177,4 +1230,5 @@
} else
G.process_all_files = TRUE; /* for speed */
+# endif
if (uO.exdir != (char *)NULL && !G.extract_flag) /* -d ignored */
@@ -1260,4 +1314,269 @@
+/*
+ -------------------------------------------------------
+ Command Line Options
+ -------------------------------------------------------
+
+ Valid command line options.
+
+ The function get_option() uses this table to check if an
+ option is valid and if it takes a value (also called an
+ option parameter). To add an option to unzip just add it
+ to this table and add a case in the main switch to handle
+ it. If either shortopt or longopt not used set to "".
+
+ The fields:
+ option_group - UZO for UnZip option, ZIO for ZipInfo option
+ shortopt - short option name (1 or 2 chars)
+ longopt - long option name
+ value_type - see zip.h for constants
+ negatable - option is negatable with trailing -
+ ID - unsigned long int returned for option
+ name - short description of option which is
+ returned on some errors and when options
+ are listed with -so option, can be NULL
+*/
+
+/* Most option IDs are set to the shortopt char. For
+ multichar short options set to arbitrary unused constant. */
+#define o_so 0x101
+
+
+/* The below is from the old main command line code with a few changes.
+ Note that UnZip and ZipInfo filter out their own options based on the
+ option_group value, so the same option letter can be used for both. */
+
+static struct option_struct far options[] = {
+
+ /* UnZip options */
+
+ /* short longopt value_type negatable
+ ID name */
+#ifdef RISCOS
+ {UZO, "/", "", o_REQUIRED_VALUE, o_NEGATABLE,
+ '/', "override Unzip$Exts"},
+#endif
+ {UZO, "a", "", o_NO_VALUE, o_NEGATABLE,
+ 'a', "text conv (EOL char, ASCII->EBCDIC"},
+#if (defined(DLL) && defined(API_DOC))
+ {UZO, "A", "", o_NO_VALUE, o_NEGATABLE,
+ 'A', "extended help for API"},
+#endif
+ {UZO, "b", "", o_NO_VALUE, o_NEGATABLE,
+ 'b', "binary, no ASCII conversions"},
+#ifdef UNIXBACKUP
+ {UZO, "B", "", o_NO_VALUE, o_NEGATABLE,
+ 'B', "back up existing files"},
+#endif
+#ifdef CMS_MVS
+ {UZO, "B", "", o_NO_VALUE, o_NEGATABLE,
+ 'b', "CMS/MVS binary"},
+#endif
+ {UZO, "c", "", o_NO_VALUE, o_NEGATABLE,
+ 'c', "output to stdout"},
+#ifdef CMS_MVS
+ /* for CMS_MVS map to lower case */
+ {UZO, "C", "", o_NO_VALUE, o_NEGATABLE,
+ 'C', "CMS/MVS lower case"},
+#endif
+#if (!defined(SFX) || defined(SFX_EXDIR))
+ {UZO, "d", "", o_REQUIRED_VALUE, o_NEGATABLE,
+ 'd', "extraction root directory"},
+#endif
+#if (!defined(NO_TIMESTAMPS))
+ {UZO, "D", "", o_NO_VALUE, o_NEGATABLE,
+ 'D', "don't restore dir (-DD: any) timestamps"},
+#endif
+ {UZO, "e", "", o_NO_VALUE, o_NEGATABLE,
+ 'e', "extract (not used?)"},
+#ifdef MACOS
+ {UZO, "E", "", o_NO_VALUE, o_NEGATABLE,
+ 'E', "display Mac e.f. when restoring"},
+#endif
+ {UZO, "f", "", o_NO_VALUE, o_NEGATABLE,
+ 'f', "freshen (extract only newer files)"},
+#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
+ {UZO, "F", "", o_NO_VALUE, o_NEGATABLE,
+ 'F', "Acorn filetype & NFS extension handling"},
+#endif
+ {UZO, "h", "", o_NO_VALUE, o_NOT_NEGATABLE,
+ 'h', "help"},
+#ifdef MACOS
+ {UZO, "i", "", o_NO_VALUE, o_NEGATABLE,
+ 'i', "ignore filenames stored in Mac ef"},
+#endif
+ {UZO, "j", "", o_NO_VALUE, o_NEGATABLE,
+ 'j', "junk directories, extract names only"},
+#if (defined(ATH_BEO) || defined(MACOS))
+ {UZO, "J", "", o_NO_VALUE, o_NEGATABLE,
+ 'J', "Junk AtheOS, BeOS or MacOS file attrs"},
+#endif
+#ifdef ATH_BEO_UNX
+ {UZO, "K", "", o_NO_VALUE, o_NEGATABLE,
+ 'K', "retain SUID/SGID/Tacky attrs"},
+#endif
+#ifndef SFX
+ {UZO, "l", "", o_NO_VALUE, o_NEGATABLE,
+ 'l', "listing verbosity"},
+#endif
+#ifndef CMS_MVS
+ {UZO, "L", "", o_NO_VALUE, o_NEGATABLE,
+ 'L', "convert (some) names to lower"},
+#endif
+#ifdef MORE
+# ifdef CMS_MVS
+ {UZO, "m", "", o_NO_VALUE, o_NEGATABLE,
+ 'm', "pipe output through more"},
+# endif
+ {UZO, "M", "", o_NO_VALUE, o_NEGATABLE,
+ 'M', "pipe output through more"},
+#endif /* MORE */
+ {UZO, "n", "", o_NO_VALUE, o_NEGATABLE,
+ 'n', "never overwrite files (no prompting)"},
+#ifdef AMIGA
+ {UZO, "N", "", o_NO_VALUE, o_NEGATABLE,
+ 'N', "restore comments as filenotes"},
+#endif
+ {UZO, "o", "", o_NO_VALUE, o_NEGATABLE,
+ 'o', "overwrite files without prompting"},
+ {UZO, "p", "", o_NO_VALUE, o_NEGATABLE,
+ 'p', "pipe extraction to stdout, no messages"},
+#if CRYPT
+ {UZO, "P", "", o_REQUIRED_VALUE, o_NEGATABLE,
+ 'P', "password"},
+#endif
+ {UZO, "q", "", o_NO_VALUE, o_NEGATABLE,
+ 'q', "quiet"},
+#ifdef QDOS
+ {UZO, "Q", "", o_NO_VALUE, o_NEGATABLE,
+ 'Q', "QDOS flags"},
+#endif
+#ifdef TANDEM
+ {UZO, "r", "", o_NO_VALUE, o_NEGATABLE,
+ 'r', "remove file extensions"},
+#endif
+#ifdef DOS_FLX_NLM_OS2_W32
+ {UZO, "s", "", o_NO_VALUE, o_NEGATABLE,
+ 's', "spaces to underscores"},
+#endif
+#ifdef VMS
+ {UZO, "S", "", o_NO_VALUE, o_NEGATABLE,
+ 'S', "VMS extract text as Stream LF"},
+#endif
+ {UZO, "t", "", o_NO_VALUE, o_NEGATABLE,
+ 't', "test"},
+#ifdef TIMESTAMP
+ {UZO, "T", "", o_NO_VALUE, o_NEGATABLE,
+ 'T', "timestamps"},
+#endif
+ {UZO, "u", "", o_NO_VALUE, o_NEGATABLE,
+ 'u', "update (extract only new/newer files)"},
+#ifdef UNICODE_SUPPORT
+ {UZO, "U", "", o_NO_VALUE, o_NEGATABLE,
+ 'U', "escape non-ASCII Unicode, disable Unicode"},
+#else /* !UNICODE_SUPPORT */
+# ifndef CMS_MVS
+ {UZO, "U", "", o_NO_VALUE, o_NEGATABLE,
+ 'U', "names to lower case"},
+# endif /* !CMS_MVS */
+#endif /* ?UNICODE_SUPPORT */
+#ifndef SFX
+ {UZO, "v", "", o_NO_VALUE, o_NEGATABLE,
+ 'v', "verbose"},
+#endif
+#ifndef CMS_MVS
+ {UZO, "V", "", o_NO_VALUE, o_NEGATABLE,
+ 'V', "don't strip VMS version numbers"},
+#endif
+#ifdef WILD_STOP_AT_DIR
+ {UZO, "W", "", o_NO_VALUE, o_NEGATABLE,
+ 'W', "wildcard * doesn't span /"},
+#endif
+ {UZO, "x", "", o_VALUE_LIST, o_NOT_NEGATABLE,
+ 'x', "exclude this list of files"},
+#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
+ {UZO, "X", "", o_NO_VALUE, o_NEGATABLE,
+ 'X', "restore owner/prot or UID/GID or ACLs"},
+#endif
+#ifdef VMS
+ {UZO, "Y", "", o_NO_VALUE, o_NEGATABLE,
+ 'Y', "VMS treat .nnn as ;nnn version"},
+#endif
+ {UZO, "z", "", o_NO_VALUE, o_NEGATABLE,
+ 'z', "display zipfile comment"},
+#ifndef SFX
+ {UZO, "Z", "", o_NO_VALUE, o_NOT_NEGATABLE,
+ 'Z', "ZipInfo mode"},
+#endif
+#ifdef VMS
+ {UZO, "2", "", o_NO_VALUE, o_NEGATABLE,
+ '2', "Force ODS2-compliant names."},
+#endif
+#ifdef DOS_H68_OS2_W32
+ {UZO, "$", "", o_NO_VALUE, o_NEGATABLE,
+ '$', "extract volume labels"},
+#endif
+#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
+ {UZO, ":", "", o_NO_VALUE, o_NEGATABLE,
+ ':', "don't skip ../ path elements"},
+#endif
+#ifdef UNIX
+ {UZO, "^", "", o_NO_VALUE, o_NEGATABLE,
+ '^', "allow control chars in filenames"},
+#endif
+
+#ifndef NO_ZIPINFO
+ /* ZipInfo options */
+
+ /* short longopt value_type negatable
+ ID name (help text) */
+ {ZIO, "1", "", o_NO_VALUE, o_NEGATABLE,
+ '1', "shortest list"},
+ {ZIO, "2", "", o_NO_VALUE, o_NEGATABLE,
+ '2', "names and headers"},
+#ifndef CMS_MVS
+ {ZIO, "C", "", o_NO_VALUE, o_NEGATABLE,
+ 'C', "ignore case"},
+#endif
+ {ZIO, "h", "", o_NO_VALUE, o_NEGATABLE,
+ 'h', "header line"},
+ {ZIO, "l", "", o_NO_VALUE, o_NEGATABLE,
+ 'l', "longer listing"},
+ {ZIO, "m", "", o_NO_VALUE, o_NEGATABLE,
+ 'm', "medium listing"},
+#ifdef MORE
+ {ZIO, "M", "", o_NO_VALUE, o_NEGATABLE,
+ 'M', "output like more"},
+#endif
+ {ZIO, "s", "", o_NO_VALUE, o_NEGATABLE,
+ 's', "shorter list"},
+ {ZIO, "t", "", o_NO_VALUE, o_NEGATABLE,
+ 't', "totals line"},
+ {ZIO, "T", "", o_NO_VALUE, o_NEGATABLE,
+ 'T', "decimal time format"},
+#ifdef UNICODE_SUPPORT
+ {ZIO, "U", "", o_NO_VALUE, o_NEGATABLE,
+ 'U', "escape non-ASCII Unicode, disable Unicode"},
+#endif
+ {ZIO, "v", "", o_NO_VALUE, o_NEGATABLE,
+ 'v', "turbo-verbose listing"},
+#ifdef WILD_STOP_AT_DIR
+ {ZIO, "W", "", o_NO_VALUE, o_NEGATABLE,
+ 'W', "wild stop at /"},
+#endif
+ {ZIO, "x", "", o_VALUE_LIST, o_NOT_NEGATABLE,
+ 'x', "exclude this list of files"},
+ {ZIO, "z", "", o_NO_VALUE, o_NEGATABLE,
+ 'z', "print zipfile comment"},
+ {ZIO, "Z", "", o_NO_VALUE, o_NEGATABLE,
+ 'Z', "ZipInfo mode"},
+#endif /* !NO_ZIPINFO */
+
+ /* the end of the list */
+ {0, NULL, NULL, o_NO_VALUE, o_NOT_NEGATABLE,
+ 0, NULL} /* end has option_ID = 0 */
+ };
+
@@ -1271,502 +1590,649 @@
char ***pargv;
{
- char **argv, *s;
- int argc, c, error=FALSE, negative=0;
+ char **args;
+ int argc, error=FALSE;
+ /* used by get_option */
+ unsigned long option; /* option ID returned by get_option */
+ int argcnt = 0; /* current argcnt in args */
+ int argnum = 0; /* arg number */
+ int optchar = 0; /* option state */
+ char *value = NULL; /* non-option arg, option value or NULL */
+ int negative = 0; /* 1 = option negated */
+ int fna = 0; /* current first non-opt arg */
+ int optnum = 0; /* index in table */
- argc = *pargc;
- argv = *pargv;
- while (++argv, (--argc > 0 && *argv != NULL && **argv == '-')) {
- s = *argv + 1;
- while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
-#ifdef CMS_MVS
- switch (tolower(c))
-#else
- switch (c)
-#endif
- {
- case ('-'):
- ++negative;
- break;
+ /* since get_option() returns xfiles and files one at a time, store them
+ in linked lists until have them all */
+
+ int file_count = 0;
+ struct file_list *next_file;
+
+ /* files to extract */
+ int in_files_count = 0;
+ struct file_list *in_files = NULL;
+ struct file_list *next_in_files = NULL;
+
+ /* files to exclude in -x list */
+ int in_xfiles_count = 0;
+ struct file_list *in_xfiles = NULL;
+ struct file_list *next_in_xfiles = NULL;
+
+ G.wildzipfn = NULL;
+
+ /* make copy of args that can use with insert_arg() used by get_option() */
+ args = copy_args(*pargv, 0);
+
+
+ /* Initialize lists */
+ G.filespecs = 0;
+ G.xfilespecs = 0;
+
+
+ /*
+ -------------------------------------------
+ Process command line using get_option
+ -------------------------------------------
+
+ Each call to get_option() returns either a command
+ line option and possible value or a non-option argument.
+ Arguments are permuted so that all options (-r, -b temp)
+ are returned before non-option arguments (zipfile).
+ Returns 0 when nothing left to read.
+ */
+
+ /* set argnum = 0 on first call to init get_option */
+ argnum = 0;
+
+ /* get_option returns the option ID and updates parameters:
+ args - usually same as argv if no argument file support
+ argcnt - current argc for args
+ value - char* to value (free() when done with it) or NULL if none
+ negated - option was negated with trailing -
+ */
+
+ while ((option = get_option(UZO, &args, &argcnt, &argnum,
+ &optchar, &value, &negative,
+ &fna, &optnum, 0)))
+ {
+ if(option == o_BAD_ERR) {
+ return(PK_PARAM);
+ }
+
+ switch (option)
+ {
#ifdef RISCOS
- case ('/'):
- if (negative) { /* negative not allowed with -/ swap */
- Info(slide, 0x401, ((char *)slide,
- "error: must give extensions list"));
- return(PK_PARAM); /* don't extract here by accident */
- }
- exts2swap = s; /* override Unzip$Exts */
- s += strlen(s);
- break;
-#endif
- case ('a'):
- if (negative) {
- uO.aflag = MAX(uO.aflag-negative,0);
- negative = 0;
- } else
- ++uO.aflag;
- break;
+ case ('/'):
+ if (negative) { /* negative not allowed with -/ swap */
+ Info(slide, 0x401, ((char *)slide,
+ "error: must give extensions list"));
+ return(PK_PARAM); /* don't extract here by accident */
+ }
+ exts2swap = value; /* override Unzip$Exts */
+ break;
+#endif
+ case ('a'):
+ if (negative) {
+ uO.aflag = MAX(uO.aflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.aflag;
+ break;
#if (defined(DLL) && defined(API_DOC))
- case ('A'): /* extended help for API */
- APIhelp(__G__ argc, argv);
- *pargc = -1; /* signal to exit successfully */
- return 0;
+ case ('A'): /* extended help for API */
+ APIhelp(__G__ argc, args);
+ *pargc = -1; /* signal to exit successfully */
+ return 0;
#endif
- case ('b'):
- if (negative) {
+ case ('b'):
+ if (negative) {
#if (defined(TANDEM) || defined(VMS))
- uO.bflag = MAX(uO.bflag-negative,0);
+ uO.bflag = MAX(uO.bflag-negative,0);
#endif
- negative = 0; /* do nothing: "-b" is default */
- } else {
+ negative = 0; /* do nothing: "-b" is default */
+ } else {
#ifdef VMS
- if (uO.aflag == 0)
- ++uO.bflag;
+ if (uO.aflag == 0)
+ ++uO.bflag;
#endif
#ifdef TANDEM
- ++uO.bflag;
+ ++uO.bflag;
#endif
- uO.aflag = 0;
- }
- break;
+ uO.aflag = 0;
+ }
+ break;
#ifdef UNIXBACKUP
- case ('B'): /* -B: back up existing files */
- if (negative)
- uO.B_flag = FALSE, negative = 0;
- else
- uO.B_flag = TRUE;
- break;
-#endif
- case ('c'):
- if (negative) {
- uO.cflag = FALSE, negative = 0;
+ case ('B'): /* -B: back up existing files */
+ if (negative)
+ uO.B_flag = FALSE, negative = 0;
+ else
+ uO.B_flag = TRUE;
+ break;
+#endif
+ case ('c'):
+ if (negative) {
+ uO.cflag = FALSE, negative = 0;
#ifdef NATIVE
- uO.aflag = 0;
+ uO.aflag = 0;
#endif
- } else {
- uO.cflag = TRUE;
+ } else {
+ uO.cflag = TRUE;
#ifdef NATIVE
- uO.aflag = 2; /* so you can read it on the screen */
+ uO.aflag = 2; /* so you can read it on the screen */
#endif
#ifdef DLL
- if (G.redirect_text)
- G.redirect_data = 2;
+ if (G.redirect_text)
+ G.redirect_data = 2;
#endif
- }
- break;
+ }
+ break;
#ifndef CMS_MVS
- case ('C'): /* -C: match filenames case-insensitively */
- if (negative)
- uO.C_flag = FALSE, negative = 0;
- else
- uO.C_flag = TRUE;
- break;
+ case ('C'): /* -C: match filenames case-insensitively */
+ if (negative)
+ uO.C_flag = FALSE, negative = 0;
+ else
+ uO.C_flag = TRUE;
+ break;
#endif /* !CMS_MVS */
#if (!defined(SFX) || defined(SFX_EXDIR))
- case ('d'):
- if (negative) { /* negative not allowed with -d exdir */
+ case ('d'):
+ if (negative) { /* negative not allowed with -d exdir */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(MustGiveExdir)));
+ return(PK_PARAM); /* don't extract here by accident */
+ }
+ if (uO.exdir != (char *)NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OnlyOneExdir)));
+ return(PK_PARAM); /* GRR: stupid restriction? */
+ } else {
+ /* first check for "-dexdir", then for "-d exdir" */
+ uO.exdir = value;
+ if (uO.exdir == NULL || *uO.exdir == '\0') {
Info(slide, 0x401, ((char *)slide,
LoadFarString(MustGiveExdir)));
- return(PK_PARAM); /* don't extract here by accident */
- }
- if (uO.exdir != (char *)NULL) {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(OnlyOneExdir)));
- return(PK_PARAM); /* GRR: stupid restriction? */
- } else {
- /* first check for "-dexdir", then for "-d exdir" */
- uO.exdir = s;
- if (*uO.exdir == '\0') {
- if (argc > 1) {
- --argc;
- uO.exdir = *++argv;
- if (*uO.exdir == '-') {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(MustGiveExdir)));
- return(PK_PARAM);
- }
- /* else uO.exdir points at extraction dir */
- } else {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(MustGiveExdir)));
- return(PK_PARAM);
- }
- }
- /* uO.exdir now points at extraction dir (-dexdir or
- * -d exdir); point s at end of exdir to avoid mis-
- * interpretation of exdir characters as more options
- */
- if (*s != 0)
- while (*++s != 0)
- ;
+ return(PK_PARAM);
}
- break;
+ /* else uO.exdir points at extraction dir */
+ }
+ break;
#endif /* !SFX || SFX_EXDIR */
#if (!defined(NO_TIMESTAMPS))
- case ('D'): /* -D: Skip restoring dir (or any) timestamp. */
- if (negative) {
- uO.D_flag = MAX(uO.D_flag-negative,0);
- negative = 0;
- } else
- uO.D_flag++;
- break;
+ case ('D'): /* -D: Skip restoring dir (or any) timestamp. */
+ if (negative) {
+ uO.D_flag = MAX(uO.D_flag-negative,0);
+ negative = 0;
+ } else
+ uO.D_flag++;
+ break;
#endif /* (!NO_TIMESTAMPS) */
- case ('e'): /* just ignore -e, -x options (extract) */
- break;
+ case ('e'): /* just ignore -e, -x options (extract) */
+ break;
#ifdef MACOS
- case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
- if( negative ) {
- uO.E_flag = FALSE, negative = 0;
- } else {
- uO.E_flag = TRUE;
- }
- break;
+ case ('E'): /* -E [MacOS] display Mac e.f. when restoring */
+ if( negative ) {
+ uO.E_flag = FALSE, negative = 0;
+ } else {
+ uO.E_flag = TRUE;
+ }
+ break;
#endif /* MACOS */
- case ('f'): /* "freshen" (extract only newer files) */
- if (negative)
- uO.fflag = uO.uflag = FALSE, negative = 0;
- else
- uO.fflag = uO.uflag = TRUE;
- break;
+ case ('f'): /* "freshen" (extract only newer files) */
+ if (negative)
+ uO.fflag = uO.uflag = FALSE, negative = 0;
+ else
+ uO.fflag = uO.uflag = TRUE;
+ break;
#if (defined(RISCOS) || defined(ACORN_FTYPE_NFS))
- case ('F'): /* Acorn filetype & NFS extension handling */
- if (negative)
- uO.acorn_nfs_ext = FALSE, negative = 0;
- else
- uO.acorn_nfs_ext = TRUE;
- break;
+ case ('F'): /* Acorn filetype & NFS extension handling */
+ if (negative)
+ uO.acorn_nfs_ext = FALSE, negative = 0;
+ else
+ uO.acorn_nfs_ext = TRUE;
+ break;
#endif /* RISCOS || ACORN_FTYPE_NFS */
- case ('h'): /* just print help message and quit */
- *pargc = -1;
- return USAGE(PK_OK);
+ case ('h'): /* just print help message and quit */
+ *pargc = -1;
+ return USAGE(PK_OK);
#ifdef MACOS
- case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
- if( negative ) {
- uO.i_flag = FALSE, negative = 0;
- } else {
- uO.i_flag = TRUE;
- }
- break;
+ case ('i'): /* -i [MacOS] ignore filenames stored in Mac ef */
+ if( negative ) {
+ uO.i_flag = FALSE, negative = 0;
+ } else {
+ uO.i_flag = TRUE;
+ }
+ break;
#endif /* MACOS */
- case ('j'): /* junk pathnames/directory structure */
- if (negative)
- uO.jflag = FALSE, negative = 0;
- else
- uO.jflag = TRUE;
- break;
+ case ('j'): /* junk pathnames/directory structure */
+ if (negative)
+ uO.jflag = FALSE, negative = 0;
+ else
+ uO.jflag = TRUE;
+ break;
#if (defined(ATH_BEO) || defined(MACOS))
- case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */
- if( negative ) {
- uO.J_flag = FALSE, negative = 0;
- } else {
- uO.J_flag = TRUE;
- }
- break;
+ case ('J'): /* Junk AtheOS, BeOS or MacOS file attributes */
+ if( negative ) {
+ uO.J_flag = FALSE, negative = 0;
+ } else {
+ uO.J_flag = TRUE;
+ }
+ break;
#endif /* ATH_BEO || MACOS */
#ifdef ATH_BEO_UNX
- case ('K'):
- if (negative) {
- uO.K_flag = FALSE, negative = 0;
- } else {
- uO.K_flag = TRUE;
- }
- break;
+ case ('K'):
+ if (negative) {
+ uO.K_flag = FALSE, negative = 0;
+ } else {
+ uO.K_flag = TRUE;
+ }
+ break;
#endif /* ATH_BEO_UNX */
#ifndef SFX
- case ('l'):
- if (negative) {
- uO.vflag = MAX(uO.vflag-negative,0);
- negative = 0;
- } else
- ++uO.vflag;
- break;
+ case ('l'):
+ if (negative) {
+ uO.vflag = MAX(uO.vflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.vflag;
+ break;
#endif /* !SFX */
#ifndef CMS_MVS
- case ('L'): /* convert (some) filenames to lowercase */
- if (negative) {
- uO.L_flag = MAX(uO.L_flag-negative,0);
- negative = 0;
- } else
- ++uO.L_flag;
- break;
+ case ('L'): /* convert (some) filenames to lowercase */
+ if (negative) {
+ uO.L_flag = MAX(uO.L_flag-negative,0);
+ negative = 0;
+ } else
+ ++uO.L_flag;
+ break;
#endif /* !CMS_MVS */
#ifdef MORE
#ifdef CMS_MVS
- case ('m'):
+ case ('m'):
#endif
- case ('M'): /* send all screen output through "more" fn. */
+ case ('M'): /* send all screen output through "more" fn. */
/* GRR: eventually check for numerical argument => height */
- if (negative)
- G.M_flag = FALSE, negative = 0;
- else
- G.M_flag = TRUE;
- break;
+ if (negative)
+ G.M_flag = FALSE, negative = 0;
+ else
+ G.M_flag = TRUE;
+ break;
#endif /* MORE */
- case ('n'): /* don't overwrite any files */
- if (negative)
- uO.overwrite_none = FALSE, negative = 0;
- else
- uO.overwrite_none = TRUE;
- break;
+ case ('n'): /* don't overwrite any files */
+ if (negative)
+ uO.overwrite_none = FALSE, negative = 0;
+ else
+ uO.overwrite_none = TRUE;
+ break;
#ifdef AMIGA
- case ('N'): /* restore comments as filenotes */
- if (negative)
- uO.N_flag = FALSE, negative = 0;
- else
- uO.N_flag = TRUE;
- break;
+ case ('N'): /* restore comments as filenotes */
+ if (negative)
+ uO.N_flag = FALSE, negative = 0;
+ else
+ uO.N_flag = TRUE;
+ break;
#endif /* AMIGA */
- case ('o'): /* OK to overwrite files without prompting */
- if (negative) {
- uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
- negative = 0;
- } else
- ++uO.overwrite_all;
- break;
- case ('p'): /* pipes: extract to stdout, no messages */
- if (negative) {
- uO.cflag = FALSE;
- uO.qflag = MAX(uO.qflag-999,0);
- negative = 0;
- } else {
- uO.cflag = TRUE;
- uO.qflag += 999;
- }
- break;
+ case ('o'): /* OK to overwrite files without prompting */
+ if (negative) {
+ uO.overwrite_all = MAX(uO.overwrite_all-negative,0);
+ negative = 0;
+ } else
+ ++uO.overwrite_all;
+ break;
+ case ('p'): /* pipes: extract to stdout, no messages */
+ if (negative) {
+ uO.cflag = FALSE;
+ uO.qflag = MAX(uO.qflag-999,0);
+ negative = 0;
+ } else {
+ uO.cflag = TRUE;
+ uO.qflag += 999;
+ }
+ break;
#if CRYPT
- /* GRR: yes, this is highly insecure, but dozens of people
- * have pestered us for this, so here we go... */
- case ('P'):
- if (negative) { /* negative not allowed with -P passwd */
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(MustGivePasswd)));
- return(PK_PARAM); /* don't extract here by accident */
- }
- if (uO.pwdarg != (char *)NULL) {
+ /* GRR: yes, this is highly insecure, but dozens of people
+ * have pestered us for this, so here we go... */
+ case ('P'):
+ if (negative) { /* negative not allowed with -P passwd */
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(MustGivePasswd)));
+ return(PK_PARAM); /* don't extract here by accident */
+ }
+ if (uO.pwdarg != (char *)NULL) {
/*
- GRR: eventually support multiple passwords?
+ GRR: eventually support multiple passwords?
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(OnlyOnePasswd)));
+ return(PK_PARAM);
+*/
+ } else {
+ /* first check for "-Ppasswd", then for "-P passwd" */
+ uO.pwdarg = value;
+ if (uO.pwdarg == NULL || *uO.pwdarg == '\0') {
Info(slide, 0x401, ((char *)slide,
- LoadFarString(OnlyOnePasswd)));
+ LoadFarString(MustGivePasswd)));
return(PK_PARAM);
- */
- } else {
- /* first check for "-Ppasswd", then for "-P passwd" */
- uO.pwdarg = s;
- if (*uO.pwdarg == '\0') {
- if (argc > 1) {
- --argc;
- uO.pwdarg = *++argv;
- if (*uO.pwdarg == '-') {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(MustGivePasswd)));
- return(PK_PARAM);
- }
- /* else pwdarg points at decryption password */
- } else {
- Info(slide, 0x401, ((char *)slide,
- LoadFarString(MustGivePasswd)));
- return(PK_PARAM);
- }
- }
- /* pwdarg now points at decryption password (-Ppasswd or
- * -P passwd); point s at end of passwd to avoid mis-
- * interpretation of passwd characters as more options
- */
- if (*s != 0)
- while (*++s != 0)
- ;
+ /* else pwdarg points at decryption password */
}
- break;
+ }
+ break;
#endif /* CRYPT */
- case ('q'): /* quiet: fewer comments/messages */
- if (negative) {
- uO.qflag = MAX(uO.qflag-negative,0);
- negative = 0;
- } else
- ++uO.qflag;
- break;
+ case ('q'): /* quiet: fewer comments/messages */
+ if (negative) {
+ uO.qflag = MAX(uO.qflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.qflag;
+ break;
#ifdef QDOS
- case ('Q'): /* QDOS flags */
- qlflag ^= strtol(s, &s, 10);
- break; /* we XOR this as we can config qlflags */
+ case ('Q'): /* QDOS flags */
+ qlflag ^= strtol(value, &value, 10);
+ break; /* we XOR this as we can config qlflags */
#endif
#ifdef TANDEM
- case ('r'): /* remove file extensions */
- if (negative)
- uO.rflag = FALSE, negative = 0;
- else
- uO.rflag = TRUE;
- break;
+ case ('r'): /* remove file extensions */
+ if (negative)
+ uO.rflag = FALSE, negative = 0;
+ else
+ uO.rflag = TRUE;
+ break;
#endif /* TANDEM */
#ifdef DOS_FLX_NLM_OS2_W32
- case ('s'): /* spaces in filenames: allow by default */
- if (negative)
- uO.sflag = FALSE, negative = 0;
- else
- uO.sflag = TRUE;
- break;
+ case ('s'): /* spaces in filenames: allow by default */
+ if (negative)
+ uO.sflag = FALSE, negative = 0;
+ else
+ uO.sflag = TRUE;
+ break;
#endif /* DOS_FLX_NLM_OS2_W32 */
#ifdef VMS
- /* VMS: extract "text" files in Stream_LF format (-a[a]) */
- case ('S'):
- if (negative)
- uO.S_flag = FALSE, negative = 0;
- else
- uO.S_flag = TRUE;
- break;
+ /* VMS: extract "text" files in Stream_LF format (-a[a]) */
+ case ('S'):
+ if (negative)
+ uO.S_flag = FALSE, negative = 0;
+ else
+ uO.S_flag = TRUE;
+ break;
#endif /* VMS */
- case ('t'):
- if (negative)
- uO.tflag = FALSE, negative = 0;
- else
- uO.tflag = TRUE;
- break;
+ case ('t'):
+ if (negative)
+ uO.tflag = FALSE, negative = 0;
+ else
+ uO.tflag = TRUE;
+ break;
#ifdef TIMESTAMP
- case ('T'):
- if (negative)
- uO.T_flag = FALSE, negative = 0;
- else
- uO.T_flag = TRUE;
- break;
-#endif
- case ('u'): /* update (extract only new and newer files) */
- if (negative)
- uO.uflag = FALSE, negative = 0;
- else
- uO.uflag = TRUE;
- break;
+ case ('T'):
+ if (negative)
+ uO.T_flag = FALSE, negative = 0;
+ else
+ uO.T_flag = TRUE;
+ break;
+#endif
+ case ('u'): /* update (extract only new and newer files) */
+ if (negative)
+ uO.uflag = FALSE, negative = 0;
+ else
+ uO.uflag = TRUE;
+ break;
#ifdef UNICODE_SUPPORT
- case ('U'): /* escape UTF-8, or disable UTF-8 support */
- if (negative) {
- uO.U_flag = MAX(uO.U_flag-negative,0);
- negative = 0;
- } else
- uO.U_flag++;
- break;
+ case ('U'): /* escape UTF-8, or disable UTF-8 support */
+ if (negative)
+ uO.U_flag = MAX(uO.U_flag - 1, 0);
+ else
+ uO.U_flag++;
+ break;
#else /* !UNICODE_SUPPORT */
#ifndef CMS_MVS
- case ('U'): /* obsolete; to be removed in version 6.0 */
- if (negative)
- uO.L_flag = TRUE, negative = 0;
- else
- uO.L_flag = FALSE;
- break;
+ case ('U'): /* obsolete; to be removed in version 6.0 */
+ if (negative)
+ uO.L_flag = TRUE, negative = 0;
+ else
+ uO.L_flag = FALSE;
+ break;
#endif /* !CMS_MVS */
#endif /* ?UNICODE_SUPPORT */
#ifndef SFX
- case ('v'): /* verbose */
- if (negative) {
- uO.vflag = MAX(uO.vflag-negative,0);
- negative = 0;
- } else if (uO.vflag)
- ++uO.vflag;
- else
- uO.vflag = 2;
- break;
+ case ('v'): /* verbose */
+ if (negative) {
+ uO.vflag = MAX(uO.vflag-negative,0);
+ negative = 0;
+ } else if (uO.vflag)
+ ++uO.vflag;
+ else
+ uO.vflag = 2;
+ break;
#endif /* !SFX */
#ifndef CMS_MVS
- case ('V'): /* Version (retain VMS/DEC-20 file versions) */
- if (negative)
- uO.V_flag = FALSE, negative = 0;
- else
- uO.V_flag = TRUE;
- break;
+ case ('V'): /* Version (retain VMS/DEC-20 file versions) */
+ if (negative)
+ uO.V_flag = FALSE, negative = 0;
+ else
+ uO.V_flag = TRUE;
+ break;
#endif /* !CMS_MVS */
#ifdef WILD_STOP_AT_DIR
- case ('W'): /* Wildcard interpretation (stop at '/'?) */
- if (negative)
- uO.W_flag = FALSE, negative = 0;
- else
- uO.W_flag = TRUE;
- break;
+ case ('W'): /* Wildcard interpretation (stop at '/'?) */
+ if (negative)
+ uO.W_flag = FALSE, negative = 0;
+ else
+ uO.W_flag = TRUE;
+ break;
#endif /* WILD_STOP_AT_DIR */
- case ('x'): /* extract: default */
-#ifdef SFX
- /* when 'x' is the only option in this argument, and the
- * next arg is not an option, assume this initiates an
- * exclusion list (-x xlist): terminate option-scanning
- * and leave uz_opts with argv still pointing to "-x";
- * the xlist is processed later
- */
- if (s - argv[0] == 2 && *s == '\0' &&
- argc > 1 && argv[1][0] != '-') {
- /* break out of nested loops without "++argv;--argc" */
- goto opts_done;
+ case ('x'): /* extract: default */
+ /* add -x file to linked list */
+
+ if (in_xfiles_count == 0) {
+ /* first entry */
+ if ((in_xfiles = (struct file_list *)
+ malloc(sizeof(struct file_list))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NoMemArgsList)));
+ return PK_MEM;
+ }
+ in_xfiles->name = value;
+ in_xfiles->next = NULL;
+ next_in_xfiles = in_xfiles;
+ } else {
+ /* add next entry */
+ if ((next_file = (struct file_list *)
+ malloc(sizeof(struct file_list))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NoMemArgsList)));
+ return PK_MEM;
}
+ next_in_xfiles->next = next_file;
+ next_file->name = value;
+ next_file->next = NULL;
+ next_in_xfiles = next_file;
+ }
+ in_xfiles_count++;
+
+#if 0
+#ifdef SFX
+ /* now get -x list one entry at a time */
+
+
+
+ /* when 'x' is the only option in this argument, and the
+ * next arg is not an option, assume this initiates an
+ * exclusion list (-x xlist): terminate option-scanning
+ * and leave uz_opts with argv still pointing to "-x";
+ * the xlist is processed later
+ */
+ if (s - argv[0] == 2 && *s == '\0' &&
+ argc > 1 && argv[1][0] != '-') {
+ /* break out of nested loops without "++argv;--argc" */
+ goto opts_done;
+ }
#endif /* SFX */
- break;
+#endif
+ break;
#if (defined(RESTORE_UIDGID) || defined(RESTORE_ACL))
- case ('X'): /* restore owner/protection info (need privs?) */
- if (negative) {
- uO.X_flag = MAX(uO.X_flag-negative,0);
- negative = 0;
- } else
- ++uO.X_flag;
- break;
+ case ('X'): /* restore owner/protection info (need privs?) */
+ if (negative) {
+ uO.X_flag = MAX(uO.X_flag-negative,0);
+ negative = 0;
+ } else
+ ++uO.X_flag;
+ break;
#endif /* RESTORE_UIDGID || RESTORE_ACL */
#ifdef VMS
- case ('Y'): /* Treat ".nnn" as ";nnn" version. */
- if (negative)
- uO.Y_flag = FALSE, negative = 0;
- else
- uO.Y_flag = TRUE;
- break;
+ case ('Y'): /* Treat ".nnn" as ";nnn" version. */
+ if (negative)
+ uO.Y_flag = FALSE, negative = 0;
+ else
+ uO.Y_flag = TRUE;
+ break;
#endif /* VMS */
- case ('z'): /* display only the archive comment */
- if (negative) {
- uO.zflag = MAX(uO.zflag-negative,0);
- negative = 0;
- } else
- ++uO.zflag;
- break;
+ case ('z'): /* display only the archive comment */
+ if (negative) {
+ uO.zflag = MAX(uO.zflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.zflag;
+ break;
#ifndef SFX
- case ('Z'): /* should have been first option (ZipInfo) */
- Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
- error = TRUE;
- break;
+ case ('Z'): /* should have been first option (ZipInfo) */
+ Info(slide, 0x401, ((char *)slide, LoadFarString(Zfirst)));
+ error = TRUE;
+ break;
#endif /* !SFX */
#ifdef VMS
- case ('2'): /* Force ODS2-compliant names. */
- if (negative)
- uO.ods2_flag = FALSE, negative = 0;
- else
- uO.ods2_flag = TRUE;
- break;
+ case ('2'): /* Force ODS2-compliant names. */
+ if (negative)
+ uO.ods2_flag = FALSE, negative = 0;
+ else
+ uO.ods2_flag = TRUE;
+ break;
#endif /* VMS */
#ifdef DOS_H68_OS2_W32
- case ('$'):
- if (negative) {
- uO.volflag = MAX(uO.volflag-negative,0);
- negative = 0;
- } else
- ++uO.volflag;
- break;
+ case ('$'):
+ if (negative) {
+ uO.volflag = MAX(uO.volflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.volflag;
+ break;
#endif /* DOS_H68_OS2_W32 */
#if (!defined(RISCOS) && !defined(CMS_MVS) && !defined(TANDEM))
- case (':'): /* allow "parent dir" path components */
- if (negative) {
- uO.ddotflag = MAX(uO.ddotflag-negative,0);
- negative = 0;
- } else
- ++uO.ddotflag;
- break;
+ case (':'): /* allow "parent dir" path components */
+ if (negative) {
+ uO.ddotflag = MAX(uO.ddotflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.ddotflag;
+ break;
#endif /* !RISCOS && !CMS_MVS && !TANDEM */
#ifdef UNIX
- case ('^'): /* allow control chars in filenames */
- if (negative) {
- uO.cflxflag = MAX(uO.cflxflag-negative,0);
- negative = 0;
- } else
- ++uO.cflxflag;
- break;
+ case ('^'): /* allow control chars in filenames */
+ if (negative) {
+ uO.cflxflag = MAX(uO.cflxflag-negative,0);
+ negative = 0;
+ } else
+ ++uO.cflxflag;
+ break;
#endif /* UNIX */
- default:
- error = TRUE;
- break;
-
- } /* end switch */
- } /* end while (not end of argument string) */
- } /* end while (not done with switches) */
+ case o_NON_OPTION_ARG:
+ /* not an option */
+ /* no more options as permuting */
+
+
+ if (G.wildzipfn == NULL) {
+ /* first non-option argument is zip file */
+ G.wildzipfn = value;
+
+ } else {
+ /* add include file to list */
+ if (in_files_count == 0) {
+ /* first entry */
+ if ((next_file = (struct file_list *)
+ malloc(sizeof(struct file_list))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NoMemArgsList)));
+ return PK_MEM;
+ }
+ next_file->name = value;
+ next_file->next = NULL;
+ in_files = next_file;
+ next_in_files = next_file;
+ } else {
+ /* add next entry */
+ if ((next_file = (struct file_list *)
+ malloc(sizeof(struct file_list))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide,
+ LoadFarString(NoMemArgsList)));
+ return PK_MEM;
+ }
+ next_in_files->next = next_file;
+ next_file->name = value;
+ next_file->next = NULL;
+ next_in_files = next_file;
+ }
+ in_files_count++;
+ }
+ break;
+ default:
+ error = TRUE;
+ break;
+
+ } /* end switch */
+ } /* get_option() */
+
+
+ /* convert files and xfiles lists to arrays */
+
+ /* convert files list to array */
+ if (in_files_count) {
+ if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));
+ return PK_MEM;
+ }
+ file_count = 0;
+ for (next_file = in_files; next_file;) {
+ G.pfnames[file_count] = next_file->name;
+ in_files = next_file;
+ next_file = next_file->next;
+ free(in_files);
+ file_count++;
+ }
+ G.pfnames[file_count] = NULL;
+ G.filespecs = in_files_count;
+ }
+
+ /* convert xfiles list to array */
+ if (in_xfiles_count) {
+ if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))
+ ) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArgsList)));
+ return PK_MEM;
+ }
+ file_count = 0;
+ for (next_file = in_xfiles; next_file;) {
+ G.pxnames[file_count] = next_file->name;
+ in_xfiles = next_file;
+ next_file = next_file->next;
+ free(in_xfiles);
+ file_count++;
+ }
+ G.pxnames[file_count] = NULL;
+ G.xfilespecs = in_xfiles_count;
+ }
+
+ if (in_files_count || in_xfiles_count) {
+ G.process_all_files = FALSE;
+ } else {
+ G.process_all_files = TRUE; /* for speed */
+ }
+
+
+ /* it's possible the arg count could have been changed by get_option() */
+ argc = arg_count(args);
+
+
/*---------------------------------------------------------------------------
@@ -1774,7 +2240,77 @@
---------------------------------------------------------------------------*/
+ if ((uO.cflag && (uO.tflag || uO.uflag)) ||
+ (uO.tflag && uO.uflag) || (uO.fflag && uO.overwrite_none))
+ {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(InvalidOptionsMsg)));
+ error = TRUE;
+ }
+ if (uO.aflag > 2)
+ uO.aflag = 2;
+#ifdef VMS
+ if (uO.bflag > 2)
+ uO.bflag = 2;
+ /* Clear -s flag when converting text files. */
+ if (uO.aflag <= 0)
+ uO.S_flag = 0;
+#endif /* VMS */
+ if (uO.overwrite_all && uO.overwrite_none) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
+ uO.overwrite_all = FALSE;
+ }
+#ifdef MORE
+ if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */
+ G.M_flag = 0;
+#endif
+
+#ifdef SFX
+ if (error)
+#else
+ if ((G.wildzipfn == NULL) || error)
+#endif
+ {
+ /* tell caller to exit */
+ if (argc <= 2)
+ argc = -1;
+
+ *pargc = argc;
+ *pargv = args;
+#ifndef SFX
+ if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */
+ show_version_info(__G);
+ return PK_OK;
+ }
+ if (!G.noargs && !error)
+ error = TRUE; /* had options (not -h or -v) but no zipfile */
+#endif /* !SFX */
+ return USAGE(error);
+ }
+
#ifdef SFX
-opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */
+ /* print our banner unless we're being fairly quiet */
+ if (uO.qflag < 2)
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(UnzipSFXBanner),
+ UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
+ LoadFarStringSmall(VersionDate)));
+#ifdef BETA
+ /* always print the beta warning: no unauthorized distribution!! */
+ Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
+ "SFX"));
+#endif
+#endif /* SFX */
+
+ if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
+#ifdef TIMESTAMP
+ || uO.T_flag
#endif
+ )
+ G.extract_flag = FALSE;
+ else
+ G.extract_flag = TRUE;
+
+#if 0
+# ifdef SFX
+opts_done: /* yes, very ugly...but only used by UnZipSFX with -x xlist */
+# endif
if ((uO.cflag && (uO.tflag || uO.uflag)) ||
@@ -1786,5 +2322,5 @@
if (uO.aflag > 2)
uO.aflag = 2;
-#ifdef VMS
+# ifdef VMS
if (uO.bflag > 2)
uO.bflag = 2;
@@ -1792,23 +2328,23 @@
if (uO.aflag <= 0)
uO.S_flag = 0;
-#endif /* VMS */
+# endif /* VMS */
if (uO.overwrite_all && uO.overwrite_none) {
Info(slide, 0x401, ((char *)slide, LoadFarString(IgnoreOOptionMsg)));
uO.overwrite_all = FALSE;
}
-#ifdef MORE
+# ifdef MORE
if (G.M_flag && !isatty(1)) /* stdout redirected: "more" func. useless */
G.M_flag = 0;
-#endif
+# endif
-#ifdef SFX
+# ifdef SFX
if (error)
-#else
+# else
if ((argc-- == 0) || error)
-#endif
+# endif
{
*pargc = argc;
- *pargv = argv;
-#ifndef SFX
+ *pargv = args;
+# ifndef SFX
if (uO.vflag >= 2 && argc == -1) { /* "unzip -v" */
show_version_info(__G);
@@ -1817,9 +2353,9 @@
if (!G.noargs && !error)
error = TRUE; /* had options (not -h or -v) but no zipfile */
-#endif /* !SFX */
+# endif /* !SFX */
return USAGE(error);
}
-#ifdef SFX
+# ifdef SFX
/* print our banner unless we're being fairly quiet */
if (uO.qflag < 2)
@@ -1827,22 +2363,23 @@
UZ_MAJORVER, UZ_MINORVER, UZ_PATCHLEVEL, UZ_BETALEVEL,
LoadFarStringSmall(VersionDate)));
-#ifdef BETA
+# ifdef BETA
/* always print the beta warning: no unauthorized distribution!! */
Info(slide, error? 1 : 0, ((char *)slide, LoadFarString(BetaVersion), "\n",
"SFX"));
-#endif
-#endif /* SFX */
+# endif
+# endif /* SFX */
if (uO.cflag || uO.tflag || uO.vflag || uO.zflag
-#ifdef TIMESTAMP
+# ifdef TIMESTAMP
|| uO.T_flag
-#endif
+# endif
)
G.extract_flag = FALSE;
else
G.extract_flag = TRUE;
+#endif
*pargc = argc;
- *pargv = argv;
+ *pargv = args;
return PK_OK;
@@ -2314,2 +2851,1366 @@
#endif /* !SFX */
#endif /* !WINDLL */
+
+
+
+
+
+
+/*---------------------------------------------------------------
+ * Long option support
+ * 8/23/2003
+ * Updated 3/1/2008 to support UnZip
+ *
+ * Defines function get_option() to get and process the command
+ * line options and arguments from argv[]. The caller calls
+ * get_option() in a loop to get either one option and possible
+ * value or a non-option argument each loop.
+ *
+ * This version has been modified to work with UnZip and ZipInfo.
+ * the major changes are removing the error returns, instead
+ * passing back error codes for errors, and supporting separate
+ * groups of options for UnZip and ZipInfo and selecting the option
+ * group by an argument.
+ *
+ * This version does not include argument file support and can
+ * work directly on argv. The argument file code complicates things and
+ * it seemed best to leave it out for now. If argument file support
+ * (reading in command line arguments stored in a file and inserting into
+ * command line where @filename is found) is added later the arguments
+ * can change and a freeable copy of argv will be needed and can be
+ * created using copy_args in the left out code.
+ *
+ * Supports short and long options as defined in the array options[]
+ * in zip.c, multiple short options in an argument (like -jlv), long
+ * option abbreviation (like --te for --temp-file if --te unique),
+ * short and long option values (like -b filename or --temp-file filename
+ * or --temp-file=filename), optional and required values, option negation
+ * by trailing - (like -S- to not include hidden and system files in MSDOS),
+ * value lists (like -x a b c), argument permuting (returning all options
+ * and values before any non-option arguments), and argument files (where
+ * any non-option non-value argument in form @path gets substituted with
+ * the white space separated arguments in the text file at path). In this
+ * version argument file support has been removed to simplify development
+ * but may be added later.
+ *
+ * E. Gordon
+ */
+
+
+/* message output - char casts are needed to handle constants */
+#define oWARN(message) Info(slide, 0x401, ((char *)slide, (char *)message))
+
+
+
+/* Although the below provides some support for multibyte characters
+ the proper thing to do may be to use wide characters and support
+ Unicode. May get to it soon. Wide support would likely require
+ the ability to convert the command line to wide strings, which most
+ modern OS should support now. EG
+ */
+
+/* For now stay with multi-byte characters. May support wide characters
+ in Zip 3.1 and UnZip 6.1.
+ */
+
+/* multibyte character set support
+ Multibyte characters use typically two or more sequential bytes
+ to represent additional characters than can fit in a single byte
+ character set. The code used here is based on the ANSI mblen function. */
+#define MB_CLEN(ptr) CLEN(ptr)
+#define MB_NEXTCHAR(ptr) PREINCSTR(ptr)
+
+
+/* constants */
+
+/* function get_args_from_arg_file() can return this in depth parameter */
+#define ARG_FILE_ERR -1
+
+/* internal settings for optchar */
+#define SKIP_VALUE_ARG -1
+#define THIS_ARG_DONE -2
+#define START_VALUE_LIST -3
+#define IN_VALUE_LIST -4
+#define NON_OPTION_ARG -5
+#define STOP_VALUE_LIST -6
+/* 7/25/04 EG */
+#define READ_REST_ARGS_VERBATIM -7
+
+
+/* global veriables */
+
+int enable_permute = 1; /* yes - return options first */
+/* 7/25/04 EG */
+int doubledash_ends_options = 1; /* when -- what follows are not options */
+
+/* buffer for error messages (this sizing is a guess but must hold 2 paths) */
+#define OPTIONERR_BUF_SIZE (80+ 2*FILENAME_MAX)
+char optionerrbuf[OPTIONERR_BUF_SIZE + 1];
+
+/* error messages */
+static ZCONST char Far op_not_neg_err[] =
+ "option %s not negatable";
+static ZCONST char Far op_req_val_err[] =
+ "option %s requires a value";
+static ZCONST char Far op_no_allow_val_err[] =
+ "option %s does not allow a value";
+static ZCONST char Far sh_op_not_sup_err[] =
+ "short option '%c' not supported";
+static ZCONST char Far oco_req_val_err[] =
+ "option %s requires one character value";
+static ZCONST char Far oco_no_mbc_err[] =
+ "option %s does not support multibyte values";
+static ZCONST char Far num_req_val_err[] =
+ "option %s requires number value";
+static ZCONST char Far long_op_ambig_err[] =
+ "long option '%s' ambiguous";
+static ZCONST char Far long_op_not_sup_err[] =
+ "long option '%s' not supported";
+
+static ZCONST char Far no_arg_files_err[] = "argument files not enabled\n";
+
+
+/* below removed as only used for processing argument files */
+
+/* get_nextarg */
+/* get_args_from_string */
+/* get_args_from_arg_file */
+
+
+/* copy error, option name, and option description if any to buf */
+static int optionerr(options, buf, err, optind, islong)
+ struct option_struct *options;
+ char *buf;
+ ZCONST char Far *err;
+ int optind;
+ int islong;
+{
+ char optname[50];
+
+ if (options[optind].name && options[optind].name[0] != '\0') {
+ sprintf(optname, "'%s' (%s)",
+ LoadFarStringSmall2(islong ? options[optind].longopt
+ : options[optind].shortopt),
+ LoadFarStringSmall(options[optind].name));
+ } else {
+ sprintf(optname, "'%s'",
+ LoadFarStringSmall2(islong ? options[optind].longopt
+ : options[optind].shortopt));
+ }
+ sprintf(buf, LoadFarStringSmall(err), optname);
+ return 0;
+}
+
+
+/* copy_args
+ *
+ * Copy arguments in args, allocating storage with malloc.
+ * Copies until a NULL argument is found or until max_args args
+ * including args[0] are copied. Set max_args to 0 to copy
+ * until NULL. Always terminates returned args[] with NULL arg.
+ *
+ * Any argument in the returned args can be freed with free(). Any
+ * freed argument should be replaced with either another string
+ * allocated with malloc or by NULL if last argument so that free_args
+ * will properly work.
+ */
+char **copy_args(args, max_args)
+ char **args;
+ int max_args;
+{
+ int j;
+ char **new_args;
+
+ if (args == NULL) {
+ return NULL;
+ }
+
+ /* count args */
+ for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) ;
+
+ if ((new_args = (char **) malloc((j + 1) * sizeof(char *))) == NULL) {
+ oWARN("memory - ca");
+ return NULL;
+ }
+
+ for (j = 0; args[j] && (max_args == 0 || j < max_args); j++) {
+ if (args[j] == NULL) {
+ /* null argument is end of args */
+ new_args[j] = NULL;
+ break;
+ }
+ if ((new_args[j] = malloc(strlen(args[j]) + 1)) == NULL) {
+ free_args(new_args);
+ oWARN("memory - ca");
+ return NULL;
+ }
+ strcpy(new_args[j], args[j]);
+ }
+ new_args[j] = NULL;
+
+ return new_args;
+}
+
+
+/* count args - count args in argv like array */
+int arg_count(args)
+ char **args;
+{
+ int i;
+
+ if (args == NULL) {
+ return 0;
+ }
+
+ for (i = 0; args[i]; i++) {
+ }
+ return i;
+}
+
+
+/* free args - free args created with one of these functions */
+int free_args(args)
+ char **args;
+{
+ int i;
+
+ if (args == NULL) {
+ return 0;
+ }
+
+ for (i = 0; args[i]; i++) {
+ free(args[i]);
+ }
+ free(args);
+ return i;
+}
+
+
+/* insert_arg
+ *
+ * Insert the argument arg into the array args before argument at_arg.
+ * If at_arg = -1 then append to end.
+ * Return the new count of arguments (argc).
+ *
+ * If free_args is true, this function frees the old args array
+ * (but not the component strings). DO NOT set free_args on original
+ * argv but only on args allocated with malloc.
+ */
+
+int insert_arg(pargs, arg, at_arg, free_args)
+ char ***pargs;
+ ZCONST char *arg;
+ int at_arg;
+ int free_args;
+{
+ char *newarg = NULL;
+ char **args;
+ char **newargs = NULL;
+ int argnum;
+ int newargnum;
+ int argcnt;
+ int newargcnt;
+
+ if (pargs == NULL) {
+ return 0;
+ }
+ args = *pargs;
+
+ /* count args */
+ if (args == NULL) {
+ argcnt = 0;
+ } else {
+ for (argcnt = 0; args[argcnt]; argcnt++) ;
+ }
+ if (arg == NULL) {
+ /* done */
+ return argcnt;
+ }
+ if (at_arg == -1) {
+ at_arg = argcnt;
+ }
+ newargcnt = argcnt + 1;
+
+ /* get storage for new args */
+ if ((newargs = (char **) malloc((newargcnt + 1) * sizeof(char *))) == NULL)
+ {
+ oWARN("memory - ia");
+ return 0;
+ }
+
+ /* copy argument pointers from args to position at_arg, copy the new arg,
+ then copy the rest of the args */
+ argnum = 0;
+ newargnum = 0;
+ if (args) {
+ for (; args[argnum] && argnum < at_arg; argnum++) {
+ newargs[newargnum++] = args[argnum];
+ }
+ }
+ /* copy new arg */
+ if ((newarg = (char *) malloc(strlen(arg) + 1)) == NULL) {
+ oWARN("memory - ia");
+ return 0;
+ }
+ strcpy(newarg, arg);
+
+ newargs[newargnum++] = newarg;
+ if (args) {
+ for ( ; args[argnum]; argnum++) {
+ newargs[newargnum++] = args[argnum];
+ }
+ }
+ newargs[newargnum] = NULL;
+
+ /* free old args array but not component strings - this assumes that
+ args was allocated with malloc as copy_args does. DO NOT DO THIS
+ on the original argv.
+ */
+ if (free_args)
+ free(args);
+
+ *pargs = newargs;
+
+ return newargnum;
+}
+
+/* ------------------------------------- */
+
+/* get_shortopt
+ *
+ * Get next short option from arg. The state is stored in argnum, optchar, and
+ * option_num so no static storage is used. Returns the option_ID.
+ *
+ * parameters:
+ * option_group - either UZO for UnZip options or ZIO for ZipInfo options
+ * args - argv array of arguments
+ * argnum - index of current arg in args
+ * optchar - pointer to index of next char to process. Can be 0 or
+ * const defined at top of this file like THIS_ARG_DONE
+ * negated - on return pointer to int set to 1 if option negated
+ * or 0 otherwise
+ * value - on return pointer to string set to value of option if any
+ * or NULL if none. If value is returned then the caller
+ * should free() it when not needed anymore.
+ * option_num - pointer to index in options[] of returned option or
+ * o_NO_OPTION_MATCH if none. Do not change as used by
+ * value lists.
+ * depth - recursion depth (0 at top level, 1 or more in arg files)
+ */
+static unsigned long get_shortopt(option_group, args, argnum, optchar, negated,
+ value, option_num, depth)
+ int option_group;
+ ZCONST char **args;
+ int argnum;
+ int *optchar;
+ int *negated;
+ char **value;
+ int *option_num;
+ int depth;
+{
+ ZCONST char *shortopt;
+ int clen;
+ ZCONST char *nextchar;
+ ZCONST char *s;
+ ZCONST char *start;
+ int op;
+ ZCONST char *arg;
+ int match = -1;
+
+
+ /* get arg */
+ arg = args[argnum];
+ /* current char in arg */
+ nextchar = arg + (*optchar);
+ clen = MB_CLEN(nextchar);
+ /* next char in arg */
+ (*optchar) += clen;
+ /* get first char of short option */
+ shortopt = arg + (*optchar);
+ /* no value */
+ *value = NULL;
+
+ if (*shortopt == '\0') {
+ /* no more options in arg */
+ *optchar = 0;
+ *option_num = o_NO_OPTION_MATCH;
+ return 0;
+ }
+
+ /* look for match in options */
+ clen = MB_CLEN(shortopt);
+ for (op = 0; options[op].option_ID; op++) {
+ /* Only look at options in this option group */
+ if (options[op].option_group == option_group) {
+ s = options[op].shortopt;
+ if (s && s[0] == shortopt[0]) {
+ if (s[1] == '\0' && clen == 1) {
+ /* single char match */
+ match = op;
+ } else {
+ /* 2 wide short opt. Could support more chars but should use long opts instead */
+ if (s[1] == shortopt[1]) {
+ /* match 2 char short opt or 2 byte char */
+ match = op;
+ if (clen == 1) (*optchar)++;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (match > -1) {
+ /* match */
+ clen = MB_CLEN(shortopt);
+ nextchar = arg + (*optchar) + clen;
+ /* check for trailing dash negating option */
+ if (*nextchar == '-') {
+ /* negated */
+ if (options[match].negatable == o_NOT_NEGATABLE) {
+ if (options[match].value_type == o_NO_VALUE) {
+ optionerr(options, optionerrbuf, op_not_neg_err, match, 0);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ } else {
+ *negated = 1;
+ /* set up to skip negating dash */
+ (*optchar) += clen;
+ clen = 1;
+ }
+ }
+
+ /* value */
+ clen = MB_CLEN(arg + (*optchar));
+ /* optional value, one char value, and number value must follow option */
+ if (options[match].value_type == o_ONE_CHAR_VALUE) {
+ /* one char value */
+ if (arg[(*optchar) + clen]) {
+ /* has value */
+ if (MB_CLEN(arg + (*optchar) + clen) > 1) {
+ /* multibyte value not allowed for now */
+ optionerr(options, optionerrbuf, oco_no_mbc_err, match, 0);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ if ((*value = (char *) malloc(2)) == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ (*value)[0] = *(arg + (*optchar) + clen);
+ (*value)[1] = '\0';
+ *optchar += clen;
+ clen = 1;
+ } else {
+ /* one char values require a value */
+ optionerr(options, optionerrbuf, oco_req_val_err, match, 0);
+ if (depth > 0) {
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ } else if (options[match].value_type == o_NUMBER_VALUE) {
+ /* read chars until end of number */
+ start = arg + (*optchar) + clen;
+ if (*start == '+' || *start == '-') {
+ start++;
+ }
+ s = start;
+ for (; isdigit(*s); MB_NEXTCHAR(s)) ;
+ if (s == start) {
+ /* no digits */
+ optionerr(options, optionerrbuf, num_req_val_err, match, 0);
+ if (depth > 0) {
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ start = arg + (*optchar) + clen;
+ if ((*value = (char *) malloc((int)(s - start) + 1)) == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ *optchar += (int)(s - start);
+ strncpy(*value, start, (int)(s - start));
+ (*value)[(int)(s - start)] = '\0';
+ clen = MB_CLEN(s);
+ } else if (options[match].value_type == o_OPTIONAL_VALUE) {
+ /* optional value */
+ /* This seemed inconsistent so now if no value attached to argument look
+ to the next argument if that argument is not an option for option
+ value - 11/12/04 EG */
+ if (arg[(*optchar) + clen]) {
+ /* has value */
+ /* add support for optional = - 2/6/05 EG */
+ if (arg[(*optchar) + clen] == '=') {
+ /* skip = */
+ clen++;
+ }
+ if (arg[(*optchar) + clen]) {
+ if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))
+ == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg + (*optchar) + clen);
+ }
+ *optchar = THIS_ARG_DONE;
+ } else if (args[argnum + 1] && args[argnum + 1][0] != '-') {
+ /* use next arg for value */
+ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ /* using next arg as value */
+ strcpy(*value, args[argnum + 1]);
+ *optchar = SKIP_VALUE_ARG;
+ }
+ } else if (options[match].value_type == o_REQUIRED_VALUE ||
+ options[match].value_type == o_VALUE_LIST) {
+ /* see if follows option */
+ if (arg[(*optchar) + clen]) {
+ /* has value following option as -ovalue */
+ /* add support for optional = - 6/5/05 EG */
+ if (arg[(*optchar) + clen] == '=') {
+ /* skip = */
+ clen++;
+ }
+ if ((*value = (char *)malloc(strlen(arg + (*optchar) + clen) + 1))
+ == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg + (*optchar) + clen);
+ *optchar = THIS_ARG_DONE;
+ } else {
+ /* use next arg for value */
+ if (args[argnum + 1]) {
+ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1))
+ == NULL) {
+ oWARN("memory - gso");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, args[argnum + 1]);
+ if (options[match].value_type == o_VALUE_LIST) {
+ *optchar = START_VALUE_LIST;
+ } else {
+ *optchar = SKIP_VALUE_ARG;
+ }
+ } else {
+ /* no value found */
+ optionerr(options, optionerrbuf, op_req_val_err, match, 0);
+ if (depth > 0) {
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ }
+ }
+
+ *option_num = match;
+ return options[match].option_ID;
+ }
+ sprintf(optionerrbuf, LoadFarStringSmall(sh_op_not_sup_err), *shortopt);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ return 0;
+}
+
+
+/* get_longopt
+ *
+ * Get the long option in args array at argnum.
+ * Parameters same as for get_shortopt.
+ */
+
+static unsigned long get_longopt(option_group, args, argnum, optchar, negated,
+ value, option_num, depth)
+ int option_group;
+ ZCONST char **args;
+ int argnum;
+ int *optchar;
+ int *negated;
+ char **value;
+ int *option_num;
+ int depth;
+{
+ char *longopt;
+ char *lastchr;
+ char *valuestart;
+ int op;
+ char *arg;
+ int match = -1;
+ *value = NULL;
+
+ if (args == NULL) {
+ *option_num = o_NO_OPTION_MATCH;
+ return 0;
+ }
+ if (args[argnum] == NULL) {
+ *option_num = o_NO_OPTION_MATCH;
+ return 0;
+ }
+ /* copy arg so can chop end if value */
+ if ((arg = (char *)malloc(strlen(args[argnum]) + 1)) == NULL) {
+ oWARN("memory - glo");
+ return o_BAD_ERR;
+ }
+ strcpy(arg, args[argnum]);
+
+ /* get option */
+ longopt = arg + 2;
+ /* no value */
+ *value = NULL;
+
+ /* find = */
+ for (lastchr = longopt, valuestart = longopt;
+ *valuestart && *valuestart != '=';
+ lastchr = valuestart, MB_NEXTCHAR(valuestart)) ;
+ if (*valuestart) {
+ /* found =value */
+ *valuestart = '\0';
+ valuestart++;
+ } else {
+ valuestart = NULL;
+ }
+
+ if (*lastchr == '-') {
+ /* option negated */
+ *negated = 1;
+ *lastchr = '\0';
+ } else {
+ *negated = 0;
+ }
+
+ /* look for long option match */
+ for (op = 0; options[op].option_ID; op++) {
+ /* Only look at options in the option group */
+ if (options[op].option_group == option_group) {
+ if (options[op].longopt &&
+ strcmp(LoadFarStringSmall(options[op].longopt), longopt) == 0) {
+ /* exact match */
+ match = op;
+ break;
+ }
+ if (options[op].longopt &&
+ strncmp(LoadFarStringSmall(options[op].longopt),
+ longopt, strlen(longopt)) == 0) {
+ if (match > -1) {
+ sprintf(optionerrbuf, LoadFarStringSmall(long_op_ambig_err),
+ longopt);
+ free(arg);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ match = op;
+ }
+ }
+ }
+
+ if (match == -1) {
+ sprintf(optionerrbuf, LoadFarStringSmall(long_op_not_sup_err), longopt);
+ free(arg);
+ if (depth > 0) {
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+
+ /* one long option an arg */
+ *optchar = THIS_ARG_DONE;
+
+ /* if negated then see if allowed */
+ if (*negated && options[match].negatable == o_NOT_NEGATABLE) {
+ optionerr(options, optionerrbuf, op_not_neg_err, match, 1);
+ free(arg);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ /* get value */
+ if (options[match].value_type == o_OPTIONAL_VALUE) {
+ /* optional value in form option=value */
+ if (valuestart) {
+ /* option=value */
+ if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {
+ free(arg);
+ oWARN("memory - glo");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, valuestart);
+ }
+ } else if (options[match].value_type == o_REQUIRED_VALUE ||
+ options[match].value_type == o_NUMBER_VALUE ||
+ options[match].value_type == o_ONE_CHAR_VALUE ||
+ options[match].value_type == o_VALUE_LIST) {
+ /* handle long option one char and number value as required value */
+ if (valuestart) {
+ /* option=value */
+ if ((*value = (char *)malloc(strlen(valuestart) + 1)) == NULL) {
+ free(arg);
+ oWARN("memory - glo");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, valuestart);
+ } else {
+ /* use next arg */
+ if (args[argnum + 1]) {
+ if ((*value = (char *)malloc(strlen(args[argnum + 1]) + 1)) == NULL) {
+ free(arg);
+ oWARN("memory - glo");
+ return o_BAD_ERR;
+ }
+ /* using next arg as value */
+ strcpy(*value, args[argnum + 1]);
+ if (options[match].value_type == o_VALUE_LIST) {
+ *optchar = START_VALUE_LIST;
+ } else {
+ *optchar = SKIP_VALUE_ARG;
+ }
+ } else {
+ /* no value found */
+ optionerr(options, optionerrbuf, op_req_val_err, match, 1);
+ free(arg);
+ if (depth > 0) {
+ /* unwind */
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ }
+ } else if (options[match].value_type == o_NO_VALUE) {
+ /* this option does not accept a value */
+ if (valuestart) {
+ /* --option=value */
+ optionerr(options, optionerrbuf, op_no_allow_val_err, match, 1);
+ free(arg);
+ if (depth > 0) {
+ oWARN(optionerrbuf);
+ return o_ARG_FILE_ERR;
+ } else {
+ oWARN(optionerrbuf);
+ return o_BAD_ERR;
+ }
+ }
+ }
+ free(arg);
+
+ *option_num = match;
+ return options[match].option_ID;
+}
+
+
+
+/* get_option
+ *
+ * Main interface for user. Use this function to get options, values and
+ * non-option arguments from a command line provided in argv form.
+ *
+ * To use get_option() first define valid options by setting
+ * the global variable options[] to an array of option_struct. Also
+ * either change defaults below or make variables global and set elsewhere.
+ * Zip uses below defaults.
+ *
+ * Call get_option() to get an option (like -b or --temp-file) and any
+ * value for that option (like filename for -b) or a non-option argument
+ * (like archive name) each call. If *value* is not NULL after calling
+ * get_option() it is a returned value and the caller should either store
+ * the char pointer or free() it before calling get_option() again to avoid
+ * leaking memory. If a non-option non-value argument is returned get_option()
+ * returns o_NON_OPTION_ARG and value is set to the entire argument.
+ * When there are no more arguments get_option() returns 0.
+ *
+ * The parameters argnum (after set to 0 on initial call),
+ * optchar, first_nonopt_arg, option_num, and depth (after initial
+ * call) are set and maintained by get_option() and should not be
+ * changed. The parameters argc, negated, and value are outputs and
+ * can be used by the calling program. get_option() returns either the
+ * option_ID for the current option, a special value defined in
+ * zip.h, or 0 when no more arguments.
+ *
+ * The value returned by get_option() is the ID value in the options
+ * table. This value can be duplicated in the table if different
+ * options are really the same option. The index into the options[]
+ * table is given by option_num, though the ID should be used as
+ * option numbers change when the table is changed. The ID must
+ * not be 0 for any option as this ends the table. If get_option()
+ * finds an option not in the table it calls oERR to post an
+ * error and exit. Errors also result if the option requires a
+ * value that is missing, a value is present but the option does
+ * not take one, and an option is negated but is not
+ * negatable. Non-option arguments return o_NON_OPTION_ARG
+ * with the entire argument in value.
+ *
+ * For Zip and UnZip, permuting is on and all options and their values
+ * are returned before any non-option arguments like archive name.
+ *
+ * The arguments "-" alone and "--" alone return as non-option arguments.
+ * Note that "-" should not be used as part of a short option
+ * entry in the table but can be used in the middle of long
+ * options such as in the long option "a-long-option". Now "--" alone
+ * stops option processing, returning any arguments following "--" as
+ * non-option arguments instead of options.
+ *
+ * Argument file support is removed from this version. It may be added later.
+ *
+ * After each call:
+ * argc is set to the current size of args[] but should not change
+ * with argument file support removed,
+ * argnum is the index of the current arg,
+ * value is either the value of the returned option or non-option
+ * argument or NULL if option with no value,
+ * negated is set if the option was negated by a trailing dash (-)
+ * option_num is set to either the index in options[] for the option or
+ * o_NO_OPTION_MATCH if no match.
+ * Negation is checked before the value is read if the option is negatable so
+ * that the - is not included in the value. If the option is not negatable
+ * but takes a value then the - will start the value. If permuting then
+ * argnum and first_nonopt_arg are unreliable and should not be used.
+ *
+ * Command line is read from left to right. As get_option() finds non-option
+ * arguments (arguments not starting with - and that are not values to options)
+ * it moves later options and values in front of the non-option arguments.
+ * This permuting is turned off by setting enable_permute to 0. Then
+ * get_option() will return options and non-option arguments in the order
+ * found. Currently permuting is only done after an argument is completely
+ * processed so that any value can be moved with options they go with. All
+ * state information is stored in the parameters argnum, optchar,
+ * first_nonopt_arg and option_num. You should not change these after the
+ * first call to get_option(). If you need to back up to a previous arg then
+ * set argnum to that arg (remembering that args may have been permuted) and
+ * set optchar = 0 and first_nonopt_arg to the first non-option argument if
+ * permuting. After all arguments are returned the next call to get_option()
+ * returns 0. The caller can then call free_args(args) if appropriate.
+ *
+ * get_option() accepts arguments in the following forms:
+ * short options
+ * of 1 and 2 characters, e.g. a, b, cc, d, and ba, after a single
+ * leading -, as in -abccdba. In this example if 'b' is followed by 'a'
+ * it matches short option 'ba' else it is interpreted as short option
+ * b followed by another option. The character - is not legal as a
+ * short option or as part of a 2 character short option.
+ *
+ * If a short option has a value it immediately follows the option or
+ * if that option is the end of the arg then the next arg is used as
+ * the value. So if short option e has a value, it can be given as
+ * -evalue
+ * or
+ * -e value
+ * and now
+ * -e=value
+ * but now that = is optional a leading = is stripped for the first.
+ * This change allows optional short option values to be defaulted as
+ * -e=
+ * Either optional or required values can be specified. Optional values
+ * now use both forms as ignoring the later got confusing. Any
+ * non-value short options can preceed a valued short option as in
+ * -abevalue
+ * Some value types (one_char and number) allow options after the value
+ * so if oc is an option that takes a character and n takes a number
+ * then
+ * -abocVccn42evalue
+ * returns value V for oc and value 42 for n. All values are strings
+ * so programs may have to convert the "42" to a number. See long
+ * options below for how value lists are handled.
+ *
+ * Any short option can be negated by following it with -. Any - is
+ * handled and skipped over before any value is read unless the option
+ * is not negatable but takes a value and then - starts the value.
+ *
+ * If the value for an optional value is just =, then treated as no
+ * value.
+ *
+ * long options
+ * of arbitrary length are assumed if an arg starts with -- but is not
+ * exactly --. Long options are given one per arg and can be abbreviated
+ * if the abbreviation uniquely matches one of the long options.
+ * Exact matches always match before partial matches. If ambiguous an
+ * error is generated.
+ *
+ * Values are specified either in the form
+ * --longoption=value
+ * or can be the following arg if the value is required as in
+ * --longoption value
+ * Optional values to long options must be in the first form.
+ *
+ * Value lists are specified by o_VALUE_LIST and consist of an option
+ * that takes a value followed by one or more value arguments.
+ * The two forms are
+ * --option=value
+ * or
+ * -ovalue
+ * for a single value or
+ * --option value1 value2 value3 ... --option2
+ * or
+ * -o value1 value2 value3 ...
+ * for a list of values. The list ends at the next option, the
+ * end of the command line, or at a single "@" argument.
+ * Each value is treated as if it was preceeded by the option, so
+ * --option1 val1 val2
+ * with option1 value_type set to o_VALUE_LIST is the same as
+ * --option1=val1 --option1=val2
+ *
+ * Long options can be negated by following the option with - as in
+ * --longoption-
+ * Long options with values can also be negated if this makes sense for
+ * the caller as:
+ * --longoption-=value
+ * If = is not followed by anything it is treated as no value.
+ *
+ * @path
+ * Argument files support removed from this version. It may be added
+ * back later.
+ *
+ * non-option argument
+ * is any argument not given above. If enable_permute is 1 then
+ * these are returned after all options, otherwise all options and
+ * args are returned in order. Returns option ID o_NON_OPTION_ARG
+ * and sets value to the argument.
+ *
+ *
+ * Arguments to get_option:
+ * int option_group - either UZO for UnZip or ZIO for ZipInfo
+ * char ***pargs - pointer to arg array in the argv form
+ * int *argc - returns the current argc for args incl. args[0]
+ * int *argnum - the index of the current argument (caller
+ * should set = 0 on first call and not change
+ * after that)
+ * int *optchar - index of next short opt in arg or special
+ * int *first_nonopt_arg - used by get_option to permute args
+ * int *negated - option was negated (had trailing -)
+ * char *value - value of option if any (free when done with it)
+ * or NULL
+ * int *option_num - the index in options of the last option returned
+ * (can be o_NO_OPTION_MATCH)
+ * int recursion_depth - current depth of recursion
+ * (always set to 0 by caller)
+ * (always 0 with argument files support removed)
+ *
+ * Caller should only read the returned option ID and the value, negated,
+ * and option_num (if required) parameters after each call.
+ *
+ * Ed Gordon
+ * 8/24/2003 (last updated 3/1/2008 EG)
+ *
+ */
+
+unsigned long get_option(option_group, pargs, argc, argnum, optchar, value,
+ negated, first_nonopt_arg, option_num, recursion_depth)
+ int option_group;
+ char ***pargs;
+ int *argc;
+ int *argnum;
+ int *optchar;
+ char **value;
+ int *negated;
+ int *first_nonopt_arg;
+ int *option_num;
+ int recursion_depth;
+{
+ char **args;
+ unsigned long option_ID;
+
+ int argcnt;
+ int first_nonoption_arg;
+ char *arg = NULL;
+ int h;
+ int optc;
+ int argn;
+ int j;
+ int v;
+ int read_rest_args_verbatim = 0; /* 7/25/04 - ignore options and arg files for rest args */
+
+ /* caller should free value or assign it to another
+ variable before calling get_option again. */
+ *value = NULL;
+
+ /* if args is NULL then done */
+ if (pargs == NULL) {
+ *argc = 0;
+ return 0;
+ }
+ args = *pargs;
+ if (args == NULL) {
+ *argc = 0;
+ return 0;
+ }
+
+ /* count args */
+ for (argcnt = 0; args[argcnt]; argcnt++) ;
+
+ /* if no provided args then nothing to do */
+ if (argcnt < 1 || (recursion_depth == 0 && argcnt < 2)) {
+ *argc = argcnt;
+ /* return 0 to note that no args are left */
+ return 0;
+ }
+
+ *negated = 0;
+ first_nonoption_arg = *first_nonopt_arg;
+ argn = *argnum;
+ optc = *optchar;
+
+ if (optc == READ_REST_ARGS_VERBATIM) {
+ read_rest_args_verbatim = 1;
+ }
+
+ if (argn == -1 || (recursion_depth == 0 && argn == 0)) {
+ /* first call */
+ /* if depth = 0 then args[0] is argv[0] so skip */
+ *option_num = o_NO_OPTION_MATCH;
+ optc = THIS_ARG_DONE;
+ first_nonoption_arg = -1;
+ }
+
+ /* if option_num is set then restore last option_ID in case continuing
+ value list */
+ option_ID = 0;
+ if (*option_num != o_NO_OPTION_MATCH) {
+ option_ID = options[*option_num].option_ID;
+ }
+
+ /* get next option if any */
+ for (;;) {
+ if (read_rest_args_verbatim) {
+ /* rest of args after "--" are non-option args if doubledash_ends_options
+ set */
+ argn++;
+ if (argn > argcnt || args[argn] == NULL) {
+ /* done */
+ option_ID = 0;
+ break;
+ }
+ arg = args[argn];
+ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg);
+ *option_num = o_NO_OPTION_MATCH;
+ option_ID = o_NON_OPTION_ARG;
+ break;
+
+ /* permute non-option args after option args so options are returned
+ first */
+ } else if (enable_permute) {
+ if (optc == SKIP_VALUE_ARG || optc == THIS_ARG_DONE ||
+ optc == START_VALUE_LIST || optc == IN_VALUE_LIST ||
+ optc == STOP_VALUE_LIST) {
+ /* moved to new arg */
+ if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {
+ /* do the permuting - move non-options after this option */
+ /* if option and value separate args or starting list skip option */
+ if (optc == SKIP_VALUE_ARG || optc == START_VALUE_LIST) {
+ v = 1;
+ } else {
+ v = 0;
+ }
+ for (h = first_nonoption_arg; h < argn; h++) {
+ arg = args[first_nonoption_arg];
+ for (j = first_nonoption_arg; j < argn + v; j++) {
+ args[j] = args[j + 1];
+ }
+ args[j] = arg;
+ }
+ first_nonoption_arg += 1 + v;
+ }
+ }
+ } else if (optc == NON_OPTION_ARG) {
+ /* if not permuting then already returned arg */
+ optc = THIS_ARG_DONE;
+ }
+
+ /* value lists */
+ if (optc == STOP_VALUE_LIST) {
+ optc = THIS_ARG_DONE;
+ }
+
+ if (optc == START_VALUE_LIST || optc == IN_VALUE_LIST) {
+ if (optc == START_VALUE_LIST) {
+ /* already returned first value */
+ argn++;
+ optc = IN_VALUE_LIST;
+ }
+ argn++;
+ arg = args[argn];
+ /* if end of args and still in list and there are non-option args then
+ terminate list */
+ if (arg == NULL && (optc == START_VALUE_LIST || optc == IN_VALUE_LIST)
+ && first_nonoption_arg > -1) {
+ /* terminate value list with @ */
+ /* this is only needed for argument files */
+ /* but is also good for show command line so command lines with lists
+ can always be read back in */
+ argcnt = insert_arg(&args, "@", first_nonoption_arg, 1);
+ argn++;
+ if (first_nonoption_arg > -1) {
+ first_nonoption_arg++;
+ }
+ }
+
+ arg = args[argn];
+ if (arg && arg[0] == '@' && arg[1] == '\0') {
+ /* inserted arguments terminator */
+ optc = STOP_VALUE_LIST;
+ continue;
+ } else if (arg && arg[0] != '-') { /* not option */
+ /* - and -- are not allowed in value lists unless escaped */
+ /* another value in value list */
+ if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, args[argn]);
+ break;
+
+ } else {
+ argn--;
+ optc = THIS_ARG_DONE;
+ }
+ }
+
+ /* move to next arg */
+ if (optc == SKIP_VALUE_ARG) {
+ argn += 2;
+ optc = 0;
+ } else if (optc == THIS_ARG_DONE) {
+ argn++;
+ optc = 0;
+ }
+ if (argn > argcnt) {
+ break;
+ }
+ if (args[argn] == NULL) {
+ /* done unless permuting and non-option args */
+ if (first_nonoption_arg > -1 && args[first_nonoption_arg]) {
+ /* return non-option arguments at end */
+ if (optc == NON_OPTION_ARG) {
+ first_nonoption_arg++;
+ }
+ /* after first pass args are permuted but skipped over non-option
+ args */
+ /* swap so argn points to first non-option arg */
+ j = argn;
+ argn = first_nonoption_arg;
+ first_nonoption_arg = j;
+ }
+ if (argn > argcnt || args[argn] == NULL) {
+ /* done */
+ option_ID = 0;
+ break;
+ }
+ }
+
+ /* after swap first_nonoption_arg points to end which is NULL */
+ if (first_nonoption_arg > -1 && (args[first_nonoption_arg] == NULL)) {
+ /* only non-option args left */
+ if (optc == NON_OPTION_ARG) {
+ argn++;
+ }
+ if (argn > argcnt || args[argn] == NULL) {
+ /* done */
+ option_ID = 0;
+ break;
+ }
+ if ((*value = (char *)malloc(strlen(args[argn]) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, args[argn]);
+ optc = NON_OPTION_ARG;
+ option_ID = o_NON_OPTION_ARG;
+ break;
+ }
+
+ arg = args[argn];
+
+ /* is it an option */
+ if (arg[0] == '-') {
+ /* option */
+ if (arg[1] == '\0') {
+ /* arg = - */
+ /* treat like non-option arg */
+ *option_num = o_NO_OPTION_MATCH;
+ if (enable_permute) {
+ /* permute args to move all non-option args to end */
+ if (first_nonoption_arg < 0) {
+ first_nonoption_arg = argn;
+ }
+ argn++;
+ } else {
+ /* not permute args so return non-option args when found */
+ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg);
+ optc = NON_OPTION_ARG;
+ option_ID = o_NON_OPTION_ARG;
+ break;
+ }
+
+ } else if (arg[1] == '-') {
+ /* long option */
+ if (arg[2] == '\0') {
+ /* arg = -- */
+ if (doubledash_ends_options) {
+ /* Now -- stops permuting and forces the rest of
+ the command line to be read verbatim - 7/25/04 EG */
+
+ /* never permute args after -- and return as non-option args */
+ if (first_nonoption_arg < 1) {
+ /* -- is first non-option argument - 8/7/04 EG */
+ argn--;
+ } else {
+ /* go back to start of non-option args - 8/7/04 EG */
+ argn = first_nonoption_arg - 1;
+ }
+
+ /* disable permuting and treat remaining arguments as not
+ options */
+ read_rest_args_verbatim = 1;
+ optc = READ_REST_ARGS_VERBATIM;
+
+ } else {
+ /* treat like non-option arg */
+ *option_num = o_NO_OPTION_MATCH;
+ if (enable_permute) {
+ /* permute args to move all non-option args to end */
+ if (first_nonoption_arg < 0) {
+ first_nonoption_arg = argn;
+ }
+ argn++;
+ } else {
+ /* not permute args so return non-option args when found */
+ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg);
+ optc = NON_OPTION_ARG;
+ option_ID = o_NON_OPTION_ARG;
+ break;
+ }
+ }
+
+ } else {
+ option_ID = get_longopt(option_group, (ZCONST char **)args, argn,
+ &optc, negated,
+ value, option_num, recursion_depth);
+ if (option_ID == o_BAD_ERR) {
+ return o_BAD_ERR;
+ } else if (option_ID == o_ARG_FILE_ERR) {
+ /* unwind as only get this if recursion_depth > 0 */
+ return option_ID;
+ }
+ break;
+ }
+
+ } else {
+ /* short option */
+ option_ID = get_shortopt(option_group, (ZCONST char **)args, argn,
+ &optc, negated,
+ value, option_num, recursion_depth);
+
+ if (option_ID == o_BAD_ERR) {
+ return o_BAD_ERR;
+ } else if (option_ID == o_ARG_FILE_ERR) {
+ /* unwind as only get this if recursion_depth > 0 */
+ return option_ID;
+ }
+
+ if (optc == 0) {
+ /* if optc = 0 then ran out of short opts this arg */
+ optc = THIS_ARG_DONE;
+ } else {
+ break;
+ }
+ }
+
+#if 0
+ /* argument file code left out
+ so for now let filenames start with @
+ */
+
+ } else if (allow_arg_files && arg[0] == '@') {
+ /* arg file */
+ oERR(PK_PARMS, no_arg_files_err);
+#endif
+
+ } else {
+ /* non-option */
+ if (enable_permute) {
+ /* permute args to move all non-option args to end */
+ if (first_nonoption_arg < 0) {
+ first_nonoption_arg = argn;
+ }
+ argn++;
+ } else {
+ /* no permute args so return non-option args when found */
+ if ((*value = (char *)malloc(strlen(arg) + 1)) == NULL) {
+ oWARN("memory - go");
+ return o_BAD_ERR;
+ }
+ strcpy(*value, arg);
+ *option_num = o_NO_OPTION_MATCH;
+ optc = NON_OPTION_ARG;
+ option_ID = o_NON_OPTION_ARG;
+ break;
+ }
+
+ }
+ }
+
+ *pargs = args;
+ *argc = argcnt;
+ *first_nonopt_arg = first_nonoption_arg;
+ *argnum = argn;
+ *optchar = optc;
+
+ return option_ID;
+}
diff -ru2 unz60e03/unzpriv.h u6e3_np/unzpriv.h
--- unz60e03/unzpriv.h Mon Mar 24 11:53:24 2008
+++ u6e3_np/unzpriv.h Mon Mar 24 14:13:02 2008
@@ -1271,4 +1271,89 @@
#endif
+
+/*--------------------------------------------------------------------
+ Long option support
+ 23 August 2003
+ Updated for UnZip 1 March 2008
+ See unzip.c
+ --------------------------------------------------------------------*/
+
+/* The below is for use in the caller-provided options table */
+
+/* option groups */
+#define UZO 1 /* UnZip option */
+#define ZIO 2 /* ZipInfo option */
+
+
+/* value_type - value is always returned as a string. */
+#define o_NO_VALUE 0 /* this option does not take a value */
+#define o_REQUIRED_VALUE 1 /* this option requires a value */
+#define o_OPTIONAL_VALUE 2 /* value is optional (see get_option() for details) */
+#define o_VALUE_LIST 3 /* this option takes a list of values */
+#define o_ONE_CHAR_VALUE 4 /* next char is value (does not end short opt string) */
+#define o_NUMBER_VALUE 5 /* value is integer (does not end short opt string) */
+
+
+/* negatable - a dash following the option (but before any value) sets negated. */
+#define o_NOT_NEGATABLE 0 /* trailing '-' to negate either starts value or generates error */
+#define o_NEGATABLE 1 /* trailing '-' sets negated to TRUE */
+
+
+/* option_num can be this when option not in options table */
+#define o_NO_OPTION_MATCH -1
+
+/* special values returned by get_option - do not use these as option IDs */
+#define o_NON_OPTION_ARG ((unsigned long) 0xFFFF) /* returned for non-option
+ args */
+#define o_ARG_FILE_ERR ((unsigned long) 0xFFFE) /* internal recursion
+ return (user never sees) */
+#define o_BAD_ERR ((unsigned long) 0xFFFD) /* bad error */
+
+/* options array is set in unzip.c */
+struct option_struct {
+ int option_group; /* either UZO for UnZip or ZIO for ZipInfo syntax */
+ char Far *shortopt; /* pointer to short option string */
+ char Far *longopt; /* pointer to long option string */
+ int value_type; /* from above */
+ int negatable; /* from above */
+ unsigned long option_ID; /* value returned by get_option when this option
+ is found */
+ char Far *name; /* optional string for option returned on some
+ errors */
+};
+
+/* structure used to create -x and include file lists */
+struct file_list {
+ char *name;
+ struct file_list *next;
+};
+
+
+/* function prototypes */
+
+/* get the next option from args */
+unsigned long get_option OF((int option_group,
+ char ***pargs, int *argc, int *argnum,
+ int *optchar,
+ char **value, int *negated, int *first_nonopt_arg,
+ int *option_num, int recursion_depth));
+
+/* copy args - copy an args array, allocating space as needed */
+char **copy_args OF((char **args, int max_args));
+
+/* arg count - count args in argv like array */
+int arg_count OF((char **args));
+
+/* free args - free args created with one of these functions */
+int free_args OF((char **args));
+
+/* insert arg - copy an arg into args */
+int insert_arg OF((char ***args, ZCONST char *arg, int insert_at,
+ int free_args));
+
+/*--------------------------------------------------------------------
+ End of Long option support
+ --------------------------------------------------------------------*/
+
/***********************************/
/* LARGE_FILE_SUPPORT */
diff -ru2 unz60e03/vms/cmdline.c u6e3_np/vms/cmdline.c
--- unz60e03/vms/cmdline.c Tue Feb 12 01:37:42 2008
+++ u6e3_np/vms/cmdline.c Mon Mar 24 14:13:10 2008
@@ -34,4 +34,6 @@
** Modified by:
**
+** 02-014 E. Gordon 10-Mar-2008 03:12
+** Modified to work with get_options().
** 02-013 S. Schweda, C. Spieler 29-Dec-2007 03:34
** Extended /RESTORE qualifier to support timestamp restoration
@@ -172,10 +174,10 @@
$DESCRIPTOR(cli_text_auto, "TEXT.AUTO"); /* -a */
$DESCRIPTOR(cli_text_all, "TEXT.ALL"); /* -aa */
-$DESCRIPTOR(cli_text_none, "TEXT.NONE"); /* ---a */
+$DESCRIPTOR(cli_text_none, "TEXT.NONE"); /* -a- */
$DESCRIPTOR(cli_text_stmlf, "TEXT.STMLF"); /* -S */
$DESCRIPTOR(cli_binary, "BINARY"); /* -b[b] */
$DESCRIPTOR(cli_binary_auto, "BINARY.AUTO"); /* -b */
$DESCRIPTOR(cli_binary_all, "BINARY.ALL"); /* -bb */
-$DESCRIPTOR(cli_binary_none, "BINARY.NONE"); /* ---b */
+$DESCRIPTOR(cli_binary_none, "BINARY.NONE"); /* -b- */
$DESCRIPTOR(cli_case_insensitive,"CASE_INSENSITIVE"); /* -C */
$DESCRIPTOR(cli_screen, "SCREEN"); /* -c */
@@ -202,5 +204,5 @@
$DESCRIPTOR(cli_restore_own, "RESTORE.OWNER_PROT"); /* -X */
$DESCRIPTOR(cli_restore_date, "RESTORE.DATE"); /* -DD */
-$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL"); /* --D */
+$DESCRIPTOR(cli_restore_date_all, "RESTORE.DATE.ALL"); /* -D- */
$DESCRIPTOR(cli_restore_date_files, "RESTORE.DATE.FILES"); /* -D */
$DESCRIPTOR(cli_dot_version, "DOT_VERSION"); /* -Y */
@@ -299,4 +301,6 @@
** SS$_ABORT - Bad time value
**
+** Modified to work with the get_option() command line parser. 10 March 2008
+**
*/
register unsigned long status;
@@ -419,5 +423,4 @@
if (status != CLI$_ABSENT) {
*ptr++ = '-';
- *ptr++ = '-';
*ptr++ = 'b';
if ((status & 1) &&
@@ -427,4 +430,5 @@
*ptr++ = 'b';
}
+ *ptr++ = '-';
}
@@ -436,5 +440,4 @@
if (status != CLI$_ABSENT) {
*ptr++ = '-';
- *ptr++ = '-';
*ptr++ = 'a';
if ((status & 1) &&
@@ -446,4 +449,5 @@
*ptr++ = 'S';
}
+ *ptr++ = '-';
}
diff -ru2 unz60e03/zipinfo.c u6e3_np/zipinfo.c
--- unz60e03/zipinfo.c Mon Mar 24 14:23:54 2008
+++ u6e3_np/zipinfo.c Mon Mar 24 14:25:24 2008
@@ -171,4 +171,6 @@
static ZCONST char Far ZipfileCommTruncMsg[] =
"\ncaution: zipfile comment truncated\n";
+static ZCONST char Far NoMemArguments[] =
+ "envargs: cannot get memory for arguments";
static ZCONST char Far CentralDirEntry[] =
@@ -459,10 +461,48 @@
__GDEF
{
- char **argv, *s;
- int argc, c, error=FALSE, negative=0;
+ int argc, error=FALSE;
int hflag_slmv=TRUE, hflag_2=FALSE; /* diff options => diff defaults */
int tflag_slm=TRUE, tflag_2v=FALSE;
int explicit_h=FALSE, explicit_t=FALSE;
+ char **args;
+
+
+ /* used by get_option */
+ unsigned long option; /* option ID returned by get_option */
+ int argcnt = 0; /* current argcnt in args */
+ int argnum = 0; /* arg number */
+ int optchar = 0; /* option state */
+ char *value = NULL; /* non-option arg, option value or NULL */
+ int negative = 0; /* 1 = option negated */
+ int fna = 0; /* current first non-opt arg */
+ int optnum = 0; /* index in table */
+
+
+ /* since get_option() returns xfiles and files one at a time, store them in
+ linked lists until have them all */
+
+ int file_count;
+ struct file_list *next_file;
+
+ /* files to extract */
+ int in_files_count = 0;
+ struct file_list *in_files = NULL;
+ struct file_list *next_in_files = NULL;
+
+ /* files to exclude in -x list */
+ int in_xfiles_count = 0;
+ struct file_list *in_xfiles = NULL;
+ struct file_list *next_in_xfiles = NULL;
+
+ G.wildzipfn = NULL;
+
+ /* make copy of args that can use with insert_arg() used by get_option() */
+ args = copy_args(*pargv, 0);
+
+
+ /* Initialize lists */
+ G.filespecs = 0;
+ G.xfilespecs = 0;
#ifdef MACOS
@@ -470,17 +510,41 @@
#endif
G.extract_flag = FALSE; /* zipinfo does not extract to disk */
- argc = *pargc;
- argv = *pargv;
- while (--argc > 0 && (*++argv)[0] == '-') {
- s = argv[0] + 1;
- while ((c = *s++) != 0) { /* "!= 0": prevent Turbo C warning */
- switch (c) {
- case '-':
- ++negative;
- break;
+
+ /*
+ -------------------------------------------
+ Process command line using get_option
+ -------------------------------------------
+
+ Each call to get_option() returns either a command
+ line option and possible value or a non-option argument.
+ Arguments are permuted so that all options (-r, -b temp)
+ are returned before non-option arguments (zipfile).
+ Returns 0 when nothing left to read.
+ */
+
+ /* set argnum = 0 on first call to init get_option */
+ argnum = 0;
+
+ /* get_option returns the option ID and updates parameters:
+ args - usually same as argv if no argument file support
+ argcnt - current argc for args
+ value - char* to value (free() when done with it) or NULL if no value
+ negated - option was negated with trailing -
+ */
+
+ while ((option = get_option(ZIO, &args, &argcnt, &argnum,
+ &optchar, &value, &negative,
+ &fna, &optnum, 0)))
+ {
+ if(option == o_BAD_ERR) {
+ return(PK_PARAM);
+ }
+
+ switch (option)
+ {
case '1': /* shortest listing: JUST filenames */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 1;
@@ -488,5 +552,5 @@
case '2': /* just filenames, plus headers if specified */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 2;
@@ -495,5 +559,5 @@
case ('C'): /* -C: match filenames case-insensitively */
if (negative)
- uO.C_flag = FALSE, negative = 0;
+ uO.C_flag = FALSE;
else
uO.C_flag = TRUE;
@@ -502,5 +566,5 @@
case 'h': /* header line */
if (negative)
- hflag_2 = hflag_slmv = FALSE, negative = 0;
+ hflag_2 = hflag_slmv = FALSE;
else {
hflag_2 = hflag_slmv = explicit_h = TRUE;
@@ -511,5 +575,5 @@
case 'l': /* longer form of "ls -l" type listing */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 5;
@@ -517,5 +581,5 @@
case 'm': /* medium form of "ls -l" type listing */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 4;
@@ -524,5 +588,5 @@
case 'M': /* send output through built-in "more" */
if (negative)
- G.M_flag = FALSE, negative = 0;
+ G.M_flag = FALSE;
else
G.M_flag = TRUE;
@@ -531,5 +595,5 @@
case 's': /* default: shorter "ls -l" type listing */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 3;
@@ -537,5 +601,5 @@
case 't': /* totals line */
if (negative)
- tflag_2v = tflag_slm = FALSE, negative = 0;
+ tflag_2v = tflag_slm = FALSE;
else {
tflag_2v = tflag_slm = explicit_t = TRUE;
@@ -546,5 +610,5 @@
case ('T'): /* use (sortable) decimal time format */
if (negative)
- uO.T_flag = FALSE, negative = 0;
+ uO.T_flag = FALSE;
else
uO.T_flag = TRUE;
@@ -552,8 +616,7 @@
#ifdef UNICODE_SUPPORT
case ('U'): /* escape UTF-8, or disable UTF-8 support */
- if (negative) {
- uO.U_flag = MAX(uO.U_flag-negative,0);
- negative = 0;
- } else
+ if (negative)
+ uO.U_flag = MAX(uO.U_flag - 1, 0);
+ else
uO.U_flag++;
break;
@@ -561,5 +624,5 @@
case 'v': /* turbo-verbose listing */
if (negative)
- uO.lflag = -2, negative = 0;
+ uO.lflag = -2;
else
uO.lflag = 10;
@@ -568,12 +631,36 @@
case ('W'): /* Wildcard interpretation (stop at '/'?) */
if (negative)
- uO.W_flag = FALSE, negative = 0;
+ uO.W_flag = FALSE;
else
uO.W_flag = TRUE;
break;
#endif /* WILD_STOP_AT_DIR */
+ case ('x'): /* extract: default */
+ /* add -x file to linked list */
+
+ if (in_xfiles_count == 0) {
+ /* first entry */
+ if ((in_xfiles = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ in_xfiles->name = value;
+ in_xfiles->next = NULL;
+ next_in_xfiles = in_xfiles;
+ } else {
+ /* add next entry */
+ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ next_in_xfiles->next = next_file;
+ next_file->name = value;
+ next_file->next = NULL;
+ next_in_xfiles = next_file;
+ }
+ in_xfiles_count++;
case 'z': /* print zipfile comment */
if (negative)
- uO.zflag = negative = 0;
+ uO.zflag = 0;
else
uO.zflag = 1;
@@ -581,13 +668,96 @@
case 'Z': /* ZipInfo mode: ignore */
break;
+ case o_NON_OPTION_ARG:
+ /* not an option */
+ /* no more options as permuting */
+
+
+ if (G.wildzipfn == NULL) {
+ /* first non-option argument is zip file */
+ G.wildzipfn = value;
+
+ } else {
+ /* add include file to list */
+ if (in_files_count == 0) {
+ /* first entry */
+ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ next_file->name = value;
+ next_file->next = NULL;
+ in_files = next_file;
+ next_in_files = next_file;
+ } else {
+ /* add next entry */
+ if ((next_file = (struct file_list *) malloc(sizeof(struct file_list))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ next_in_files->next = next_file;
+ next_file->name = value;
+ next_file->next = NULL;
+ next_in_files = next_file;
+ }
+ in_files_count++;
+ }
+ break;
default:
error = TRUE;
break;
- }
- }
+ } /* switch */
+ } /* get_option() */
+
+ /* convert files and xfiles lists to arrays */
+
+ /* convert files list to array */
+ if (in_files_count) {
+ if ((G.pfnames = (char **) malloc((in_files_count + 1) * sizeof(char *))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ file_count = 0;
+ for (next_file = in_files; next_file;) {
+ G.pfnames[file_count] = next_file->name;
+ in_files = next_file;
+ next_file = next_file->next;
+ free(in_files);
+ file_count++;
+ }
+ G.pfnames[file_count] = NULL;
+ G.filespecs = in_files_count;
+ }
+
+ /* convert xfiles list to array */
+ if (in_xfiles_count) {
+ if ((G.pxnames = (char **) malloc((in_xfiles_count + 1) * sizeof(char *))) == NULL) {
+ Info(slide, 0x401, ((char *)slide, LoadFarString(NoMemArguments)));
+ return PK_MEM;
+ }
+ file_count = 0;
+ for (next_file = in_xfiles; next_file;) {
+ G.pxnames[file_count] = next_file->name;
+ in_xfiles = next_file;
+ next_file = next_file->next;
+ free(in_xfiles);
+ file_count++;
+ }
+ G.pxnames[file_count] = NULL;
+ G.xfilespecs = in_xfiles_count;
}
- if ((argc-- == 0) || error) {
+
+ if (in_files_count || in_xfiles_count) {
+ G.process_all_files = FALSE;
+ } else {
+ G.process_all_files = TRUE; /* for speed */
+ }
+
+ /* it's possible the arg count could have been changed by get_option() */
+ argc = arg_count(args);
+
+ if ((G.wildzipfn == NULL) || error) {
+ argc = -1; /* tell the caller to stop processing */
*pargc = argc;
- *pargv = argv;
+ *pargv = args;
return USAGE(error);
}
@@ -628,5 +798,5 @@
*pargc = argc;
- *pargv = argv;
+ *pargv = args;
return 0;