home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 9 Archive / 09-Archive.zip / unzip540.zip / envargs.c < prev    next >
C/C++ Source or Header  |  1998-04-28  |  9KB  |  315 lines

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