Subversion Repositories Kolibri OS

Rev

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

  1. /*
  2.   Copyright (c) 1990-2005 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2000-Apr-09 or later
  5.   (the contents of which are also included in unzip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. /*----------------------------------------------------------------*
  10.  | envargs - add default options from environment to command line
  11.  |----------------------------------------------------------------
  12.  | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
  13.  | This program is in the public domain.
  14.  |----------------------------------------------------------------
  15.  | Minor program notes:
  16.  |  1. Yes, the indirection is a tad complex
  17.  |  2. Parentheses were added where not needed in some cases
  18.  |     to make the action of the code less obscure.
  19.  |----------------------------------------------------------------
  20.  | UnZip notes: 24 May 92 ("v1.4"):
  21.  |  1. #include "unzip.h" for prototypes (24 May 92)
  22.  |  2. changed ch to type char (24 May 92)
  23.  |  3. added an ifdef to avoid Borland warnings (24 May 92)
  24.  |  4. included Rich Wales' mksargs() routine (for MS-DOS, maybe
  25.  |     OS/2? NT?) (4 Dec 93)
  26.  |  5. added alternate-variable string envstr2 (21 Apr 94)
  27.  |  6. added support for quoted arguments (6 Jul 96)
  28.  *----------------------------------------------------------------*/
  29.  
  30.  
  31. #define __ENVARGS_C     /* identifies this source module */
  32. #define UNZIP_INTERNAL
  33. #include "unzip.h"
  34.  
  35. #ifdef __EMX__          /* emx isspace() returns TRUE on extended ASCII !! */
  36. #  define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c))
  37. #else
  38. #  define ISspace(c) isspace((unsigned)c)
  39. #endif /* ?__EMX__ */
  40.  
  41. #if (!defined(RISCOS) && (!defined(MODERN) || defined(NO_STDLIB_H)))
  42. extern char *getenv();
  43. #endif
  44. static int count_args OF((ZCONST char *));
  45.  
  46.  
  47. /* envargs() returns PK-style error code */
  48.  
  49. int envargs(Pargc, Pargv, envstr, envstr2)
  50.     int *Pargc;
  51.     char ***Pargv;
  52.     ZCONST char *envstr, *envstr2;
  53. {
  54.     char *envptr;       /* value returned by getenv */
  55.     char *bufptr;       /* copy of env info */
  56.     int argc = 0;       /* internal arg count */
  57.     register int ch;    /* spare temp value */
  58.     char **argv;        /* internal arg vector */
  59.     char **argvect;     /* copy of vector address */
  60.  
  61.     /* see if anything in the environment */
  62.     if ((envptr = getenv(envstr)) != (char *)NULL)        /* usual var */
  63.         while (ISspace(*envptr))        /* must discard leading spaces */
  64.             envptr++;
  65.     if (envptr == (char *)NULL || *envptr == '\0')
  66.         if ((envptr = getenv(envstr2)) != (char *)NULL)   /* alternate var */
  67.             while (ISspace(*envptr))
  68.                 envptr++;
  69.     if (envptr == (char *)NULL || *envptr == '\0')
  70.         return PK_OK;
  71.  
  72.     bufptr = malloc(1 + strlen(envptr));
  73.     if (bufptr == (char *)NULL)
  74.         return PK_MEM;
  75. #if ((defined(WIN32) || defined(WINDLL)) && !defined(_WIN32_WCE))
  76. # ifdef WIN32
  77.     if (IsWinNT()) {
  78.         /* SPC: don't know codepage of 'real' WinNT console */
  79.         strcpy(bufptr, envptr);
  80.     } else {
  81.         /* Win95 environment is DOS and uses OEM character coding */
  82.         OEM_TO_INTERN(envptr, bufptr);
  83.     }
  84. # else /* !WIN32 */
  85.     /* DOS (Win 3.x) environment uses OEM codepage */
  86.     OEM_TO_INTERN(envptr, bufptr);
  87. # endif
  88. #else /* !((WIN32 || WINDLL) && !_WIN32_WCE) */
  89.     strcpy(bufptr, envptr);
  90. #endif /* ?((WIN32 || WINDLL) && !_WIN32_WCE) */
  91.  
  92.     /* count the args so we can allocate room for them */
  93.     argc = count_args(bufptr);
  94.     /* allocate a vector large enough for all args */
  95.     argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
  96.     if (argv == (char **)NULL) {
  97.         free(bufptr);
  98.         return PK_MEM;
  99.     }
  100.     argvect = argv;
  101.  
  102.     /* copy the program name first, that's always true */
  103.     *(argv++) = *((*Pargv)++);
  104.  
  105.     /* copy the environment args next, may be changed */
  106.     do {
  107. #if defined(AMIGA) || defined(UNIX)
  108.         if (*bufptr == '"') {
  109.             char *argstart = ++bufptr;
  110.  
  111.             *(argv++) = argstart;
  112.             for (ch = *bufptr; ch != '\0' && ch != '\"';
  113.                  ch = *PREINCSTR(bufptr))
  114.                 if (ch == '\\' && bufptr[1] != '\0')
  115.                     ++bufptr;           /* advance to char after backslash */
  116.             if (ch != '\0')
  117.                 *(bufptr++) = '\0';     /* overwrite trailing " */
  118.  
  119.             /* remove escape characters */
  120.             while ((argstart = MBSCHR(argstart, '\\')) != (char *)NULL) {
  121.                 strcpy(argstart, argstart + 1);
  122.                 if (*argstart)
  123.                     ++argstart;
  124.             }
  125.         } else {
  126.             *(argv++) = bufptr;
  127.             while ((ch = *bufptr) != '\0' && !ISspace(ch))
  128.                 INCSTR(bufptr);
  129.             if (ch != '\0')
  130.                 *(bufptr++) = '\0';
  131.         }
  132. #else
  133. #ifdef DOS_FLX_NLM_OS2_W32
  134.         /* we do not support backslash-quoting of quotes in quoted
  135.          * strings under DOS_FLX_NLM_OS2_W32, because backslashes are
  136.          * directory separators and double quotes are illegal in filenames */
  137.         if (*bufptr == '"') {
  138.             *(argv++) = ++bufptr;
  139.             while ((ch = *bufptr) != '\0' && ch != '\"')
  140.                 INCSTR(bufptr);
  141.             if (ch != '\0')
  142.                 *(bufptr++) = '\0';
  143.         } else {
  144.             *(argv++) = bufptr;
  145.             while ((ch = *bufptr) != '\0' && !ISspace(ch))
  146.                 INCSTR(bufptr);
  147.             if (ch != '\0')
  148.                 *(bufptr++) = '\0';
  149.         }
  150. #else
  151.         *(argv++) = bufptr;
  152.         while ((ch = *bufptr) != '\0' && !ISspace(ch))
  153.             INCSTR(bufptr);
  154.         if (ch != '\0')
  155.             *(bufptr++) = '\0';
  156. #endif /* ?DOS_FLX_NLM_OS2_W32 */
  157. #endif /* ?(AMIGA || UNIX) */
  158.         while ((ch = *bufptr) != '\0' && ISspace(ch))
  159.             INCSTR(bufptr);
  160.     } while (ch);
  161.  
  162.     /* now save old argc and copy in the old args */
  163.     argc += *Pargc;
  164.     while (--(*Pargc))
  165.         *(argv++) = *((*Pargv)++);
  166.  
  167.     /* finally, add a NULL after the last arg, like Unix */
  168.     *argv = (char *)NULL;
  169.  
  170.     /* save the values and return, indicating succes */
  171.     *Pargv = argvect;
  172.     *Pargc = argc;
  173.  
  174.     return PK_OK;
  175. }
  176.  
  177.  
  178.  
  179. static int count_args(s)
  180.     ZCONST char *s;
  181. {
  182.     int count = 0;
  183.     char ch;
  184.  
  185.     do {
  186.         /* count and skip args */
  187.         ++count;
  188. #if defined(AMIGA) || defined(UNIX)
  189.         if (*s == '\"') {
  190.             for (ch = *PREINCSTR(s);  ch != '\0' && ch != '\"';
  191.                  ch = *PREINCSTR(s))
  192.                 if (ch == '\\' && s[1] != '\0')
  193.                     ++s;
  194.             if (*s)
  195.                 ++s;        /* trailing quote */
  196.         } else
  197. #else
  198. #ifdef DOS_FLX_NLM_OS2_W32
  199.         if (*s == '\"') {
  200.             ++s;                /* leading quote */
  201.             while ((ch = *s) != '\0' && ch != '\"')
  202.                 INCSTR(s);
  203.             if (*s)
  204.                 ++s;        /* trailing quote */
  205.         } else
  206. #endif /* DOS_FLX_NLM_OS2_W32 */
  207. #endif /* ?(AMIGA || UNIX) */
  208.         while ((ch = *s) != '\0' && !ISspace(ch))  /* note else-clauses above */
  209.             INCSTR(s);
  210.         while ((ch = *s) != '\0' && ISspace(ch))
  211.             INCSTR(s);
  212.     } while (ch);
  213.  
  214.     return count;
  215. }
  216.  
  217.  
  218.  
  219. #ifdef TEST
  220.  
  221. int main(argc, argv)
  222.     int argc;
  223.     char **argv;
  224. {
  225.     int err;
  226.  
  227.     printf("Orig argv: %p\n", argv);
  228.     dump_args(argc, argv);
  229.     if ((err = envargs(&argc, &argv, "ENVTEST")) != PK_OK) {
  230.         perror("envargs:  cannot get memory for arguments");
  231.         EXIT(err);
  232.     }
  233.     printf(" New argv: %p\n", argv);
  234.     dump_args(argc, argv);
  235. }
  236.  
  237.  
  238.  
  239. void dump_args(argc, argv)
  240.     int argc;
  241.     char *argv[];
  242. {
  243.     int i;
  244.  
  245.     printf("\nDump %d args:\n", argc);
  246.     for (i = 0; i < argc; ++i)
  247.         printf("%3d %s\n", i, argv[i]);
  248. }
  249.  
  250. #endif /* TEST */
  251.  
  252.  
  253.  
  254. #ifdef MSDOS   /* DOS_OS2?  DOS_OS2_W32? */
  255.  
  256. /*
  257.  * void mksargs(int *argcp, char ***argvp)
  258.  *
  259.  *    Substitutes the extended command line argument list produced by
  260.  *    the MKS Korn Shell in place of the command line info from DOS.
  261.  *
  262.  *    The MKS shell gets around DOS's 128-byte limit on the length of
  263.  *    a command line by passing the "real" command line in the envi-
  264.  *    ronment.  The "real" arguments are flagged by prepending a tilde
  265.  *    (~) to each one.
  266.  *
  267.  *    This "mksargs" routine creates a new argument list by scanning
  268.  *    the environment from the beginning, looking for strings begin-
  269.  *    ning with a tilde character.  The new list replaces the original
  270.  *    "argv" (pointed to by "argvp"), and the number of arguments
  271.  *    in the new list replaces the original "argc" (pointed to by
  272.  *    "argcp").
  273.  *
  274.  *    Rich Wales
  275.  */
  276. void mksargs(argcp, argvp)
  277.     int *argcp;
  278.     char ***argvp;
  279. {
  280. #ifndef MSC /* declared differently in MSC 7.0 headers, at least */
  281. #ifndef __WATCOMC__
  282.     extern char **environ;          /* environment */
  283. #endif
  284. #endif
  285.     char        **envp;             /* pointer into environment */
  286.     char        **newargv;          /* new argument list */
  287.     char        **argp;             /* pointer into new arg list */
  288.     int         newargc;            /* new argument count */
  289.  
  290.     /* sanity check */
  291.     if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL)
  292.         return;
  293.  
  294.     /* find out how many environment arguments there are */
  295.     for (envp = environ, newargc = 0;
  296.          *envp != NULL && (*envp)[0] == '~';
  297.          envp++, newargc++)
  298.         ;
  299.     if (newargc == 0)
  300.         return;     /* no environment arguments */
  301.  
  302.     /* set up new argument list */
  303.     newargv = (char **) malloc(sizeof(char **) * (newargc+1));
  304.     if (newargv == NULL)
  305.         return;     /* malloc failed */
  306.  
  307.     for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~';
  308.          *argp++ = &(*envp++)[1])
  309.         ;
  310.     *argp = NULL;   /* null-terminate the list */
  311.  
  312.     /* substitute new argument list in place of old one */
  313.     *argcp = newargc;
  314.     *argvp = newargv;
  315. }
  316.  
  317. #endif /* MSDOS */
  318.