Commit | Line | Data |
---|---|---|
ecc449eb KB |
1 | /*- |
2 | * Copyright (c) 1980, 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
b79f4fa9 DF |
6 | */ |
7 | ||
35371dec | 8 | #ifndef lint |
4aad0a53 | 9 | static char sccsid[] = "@(#)glob.c 5.24 (Berkeley) %G%"; |
ecc449eb | 10 | #endif /* not lint */ |
9363f20d | 11 | |
b9c4f741 KB |
12 | #include <sys/param.h> |
13 | #include <glob.h> | |
14 | #include <errno.h> | |
15 | #include <stdlib.h> | |
16 | #include <string.h> | |
17 | #include <unistd.h> | |
4df6491c CZ |
18 | #if __STDC__ |
19 | # include <stdarg.h> | |
20 | #else | |
21 | # include <varargs.h> | |
22 | #endif | |
23 | ||
4d7b2685 KB |
24 | #include "csh.h" |
25 | #include "extern.h" | |
b6e604fd | 26 | |
454c2aa3 | 27 | static int noglob; |
c8fda9bd | 28 | static int pargsiz, gargsiz; |
6e37afca | 29 | |
b6e604fd | 30 | /* |
c8fda9bd | 31 | * Values for gflag |
b6e604fd | 32 | */ |
6e37afca KB |
33 | #define G_NONE 0 /* No globbing needed */ |
34 | #define G_GLOB 1 /* string contains *?[] characters */ | |
35 | #define G_CSH 2 /* string contains ~`{ characters */ | |
36 | ||
37 | #define GLOBSPACE 100 /* Alloc increment */ | |
b6e604fd | 38 | |
c8fda9bd KB |
39 | #define LBRC '{' |
40 | #define RBRC '}' | |
41 | #define LBRK '[' | |
42 | #define RBRK ']' | |
c8fda9bd | 43 | #define EOS '\0' |
6e37afca | 44 | |
0aec749d | 45 | Char **gargv = NULL; |
6e37afca | 46 | long gargc = 0; |
0aec749d | 47 | Char **pargv = NULL; |
6e37afca | 48 | long pargc = 0; |
b6e604fd | 49 | |
291a8333 | 50 | /* |
c8fda9bd | 51 | * globbing is now done in two stages. In the first pass we expand |
6e37afca | 52 | * csh globbing idioms ~`{ and then we proceed doing the normal |
c8fda9bd KB |
53 | * globbing if needed ?*[ |
54 | * | |
55 | * Csh type globbing is handled in globexpand() and the rest is | |
1fedb07b | 56 | * handled in glob() which is part of the 4.4BSD libc. |
6e37afca | 57 | * |
291a8333 | 58 | */ |
0aec749d CZ |
59 | static Char *globtilde __P((Char **, Char *)); |
60 | static Char **libglob __P((Char **)); | |
61 | static Char **globexpand __P((Char **)); | |
62 | static int globbrace __P((Char *, Char *, Char ***)); | |
63 | static void pword __P((void)); | |
64 | static void psave __P((int)); | |
65 | static void backeval __P((Char *, bool)); | |
6a422336 | 66 | |
b6e604fd | 67 | |
6e37afca | 68 | static Char * |
1fedb07b | 69 | globtilde(nv, s) |
6e37afca | 70 | Char **nv, *s; |
b6e604fd | 71 | { |
6e37afca KB |
72 | Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e; |
73 | ||
74 | gstart = gbuf; | |
75 | *gstart++ = *s++; | |
76 | u = s; | |
77 | for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e; | |
78 | *b++ = *s++); | |
79 | *b = EOS; | |
80 | if (gethdir(gstart)) { | |
81 | blkfree(nv); | |
82 | if (*gstart) | |
83 | stderror(ERR_UNKUSER, short2str(gstart)); | |
84 | else | |
85 | stderror(ERR_NOHOME); | |
86 | } | |
87 | b = &gstart[Strlen(gstart)]; | |
88 | while (*s) | |
89 | *b++ = *s++; | |
90 | *b = EOS; | |
91 | --u; | |
92 | xfree((ptr_t) u); | |
93 | return (Strsave(gstart)); | |
b6e604fd BJ |
94 | } |
95 | ||
c8fda9bd KB |
96 | static int |
97 | globbrace(s, p, bl) | |
6e37afca | 98 | Char *s, *p, ***bl; |
b6e604fd | 99 | { |
6e37afca KB |
100 | int i, len; |
101 | Char *pm, *pe, *lm, *pl; | |
102 | Char **nv, **vl; | |
103 | Char gbuf[MAXPATHLEN]; | |
104 | int size = GLOBSPACE; | |
105 | ||
106 | nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); | |
0aec749d | 107 | *vl = NULL; |
6e37afca KB |
108 | |
109 | len = 0; | |
110 | /* copy part up to the brace */ | |
111 | for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) | |
112 | continue; | |
113 | ||
114 | /* check for balanced braces */ | |
115 | for (i = 0, pe = ++p; *pe; pe++) | |
116 | if (*pe == LBRK) { | |
117 | /* Ignore everything between [] */ | |
118 | for (++pe; *pe != RBRK && *pe != EOS; pe++) | |
b6e604fd | 119 | continue; |
6e37afca | 120 | if (*pe == EOS) { |
c8fda9bd | 121 | blkfree(nv); |
6e37afca KB |
122 | return (-LBRK); |
123 | } | |
124 | } | |
125 | else if (*pe == LBRC) | |
126 | i++; | |
127 | else if (*pe == RBRC) { | |
128 | if (i == 0) | |
129 | break; | |
130 | i--; | |
b6e604fd | 131 | } |
b6e604fd | 132 | |
2f3717d9 | 133 | if (i != 0 || *pe == '\0') { |
6e37afca | 134 | blkfree(nv); |
2f3717d9 | 135 | return (-RBRC); |
6e37afca KB |
136 | } |
137 | ||
138 | for (i = 0, pl = pm = p; pm <= pe; pm++) | |
c8fda9bd KB |
139 | switch (*pm) { |
140 | case LBRK: | |
6e37afca KB |
141 | for (++pm; *pm != RBRK && *pm != EOS; pm++) |
142 | continue; | |
143 | if (*pm == EOS) { | |
0aec749d | 144 | *vl = NULL; |
6e37afca KB |
145 | blkfree(nv); |
146 | return (-RBRK); | |
147 | } | |
148 | break; | |
c8fda9bd | 149 | case LBRC: |
6e37afca KB |
150 | i++; |
151 | break; | |
c8fda9bd | 152 | case RBRC: |
6e37afca KB |
153 | if (i) { |
154 | i--; | |
155 | break; | |
156 | } | |
157 | /* FALLTHROUGH */ | |
b6e604fd | 158 | case ',': |
6e37afca | 159 | if (i && *pm == ',') |
c8fda9bd | 160 | break; |
6e37afca KB |
161 | else { |
162 | Char savec = *pm; | |
163 | ||
164 | *pm = EOS; | |
165 | (void) Strcpy(lm, pl); | |
166 | (void) Strcat(gbuf, pe + 1); | |
167 | *pm = savec; | |
168 | *vl++ = Strsave(gbuf); | |
169 | len++; | |
170 | pl = pm + 1; | |
171 | if (vl == &nv[size]) { | |
172 | size += GLOBSPACE; | |
173 | nv = (Char **) xrealloc((ptr_t) nv, (size_t) | |
174 | size * sizeof(Char *)); | |
175 | vl = &nv[size - GLOBSPACE]; | |
176 | } | |
177 | } | |
178 | break; | |
b6e604fd | 179 | } |
0aec749d | 180 | *vl = NULL; |
6e37afca KB |
181 | *bl = nv; |
182 | return (len); | |
b6e604fd BJ |
183 | } |
184 | ||
6e37afca | 185 | static Char ** |
c8fda9bd | 186 | globexpand(v) |
6e37afca | 187 | Char **v; |
b6e604fd | 188 | { |
6e37afca KB |
189 | Char *s; |
190 | Char **nv, **vl, **el; | |
191 | int size = GLOBSPACE; | |
192 | ||
193 | ||
194 | nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); | |
0aec749d | 195 | *vl = NULL; |
6e37afca KB |
196 | |
197 | /* | |
198 | * Step 1: expand backquotes. | |
199 | */ | |
200 | while (s = *v++) { | |
201 | if (Strchr(s, '`')) { | |
202 | int i; | |
203 | ||
204 | (void) dobackp(s, 0); | |
205 | for (i = 0; i < pargc; i++) { | |
206 | *vl++ = pargv[i]; | |
207 | if (vl == &nv[size]) { | |
208 | size += GLOBSPACE; | |
209 | nv = (Char **) xrealloc((ptr_t) nv, | |
210 | (size_t) size * sizeof(Char *)); | |
211 | vl = &nv[size - GLOBSPACE]; | |
212 | } | |
213 | } | |
214 | xfree((ptr_t) pargv); | |
0aec749d | 215 | pargv = NULL; |
6e37afca KB |
216 | } |
217 | else { | |
218 | *vl++ = Strsave(s); | |
219 | if (vl == &nv[size]) { | |
220 | size += GLOBSPACE; | |
221 | nv = (Char **) xrealloc((ptr_t) nv, (size_t) | |
222 | size * sizeof(Char *)); | |
223 | vl = &nv[size - GLOBSPACE]; | |
224 | } | |
225 | } | |
226 | } | |
0aec749d | 227 | *vl = NULL; |
6e37afca KB |
228 | |
229 | if (noglob) | |
230 | return (nv); | |
231 | ||
232 | /* | |
233 | * Step 2: expand braces | |
234 | */ | |
235 | el = vl; | |
236 | vl = nv; | |
237 | for (s = *vl; s; s = *++vl) { | |
238 | Char *b; | |
239 | Char **vp, **bp; | |
240 | ||
454c2aa3 | 241 | if ((b = Strchr(s, LBRC)) != NULL && b[1] != '\0') { |
6e37afca KB |
242 | Char **bl; |
243 | int len; | |
244 | ||
245 | if ((len = globbrace(s, b, &bl)) < 0) { | |
246 | blkfree(nv); | |
247 | stderror(ERR_MISSING, -len); | |
248 | } | |
249 | xfree((ptr_t) s); | |
250 | if (len == 1) { | |
251 | *vl-- = *bl; | |
252 | xfree((ptr_t) bl); | |
253 | continue; | |
254 | } | |
255 | len = blklen(bl); | |
256 | if (&el[len] >= &nv[size]) { | |
257 | int l, e; | |
258 | ||
259 | l = &el[len] - &nv[size]; | |
260 | size += GLOBSPACE > l ? GLOBSPACE : l; | |
261 | l = vl - nv; | |
262 | e = el - nv; | |
263 | nv = (Char **) xrealloc((ptr_t) nv, (size_t) | |
264 | size * sizeof(Char *)); | |
265 | vl = nv + l; | |
266 | el = nv + e; | |
267 | } | |
268 | vp = vl--; | |
269 | *vp = *bl; | |
270 | len--; | |
271 | for (bp = el; bp != vp; bp--) | |
272 | bp[len] = *bp; | |
273 | el += len; | |
274 | vp++; | |
275 | for (bp = bl + 1; *bp; *vp++ = *bp++) | |
276 | continue; | |
277 | xfree((ptr_t) bl); | |
278 | } | |
b6e604fd | 279 | |
6e37afca KB |
280 | } |
281 | ||
282 | /* | |
283 | * Step 3: expand ~ | |
284 | */ | |
285 | vl = nv; | |
286 | for (s = *vl; s; s = *++vl) | |
287 | if (*s == '~') | |
288 | *vl = globtilde(nv, s); | |
289 | vl = nv; | |
290 | return (vl); | |
291 | } | |
b6e604fd | 292 | |
6e37afca KB |
293 | static Char * |
294 | handleone(str, vl, action) | |
295 | Char *str, **vl; | |
296 | int action; | |
297 | { | |
b6e604fd | 298 | |
6e37afca KB |
299 | Char *cp, **vlp = vl; |
300 | ||
301 | switch (action) { | |
302 | case G_ERROR: | |
303 | setname(short2str(str)); | |
304 | blkfree(vl); | |
305 | stderror(ERR_NAME | ERR_AMBIG); | |
306 | break; | |
307 | case G_APPEND: | |
308 | trim(vlp); | |
309 | str = Strsave(*vlp++); | |
310 | do { | |
311 | cp = Strspl(str, STRspace); | |
312 | xfree((ptr_t) str); | |
313 | str = Strspl(cp, *vlp); | |
314 | xfree((ptr_t) cp); | |
c8fda9bd | 315 | } |
6e37afca KB |
316 | while (*++vlp); |
317 | blkfree(vl); | |
318 | break; | |
319 | case G_IGNORE: | |
320 | str = Strsave(strip(*vlp)); | |
321 | blkfree(vl); | |
322 | break; | |
323 | } | |
324 | return (str); | |
325 | } | |
b6e604fd | 326 | |
6e37afca KB |
327 | static Char ** |
328 | libglob(vl) | |
329 | Char **vl; | |
330 | { | |
454c2aa3 | 331 | int gflgs = GLOB_QUOTE | GLOB_NOMAGIC; |
6e37afca KB |
332 | glob_t globv; |
333 | char *ptr; | |
454c2aa3 | 334 | int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; |
6e37afca KB |
335 | |
336 | globv.gl_offs = 0; | |
337 | globv.gl_pathv = 0; | |
338 | globv.gl_pathc = 0; | |
454c2aa3 CZ |
339 | |
340 | if (nonomatch) | |
341 | gflgs |= GLOB_NOCHECK; | |
342 | ||
6e37afca KB |
343 | do { |
344 | ptr = short2qstr(*vl); | |
345 | switch (glob(ptr, gflgs, 0, &globv)) { | |
346 | case GLOB_ABEND: | |
347 | setname(ptr); | |
348 | stderror(ERR_NAME | ERR_GLOB); | |
349 | /* NOTREACHED */ | |
350 | case GLOB_NOSPACE: | |
351 | stderror(ERR_NOMEM); | |
352 | /* NOTREACHED */ | |
353 | default: | |
354 | break; | |
b6e604fd | 355 | } |
454c2aa3 CZ |
356 | if (globv.gl_flags & GLOB_MAGCHAR) { |
357 | match |= (globv.gl_matchc != 0); | |
358 | magic = 1; | |
6e37afca KB |
359 | } |
360 | gflgs |= GLOB_APPEND; | |
361 | } | |
362 | while (*++vl); | |
454c2aa3 CZ |
363 | vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? |
364 | NULL : blk2short(globv.gl_pathv); | |
6e37afca KB |
365 | globfree(&globv); |
366 | return (vl); | |
b6e604fd BJ |
367 | } |
368 | ||
6e37afca KB |
369 | Char * |
370 | globone(str, action) | |
371 | Char *str; | |
372 | int action; | |
b6e604fd | 373 | { |
6e37afca | 374 | Char *v[2], **vl, **vo; |
4aad0a53 | 375 | int gflg; |
b6e604fd | 376 | |
6e37afca KB |
377 | noglob = adrof(STRnoglob) != 0; |
378 | gflag = 0; | |
379 | v[0] = str; | |
380 | v[1] = 0; | |
381 | tglob(v); | |
4aad0a53 CZ |
382 | gflg = gflag; |
383 | if (gflg == G_NONE) | |
6e37afca | 384 | return (strip(Strsave(str))); |
b6e604fd | 385 | |
4aad0a53 | 386 | if (gflg & G_CSH) { |
6e37afca KB |
387 | /* |
388 | * Expand back-quote, tilde and brace | |
389 | */ | |
390 | vo = globexpand(v); | |
4aad0a53 | 391 | if (noglob || (gflg & G_GLOB) == 0) { |
6cc6e21d CZ |
392 | if (vo[0] == NULL) { |
393 | xfree((ptr_t) vo); | |
394 | return (Strsave(STRNULL)); | |
395 | } | |
0aec749d | 396 | if (vo[1] != NULL) |
6e37afca KB |
397 | return (handleone(str, vo, action)); |
398 | else { | |
399 | str = strip(vo[0]); | |
400 | xfree((ptr_t) vo); | |
401 | return (str); | |
402 | } | |
c8fda9bd | 403 | } |
6e37afca | 404 | } |
4aad0a53 | 405 | else if (noglob || (gflg & G_GLOB) == 0) |
6e37afca KB |
406 | return (strip(Strsave(str))); |
407 | else | |
408 | vo = v; | |
409 | ||
410 | vl = libglob(vo); | |
4aad0a53 | 411 | if (gflg & G_CSH) |
6e37afca | 412 | blkfree(vo); |
0aec749d | 413 | if (vl == NULL) { |
6e37afca KB |
414 | setname(short2str(str)); |
415 | stderror(ERR_NAME | ERR_NOMATCH); | |
416 | } | |
6cc6e21d CZ |
417 | if (vl[0] == NULL) { |
418 | xfree((ptr_t) vl); | |
419 | return (Strsave(STRNULL)); | |
420 | } | |
421 | if (vl[1] != NULL) | |
6e37afca KB |
422 | return (handleone(str, vl, action)); |
423 | else { | |
424 | str = strip(*vl); | |
425 | xfree((ptr_t) vl); | |
6cc6e21d | 426 | return (str); |
6e37afca | 427 | } |
b6e604fd BJ |
428 | } |
429 | ||
6e37afca | 430 | Char ** |
c8fda9bd | 431 | globall(v) |
6e37afca | 432 | Char **v; |
b6e604fd | 433 | { |
6e37afca | 434 | Char **vl, **vo; |
4aad0a53 | 435 | int gflg = gflag; |
35371dec | 436 | |
6e37afca KB |
437 | if (!v || !v[0]) { |
438 | gargv = saveblk(v); | |
439 | gargc = blklen(gargv); | |
440 | return (gargv); | |
441 | } | |
b6e604fd | 442 | |
6e37afca | 443 | noglob = adrof(STRnoglob) != 0; |
b6e604fd | 444 | |
4aad0a53 | 445 | if (gflg & G_CSH) |
6e37afca KB |
446 | /* |
447 | * Expand back-quote, tilde and brace | |
448 | */ | |
449 | vl = vo = globexpand(v); | |
450 | else | |
451 | vl = vo = saveblk(v); | |
452 | ||
4aad0a53 | 453 | if (!noglob && (gflg & G_GLOB)) { |
6e37afca | 454 | vl = libglob(vo); |
4aad0a53 | 455 | if (gflg & G_CSH) |
6e37afca KB |
456 | blkfree(vo); |
457 | } | |
458 | ||
459 | gargc = vl ? blklen(vl) : 0; | |
460 | return (gargv = vl); | |
c8fda9bd | 461 | } |
6e37afca KB |
462 | |
463 | void | |
c8fda9bd KB |
464 | ginit() |
465 | { | |
6e37afca KB |
466 | gargsiz = GLOBSPACE; |
467 | gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz); | |
468 | gargv[0] = 0; | |
469 | gargc = 0; | |
b6e604fd BJ |
470 | } |
471 | ||
6e37afca | 472 | void |
b6e604fd | 473 | rscan(t, f) |
6e37afca KB |
474 | register Char **t; |
475 | void (*f) (); | |
b6e604fd | 476 | { |
6e37afca | 477 | register Char *p; |
b6e604fd | 478 | |
6e37afca KB |
479 | while (p = *t++) |
480 | while (*p) | |
481 | (*f) (*p++); | |
b6e604fd BJ |
482 | } |
483 | ||
6e37afca | 484 | void |
35371dec | 485 | trim(t) |
6e37afca | 486 | register Char **t; |
b6e604fd | 487 | { |
6e37afca | 488 | register Char *p; |
b6e604fd | 489 | |
6e37afca KB |
490 | while (p = *t++) |
491 | while (*p) | |
492 | *p++ &= TRIM; | |
b6e604fd BJ |
493 | } |
494 | ||
6e37afca | 495 | void |
35371dec | 496 | tglob(t) |
6e37afca | 497 | register Char **t; |
b6e604fd | 498 | { |
6e37afca KB |
499 | register Char *p, c; |
500 | ||
501 | while (p = *t++) { | |
502 | if (*p == '~' || *p == '=') | |
503 | gflag |= G_CSH; | |
504 | else if (*p == '{' && | |
505 | (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) | |
506 | continue; | |
507 | while (c = *p++) | |
508 | if (isglob(c)) | |
509 | gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB; | |
510 | } | |
b6e604fd BJ |
511 | } |
512 | ||
b6e604fd | 513 | /* |
c8fda9bd KB |
514 | * Command substitute cp. If literal, then this is a substitution from a |
515 | * << redirection, and so we should not crunch blanks and tabs, separating | |
516 | * words only at newlines. | |
b6e604fd | 517 | */ |
6e37afca | 518 | Char ** |
b6e604fd | 519 | dobackp(cp, literal) |
6e37afca KB |
520 | Char *cp; |
521 | bool literal; | |
b6e604fd | 522 | { |
6e37afca KB |
523 | register Char *lp, *rp; |
524 | Char *ep, word[MAXPATHLEN]; | |
525 | ||
526 | if (pargv) { | |
527 | abort(); | |
528 | blkfree(pargv); | |
529 | } | |
530 | pargsiz = GLOBSPACE; | |
531 | pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz); | |
532 | pargv[0] = NULL; | |
533 | pargcp = pargs = word; | |
534 | pargc = 0; | |
535 | pnleft = MAXPATHLEN - 4; | |
536 | for (;;) { | |
537 | for (lp = cp; *lp != '`'; lp++) { | |
538 | if (*lp == 0) { | |
539 | if (pargcp != pargs) | |
540 | pword(); | |
541 | return (pargv); | |
542 | } | |
543 | psave(*lp); | |
b6e604fd | 544 | } |
6e37afca KB |
545 | lp++; |
546 | for (rp = lp; *rp && *rp != '`'; rp++) | |
547 | if (*rp == '\\') { | |
548 | rp++; | |
b6e604fd | 549 | if (!*rp) |
6e37afca KB |
550 | goto oops; |
551 | } | |
552 | if (!*rp) | |
553 | oops: stderror(ERR_UNMATCHED, '`'); | |
554 | ep = Strsave(lp); | |
555 | ep[rp - lp] = 0; | |
556 | backeval(ep, literal); | |
557 | cp = rp + 1; | |
558 | } | |
b6e604fd BJ |
559 | } |
560 | ||
6e37afca | 561 | static void |
b6e604fd | 562 | backeval(cp, literal) |
6e37afca KB |
563 | Char *cp; |
564 | bool literal; | |
b6e604fd | 565 | { |
6e37afca KB |
566 | register int icnt, c; |
567 | register Char *ip; | |
568 | struct command faket; | |
569 | bool hadnl; | |
570 | int pvec[2], quoted; | |
571 | Char *fakecom[2], ibuf[BUFSIZ]; | |
572 | char tibuf[BUFSIZ]; | |
573 | ||
574 | hadnl = 0; | |
575 | icnt = 0; | |
576 | quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; | |
577 | faket.t_dtyp = NODE_COMMAND; | |
578 | faket.t_dflg = 0; | |
579 | faket.t_dlef = 0; | |
580 | faket.t_drit = 0; | |
581 | faket.t_dspr = 0; | |
582 | faket.t_dcom = fakecom; | |
583 | fakecom[0] = STRfakecom1; | |
584 | fakecom[1] = 0; | |
585 | ||
586 | /* | |
587 | * We do the psave job to temporarily change the current job so that the | |
588 | * following fork is considered a separate job. This is so that when | |
589 | * backquotes are used in a builtin function that calls glob the "current | |
590 | * job" is not corrupted. We only need one level of pushed jobs as long as | |
591 | * we are sure to fork here. | |
592 | */ | |
593 | psavejob(); | |
594 | ||
595 | /* | |
596 | * It would be nicer if we could integrate this redirection more with the | |
597 | * routines in sh.sem.c by doing a fake execute on a builtin function that | |
598 | * was piped out. | |
599 | */ | |
600 | mypipe(pvec); | |
601 | if (pfork(&faket, -1) == 0) { | |
602 | struct wordent paraml; | |
603 | struct command *t; | |
c8fda9bd | 604 | |
6e37afca KB |
605 | (void) close(pvec[0]); |
606 | (void) dmove(pvec[1], 1); | |
454c2aa3 | 607 | (void) dmove(SHERR, 2); |
6e37afca | 608 | initdesc(); |
b6e604fd | 609 | /* |
6e37afca KB |
610 | * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, |
611 | * posted to comp.bugs.4bsd 12 Sep. 1989. | |
b6e604fd | 612 | */ |
6e37afca KB |
613 | if (pargv) /* mg, 21.dec.88 */ |
614 | blkfree(pargv), pargv = 0, pargsiz = 0; | |
615 | /* mg, 21.dec.88 */ | |
616 | arginp = cp; | |
617 | while (*cp) | |
618 | *cp++ &= TRIM; | |
619 | (void) lex(¶ml); | |
620 | if (seterr) | |
621 | stderror(ERR_OLD); | |
622 | alias(¶ml); | |
623 | t = syntax(paraml.next, ¶ml, 0); | |
624 | if (seterr) | |
625 | stderror(ERR_OLD); | |
626 | if (t) | |
627 | t->t_dflg |= F_NOFORK; | |
628 | (void) signal(SIGTSTP, SIG_IGN); | |
629 | (void) signal(SIGTTIN, SIG_IGN); | |
630 | (void) signal(SIGTTOU, SIG_IGN); | |
4d7b2685 | 631 | execute(t, -1, NULL, NULL); |
6e37afca KB |
632 | exitstat(); |
633 | } | |
634 | xfree((ptr_t) cp); | |
635 | (void) close(pvec[1]); | |
636 | c = 0; | |
0aec749d | 637 | ip = NULL; |
6e37afca KB |
638 | do { |
639 | int cnt = 0; | |
c8fda9bd | 640 | |
6e37afca KB |
641 | for (;;) { |
642 | if (icnt == 0) { | |
643 | int i; | |
644 | ||
645 | ip = ibuf; | |
646 | do | |
647 | icnt = read(pvec[0], tibuf, BUFSIZ); | |
648 | while (icnt == -1 && errno == EINTR); | |
649 | if (icnt <= 0) { | |
650 | c = -1; | |
651 | break; | |
b6e604fd | 652 | } |
6e37afca KB |
653 | for (i = 0; i < icnt; i++) |
654 | ip[i] = (unsigned char) tibuf[i]; | |
655 | } | |
656 | if (hadnl) | |
657 | break; | |
658 | --icnt; | |
659 | c = (*ip++ & TRIM); | |
660 | if (c == 0) | |
661 | break; | |
662 | if (c == '\n') { | |
b6e604fd | 663 | /* |
6e37afca KB |
664 | * Continue around the loop one more time, so that we can eat |
665 | * the last newline without terminating this word. | |
b6e604fd | 666 | */ |
6e37afca KB |
667 | hadnl = 1; |
668 | continue; | |
669 | } | |
670 | if (!quoted && (c == ' ' || c == '\t')) | |
671 | break; | |
672 | cnt++; | |
673 | psave(c | quoted); | |
674 | } | |
675 | /* | |
676 | * Unless at end-of-file, we will form a new word here if there were | |
677 | * characters in the word, or in any case when we take text literally. | |
678 | * If we didn't make empty words here when literal was set then we | |
679 | * would lose blank lines. | |
680 | */ | |
681 | if (c != -1 && (cnt || literal)) | |
682 | pword(); | |
683 | hadnl = 0; | |
684 | } while (c >= 0); | |
685 | (void) close(pvec[0]); | |
686 | pwait(); | |
687 | prestjob(); | |
b6e604fd BJ |
688 | } |
689 | ||
6e37afca | 690 | static void |
b6e604fd | 691 | psave(c) |
0aec749d | 692 | int c; |
b6e604fd | 693 | { |
6e37afca KB |
694 | if (--pnleft <= 0) |
695 | stderror(ERR_WTOOLONG); | |
696 | *pargcp++ = c; | |
b6e604fd BJ |
697 | } |
698 | ||
6e37afca | 699 | static void |
b6e604fd BJ |
700 | pword() |
701 | { | |
6e37afca KB |
702 | psave(0); |
703 | if (pargc == pargsiz - 1) { | |
704 | pargsiz += GLOBSPACE; | |
705 | pargv = (Char **) xrealloc((ptr_t) pargv, | |
706 | (size_t) pargsiz * sizeof(Char *)); | |
707 | } | |
708 | pargv[pargc++] = Strsave(pargs); | |
709 | pargv[pargc] = NULL; | |
710 | pargcp = pargs; | |
711 | pnleft = MAXPATHLEN - 4; | |
c8fda9bd KB |
712 | } |
713 | ||
6e37afca | 714 | int |
c8fda9bd | 715 | Gmatch(string, pattern) |
6e37afca | 716 | register Char *string, *pattern; |
c8fda9bd | 717 | { |
6e37afca KB |
718 | register Char stringc, patternc; |
719 | int match; | |
720 | Char rangec; | |
721 | ||
722 | for (;; ++string) { | |
723 | stringc = *string & TRIM; | |
724 | patternc = *pattern++; | |
725 | switch (patternc) { | |
726 | case 0: | |
727 | return (stringc == 0); | |
728 | case '?': | |
729 | if (stringc == 0) | |
730 | return (0); | |
731 | break; | |
732 | case '*': | |
733 | if (!*pattern) | |
734 | return (1); | |
735 | while (*string) | |
736 | if (Gmatch(string++, pattern)) | |
737 | return (1); | |
738 | return (0); | |
739 | case '[': | |
740 | match = 0; | |
741 | while (rangec = *pattern++) { | |
742 | if (rangec == ']') | |
743 | if (match) | |
c8fda9bd | 744 | break; |
6e37afca | 745 | else |
c8fda9bd | 746 | return (0); |
6e37afca KB |
747 | if (match) |
748 | continue; | |
2b00e1e7 CZ |
749 | if (rangec == '-' && *(pattern - 2) != '[' && *pattern != ']') { |
750 | match = (stringc <= (*pattern & TRIM) && | |
751 | (*(pattern - 2) & TRIM) <= stringc); | |
6e37afca | 752 | pattern++; |
c8fda9bd | 753 | } |
6e37afca KB |
754 | else |
755 | match = (stringc == rangec); | |
756 | } | |
757 | if (rangec == 0) | |
758 | stderror(ERR_NAME | ERR_MISSING, ']'); | |
759 | break; | |
760 | default: | |
761 | if ((patternc & TRIM) != stringc) | |
762 | return (0); | |
763 | break; | |
764 | ||
c8fda9bd | 765 | } |
6e37afca | 766 | } |
c8fda9bd KB |
767 | } |
768 | ||
6e37afca | 769 | void |
c8fda9bd | 770 | Gcat(s1, s2) |
6e37afca | 771 | Char *s1, *s2; |
c8fda9bd | 772 | { |
6e37afca KB |
773 | register Char *p, *q; |
774 | int n; | |
775 | ||
776 | for (p = s1; *p++;); | |
777 | for (q = s2; *q++;); | |
778 | n = (p - s1) + (q - s2) - 1; | |
779 | if (++gargc >= gargsiz) { | |
780 | gargsiz += GLOBSPACE; | |
781 | gargv = (Char **) xrealloc((ptr_t) gargv, | |
782 | (size_t) gargsiz * sizeof(Char *)); | |
783 | } | |
784 | gargv[gargc] = 0; | |
785 | p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char)); | |
786 | for (q = s1; *p++ = *q++;); | |
787 | for (p--, q = s2; *p++ = *q++;); | |
c8fda9bd KB |
788 | } |
789 | ||
6e37afca | 790 | #ifdef FILEC |
c8fda9bd | 791 | int |
6e37afca KB |
792 | sortscmp(a, b) |
793 | register Char **a, **b; | |
c8fda9bd | 794 | { |
6e37afca KB |
795 | #if defined(NLS) && !defined(NOSTRCOLL) |
796 | char buf[2048]; | |
797 | ||
798 | #endif | |
799 | ||
800 | if (!a) /* check for NULL */ | |
801 | return (b ? 1 : 0); | |
802 | if (!b) | |
803 | return (-1); | |
804 | ||
805 | if (!*a) /* check for NULL */ | |
806 | return (*b ? 1 : 0); | |
807 | if (!*b) | |
808 | return (-1); | |
809 | ||
810 | #if defined(NLS) && !defined(NOSTRCOLL) | |
811 | (void) strcpy(buf, short2str(*a)); | |
812 | return ((int) strcoll(buf, short2str(*b))); | |
813 | #else | |
814 | return ((int) Strcmp(*a, *b)); | |
815 | #endif | |
b6e604fd | 816 | } |
6e37afca | 817 | #endif /* FILEC */ |