147823Sbostic /*-
2*60765Sbostic * Copyright (c) 1980, 1991, 1993
3*60765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621934Sdist */
721934Sdist
817514Sedward #ifndef lint
9*60765Sbostic static char sccsid[] = "@(#)glob.c 8.1 (Berkeley) 05/31/93";
1047823Sbostic #endif /* not lint */
115774Smckusic
1250028Sbostic #include <sys/param.h>
1350028Sbostic #include <glob.h>
1450028Sbostic #include <errno.h>
1550028Sbostic #include <stdlib.h>
1650028Sbostic #include <string.h>
1750028Sbostic #include <unistd.h>
1850033Schristos #if __STDC__
1950033Schristos # include <stdarg.h>
2050033Schristos #else
2150033Schristos # include <varargs.h>
2250033Schristos #endif
2350033Schristos
2450023Sbostic #include "csh.h"
2550023Sbostic #include "extern.h"
261295Sbill
2750439Schristos static int noglob;
2849992Sbostic static int pargsiz, gargsiz;
2947414Sbostic
301295Sbill /*
3147414Sbostic * Values for gflag
321295Sbill */
3349992Sbostic #define G_NONE 0 /* No globbing needed */
3449992Sbostic #define G_GLOB 1 /* string contains *?[] characters */
3549992Sbostic #define G_CSH 2 /* string contains ~`{ characters */
361295Sbill
3749992Sbostic #define GLOBSPACE 100 /* Alloc increment */
3849992Sbostic
3947414Sbostic #define LBRC '{'
4047414Sbostic #define RBRC '}'
4147414Sbostic #define LBRK '['
4247414Sbostic #define RBRK ']'
4347414Sbostic #define EOS '\0'
441295Sbill
4550024Schristos Char **gargv = NULL;
4649992Sbostic long gargc = 0;
4750024Schristos Char **pargv = NULL;
4849992Sbostic long pargc = 0;
4949992Sbostic
5028055Slepreau /*
5147414Sbostic * globbing is now done in two stages. In the first pass we expand
5249992Sbostic * csh globbing idioms ~`{ and then we proceed doing the normal
5347414Sbostic * globbing if needed ?*[
5447414Sbostic *
5547414Sbostic * Csh type globbing is handled in globexpand() and the rest is
5648513Sbostic * handled in glob() which is part of the 4.4BSD libc.
5749992Sbostic *
5828055Slepreau */
5950024Schristos static Char *globtilde __P((Char **, Char *));
6050024Schristos static Char **libglob __P((Char **));
6150024Schristos static Char **globexpand __P((Char **));
6250024Schristos static int globbrace __P((Char *, Char *, Char ***));
6352372Schristos static void expbrace __P((Char ***, Char ***, int));
6452375Schristos static int pmatch __P((Char *, Char *));
6550024Schristos static void pword __P((void));
6650024Schristos static void psave __P((int));
6750024Schristos static void backeval __P((Char *, bool));
681295Sbill
691295Sbill
7049992Sbostic static Char *
globtilde(nv,s)7148513Sbostic globtilde(nv, s)
7249992Sbostic Char **nv, *s;
731295Sbill {
7449992Sbostic Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e;
751295Sbill
7649992Sbostic gstart = gbuf;
7749992Sbostic *gstart++ = *s++;
7849992Sbostic u = s;
7951437Sleres for (b = gstart, e = &gbuf[MAXPATHLEN - 1];
8051357Schristos *s && *s != '/' && *s != ':' && b < e;
8151437Sleres *b++ = *s++)
8251437Sleres continue;
8349992Sbostic *b = EOS;
8449992Sbostic if (gethdir(gstart)) {
8549992Sbostic blkfree(nv);
8649992Sbostic if (*gstart)
8751589Schristos stderror(ERR_UNKUSER, vis_str(gstart));
8849992Sbostic else
8949992Sbostic stderror(ERR_NOHOME);
9049992Sbostic }
9149992Sbostic b = &gstart[Strlen(gstart)];
9249992Sbostic while (*s)
9349992Sbostic *b++ = *s++;
9449992Sbostic *b = EOS;
9549992Sbostic --u;
9649992Sbostic xfree((ptr_t) u);
9749992Sbostic return (Strsave(gstart));
981295Sbill }
991295Sbill
10047414Sbostic static int
globbrace(s,p,bl)10147414Sbostic globbrace(s, p, bl)
10249992Sbostic Char *s, *p, ***bl;
1031295Sbill {
10449992Sbostic int i, len;
10549992Sbostic Char *pm, *pe, *lm, *pl;
10649992Sbostic Char **nv, **vl;
10749992Sbostic Char gbuf[MAXPATHLEN];
10849992Sbostic int size = GLOBSPACE;
1091295Sbill
11049992Sbostic nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
11150024Schristos *vl = NULL;
1121295Sbill
11349992Sbostic len = 0;
11449992Sbostic /* copy part up to the brace */
11549992Sbostic for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++)
11649992Sbostic continue;
11749992Sbostic
11849992Sbostic /* check for balanced braces */
11949992Sbostic for (i = 0, pe = ++p; *pe; pe++)
12049992Sbostic if (*pe == LBRK) {
12149992Sbostic /* Ignore everything between [] */
12249992Sbostic for (++pe; *pe != RBRK && *pe != EOS; pe++)
1231295Sbill continue;
12449992Sbostic if (*pe == EOS) {
12547414Sbostic blkfree(nv);
12652372Schristos return (-RBRK);
12749992Sbostic }
1281295Sbill }
12949992Sbostic else if (*pe == LBRC)
13049992Sbostic i++;
13149992Sbostic else if (*pe == RBRC) {
13249992Sbostic if (i == 0)
13349992Sbostic break;
13449992Sbostic i--;
13549992Sbostic }
1361295Sbill
13750386Schristos if (i != 0 || *pe == '\0') {
13849992Sbostic blkfree(nv);
13950386Schristos return (-RBRC);
14049992Sbostic }
14149992Sbostic
14249992Sbostic for (i = 0, pl = pm = p; pm <= pe; pm++)
14347414Sbostic switch (*pm) {
14447414Sbostic case LBRK:
14549992Sbostic for (++pm; *pm != RBRK && *pm != EOS; pm++)
14649992Sbostic continue;
14749992Sbostic if (*pm == EOS) {
14850024Schristos *vl = NULL;
14949992Sbostic blkfree(nv);
15049992Sbostic return (-RBRK);
15149992Sbostic }
15249992Sbostic break;
15347414Sbostic case LBRC:
15449992Sbostic i++;
15549992Sbostic break;
15649992Sbostic case RBRC:
15749992Sbostic if (i) {
15849992Sbostic i--;
15947414Sbostic break;
16049992Sbostic }
16149992Sbostic /* FALLTHROUGH */
1621295Sbill case ',':
16349992Sbostic if (i && *pm == ',')
16449992Sbostic break;
16549992Sbostic else {
16649992Sbostic Char savec = *pm;
16749992Sbostic
16849992Sbostic *pm = EOS;
16949992Sbostic (void) Strcpy(lm, pl);
17049992Sbostic (void) Strcat(gbuf, pe + 1);
17149992Sbostic *pm = savec;
17249992Sbostic *vl++ = Strsave(gbuf);
17349992Sbostic len++;
17449992Sbostic pl = pm + 1;
17549992Sbostic if (vl == &nv[size]) {
17649992Sbostic size += GLOBSPACE;
17749992Sbostic nv = (Char **) xrealloc((ptr_t) nv, (size_t)
17849992Sbostic size * sizeof(Char *));
17949992Sbostic vl = &nv[size - GLOBSPACE];
18047414Sbostic }
18149992Sbostic }
18249992Sbostic break;
18352372Schristos default:
18452372Schristos break;
1851295Sbill }
18650024Schristos *vl = NULL;
18749992Sbostic *bl = nv;
18849992Sbostic return (len);
1891295Sbill }
1901295Sbill
19152372Schristos
19252372Schristos static void
expbrace(nvp,elp,size)19352372Schristos expbrace(nvp, elp, size)
19452372Schristos Char ***nvp, ***elp;
19552372Schristos int size;
19652372Schristos {
19752372Schristos Char **vl, **el, **nv, *s;
19852372Schristos
19952372Schristos vl = nv = *nvp;
20052372Schristos if (elp != NULL)
20152372Schristos el = *elp;
20252372Schristos else
20352372Schristos for (el = vl; *el; el++)
20452372Schristos continue;
20552372Schristos
20652372Schristos for (s = *vl; s; s = *++vl) {
20752372Schristos Char *b;
20852372Schristos Char **vp, **bp;
20952372Schristos
21052372Schristos /* leave {} untouched for find */
21152372Schristos if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
21252372Schristos continue;
21360237Schristos if ((b = Strchr(s, '{')) != NULL) {
21452372Schristos Char **bl;
21552372Schristos int len;
21652372Schristos
21752372Schristos if ((len = globbrace(s, b, &bl)) < 0) {
21852372Schristos xfree((ptr_t) nv);
21952372Schristos stderror(ERR_MISSING, -len);
22052372Schristos }
22152372Schristos xfree((ptr_t) s);
22252372Schristos if (len == 1) {
22352372Schristos *vl-- = *bl;
22452372Schristos xfree((ptr_t) bl);
22552372Schristos continue;
22652372Schristos }
22752372Schristos len = blklen(bl);
22852372Schristos if (&el[len] >= &nv[size]) {
22952372Schristos int l, e;
23052372Schristos
23152372Schristos l = &el[len] - &nv[size];
23252372Schristos size += GLOBSPACE > l ? GLOBSPACE : l;
23352372Schristos l = vl - nv;
23452372Schristos e = el - nv;
23552372Schristos nv = (Char **) xrealloc((ptr_t) nv, (size_t)
23652372Schristos size * sizeof(Char *));
23752372Schristos vl = nv + l;
23852372Schristos el = nv + e;
23952372Schristos }
24052372Schristos vp = vl--;
24152372Schristos *vp = *bl;
24252372Schristos len--;
24352372Schristos for (bp = el; bp != vp; bp--)
24452372Schristos bp[len] = *bp;
24552372Schristos el += len;
24652372Schristos vp++;
24752372Schristos for (bp = bl + 1; *bp; *vp++ = *bp++)
24852372Schristos continue;
24952372Schristos xfree((ptr_t) bl);
25052372Schristos }
25152372Schristos
25252372Schristos }
25352372Schristos if (elp != NULL)
25452372Schristos *elp = el;
25552372Schristos *nvp = nv;
25652372Schristos }
25752372Schristos
25849992Sbostic static Char **
globexpand(v)25947414Sbostic globexpand(v)
26049992Sbostic Char **v;
2611295Sbill {
26249992Sbostic Char *s;
26349992Sbostic Char **nv, **vl, **el;
26449992Sbostic int size = GLOBSPACE;
2651295Sbill
2661295Sbill
26749992Sbostic nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size);
26850024Schristos *vl = NULL;
2691295Sbill
27049992Sbostic /*
27149992Sbostic * Step 1: expand backquotes.
27249992Sbostic */
27360237Schristos while ((s = *v++) != NULL) {
27449992Sbostic if (Strchr(s, '`')) {
27549992Sbostic int i;
2761295Sbill
27749992Sbostic (void) dobackp(s, 0);
27849992Sbostic for (i = 0; i < pargc; i++) {
27949992Sbostic *vl++ = pargv[i];
28049992Sbostic if (vl == &nv[size]) {
28149992Sbostic size += GLOBSPACE;
28249992Sbostic nv = (Char **) xrealloc((ptr_t) nv,
28349992Sbostic (size_t) size * sizeof(Char *));
28449992Sbostic vl = &nv[size - GLOBSPACE];
28547414Sbostic }
28649992Sbostic }
28749992Sbostic xfree((ptr_t) pargv);
28850024Schristos pargv = NULL;
28947414Sbostic }
29049992Sbostic else {
29149992Sbostic *vl++ = Strsave(s);
29249992Sbostic if (vl == &nv[size]) {
29349992Sbostic size += GLOBSPACE;
29449992Sbostic nv = (Char **) xrealloc((ptr_t) nv, (size_t)
29549992Sbostic size * sizeof(Char *));
29649992Sbostic vl = &nv[size - GLOBSPACE];
29749992Sbostic }
29849992Sbostic }
29949992Sbostic }
30050024Schristos *vl = NULL;
3011295Sbill
30249992Sbostic if (noglob)
30349992Sbostic return (nv);
3041295Sbill
30549992Sbostic /*
30649992Sbostic * Step 2: expand braces
30749992Sbostic */
30849992Sbostic el = vl;
30954017Schristos expbrace(&nv, &el, size);
31049992Sbostic
31149992Sbostic /*
31249992Sbostic * Step 3: expand ~
31349992Sbostic */
31449992Sbostic vl = nv;
31549992Sbostic for (s = *vl; s; s = *++vl)
31649992Sbostic if (*s == '~')
31749992Sbostic *vl = globtilde(nv, s);
31849992Sbostic vl = nv;
31949992Sbostic return (vl);
3201295Sbill }
3211295Sbill
32249992Sbostic static Char *
handleone(str,vl,action)32349992Sbostic handleone(str, vl, action)
32449992Sbostic Char *str, **vl;
32549992Sbostic int action;
3261295Sbill {
3271295Sbill
32849992Sbostic Char *cp, **vlp = vl;
3291295Sbill
33049992Sbostic switch (action) {
33149992Sbostic case G_ERROR:
33251589Schristos setname(vis_str(str));
33349992Sbostic blkfree(vl);
33449992Sbostic stderror(ERR_NAME | ERR_AMBIG);
33549992Sbostic break;
33649992Sbostic case G_APPEND:
33749992Sbostic trim(vlp);
33849992Sbostic str = Strsave(*vlp++);
33949992Sbostic do {
34049992Sbostic cp = Strspl(str, STRspace);
34149992Sbostic xfree((ptr_t) str);
34249992Sbostic str = Strspl(cp, *vlp);
34349992Sbostic xfree((ptr_t) cp);
34449992Sbostic }
34549992Sbostic while (*++vlp);
34649992Sbostic blkfree(vl);
34749992Sbostic break;
34849992Sbostic case G_IGNORE:
34949992Sbostic str = Strsave(strip(*vlp));
35049992Sbostic blkfree(vl);
35149992Sbostic break;
35252372Schristos default:
35352372Schristos break;
35449992Sbostic }
35549992Sbostic return (str);
35649992Sbostic }
3571295Sbill
35849992Sbostic static Char **
libglob(vl)35949992Sbostic libglob(vl)
36049992Sbostic Char **vl;
36149992Sbostic {
36250439Schristos int gflgs = GLOB_QUOTE | GLOB_NOMAGIC;
36349992Sbostic glob_t globv;
36449992Sbostic char *ptr;
36550439Schristos int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
36649992Sbostic
36750738Schristos if (!vl || !vl[0])
36850738Schristos return (vl);
36950738Schristos
37049992Sbostic globv.gl_offs = 0;
37149992Sbostic globv.gl_pathv = 0;
37249992Sbostic globv.gl_pathc = 0;
37350439Schristos
37450439Schristos if (nonomatch)
37550439Schristos gflgs |= GLOB_NOCHECK;
37650439Schristos
37749992Sbostic do {
37849992Sbostic ptr = short2qstr(*vl);
37949992Sbostic switch (glob(ptr, gflgs, 0, &globv)) {
38049992Sbostic case GLOB_ABEND:
38151589Schristos setname(vis_str(*vl));
38249992Sbostic stderror(ERR_NAME | ERR_GLOB);
38349992Sbostic /* NOTREACHED */
38449992Sbostic case GLOB_NOSPACE:
38549992Sbostic stderror(ERR_NOMEM);
38649992Sbostic /* NOTREACHED */
38749992Sbostic default:
38849992Sbostic break;
38947414Sbostic }
39050439Schristos if (globv.gl_flags & GLOB_MAGCHAR) {
39150439Schristos match |= (globv.gl_matchc != 0);
39250439Schristos magic = 1;
39349992Sbostic }
39449992Sbostic gflgs |= GLOB_APPEND;
39549992Sbostic }
39649992Sbostic while (*++vl);
39751437Sleres vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
39850439Schristos NULL : blk2short(globv.gl_pathv);
39949992Sbostic globfree(&globv);
40049992Sbostic return (vl);
40149992Sbostic }
4021295Sbill
40349992Sbostic Char *
globone(str,action)40449992Sbostic globone(str, action)
40549992Sbostic Char *str;
40649992Sbostic int action;
40749992Sbostic {
40849992Sbostic Char *v[2], **vl, **vo;
40950558Schristos int gflg;
41049992Sbostic
41149992Sbostic noglob = adrof(STRnoglob) != 0;
41249992Sbostic gflag = 0;
41349992Sbostic v[0] = str;
41449992Sbostic v[1] = 0;
41549992Sbostic tglob(v);
41650558Schristos gflg = gflag;
41750558Schristos if (gflg == G_NONE)
41849992Sbostic return (strip(Strsave(str)));
41949992Sbostic
42050558Schristos if (gflg & G_CSH) {
42149992Sbostic /*
42249992Sbostic * Expand back-quote, tilde and brace
42349992Sbostic */
42449992Sbostic vo = globexpand(v);
42550558Schristos if (noglob || (gflg & G_GLOB) == 0) {
42650048Schristos if (vo[0] == NULL) {
42750048Schristos xfree((ptr_t) vo);
42850048Schristos return (Strsave(STRNULL));
42950048Schristos }
43050024Schristos if (vo[1] != NULL)
43149992Sbostic return (handleone(str, vo, action));
43249992Sbostic else {
43349992Sbostic str = strip(vo[0]);
43449992Sbostic xfree((ptr_t) vo);
43549992Sbostic return (str);
43649992Sbostic }
4371295Sbill }
43849992Sbostic }
43950558Schristos else if (noglob || (gflg & G_GLOB) == 0)
44049992Sbostic return (strip(Strsave(str)));
44149992Sbostic else
44249992Sbostic vo = v;
44349992Sbostic
44449992Sbostic vl = libglob(vo);
44550745Schristos if ((gflg & G_CSH) && vl != vo)
44649992Sbostic blkfree(vo);
44750024Schristos if (vl == NULL) {
44851589Schristos setname(vis_str(str));
44949992Sbostic stderror(ERR_NAME | ERR_NOMATCH);
45049992Sbostic }
45150048Schristos if (vl[0] == NULL) {
45250048Schristos xfree((ptr_t) vl);
45350048Schristos return (Strsave(STRNULL));
45450048Schristos }
45550048Schristos if (vl[1] != NULL)
45649992Sbostic return (handleone(str, vl, action));
45749992Sbostic else {
45849992Sbostic str = strip(*vl);
45949992Sbostic xfree((ptr_t) vl);
46050048Schristos return (str);
46149992Sbostic }
4621295Sbill }
4631295Sbill
46449992Sbostic Char **
globall(v)46547414Sbostic globall(v)
46649992Sbostic Char **v;
4671295Sbill {
46849992Sbostic Char **vl, **vo;
46950558Schristos int gflg = gflag;
4701295Sbill
47149992Sbostic if (!v || !v[0]) {
47249992Sbostic gargv = saveblk(v);
47349992Sbostic gargc = blklen(gargv);
47449992Sbostic return (gargv);
47549992Sbostic }
4761295Sbill
47749992Sbostic noglob = adrof(STRnoglob) != 0;
4781295Sbill
47950558Schristos if (gflg & G_CSH)
48049992Sbostic /*
48149992Sbostic * Expand back-quote, tilde and brace
48249992Sbostic */
48349992Sbostic vl = vo = globexpand(v);
48449992Sbostic else
48549992Sbostic vl = vo = saveblk(v);
48647596Sbostic
48750558Schristos if (!noglob && (gflg & G_GLOB)) {
48849992Sbostic vl = libglob(vo);
48950745Schristos if ((gflg & G_CSH) && vl != vo)
49049992Sbostic blkfree(vo);
49149992Sbostic }
49250806Schristos else
49350806Schristos trim(vl);
49447414Sbostic
49549992Sbostic gargc = vl ? blklen(vl) : 0;
49649992Sbostic return (gargv = vl);
4971295Sbill }
49849992Sbostic
49949992Sbostic void
ginit()50047414Sbostic ginit()
50147414Sbostic {
50249992Sbostic gargsiz = GLOBSPACE;
50349992Sbostic gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz);
50449992Sbostic gargv[0] = 0;
50549992Sbostic gargc = 0;
50647414Sbostic }
5071295Sbill
50849992Sbostic void
rscan(t,f)5091295Sbill rscan(t, f)
51049992Sbostic register Char **t;
51149992Sbostic void (*f) ();
5121295Sbill {
51349992Sbostic register Char *p;
5141295Sbill
51560237Schristos while ((p = *t++) != NULL)
51649992Sbostic while (*p)
51749992Sbostic (*f) (*p++);
5181295Sbill }
5191295Sbill
52049992Sbostic void
trim(t)52117514Sedward trim(t)
52249992Sbostic register Char **t;
5231295Sbill {
52449992Sbostic register Char *p;
5251295Sbill
52660237Schristos while ((p = *t++) != NULL)
52749992Sbostic while (*p)
52849992Sbostic *p++ &= TRIM;
5291295Sbill }
5301295Sbill
53149992Sbostic void
tglob(t)53217514Sedward tglob(t)
53349992Sbostic register Char **t;
5341295Sbill {
53549992Sbostic register Char *p, c;
5361295Sbill
53760237Schristos while ((p = *t++) != NULL) {
53849992Sbostic if (*p == '~' || *p == '=')
53949992Sbostic gflag |= G_CSH;
54049992Sbostic else if (*p == '{' &&
54152372Schristos (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
54249992Sbostic continue;
54360237Schristos while ((c = *p++) != '\0') {
54452372Schristos /*
54552372Schristos * eat everything inside the matching backquotes
54652372Schristos */
54752372Schristos if (c == '`') {
54852372Schristos gflag |= G_CSH;
54952372Schristos while (*p && *p != '`')
55052372Schristos if (*p++ == '\\') {
55152372Schristos if (*p) /* Quoted chars */
55252372Schristos p++;
55352372Schristos else
55452372Schristos break;
55552372Schristos }
55652372Schristos if (*p) /* The matching ` */
55752372Schristos p++;
55852372Schristos else
55952372Schristos break;
56052372Schristos }
56152372Schristos else if (c == '{')
56252372Schristos gflag |= G_CSH;
56352372Schristos else if (isglob(c))
56452372Schristos gflag |= G_GLOB;
56552372Schristos }
56649992Sbostic }
5671295Sbill }
5681295Sbill
5691295Sbill /*
57047414Sbostic * Command substitute cp. If literal, then this is a substitution from a
57147414Sbostic * << redirection, and so we should not crunch blanks and tabs, separating
57247414Sbostic * words only at newlines.
5731295Sbill */
57449992Sbostic Char **
dobackp(cp,literal)5751295Sbill dobackp(cp, literal)
57649992Sbostic Char *cp;
57749992Sbostic bool literal;
5781295Sbill {
57949992Sbostic register Char *lp, *rp;
58049992Sbostic Char *ep, word[MAXPATHLEN];
5811295Sbill
58249992Sbostic if (pargv) {
58352372Schristos #ifdef notdef
58449992Sbostic abort();
58552372Schristos #endif
58649992Sbostic blkfree(pargv);
58749992Sbostic }
58849992Sbostic pargsiz = GLOBSPACE;
58949992Sbostic pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz);
59049992Sbostic pargv[0] = NULL;
59149992Sbostic pargcp = pargs = word;
59249992Sbostic pargc = 0;
59349992Sbostic pnleft = MAXPATHLEN - 4;
59449992Sbostic for (;;) {
59549992Sbostic for (lp = cp; *lp != '`'; lp++) {
59649992Sbostic if (*lp == 0) {
59749992Sbostic if (pargcp != pargs)
59849992Sbostic pword();
59949992Sbostic return (pargv);
60049992Sbostic }
60149992Sbostic psave(*lp);
6021295Sbill }
60349992Sbostic lp++;
60449992Sbostic for (rp = lp; *rp && *rp != '`'; rp++)
60549992Sbostic if (*rp == '\\') {
60649992Sbostic rp++;
6071295Sbill if (!*rp)
60849992Sbostic goto oops;
60949992Sbostic }
61049992Sbostic if (!*rp)
61149992Sbostic oops: stderror(ERR_UNMATCHED, '`');
61249992Sbostic ep = Strsave(lp);
61349992Sbostic ep[rp - lp] = 0;
61449992Sbostic backeval(ep, literal);
61549992Sbostic cp = rp + 1;
61649992Sbostic }
6171295Sbill }
6181295Sbill
61949992Sbostic static void
backeval(cp,literal)6201295Sbill backeval(cp, literal)
62149992Sbostic Char *cp;
62249992Sbostic bool literal;
6231295Sbill {
62449992Sbostic register int icnt, c;
62549992Sbostic register Char *ip;
62649992Sbostic struct command faket;
62749992Sbostic bool hadnl;
62849992Sbostic int pvec[2], quoted;
62949992Sbostic Char *fakecom[2], ibuf[BUFSIZ];
63049992Sbostic char tibuf[BUFSIZ];
6311295Sbill
63249992Sbostic hadnl = 0;
63349992Sbostic icnt = 0;
63449992Sbostic quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
63549992Sbostic faket.t_dtyp = NODE_COMMAND;
63649992Sbostic faket.t_dflg = 0;
63749992Sbostic faket.t_dlef = 0;
63849992Sbostic faket.t_drit = 0;
63949992Sbostic faket.t_dspr = 0;
64049992Sbostic faket.t_dcom = fakecom;
64149992Sbostic fakecom[0] = STRfakecom1;
64249992Sbostic fakecom[1] = 0;
64347414Sbostic
64449992Sbostic /*
64549992Sbostic * We do the psave job to temporarily change the current job so that the
64649992Sbostic * following fork is considered a separate job. This is so that when
64749992Sbostic * backquotes are used in a builtin function that calls glob the "current
64849992Sbostic * job" is not corrupted. We only need one level of pushed jobs as long as
64949992Sbostic * we are sure to fork here.
65049992Sbostic */
65149992Sbostic psavejob();
65247414Sbostic
65349992Sbostic /*
65449992Sbostic * It would be nicer if we could integrate this redirection more with the
65549992Sbostic * routines in sh.sem.c by doing a fake execute on a builtin function that
65649992Sbostic * was piped out.
65749992Sbostic */
65849992Sbostic mypipe(pvec);
65949992Sbostic if (pfork(&faket, -1) == 0) {
66049992Sbostic struct wordent paraml;
66149992Sbostic struct command *t;
66249992Sbostic
66349992Sbostic (void) close(pvec[0]);
66449992Sbostic (void) dmove(pvec[1], 1);
66550439Schristos (void) dmove(SHERR, 2);
66649992Sbostic initdesc();
6671295Sbill /*
66849992Sbostic * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>,
66949992Sbostic * posted to comp.bugs.4bsd 12 Sep. 1989.
6701295Sbill */
67149992Sbostic if (pargv) /* mg, 21.dec.88 */
67249992Sbostic blkfree(pargv), pargv = 0, pargsiz = 0;
67349992Sbostic /* mg, 21.dec.88 */
67449992Sbostic arginp = cp;
67549992Sbostic while (*cp)
67649992Sbostic *cp++ &= TRIM;
67751528Schristos
67851528Schristos /*
67951528Schristos * In the child ``forget'' everything about current aliases or
68051528Schristos * eval vectors.
68151528Schristos */
68251528Schristos alvec = NULL;
68351528Schristos evalvec = NULL;
68451528Schristos alvecp = NULL;
68551528Schristos evalp = NULL;
68649992Sbostic (void) lex(¶ml);
68749992Sbostic if (seterr)
68849992Sbostic stderror(ERR_OLD);
68949992Sbostic alias(¶ml);
69049992Sbostic t = syntax(paraml.next, ¶ml, 0);
69149992Sbostic if (seterr)
69249992Sbostic stderror(ERR_OLD);
69349992Sbostic if (t)
69449992Sbostic t->t_dflg |= F_NOFORK;
69549992Sbostic (void) signal(SIGTSTP, SIG_IGN);
69649992Sbostic (void) signal(SIGTTIN, SIG_IGN);
69749992Sbostic (void) signal(SIGTTOU, SIG_IGN);
69850023Sbostic execute(t, -1, NULL, NULL);
69949992Sbostic exitstat();
70049992Sbostic }
70149992Sbostic xfree((ptr_t) cp);
70249992Sbostic (void) close(pvec[1]);
70349992Sbostic c = 0;
70450024Schristos ip = NULL;
70549992Sbostic do {
70649992Sbostic int cnt = 0;
7071295Sbill
70849992Sbostic for (;;) {
70949992Sbostic if (icnt == 0) {
71049992Sbostic int i;
71149992Sbostic
71249992Sbostic ip = ibuf;
71349992Sbostic do
71449992Sbostic icnt = read(pvec[0], tibuf, BUFSIZ);
71549992Sbostic while (icnt == -1 && errno == EINTR);
71649992Sbostic if (icnt <= 0) {
71749992Sbostic c = -1;
71849992Sbostic break;
7191295Sbill }
72049992Sbostic for (i = 0; i < icnt; i++)
72149992Sbostic ip[i] = (unsigned char) tibuf[i];
72249992Sbostic }
72349992Sbostic if (hadnl)
72449992Sbostic break;
72549992Sbostic --icnt;
72649992Sbostic c = (*ip++ & TRIM);
72749992Sbostic if (c == 0)
72849992Sbostic break;
72949992Sbostic if (c == '\n') {
7301295Sbill /*
73149992Sbostic * Continue around the loop one more time, so that we can eat
73249992Sbostic * the last newline without terminating this word.
7331295Sbill */
73449992Sbostic hadnl = 1;
73549992Sbostic continue;
73649992Sbostic }
73749992Sbostic if (!quoted && (c == ' ' || c == '\t'))
73849992Sbostic break;
73949992Sbostic cnt++;
74049992Sbostic psave(c | quoted);
74149992Sbostic }
74249992Sbostic /*
74349992Sbostic * Unless at end-of-file, we will form a new word here if there were
74449992Sbostic * characters in the word, or in any case when we take text literally.
74549992Sbostic * If we didn't make empty words here when literal was set then we
74649992Sbostic * would lose blank lines.
74749992Sbostic */
74849992Sbostic if (c != -1 && (cnt || literal))
74949992Sbostic pword();
75049992Sbostic hadnl = 0;
75149992Sbostic } while (c >= 0);
75249992Sbostic (void) close(pvec[0]);
75349992Sbostic pwait();
75449992Sbostic prestjob();
7551295Sbill }
7561295Sbill
75749992Sbostic static void
psave(c)7581295Sbill psave(c)
75950024Schristos int c;
7601295Sbill {
76149992Sbostic if (--pnleft <= 0)
76249992Sbostic stderror(ERR_WTOOLONG);
76349992Sbostic *pargcp++ = c;
7641295Sbill }
7651295Sbill
76649992Sbostic static void
pword()7671295Sbill pword()
7681295Sbill {
76949992Sbostic psave(0);
77049992Sbostic if (pargc == pargsiz - 1) {
77149992Sbostic pargsiz += GLOBSPACE;
77249992Sbostic pargv = (Char **) xrealloc((ptr_t) pargv,
77349992Sbostic (size_t) pargsiz * sizeof(Char *));
77449992Sbostic }
77549992Sbostic pargv[pargc++] = Strsave(pargs);
77649992Sbostic pargv[pargc] = NULL;
77749992Sbostic pargcp = pargs;
77849992Sbostic pnleft = MAXPATHLEN - 4;
7791295Sbill }
78047414Sbostic
78152372Schristos int
Gmatch(string,pattern)78252372Schristos Gmatch(string, pattern)
78352372Schristos Char *string, *pattern;
78452372Schristos {
78552372Schristos Char **blk, **p;
78652372Schristos int gpol = 1, gres = 0;
78752372Schristos
78852372Schristos if (*pattern == '^') {
78952372Schristos gpol = 0;
79052372Schristos pattern++;
79152372Schristos }
79252372Schristos
79352372Schristos blk = (Char **) xmalloc(GLOBSPACE * sizeof(Char *));
79452372Schristos blk[0] = Strsave(pattern);
79552372Schristos blk[1] = NULL;
79652372Schristos
79752372Schristos expbrace(&blk, NULL, GLOBSPACE);
79852372Schristos
79952372Schristos for (p = blk; *p; p++)
80052372Schristos gres |= pmatch(string, *p);
80152372Schristos
80252372Schristos blkfree(blk);
80352372Schristos return(gres == gpol);
80452372Schristos }
80552372Schristos
80652375Schristos static int
pmatch(string,pattern)80752372Schristos pmatch(string, pattern)
80849992Sbostic register Char *string, *pattern;
80947414Sbostic {
81049992Sbostic register Char stringc, patternc;
81152372Schristos int match, negate_range;
81249992Sbostic Char rangec;
81347414Sbostic
81449992Sbostic for (;; ++string) {
81549992Sbostic stringc = *string & TRIM;
81649992Sbostic patternc = *pattern++;
81749992Sbostic switch (patternc) {
81849992Sbostic case 0:
81949992Sbostic return (stringc == 0);
82049992Sbostic case '?':
82149992Sbostic if (stringc == 0)
82249992Sbostic return (0);
82349992Sbostic break;
82449992Sbostic case '*':
82549992Sbostic if (!*pattern)
82649992Sbostic return (1);
82749992Sbostic while (*string)
82849992Sbostic if (Gmatch(string++, pattern))
82949992Sbostic return (1);
83049992Sbostic return (0);
83149992Sbostic case '[':
83249992Sbostic match = 0;
83360237Schristos if ((negate_range = (*pattern == '^')) != 0)
83452372Schristos pattern++;
83560237Schristos while ((rangec = *pattern++) != '\0') {
83649992Sbostic if (rangec == ']')
83752372Schristos break;
83849992Sbostic if (match)
83949992Sbostic continue;
84052372Schristos if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') {
84150126Schristos match = (stringc <= (*pattern & TRIM) &&
84252372Schristos (*(pattern-2) & TRIM) <= stringc);
84349992Sbostic pattern++;
84449992Sbostic }
84552372Schristos else
84652372Schristos match = (stringc == (rangec & TRIM));
84749992Sbostic }
84849992Sbostic if (rangec == 0)
84949992Sbostic stderror(ERR_NAME | ERR_MISSING, ']');
85052372Schristos if (match == negate_range)
85152372Schristos return (0);
85249992Sbostic break;
85349992Sbostic default:
85449992Sbostic if ((patternc & TRIM) != stringc)
85549992Sbostic return (0);
85649992Sbostic break;
85747414Sbostic
85847414Sbostic }
85949992Sbostic }
86047414Sbostic }
86147414Sbostic
86249992Sbostic void
Gcat(s1,s2)86347414Sbostic Gcat(s1, s2)
86449992Sbostic Char *s1, *s2;
86547414Sbostic {
86649992Sbostic register Char *p, *q;
86749992Sbostic int n;
86847414Sbostic
86951437Sleres for (p = s1; *p++;)
87051437Sleres continue;
87151437Sleres for (q = s2; *q++;)
87251437Sleres continue;
87349992Sbostic n = (p - s1) + (q - s2) - 1;
87449992Sbostic if (++gargc >= gargsiz) {
87549992Sbostic gargsiz += GLOBSPACE;
87649992Sbostic gargv = (Char **) xrealloc((ptr_t) gargv,
87749992Sbostic (size_t) gargsiz * sizeof(Char *));
87849992Sbostic }
87949992Sbostic gargv[gargc] = 0;
88049992Sbostic p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char));
88160237Schristos for (q = s1; (*p++ = *q++) != '\0';)
88251437Sleres continue;
88360237Schristos for (p--, q = s2; (*p++ = *q++) != '\0';)
88451437Sleres continue;
88547414Sbostic }
88647414Sbostic
88749992Sbostic #ifdef FILEC
88847414Sbostic int
sortscmp(a,b)88949992Sbostic sortscmp(a, b)
89052372Schristos register const ptr_t a, b;
89147414Sbostic {
89249992Sbostic #if defined(NLS) && !defined(NOSTRCOLL)
89349992Sbostic char buf[2048];
89449992Sbostic #endif
89549992Sbostic
89657937Schristos if (!a) /* check for NULL */
89749992Sbostic return (b ? 1 : 0);
89849992Sbostic if (!b)
89949992Sbostic return (-1);
90049992Sbostic
90151665Sbostic if (!*(Char **)a) /* check for NULL */
90251665Sbostic return (*(Char **)b ? 1 : 0);
90351665Sbostic if (!*(Char **)b)
90449992Sbostic return (-1);
90549992Sbostic
90649992Sbostic #if defined(NLS) && !defined(NOSTRCOLL)
90751665Sbostic (void) strcpy(buf, short2str(*(Char **)a));
90851665Sbostic return ((int) strcoll(buf, short2str(*(Char **)b)));
90949992Sbostic #else
91051665Sbostic return ((int) Strcmp(*(Char **)a, *(Char **)b));
91149992Sbostic #endif
91247414Sbostic }
91349992Sbostic #endif /* FILEC */
914