Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4973 | right-hear | 1 | #include |
2 | #include |
||
3 | |||
4 | void _exit(int code) |
||
5 | { |
||
6 | __asm__ __volatile__("int $0x40"::"a"(-1)); |
||
7 | for(;;); |
||
8 | } |
||
9 | |||
10 | #include |
||
11 | #include |
||
12 | #include |
||
13 | #include |
||
14 | #include |
||
15 | #include |
||
16 | #include |
||
17 | #include |
||
18 | #include |
||
19 | |||
20 | #define ds _my_ds() |
||
21 | |||
22 | |||
23 | extern char __menuet__app_param_area[]; |
||
24 | extern char __menuet__app_path_area[]; |
||
25 | |||
26 | static void * c1xmalloc(size_t s) |
||
27 | { |
||
28 | void *q = malloc(s); |
||
29 | if (q == 0) |
||
30 | { |
||
31 | #define err(x) |
||
32 | err("No memory to gather arguments\r\n"); |
||
33 | _exit(1); |
||
34 | } |
||
35 | return q; |
||
36 | } |
||
37 | |||
38 | static int atohex(char *s) |
||
39 | { |
||
40 | int rv = 0; |
||
41 | while (*s) |
||
42 | { |
||
43 | int v = *s - '0'; |
||
44 | if (v > 9) |
||
45 | v -= 7; |
||
46 | v &= 15; /* in case it's lower case */ |
||
47 | rv = rv*16 + v; |
||
48 | s++; |
||
49 | } |
||
50 | return rv; |
||
51 | } |
||
52 | |||
53 | typedef struct Arg { |
||
54 | char *arg; |
||
55 | char **arg_globbed; |
||
56 | struct ArgList *arg_file; |
||
57 | struct Arg *next; |
||
58 | int was_quoted; |
||
59 | } Arg; |
||
60 | |||
61 | typedef struct ArgList { |
||
62 | int argc; |
||
63 | Arg **argv; |
||
64 | } ArgList; |
||
65 | |||
66 | static Arg *new_arg(void) |
||
67 | { |
||
68 | Arg *a = (Arg *)c1xmalloc(sizeof(Arg)); |
||
69 | memset(a, 0, sizeof(Arg)); |
||
70 | return a; |
||
71 | } |
||
72 | |||
73 | static void delete_arglist(ArgList *al); |
||
74 | |||
75 | static void delete_arg(Arg *a) |
||
76 | { |
||
77 | if (a->arg) free(a->arg); |
||
78 | if (a->arg_globbed) |
||
79 | { |
||
80 | int i; |
||
81 | for (i=0; a->arg_globbed[i]; i++) |
||
82 | free(a->arg_globbed[i]); |
||
83 | free(a->arg_globbed); |
||
84 | } |
||
85 | if (a->arg_file) |
||
86 | delete_arglist(a->arg_file); |
||
87 | free(a); |
||
88 | } |
||
89 | |||
90 | static ArgList * new_arglist(int count) |
||
91 | { |
||
92 | ArgList *al = (ArgList *)c1xmalloc(sizeof(ArgList)); |
||
93 | al->argc = count; |
||
94 | al->argv = (Arg **)c1xmalloc((count+1)*sizeof(Arg *)); |
||
95 | memset(al->argv, 0, (count+1)*sizeof(Arg *)); |
||
96 | return al; |
||
97 | } |
||
98 | |||
99 | static void delete_arglist(ArgList *al) |
||
100 | { |
||
101 | int i; |
||
102 | for (i=0; i |
||
103 | delete_arg(al->argv[i]); |
||
104 | free(al->argv); |
||
105 | free(al); |
||
106 | } |
||
107 | |||
108 | static char * parse_arg(char *bp, char *last, int unquote, size_t *len, int *was_quoted) |
||
109 | { |
||
110 | char *ep = bp, *epp = bp; |
||
111 | int quote=0; |
||
112 | |||
113 | while ((quote || !isspace(*(unsigned char *)ep)) && ep < last) |
||
114 | { |
||
115 | if (quote && *ep == quote) |
||
116 | { |
||
117 | quote = 0; |
||
118 | if (!unquote) |
||
119 | *epp++ = *ep; |
||
120 | ep++; |
||
121 | } |
||
122 | else if (!quote && (*ep == '\'' || *ep == '"')) |
||
123 | { |
||
124 | quote = *ep++; |
||
125 | if (!unquote) |
||
126 | *epp++ = quote; |
||
127 | } |
||
128 | else if (*ep == '\\' && strchr("'\"", ep[1]) && ep < last-1) |
||
129 | { |
||
130 | if (!unquote) |
||
131 | *epp++ = *ep; |
||
132 | ep++; |
||
133 | *epp++ = *ep++; |
||
134 | /* *was_quoted = 1; - This makes no sense. */ |
||
135 | } |
||
136 | else |
||
137 | { |
||
138 | if ((quote && (strchr("[?*", *ep) || strncmp(ep, "...", 3) == 0)) |
||
139 | && unquote) |
||
140 | *was_quoted = 1; |
||
141 | *epp++ = *ep++; |
||
142 | } |
||
143 | } |
||
144 | |||
145 | *len = epp - bp; |
||
146 | return ep; |
||
147 | } |
||
148 | |||
149 | static ArgList * parse_bytes(char *bytes, int length, int unquote) |
||
150 | { |
||
151 | int largc, i; |
||
152 | Arg *a, **anext, *afirst; |
||
153 | ArgList *al; |
||
154 | char *bp=bytes, *ep, *last=bytes+length; |
||
155 | |||
156 | anext = &afirst; |
||
157 | largc = 0; |
||
158 | while (bp |
||
159 | { |
||
160 | size_t arg_len; |
||
161 | while (isspace(*(unsigned char *)bp) && bp < last) |
||
162 | bp++; |
||
163 | if (bp == last) |
||
164 | break; |
||
165 | *anext = a = new_arg(); |
||
166 | ep = parse_arg(bp, last, unquote, &arg_len, &(a->was_quoted)); |
||
167 | anext = &(a->next); |
||
168 | largc++; |
||
169 | a->arg = (char *)c1xmalloc(arg_len+1); |
||
170 | memcpy(a->arg, bp, arg_len); |
||
171 | a->arg[arg_len] = 0; |
||
172 | bp = ep+1; |
||
173 | } |
||
174 | al = new_arglist(largc); |
||
175 | for (i=0, a=afirst; i |
||
176 | al->argv[i] = a; |
||
177 | return al; |
||
178 | } |
||
179 | |||
180 | static ArgList * parse_print0(char *bytes, int length) |
||
181 | { |
||
182 | int largc, i; |
||
183 | Arg *a, **anext, *afirst; |
||
184 | ArgList *al; |
||
185 | char *bp=bytes, *ep, *last=bytes+length; |
||
186 | |||
187 | anext = &afirst; |
||
188 | largc = 0; |
||
189 | while (bp |
||
190 | { |
||
191 | size_t arg_len = strlen(bp); |
||
192 | ep = bp; |
||
193 | bp += arg_len + 1; |
||
194 | *anext = a = new_arg(); |
||
195 | a->was_quoted = 1; |
||
196 | anext = &(a->next); |
||
197 | largc++; |
||
198 | a->arg = (char *)c1xmalloc(arg_len+1); |
||
199 | memcpy(a->arg, ep, arg_len); |
||
200 | a->arg[arg_len] = 0; |
||
201 | } |
||
202 | al = new_arglist(largc); |
||
203 | for (i=0, a=afirst; i |
||
204 | al->argv[i] = a; |
||
205 | return al; |
||
206 | } |
||
207 | |||
208 | static int count_args(ArgList *al) |
||
209 | { |
||
210 | int i, r=0; |
||
211 | for (i=0; i |
||
212 | { |
||
213 | int j; |
||
214 | if (al->argv[i]->arg_globbed) |
||
215 | { |
||
216 | for (j=0; al->argv[i]->arg_globbed[j]; j++); |
||
217 | r += j; |
||
218 | } |
||
219 | else if (al->argv[i]->arg_file) |
||
220 | { |
||
221 | r += count_args(al->argv[i]->arg_file); |
||
222 | } |
||
223 | else |
||
224 | { |
||
225 | r++; |
||
226 | } |
||
227 | } |
||
228 | return r; |
||
229 | } |
||
230 | |||
231 | static char ** fill_args(char **largv, ArgList *al) |
||
232 | { |
||
233 | int i; |
||
234 | for (i=0; i |
||
235 | { |
||
236 | int j; |
||
237 | if (al->argv[i]->arg_globbed) |
||
238 | { |
||
239 | for (j=0; al->argv[i]->arg_globbed[j]; j++) |
||
240 | { |
||
241 | *largv++ = al->argv[i]->arg_globbed[j]; |
||
242 | al->argv[i]->arg_globbed[j] = 0; |
||
243 | } |
||
244 | } |
||
245 | else if (al->argv[i]->arg_file) |
||
246 | { |
||
247 | largv = fill_args(largv, al->argv[i]->arg_file); |
||
248 | } |
||
249 | else |
||
250 | { |
||
251 | *largv++ = al->argv[i]->arg; |
||
252 | al->argv[i]->arg = 0; |
||
253 | } |
||
254 | } |
||
255 | return largv; |
||
256 | } |
||
257 | |||
258 | static void expand_response_files(ArgList *al) |
||
259 | { |
||
260 | int i, f; |
||
261 | for (i=0; i |
||
262 | { |
||
263 | if (! al->argv[i]->was_quoted && al->argv[i]->arg[0] == '@') |
||
264 | if ((f = _open(al->argv[i]->arg+1, O_RDONLY)) >= 0) |
||
265 | { |
||
266 | char *bytes; |
||
267 | int len, st_size; |
||
268 | st_size = lseek(f, 0L, SEEK_END); |
||
269 | lseek(f, 0L, SEEK_SET); |
||
270 | if (st_size < 0) |
||
271 | st_size = 0; |
||
272 | bytes = (char *)c1xmalloc(st_size+1); |
||
273 | len = _read(f, bytes, st_size); |
||
274 | if (len < 0) |
||
275 | len = 0; |
||
276 | _close(f); |
||
277 | /* if the last character is ^Z, remove it */ |
||
278 | if (len > 0 && bytes[len-1] == 0x1a) |
||
279 | len--; |
||
280 | /* assume 'find -print0' if the last char is a '\0' */ |
||
281 | if (len > 0 && bytes[len-1] == '\0') |
||
282 | al->argv[i]->arg_file = parse_print0(bytes, len); |
||
283 | else |
||
284 | al->argv[i]->arg_file = parse_bytes(bytes, len, (_crt0_startup_flags & _CRT0_FLAG_KEEP_QUOTES) == 0); |
||
285 | expand_response_files(al->argv[i]->arg_file); |
||
286 | free(bytes); |
||
287 | } |
||
288 | } |
||
289 | } |
||
290 | |||
291 | static void expand_wildcards(ArgList *al) |
||
292 | { |
||
293 | int i; |
||
294 | for (i=0; i |
||
295 | { |
||
296 | if (al->argv[i]->arg_file) |
||
297 | expand_wildcards(al->argv[i]->arg_file); |
||
298 | else if (!(al->argv[i]->was_quoted)) |
||
299 | { |
||
300 | al->argv[i]->arg_globbed = __crt0_glob_function(al->argv[i]->arg); |
||
301 | } |
||
302 | } |
||
303 | } |
||
304 | |||
305 | static void add_arg(const char* arg, const char* end) |
||
306 | { |
||
307 | char* res; |
||
308 | __crt0_argv = realloc(__crt0_argv, 4*(++__crt0_argc)); |
||
309 | res = malloc(end-arg+1); |
||
310 | if (!__crt0_argv || !res) _exit(1); |
||
311 | __crt0_argv[__crt0_argc-1] = res; |
||
312 | while (arg < end) |
||
313 | { |
||
314 | if (arg[0] == '"' && arg[1] == '"') ++arg; |
||
315 | *res++ = *arg++; |
||
316 | } |
||
317 | *res = 0; |
||
318 | } |
||
319 | |||
320 | void __crt0_setup_arguments(void) |
||
321 | { |
||
322 | #if 0 |
||
323 | // не будем страдать фигнёй... |
||
324 | ArgList *arglist; |
||
325 | char *argv0; |
||
326 | int prepend_argv0 = 1; |
||
327 | int should_expand_wildcards = 1; |
||
328 | char *proxy_v = 0; |
||
329 | argv0="menuet.app"; |
||
330 | /* |
||
331 | ** Next, scan dos's command line. |
||
332 | */ |
||
333 | { |
||
334 | char doscmd[128]; |
||
335 | memcpy(doscmd+1,__menuet__app_param_area,128); |
||
336 | arglist = parse_bytes(doscmd+1, doscmd[0] & 0x7f, |
||
337 | (_crt0_startup_flags & _CRT0_FLAG_KEEP_QUOTES) == 0); |
||
338 | } |
||
339 | |||
340 | /* |
||
341 | ** Now, expand response files |
||
342 | */ |
||
343 | if (!(_crt0_startup_flags & _CRT0_FLAG_DISALLOW_RESPONSE_FILES)) |
||
344 | expand_response_files(arglist); |
||
345 | |||
346 | /* |
||
347 | ** Now, expand wildcards |
||
348 | */ |
||
349 | |||
350 | if (should_expand_wildcards) |
||
351 | expand_wildcards(arglist); |
||
352 | |||
353 | __crt0_argc = prepend_argv0 + count_args(arglist); |
||
354 | __crt0_argv = (char **)c1xmalloc((__crt0_argc+1) * sizeof(char *)); |
||
355 | if (prepend_argv0) |
||
356 | __crt0_argv[0] = argv0; |
||
357 | *fill_args(__crt0_argv+prepend_argv0, arglist) = 0; |
||
358 | #else |
||
359 | // ...а просто разберём командную строку. - diamond |
||
360 | char* ptr; |
||
361 | char* cur_arg=NULL; |
||
362 | int bInQuote=0; |
||
363 | add_arg(__menuet__app_path_area, |
||
364 | __menuet__app_path_area + strlen(__menuet__app_path_area)); |
||
365 | for (ptr=__menuet__app_param_area;*ptr && ptr<__menuet__app_param_area+256;ptr++) |
||
366 | { |
||
367 | if (*ptr == ' ' || *ptr == '\t') |
||
368 | { |
||
369 | if (cur_arg && !bInQuote) |
||
370 | { |
||
371 | add_arg(cur_arg,ptr); |
||
372 | cur_arg = NULL; |
||
373 | } |
||
374 | continue; |
||
375 | } |
||
376 | if (*ptr == '"') |
||
377 | { |
||
378 | if (ptr[1] == '"') |
||
379 | {if (!cur_arg) cur_arg=ptr;ptr++;} |
||
380 | else |
||
381 | { |
||
382 | if (cur_arg) |
||
383 | { |
||
384 | add_arg(cur_arg,ptr); |
||
385 | if (bInQuote) |
||
386 | { |
||
387 | bInQuote = 0; |
||
388 | cur_arg = NULL; |
||
389 | continue; |
||
390 | } |
||
391 | } |
||
392 | bInQuote = 1; |
||
393 | cur_arg = ptr+1; |
||
394 | } |
||
395 | continue; |
||
396 | } |
||
397 | if (!cur_arg) cur_arg = ptr; |
||
398 | } |
||
399 | if (cur_arg) add_arg(cur_arg,ptr); |
||
400 | #endif |
||
401 | } |