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