]> git.saurik.com Git - wxWidgets.git/blob - utils/Install/sfxzip/envargs.c
MS-DOS cross-compilation w/ DJGPP
[wxWidgets.git] / utils / Install / sfxzip / envargs.c
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 */