BSD 4_4 release
[unix-history] / usr / src / bin / csh / glob.c
CommitLineData
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 35static 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 53static int noglob;
c8fda9bd 54static 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 71Char **gargv = NULL;
6e37afca 72long gargc = 0;
0aec749d 73Char **pargv = NULL;
6e37afca 74long 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
85static Char *globtilde __P((Char **, Char *));
86static Char **libglob __P((Char **));
87static Char **globexpand __P((Char **));
88static int globbrace __P((Char *, Char *, Char ***));
e71234c5 89static void expbrace __P((Char ***, Char ***, int));
1afb645a 90static int pmatch __P((Char *, Char *));
0aec749d
CZ
91static void pword __P((void));
92static void psave __P((int));
93static void backeval __P((Char *, bool));
6a422336 94
b6e604fd 95
6e37afca 96static Char *
1fedb07b 97globtilde(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
126static int
127globbrace(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
218static void
219expbrace(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 284static Char **
c8fda9bd 285globexpand(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
348static Char *
349handleone(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
384static Char **
385libglob(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
429Char *
430globone(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 490Char **
c8fda9bd 491globall(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
525void
c8fda9bd
KB
526ginit()
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 534void
b6e604fd 535rscan(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 546void
35371dec 547trim(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 557void
35371dec 558tglob(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 600Char **
b6e604fd 601dobackp(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 645static void
b6e604fd 646backeval(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(&paraml);
713 if (seterr)
714 stderror(ERR_OLD);
715 alias(&paraml);
716 t = syntax(paraml.next, &paraml, 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 783static void
b6e604fd 784psave(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 792static void
b6e604fd
BJ
793pword()
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 807int
c8fda9bd 808Gmatch(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 832static int
e71234c5 833pmatch(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 888void
c8fda9bd 889Gcat(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 914int
6e37afca 915sortscmp(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 */