git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@7748 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			315 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			315 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*----------------------------------------------------------------*
 | 
						|
 | envargs - add default options from environment to command line
 | 
						|
 |----------------------------------------------------------------
 | 
						|
 | Author: Bill Davidsen, original 10/13/91, revised 23 Oct 1991.
 | 
						|
 | This program is in the public domain.
 | 
						|
 |----------------------------------------------------------------
 | 
						|
 | Minor program notes:
 | 
						|
 |  1. Yes, the indirection is a tad complex
 | 
						|
 |  2. Parentheses were added where not needed in some cases
 | 
						|
 |     to make the action of the code less obscure.
 | 
						|
 |----------------------------------------------------------------
 | 
						|
 | UnZip notes: 24 May 92 ("v1.4"):
 | 
						|
 |  1. #include "unzip.h" for prototypes (24 May 92)
 | 
						|
 |  2. changed ch to type char (24 May 92)
 | 
						|
 |  3. added an ifdef to avoid Borland warnings (24 May 92)
 | 
						|
 |  4. included Rich Wales' mksargs() routine (for MS-DOS, maybe
 | 
						|
 |     OS/2? NT?) (4 Dec 93)
 | 
						|
 |  5. added alternate-variable string envstr2 (21 Apr 94)
 | 
						|
 |  6. added support for quoted arguments (6 Jul 96)
 | 
						|
 *----------------------------------------------------------------*/
 | 
						|
 | 
						|
 | 
						|
#define ENVARGS_C
 | 
						|
#define UNZIP_INTERNAL
 | 
						|
#include "unzip.h"
 | 
						|
 | 
						|
#ifdef __EMX__          /* emx isspace() returns TRUE on extended ASCII !! */
 | 
						|
#  define ISspace(c) ((c) & 0x80 ? 0 : isspace((unsigned)c))
 | 
						|
#else
 | 
						|
#  define ISspace(c) isspace((unsigned)c)
 | 
						|
#endif /* ?__EMX__ */
 | 
						|
 | 
						|
static int count_args OF((ZCONST char *));
 | 
						|
static void mem_err OF((__GPRO));
 | 
						|
 | 
						|
static ZCONST char Far NoMemArguments[] =
 | 
						|
  "envargs:  cannot get memory for arguments";
 | 
						|
 | 
						|
 | 
						|
