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