Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6725 | siemargl | 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 */> |