]>
Commit | Line | Data |
---|---|---|
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 | pipeit("Orig argv: %p\n", argv); | |
229 | dump_args(argc, argv); | |
230 | envargs(__G__ &argc, &argv, "ENVTEST"); | |
231 | pipeit(" 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 | pipeit("\nDump %d args:\n", argc); | |
244 | for (i = 0; i < argc; ++i) | |
245 | pipeit("%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 */ |