void envargs(__G__ Pargc, Pargv, envstr, envstr2)
 | 
						|
    __GDEF
 | 
						|
    int *Pargc;
 | 
						|
    char ***Pargv;
 | 
						|
    ZCONST char *envstr, *envstr2;
 | 
						|
{
 | 
						|
#ifndef RISCOS
 | 
						|
    char *getenv();
 | 
						|
#endif
 | 
						|
    char *envptr;       /* value returned by getenv */
 | 
						|
    char *bufptr;       /* copy of env info */
 | 
						|
    int argc = 0;       /* internal arg count */
 | 
						|
    register int ch;    /* spare temp value */
 | 
						|
    char **argv;        /* internal arg vector */
 | 
						|
    char **argvect;     /* copy of vector address */
 | 
						|
 | 
						|
    /* see if anything in the environment */
 | 
						|
    if ((envptr = getenv(envstr)) != (char *)NULL)        /* usual var */
 | 
						|
        while (ISspace(*envptr))        /* must discard leading spaces */
 | 
						|
            envptr++;
 | 
						|
    if (envptr == (char *)NULL || *envptr == '\0')
 | 
						|
        if ((envptr = getenv(envstr2)) != (char *)NULL)   /* alternate var */
 | 
						|
            while (ISspace(*envptr))
 | 
						|
                envptr++;
 | 
						|
    if (envptr == (char *)NULL || *envptr == '\0')
 | 
						|
        return;
 | 
						|
 | 
						|
    bufptr = malloc(1 + strlen(envptr));
 | 
						|
    if (bufptr == (char *)NULL)
 | 
						|
        mem_err(__G);
 | 
						|
#if (defined(WIN32) || defined(WINDLL))
 | 
						|
# ifdef WIN32
 | 
						|
    if (IsWinNT()) {
 | 
						|
        /* SPC: don't know codepage of 'real' WinNT console */
 | 
						|
        strcpy(bufptr, envptr);
 | 
						|
    } else {
 | 
						|
        /* Win95 environment is DOS and uses OEM character coding */
 | 
						|
        OEM_TO_INTERN(envptr, bufptr);
 | 
						|
    }
 | 
						|
# else /* !WIN32 */
 | 
						|
    /* DOS environment uses OEM codepage */
 | 
						|
    OEM_TO_INTERN(envptr, bufptr);
 | 
						|
# endif
 | 
						|
#else /* !(WIN32 || WINDLL) */
 | 
						|
    strcpy(bufptr, envptr);
 | 
						|
#endif /* ?(WIN32 || WINDLL) */
 | 
						|
 | 
						|
    /* count the args so we can allocate room for them */
 | 
						|
    argc = count_args(bufptr);
 | 
						|
    /* allocate a vector large enough for all args */
 | 
						|
    argv = (char **)malloc((argc + *Pargc + 1) * sizeof(char *));
 | 
						|
    if (argv == (char **)NULL) {
 | 
						|
        free(bufptr);
 | 
						|
        mem_err(__G);
 | 
						|
    }
 | 
						|
    argvect = argv;
 | 
						|
 | 
						|
    /* copy the program name first, that's always true */
 | 
						|
    *(argv++) = *((*Pargv)++);
 | 
						|
 | 
						|
    /* copy the environment args next, may be changed */
 | 
						|
    do {
 | 
						|
#if defined(AMIGA) || defined(UNIX)
 | 
						|
        if (*bufptr == '"') {
 | 
						|
            char *argstart = ++bufptr;
 | 
						|
 | 
						|
            *(argv++) = argstart;
 | 
						|
            for (ch = *bufptr; ch != '\0' && ch != '\"'; ch = *(++bufptr))
 | 
						|
                if (ch == '\\' && bufptr[1] != '\0')
 | 
						|
                    ++bufptr;           /* skip char after backslash */
 | 
						|
            if (ch != '\0')
 | 
						|
                *(bufptr++) = '\0';     /* overwrite trailing " */
 | 
						|
 | 
						|
            /* remove escape characters */
 | 
						|
            while ((argstart = strchr(argstart, '\\')) != (char *)NULL) {
 | 
						|
                strcpy(argstart, argstart + 1);
 | 
						|
                if (*argstart)
 | 
						|
                    ++argstart;
 | 
						|
            }
 | 
						|
        } else {
 | 
						|
            *(argv++) = bufptr;
 | 
						|
            while ((ch = *bufptr) != '\0' && !ISspace(ch))
 | 
						|
                ++bufptr;
 | 
						|
            if (ch != '\0')
 | 
						|
                *(bufptr++) = '\0';
 | 
						|
        }
 | 
						|
#else
 | 
						|
#ifdef DOS_FLX_OS2_W32
 | 
						|
        /* we do not support backslash-quoting of quotes in quoted
 | 
						|
         * strings under DOS_OS2_W32, because backslashes are directory
 | 
						|
         * separators and double quotes are illegal in filenames */
 | 
						|
        if (*bufptr == '"') {
 | 
						|
            *(argv++) = ++bufptr;
 | 
						|
            while ((ch = *bufptr) != '\0' && ch != '\"')
 | 
						|
                ++bufptr;
 | 
						|
            if (ch != '\0')
 | 
						|
                *(bufptr++) = '\0';
 | 
						|
        } else {
 | 
						|
            *(argv++) = bufptr;
 | 
						|
            while ((ch = *bufptr) != '\0' && !ISspace(ch))
 | 
						|
                ++bufptr;
 | 
						|
            if (ch != '\0')
 | 
						|
                *(bufptr++) = '\0';
 | 
						|
        }
 | 
						|
#else
 | 
						|
        *(argv++) = bufptr;
 | 
						|
        while ((ch = *bufptr) != '\0' && !ISspace(ch))
 | 
						|
            ++bufptr;
 | 
						|
        if (ch != '\0')
 | 
						|
            *(bufptr++) = '\0';
 | 
						|
#endif /* ?DOS_FLX_OS2_W32 */
 | 
						|
#endif /* ?(AMIGA || UNIX) */
 | 
						|
        while ((ch = *bufptr) != '\0' && ISspace(ch))
 | 
						|
            ++bufptr;
 | 
						|
    } while (ch);
 | 
						|
 | 
						|
    /* now save old argc and copy in the old args */
 | 
						|
    argc += *Pargc;
 | 
						|
    while (--(*Pargc))
 | 
						|
        *(argv++) = *((*Pargv)++);
 | 
						|
 | 
						|
    /* finally, add a NULL after the last arg, like Unix */
 | 
						|
    *argv = (char *)NULL;
 | 
						|
 | 
						|
    /* save the values and return */
 | 
						|
    *Pargv = argvect;
 | 
						|
    *Pargc = argc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static int count_args(s)
 | 
						|
    ZCONST char *s;
 | 
						|
{
 | 
						|
    int count = 0;
 | 
						|
    char ch;
 | 
						|
 | 
						|
    do {
 | 
						|
        /* count and skip args */
 | 
						|
        ++count;
 | 
						|
#if defined(AMIGA) || defined(UNIX)
 | 
						|
        if (*s == '\"') {
 | 
						|
            for (ch = *(++s);  ch != '\0' && ch != '\"';  ch = *(++s))
 | 
						|
                if (ch == '\\' && s[1] != '\0')
 | 
						|
                    ++s;
 | 
						|
            if (*s)
 | 
						|
                ++s;        /* trailing quote */
 | 
						|
        } else
 | 
						|
#else
 | 
						|
#ifdef DOS_FLX_OS2_W32
 | 
						|
        if (*s == '\"') {
 | 
						|
            ++s;                /* leading quote */
 | 
						|
            while ((ch = *s) != '\0' && ch != '\"')
 | 
						|
                ++s;
 | 
						|
            if (*s)
 | 
						|
                ++s;        /* trailing quote */
 | 
						|
        } else
 | 
						|
#endif /* DOS_FLX_OS2_W32 */
 | 
						|
#endif /* ?(AMIGA || UNIX) */
 | 
						|
        while ((ch = *s) != '\0' && !ISspace(ch))  /* note else-clauses above */
 | 
						|
            ++s;
 | 
						|
        while ((ch = *s) != '\0' && ISspace(ch))
 | 
						|
            ++s;
 | 
						|
    } while (ch);
 | 
						|
 | 
						|
    return count;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
static void mem_err(__G)
 | 
						|
    __GDEF
 | 
						|
{
 | 
						|
    perror(LoadFarString(NoMemArguments));
 | 
						|
    DESTROYGLOBALS()
 | 
						|
    EXIT(PK_MEM);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifdef TEST
 | 
						|
 | 
						|
main(argc, argv)
 | 
						|
    int argc;
 | 
						|
    char **argv;
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    pipeit("Orig argv: %p\n", argv);
 | 
						|
    dump_args(argc, argv);
 | 
						|
    envargs(__G__ &argc, &argv, "ENVTEST");
 | 
						|
    pipeit(" New argv: %p\n", argv);
 | 
						|
    dump_args(argc, argv);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
dump_args(argc, argv)
 | 
						|
    int argc;
 | 
						|
    char *argv[];
 | 
						|
{
 | 
						|
    int i;
 | 
						|
 | 
						|
    pipeit("\nDump %d args:\n", argc);
 | 
						|
    for (i = 0; i < argc; ++i)
 | 
						|
        pipeit("%3d %s\n", i, argv[i]);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* TEST */
 | 
						|
 | 
						|
 | 
						|
 | 
						|
#ifdef MSDOS   /* DOS_OS2?  DOS_OS2_W32? */
 | 
						|
 | 
						|
/*
 | 
						|
 * void mksargs(int *argcp, char ***argvp)
 | 
						|
 *
 | 
						|
 *    Substitutes the extended command line argument list produced by
 | 
						|
 *    the MKS Korn Shell in place of the command line info from DOS.
 | 
						|
 *
 | 
						|
 *    The MKS shell gets around DOS's 128-byte limit on the length of
 | 
						|
 *    a command line by passing the "real" command line in the envi-
 | 
						|
 *    ronment.  The "real" arguments are flagged by prepending a tilde
 | 
						|
 *    (~) to each one.
 | 
						|
 *
 | 
						|
 *    This "mksargs" routine creates a new argument list by scanning
 | 
						|
 *    the environment from the beginning, looking for strings begin-
 | 
						|
 *    ning with a tilde character.  The new list replaces the original
 | 
						|
 *    "argv" (pointed to by "argvp"), and the number of arguments
 | 
						|
 *    in the new list replaces the original "argc" (pointed to by
 | 
						|
 *    "argcp").
 | 
						|
 *
 | 
						|
 *    Rich Wales
 | 
						|
 */
 | 
						|
void mksargs(argcp, argvp)
 | 
						|
    int *argcp;
 | 
						|
    char ***argvp;
 | 
						|
{
 | 
						|
#ifndef MSC /* declared differently in MSC 7.0 headers, at least */
 | 
						|
#ifndef __WATCOMC__
 | 
						|
    extern char **environ;          /* environment */
 | 
						|
#endif
 | 
						|
#endif
 | 
						|
    char        **envp;             /* pointer into environment */
 | 
						|
    char        **newargv;          /* new argument list */
 | 
						|
    char        **argp;             /* pointer into new arg list */
 | 
						|
    int         newargc;            /* new argument count */
 | 
						|
 | 
						|
    /* sanity check */
 | 
						|
    if (environ == NULL || argcp == NULL || argvp == NULL || *argvp == NULL)
 | 
						|
        return;
 | 
						|
 | 
						|
    /* find out how many environment arguments there are */
 | 
						|
    for (envp = environ, newargc = 0; *envp != NULL && (*envp)[0] == '~';
 | 
						|
         envp++, newargc++)
 | 
						|
        ;
 | 
						|
    if (newargc == 0)
 | 
						|
        return;     /* no environment arguments */
 | 
						|
 | 
						|
    /* set up new argument list */
 | 
						|
    newargv = (char **) malloc(sizeof(char **) * (newargc+1));
 | 
						|
    if (newargv == NULL)
 | 
						|
        return;     /* malloc failed */
 | 
						|
 | 
						|
    for (argp = newargv, envp = environ; *envp != NULL && (*envp)[0] == '~';
 | 
						|
         *argp++ = &(*envp++)[1])
 | 
						|
        ;
 | 
						|
    *argp = NULL;   /* null-terminate the list */
 | 
						|
 | 
						|
    /* substitute new argument list in place of old one */
 | 
						|
    *argcp = newargc;
 | 
						|
    *argvp = newargv;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* MSDOS */
 |