~ubuntu-branches/ubuntu/precise/unzip/precise-proposed

« back to all changes in this revision

Viewing changes to envargs.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2004-06-06 17:57:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040606175746-nl7p2dgp3aobyc2c
Tags: upstream-5.51
ImportĀ upstreamĀ versionĀ 5.51

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (c) 1990-2002 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
static int count_args OF((ZCONST char *));
 
42
 
 
43
 
 
44
/* envargs() returns PK-style error code */
 
45
 
 
46
int envargs(Pargc, Pargv, envstr, envstr2)
 
47
    int *Pargc;
 
48
    char ***Pargv;
 
49
    ZCONST char *envstr, *envstr2;
 
50
{
 
51
#ifndef RISCOS
 
52
    char *getenv();
 
53
#endif
 
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 */