envargs.c
上传用户:andy_li
上传日期:2007-01-06
资源大小:1019k
文件大小:9k
源码类别:

压缩解压

开发平台:

MultiPlatform

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