X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/d33af40e151029b404185d8a6aaa25a70d8bd7b5..2b00e1e70058938c3686ac8eb1ee72d56165bc43:/usr/src/bin/csh/glob.c diff --git a/usr/src/bin/csh/glob.c b/usr/src/bin/csh/glob.c index 4e87ad7ab4..51214df7b1 100644 --- a/usr/src/bin/csh/glob.c +++ b/usr/src/bin/csh/glob.c @@ -1,751 +1,811 @@ -static char *sccsid = "@(#)glob.c 4.6 %G%"; - -#include "sh.h" -#include - -/* - * C Shell +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * %sccs.include.redist.c% */ -int globcnt; - -char *globchars = "`{[*?"; - -char *gpath, *gpathp, *lastgpathp; -int globbed; -bool noglob; -bool nonomatch; -char *entp; -char **sortbas; - -char ** -glob(v) - register char **v; -{ - char agpath[BUFSIZ]; - char *agargv[GAVSIZ]; - - gpath = agpath; gpathp = gpath; *gpathp = 0; - lastgpathp = &gpath[sizeof agpath - 2]; - ginit(agargv); globcnt = 0; -#ifdef GDEBUG - printf("glob entered: "); blkpr(v); printf("\n"); +#ifndef lint +static char sccsid[] = "@(#)glob.c 5.21 (Berkeley) %G%"; +#endif /* not lint */ + +#include +#include +#include +#include +#include +#include +#if __STDC__ +# include +#else +# include #endif - noglob = adrof("noglob") != 0; - nonomatch = adrof("nonomatch") != 0; - globcnt = noglob | nonomatch; - while (*v) - collect(*v++); -#ifdef GDEBUG - printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n"); -#endif - if (globcnt == 0 && (gflag&1)) { - blkfree(gargv), gargv = 0; - return (0); - } else - return (gargv = copyblk(gargv)); -} -ginit(agargv) - char **agargv; -{ +#include "csh.h" +#include "extern.h" - agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; - gnleft = NCARGS - 4; -} +static int noglob, nonomatch; +static int pargsiz, gargsiz; -collect(as) - register char *as; -{ - register int i; +/* + * Values for gflag + */ +#define G_NONE 0 /* No globbing needed */ +#define G_GLOB 1 /* string contains *?[] characters */ +#define G_CSH 2 /* string contains ~`{ characters */ - if (any('`', as)) { -#ifdef GDEBUG - printf("doing backp of %s\n", as); -#endif - dobackp(as, 0); -#ifdef GDEBUG - printf("backp done, acollect'ing\n"); -#endif - for (i = 0; i < pargc; i++) - if (noglob) { - Gcat(pargv[i], ""); - sortbas = &gargv[gargc]; - } else - acollect(pargv[i]); - if (pargv) - blkfree(pargv), pargv = 0; -#ifdef GDEBUG - printf("acollect done\n"); -#endif - } else if (noglob || eq(as, "{") || eq(as, "{}")) { - Gcat(as, ""); - sort(); - } else - acollect(as); -} +#define GLOBSPACE 100 /* Alloc increment */ -acollect(as) - register char *as; -{ - register int ogargc = gargc; - - gpathp = gpath; *gpathp = 0; globbed = 0; - expand(as); - if (gargc == ogargc) { - if (nonomatch) { - Gcat(as, ""); - sort(); - } - } else - sort(); -} +#define LBRC '{' +#define RBRC '}' +#define LBRK '[' +#define RBRK ']' +#define EOS '\0' -sort() -{ - register char **p1, **p2, *c; - char **Gvp = &gargv[gargc]; - - p1 = sortbas; - while (p1 < Gvp-1) { - p2 = p1; - while (++p2 < Gvp) - if (strcmp(*p1, *p2) > 0) - c = *p1, *p1 = *p2, *p2 = c; - p1++; - } - sortbas = Gvp; -} +Char **gargv = NULL; +long gargc = 0; +Char **pargv = NULL; +long pargc = 0; -expand(as) - char *as; +/* + * globbing is now done in two stages. In the first pass we expand + * csh globbing idioms ~`{ and then we proceed doing the normal + * globbing if needed ?*[ + * + * Csh type globbing is handled in globexpand() and the rest is + * handled in glob() which is part of the 4.4BSD libc. + * + */ +static Char *globtilde __P((Char **, Char *)); +static Char **libglob __P((Char **)); +static Char **globexpand __P((Char **)); +static int globbrace __P((Char *, Char *, Char ***)); +static void pword __P((void)); +static void psave __P((int)); +static void backeval __P((Char *, bool)); + + +static Char * +globtilde(nv, s) + Char **nv, *s; { - register char *cs; - register char *sgpathp, *oldcs; - struct stat stb; - - sgpathp = gpathp; - cs = as; - if (*cs == '~' && gpathp == gpath) { - addpath('~'); - for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) - addpath(*cs++); - if (!*cs || *cs == '/') { - if (gpathp != gpath + 1) { - *gpathp = 0; - if (gethdir(gpath + 1)) - error("Unknown user: %s", gpath + 1); - strcpy(gpath, gpath + 1); - } else - strcpy(gpath, value("home")); - gpathp = strend(gpath); - } - } - while (!any(*cs, globchars)) { - if (*cs == 0) { - if (!globbed) - Gcat(gpath, ""); - else if (stat(gpath, &stb) >= 0) { - Gcat(gpath, ""); - globcnt++; - } - goto endit; - } - addpath(*cs++); - } - oldcs = cs; - while (cs > as && *cs != '/') - cs--, gpathp--; - if (*cs == '/') - cs++, gpathp++; - *gpathp = 0; - if (*oldcs == '{') { - execbrc(cs, NOSTR); - return; - } - matchdir(cs); -endit: - gpathp = sgpathp; - *gpathp = 0; + Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e; + + gstart = gbuf; + *gstart++ = *s++; + u = s; + for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e; + *b++ = *s++); + *b = EOS; + if (gethdir(gstart)) { + blkfree(nv); + if (*gstart) + stderror(ERR_UNKUSER, short2str(gstart)); + else + stderror(ERR_NOHOME); + } + b = &gstart[Strlen(gstart)]; + while (*s) + *b++ = *s++; + *b = EOS; + --u; + xfree((ptr_t) u); + return (Strsave(gstart)); } -matchdir(pattern) - char *pattern; +static int +globbrace(s, p, bl) + Char *s, *p, ***bl; { - struct stat stb; - register struct direct *dp; - DIR *dirp; - register int cnt; - - dirp = opendir(gpath); - if (dirp == NULL) { - if (globbed) - return; - goto patherr2; - } - if (fstat(dirp->dd_fd, &stb) < 0) - goto patherr1; - if (!isdir(stb)) { - errno = ENOTDIR; - goto patherr1; + int i, len; + Char *pm, *pe, *lm, *pl; + Char **nv, **vl; + Char gbuf[MAXPATHLEN]; + int size = GLOBSPACE; + + nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); + *vl = NULL; + + len = 0; + /* copy part up to the brace */ + for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) + continue; + + /* check for balanced braces */ + for (i = 0, pe = ++p; *pe; pe++) + if (*pe == LBRK) { + /* Ignore everything between [] */ + for (++pe; *pe != RBRK && *pe != EOS; pe++) + continue; + if (*pe == EOS) { + blkfree(nv); + return (-LBRK); + } } - while ((dp = readdir(dirp)) != NULL) { - if (dp->d_ino == 0) - continue; - if (match(dp->d_name, pattern)) { - Gcat(gpath, dp->d_name); - globcnt++; - } + else if (*pe == LBRC) + i++; + else if (*pe == RBRC) { + if (i == 0) + break; + i--; } - closedir(dirp); - return; -patherr1: - closedir(dirp); -patherr2: - Perror(gpath); -} - -execbrc(p, s) - char *p, *s; -{ - char restbuf[BUFSIZ + 2]; - register char *pe, *pm, *pl; - int brclev = 0; - char *lm, savec, *sgpathp; - - for (lm = restbuf; *p != '{'; *lm++ = *p++) - continue; - for (pe = ++p; *pe; pe++) - switch (*pe) { - - case '{': - brclev++; - continue; + if (i != 0) { + blkfree(nv); + return (-LBRC); + } - case '}': - if (brclev == 0) - goto pend; - brclev--; + for (i = 0, pl = pm = p; pm <= pe; pm++) + switch (*pm) { + case LBRK: + for (++pm; *pm != RBRK && *pm != EOS; pm++) continue; - - case '[': - for (pe++; *pe && *pe != ']'; pe++) - continue; - if (!*pe) - error("Missing ]"); - continue; - } -pend: - if (brclev || !*pe) - error("Missing }"); - for (pl = pm = p; pm <= pe; pm++) - switch (*pm & (QUOTE|TRIM)) { - - case '{': - brclev++; - continue; - - case '}': - if (brclev) { - brclev--; - continue; - } - goto doit; - - case ','|QUOTE: + if (*pm == EOS) { + *vl = NULL; + blkfree(nv); + return (-RBRK); + } + break; + case LBRC: + i++; + break; + case RBRC: + if (i) { + i--; + break; + } + /* FALLTHROUGH */ case ',': - if (brclev) - continue; -doit: - savec = *pm; - *pm = 0; - strcpy(lm, pl); - strcat(restbuf, pe + 1); + if (i && *pm == ',') + break; + else { + Char savec = *pm; + + *pm = EOS; + (void) Strcpy(lm, pl); + (void) Strcat(gbuf, pe + 1); *pm = savec; - if (s == 0) { - sgpathp = gpathp; - expand(restbuf); - gpathp = sgpathp; - *gpathp = 0; - } else if (amatch(s, restbuf)) - return (1); - sort(); + *vl++ = Strsave(gbuf); + len++; pl = pm + 1; - continue; - - case '[': - for (pm++; *pm && *pm != ']'; pm++) - continue; - if (!*pm) - error("Missing ]"); - continue; + if (vl == &nv[size]) { + size += GLOBSPACE; + nv = (Char **) xrealloc((ptr_t) nv, (size_t) + size * sizeof(Char *)); + vl = &nv[size - GLOBSPACE]; + } + } + break; } - return (0); + *vl = NULL; + *bl = nv; + return (len); } -match(s, p) - char *s, *p; +static Char ** +globexpand(v) + Char **v; { - register int c; - register char *sentp; - char sglobbed = globbed; + Char *s; + Char **nv, **vl, **el; + int size = GLOBSPACE; + + + nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); + *vl = NULL; + + /* + * Step 1: expand backquotes. + */ + while (s = *v++) { + if (Strchr(s, '`')) { + int i; + + (void) dobackp(s, 0); + for (i = 0; i < pargc; i++) { + *vl++ = pargv[i]; + if (vl == &nv[size]) { + size += GLOBSPACE; + nv = (Char **) xrealloc((ptr_t) nv, + (size_t) size * sizeof(Char *)); + vl = &nv[size - GLOBSPACE]; + } + } + xfree((ptr_t) pargv); + pargv = NULL; + } + else { + *vl++ = Strsave(s); + if (vl == &nv[size]) { + size += GLOBSPACE; + nv = (Char **) xrealloc((ptr_t) nv, (size_t) + size * sizeof(Char *)); + vl = &nv[size - GLOBSPACE]; + } + } + } + *vl = NULL; + + if (noglob) + return (nv); + + /* + * Step 2: expand braces + */ + el = vl; + vl = nv; + for (s = *vl; s; s = *++vl) { + Char *b; + Char **vp, **bp; + + if (b = Strchr(s, LBRC)) { + Char **bl; + int len; + + if ((len = globbrace(s, b, &bl)) < 0) { + blkfree(nv); + stderror(ERR_MISSING, -len); + } + xfree((ptr_t) s); + if (len == 1) { + *vl-- = *bl; + xfree((ptr_t) bl); + continue; + } + len = blklen(bl); + if (&el[len] >= &nv[size]) { + int l, e; + + l = &el[len] - &nv[size]; + size += GLOBSPACE > l ? GLOBSPACE : l; + l = vl - nv; + e = el - nv; + nv = (Char **) xrealloc((ptr_t) nv, (size_t) + size * sizeof(Char *)); + vl = nv + l; + el = nv + e; + } + vp = vl--; + *vp = *bl; + len--; + for (bp = el; bp != vp; bp--) + bp[len] = *bp; + el += len; + vp++; + for (bp = bl + 1; *bp; *vp++ = *bp++) + continue; + xfree((ptr_t) bl); + } - if (*s == '.' && *p != '.') - return (0); - sentp = entp; - entp = s; - c = amatch(s, p); - entp = sentp; - globbed = sglobbed; - return (c); + } + + /* + * Step 3: expand ~ + */ + vl = nv; + for (s = *vl; s; s = *++vl) + if (*s == '~') + *vl = globtilde(nv, s); + vl = nv; + return (vl); } -amatch(s, p) - register char *s, *p; +static Char * +handleone(str, vl, action) + Char *str, **vl; + int action; { - register int scc; - int ok, lc; - char *sgpathp; - struct stat stb; - int c, cc; - globbed = 1; - for (;;) { - scc = *s++ & TRIM; - switch (c = *p++) { - - case '{': - return (execbrc(p - 1, s - 1)); - - case '[': - ok = 0; - lc = 077777; - while (cc = *p++) { - if (cc == ']') { - if (ok) - break; - return (0); - } - if (cc == '-') { - if (lc <= scc && scc <= *p++) - ok++; - } else - if (scc == (lc = cc)) - ok++; - } - if (cc == 0) - error("Missing ]"); - continue; - - case '*': - if (!*p) - return (1); - if (*p == '/') { - p++; - goto slash; - } - for (s--; *s; s++) - if (amatch(s, p)) - return (1); - return (0); - - case 0: - return (scc == 0); - - default: - if ((c & TRIM) != scc) - return (0); - continue; - - case '?': - if (scc == 0) - return (0); - continue; - - case '/': - if (scc) - return (0); -slash: - s = entp; - sgpathp = gpathp; - while (*s) - addpath(*s++); - addpath('/'); - if (stat(gpath, &stb) == 0 && isdir(stb)) - if (*p == 0) { - Gcat(gpath, ""); - globcnt++; - } else - expand(p); - gpathp = sgpathp; - *gpathp = 0; - return (0); - } + Char *cp, **vlp = vl; + + switch (action) { + case G_ERROR: + setname(short2str(str)); + blkfree(vl); + stderror(ERR_NAME | ERR_AMBIG); + break; + case G_APPEND: + trim(vlp); + str = Strsave(*vlp++); + do { + cp = Strspl(str, STRspace); + xfree((ptr_t) str); + str = Strspl(cp, *vlp); + xfree((ptr_t) cp); } + while (*++vlp); + blkfree(vl); + break; + case G_IGNORE: + str = Strsave(strip(*vlp)); + blkfree(vl); + break; + } + return (str); } -Gmatch(s, p) - register char *s, *p; +static Char ** +libglob(vl) + Char **vl; { - register int scc; - int ok, lc; - int c, cc; - - for (;;) { - scc = *s++ & TRIM; - switch (c = *p++) { - - case '[': - ok = 0; - lc = 077777; - while (cc = *p++) { - if (cc == ']') { - if (ok) - break; - return (0); - } - if (cc == '-') { - if (lc <= scc && scc <= *p++) - ok++; - } else - if (scc == (lc = cc)) - ok++; - } - if (cc == 0) - bferr("Missing ]"); - continue; - - case '*': - if (!*p) - return (1); - for (s--; *s; s++) - if (Gmatch(s, p)) - return (1); - return (0); - - case 0: - return (scc == 0); - - default: - if ((c & TRIM) != scc) - return (0); - continue; - - case '?': - if (scc == 0) - return (0); - continue; - - } + int gflgs = GLOB_QUOTE | GLOB_NOCHECK; + glob_t globv; + char *ptr; + + globv.gl_offs = 0; + globv.gl_pathv = 0; + globv.gl_pathc = 0; + nonomatch = adrof(STRnonomatch) != 0; + do { + ptr = short2qstr(*vl); + switch (glob(ptr, gflgs, 0, &globv)) { + case GLOB_ABEND: + setname(ptr); + stderror(ERR_NAME | ERR_GLOB); + /* NOTREACHED */ + case GLOB_NOSPACE: + stderror(ERR_NOMEM); + /* NOTREACHED */ + default: + break; + } + if (!nonomatch && (globv.gl_matchc == 0) && + (globv.gl_flags & GLOB_MAGCHAR)) { + globfree(&globv); + return (NULL); } + gflgs |= GLOB_APPEND; + } + while (*++vl); + vl = blk2short(globv.gl_pathv); + globfree(&globv); + return (vl); } -Gcat(s1, s2) - register char *s1, *s2; +Char * +globone(str, action) + Char *str; + int action; { - gnleft -= strlen(s1) + strlen(s2) + 1; - if (gnleft <= 0 || ++gargc >= GAVSIZ) - error("Arguments too long"); - gargv[gargc] = 0; - gargv[gargc - 1] = strspl(s1, s2); -} - -addpath(c) - char c; -{ + Char *v[2], **vl, **vo; - if (gpathp >= lastgpathp) - error("Pathname too long"); - *gpathp++ = c; - *gpathp = 0; -} + noglob = adrof(STRnoglob) != 0; + gflag = 0; + v[0] = str; + v[1] = 0; + tglob(v); + if (gflag == G_NONE) + return (strip(Strsave(str))); -rscan(t, f) - register char **t; - int (*f)(); -{ - register char *p, c; - - while (p = *t++) { - if (f == tglob) - if (*p == '~') - gflag |= 2; - else if (eq(p, "{") || eq(p, "{}")) - continue; - while (c = *p++) - (*f)(c); + if (gflag & G_CSH) { + /* + * Expand back-quote, tilde and brace + */ + vo = globexpand(v); + if (noglob || (gflag & G_GLOB) == 0) { + if (vo[0] == NULL) { + xfree((ptr_t) vo); + return (Strsave(STRNULL)); + } + if (vo[1] != NULL) + return (handleone(str, vo, action)); + else { + str = strip(vo[0]); + xfree((ptr_t) vo); + return (str); + } } + } + else if (noglob || (gflag & G_GLOB) == 0) + return (strip(Strsave(str))); + else + vo = v; + + vl = libglob(vo); + if (gflag & G_CSH) + blkfree(vo); + if (vl == NULL) { + setname(short2str(str)); + stderror(ERR_NAME | ERR_NOMATCH); + } + if (vl[0] == NULL) { + xfree((ptr_t) vl); + return (Strsave(STRNULL)); + } + if (vl[1] != NULL) + return (handleone(str, vl, action)); + else { + str = strip(*vl); + xfree((ptr_t) vl); + return (str); + } } -scan(t, f) - register char **t; - int (*f)(); +Char ** +globall(v) + Char **v; { - register char *p, c; + Char **vl, **vo; + + if (!v || !v[0]) { + gargv = saveblk(v); + gargc = blklen(gargv); + return (gargv); + } - while (p = *t++) - while (c = *p) - *p++ = (*f)(c); + noglob = adrof(STRnoglob) != 0; + + if (gflag & G_CSH) + /* + * Expand back-quote, tilde and brace + */ + vl = vo = globexpand(v); + else + vl = vo = saveblk(v); + + if (!noglob && (gflag & G_GLOB)) { + vl = libglob(vo); + if (gflag & G_CSH) + blkfree(vo); + } + + gargc = vl ? blklen(vl) : 0; + return (gargv = vl); } -tglob(c) - register char c; +void +ginit() { - - if (any(c, globchars)) - gflag |= c == '{' ? 2 : 1; - return (c); + gargsiz = GLOBSPACE; + gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz); + gargv[0] = 0; + gargc = 0; } -trim(c) - char c; +void +rscan(t, f) + register Char **t; + void (*f) (); { + register Char *p; - return (c & TRIM); + while (p = *t++) + while (*p) + (*f) (*p++); } -tback(c) - char c; +void +trim(t) + register Char **t; { + register Char *p; - if (c == '`') - gflag = 1; + while (p = *t++) + while (*p) + *p++ &= TRIM; } -char * -globone(str) - register char *str; +void +tglob(t) + register Char **t; { - char *gv[2]; - register char **gvp; - register char *cp; - - gv[0] = str; - gv[1] = 0; - gflag = 0; - rscan(gv, tglob); - if (gflag) { - gvp = glob(gv); - if (gvp == 0) { - setname(str); - bferr("No match"); - } - cp = *gvp++; - if (cp == 0) - cp = ""; - else if (*gvp) { - setname(str); - bferr("Ambiguous"); - } else - cp = strip(cp); -/* - if (cp == 0 || *gvp) { - setname(str); - bferr(cp ? "Ambiguous" : "No output"); - } -*/ - xfree((char *)gargv); gargv = 0; - } else { - scan(gv, trim); - cp = savestr(gv[0]); - } - return (cp); + register Char *p, c; + + while (p = *t++) { + if (*p == '~' || *p == '=') + gflag |= G_CSH; + else if (*p == '{' && + (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) + continue; + while (c = *p++) + if (isglob(c)) + gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB; + } } /* - * Command substitute cp. If literal, then this is - * a substitution from a << redirection, and so we should - * not crunch blanks and tabs, separating words only at newlines. + * Command substitute cp. If literal, then this is a substitution from a + * << redirection, and so we should not crunch blanks and tabs, separating + * words only at newlines. */ -char ** +Char ** dobackp(cp, literal) - char *cp; - bool literal; + Char *cp; + bool literal; { - register char *lp, *rp; - char *ep; - char word[BUFSIZ]; - char *apargv[GAVSIZ + 2]; - - if (pargv) { - abort(); - blkfree(pargv); + register Char *lp, *rp; + Char *ep, word[MAXPATHLEN]; + + if (pargv) { + abort(); + blkfree(pargv); + } + pargsiz = GLOBSPACE; + pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz); + pargv[0] = NULL; + pargcp = pargs = word; + pargc = 0; + pnleft = MAXPATHLEN - 4; + for (;;) { + for (lp = cp; *lp != '`'; lp++) { + if (*lp == 0) { + if (pargcp != pargs) + pword(); + return (pargv); + } + psave(*lp); } - pargv = apargv; - pargv[0] = NOSTR; - pargcp = pargs = word; - pargc = 0; - pnleft = BUFSIZ - 4; - for (;;) { - for (lp = cp; *lp != '`'; lp++) { - if (*lp == 0) { - if (pargcp != pargs) - pword(); -#ifdef GDEBUG - printf("leaving dobackp\n"); -#endif - return (pargv = copyblk(pargv)); - } - psave(*lp); - } - lp++; - for (rp = lp; *rp && *rp != '`'; rp++) - if (*rp == '\\') { - rp++; - if (!*rp) - goto oops; - } + lp++; + for (rp = lp; *rp && *rp != '`'; rp++) + if (*rp == '\\') { + rp++; if (!*rp) -oops: - error("Unmatched `"); - ep = savestr(lp); - ep[rp - lp] = 0; - backeval(ep, literal); -#ifdef GDEBUG - printf("back from backeval\n"); -#endif - cp = rp + 1; - } + goto oops; + } + if (!*rp) + oops: stderror(ERR_UNMATCHED, '`'); + ep = Strsave(lp); + ep[rp - lp] = 0; + backeval(ep, literal); + cp = rp + 1; + } } +static void backeval(cp, literal) - char *cp; - bool literal; + Char *cp; + bool literal; { - int pvec[2]; - int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; - char ibuf[BUFSIZ]; - register int icnt = 0, c; - register char *ip; - bool hadnl = 0; - char *fakecom[2]; - struct command faket; - - faket.t_dtyp = TCOM; - faket.t_dflg = 0; - faket.t_dlef = 0; - faket.t_drit = 0; - faket.t_dspr = 0; - faket.t_dcom = fakecom; - fakecom[0] = "` ... `"; - fakecom[1] = 0; + register int icnt, c; + register Char *ip; + struct command faket; + bool hadnl; + int pvec[2], quoted; + Char *fakecom[2], ibuf[BUFSIZ]; + char tibuf[BUFSIZ]; + + hadnl = 0; + icnt = 0; + quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; + faket.t_dtyp = NODE_COMMAND; + faket.t_dflg = 0; + faket.t_dlef = 0; + faket.t_drit = 0; + faket.t_dspr = 0; + faket.t_dcom = fakecom; + fakecom[0] = STRfakecom1; + fakecom[1] = 0; + + /* + * We do the psave job to temporarily change the current job so that the + * following fork is considered a separate job. This is so that when + * backquotes are used in a builtin function that calls glob the "current + * job" is not corrupted. We only need one level of pushed jobs as long as + * we are sure to fork here. + */ + psavejob(); + + /* + * It would be nicer if we could integrate this redirection more with the + * routines in sh.sem.c by doing a fake execute on a builtin function that + * was piped out. + */ + mypipe(pvec); + if (pfork(&faket, -1) == 0) { + struct wordent paraml; + struct command *t; + + (void) close(pvec[0]); + (void) dmove(pvec[1], 1); + (void) dmove(SHDIAG, 2); + initdesc(); /* - * We do the psave job to temporarily change the current job - * so that the following fork is considered a separate job. - * This is so that when backquotes are used in a - * builtin function that calls glob the "current job" is not corrupted. - * We only need one level of pushed jobs as long as we are sure to - * fork here. + * Bugfix for nested backquotes by Michael Greim , + * posted to comp.bugs.4bsd 12 Sep. 1989. */ - psavejob(); - /* - * It would be nicer if we could integrate this redirection more - * with the routines in sh.sem.c by doing a fake execute on a builtin - * function that was piped out. - */ - mypipe(pvec); - if (pfork(&faket, -1) == 0) { - struct wordent paraml; - struct command *t; - - close(pvec[0]); - dmove(pvec[1], 1); - dmove(SHDIAG, 2); - initdesc(); - arginp = cp; - while (*cp) - *cp++ &= TRIM; - lex(¶ml); - if (err) - error(err); - alias(¶ml); - t = syntax(paraml.next, ¶ml, 0); - if (err) - error(err); - if (t) - t->t_dflg |= FPAR; - signal(SIGTSTP, SIG_IGN); - signal(SIGTTIN, SIG_IGN); - signal(SIGTTOU, SIG_IGN); - execute(t, -1); - exitstat(); - } - xfree(cp); - close(pvec[1]); - do { - int cnt = 0; - for (;;) { - if (icnt == 0) { - ip = ibuf; - icnt = read(pvec[0], ip, BUFSIZ); - if (icnt <= 0) { - c = -1; - break; - } - } - if (hadnl) - break; - --icnt; - c = (*ip++ & TRIM); - if (c == 0) - break; - if (c == '\n') { - /* - * Continue around the loop one - * more time, so that we can eat - * the last newline without terminating - * this word. - */ - hadnl = 1; - continue; - } - if (!quoted && (c == ' ' || c == '\t')) - break; - cnt++; - psave(c | quoted); + if (pargv) /* mg, 21.dec.88 */ + blkfree(pargv), pargv = 0, pargsiz = 0; + /* mg, 21.dec.88 */ + arginp = cp; + while (*cp) + *cp++ &= TRIM; + (void) lex(¶ml); + if (seterr) + stderror(ERR_OLD); + alias(¶ml); + t = syntax(paraml.next, ¶ml, 0); + if (seterr) + stderror(ERR_OLD); + if (t) + t->t_dflg |= F_NOFORK; + (void) signal(SIGTSTP, SIG_IGN); + (void) signal(SIGTTIN, SIG_IGN); + (void) signal(SIGTTOU, SIG_IGN); + execute(t, -1, NULL, NULL); + exitstat(); + } + xfree((ptr_t) cp); + (void) close(pvec[1]); + c = 0; + ip = NULL; + do { + int cnt = 0; + + for (;;) { + if (icnt == 0) { + int i; + + ip = ibuf; + do + icnt = read(pvec[0], tibuf, BUFSIZ); + while (icnt == -1 && errno == EINTR); + if (icnt <= 0) { + c = -1; + break; } + for (i = 0; i < icnt; i++) + ip[i] = (unsigned char) tibuf[i]; + } + if (hadnl) + break; + --icnt; + c = (*ip++ & TRIM); + if (c == 0) + break; + if (c == '\n') { /* - * Unless at end-of-file, we will form a new word - * here if there were characters in the word, or in - * any case when we take text literally. If - * we didn't make empty words here when literal was - * set then we would lose blank lines. + * Continue around the loop one more time, so that we can eat + * the last newline without terminating this word. */ - if (c != -1 && (cnt || literal)) - pword(); - hadnl = 0; - } while (c >= 0); -#ifdef GDEBUG - printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); - printf("also c = %c <%o>\n", c, c); -#endif - close(pvec[0]); - pwait(); - prestjob(); + hadnl = 1; + continue; + } + if (!quoted && (c == ' ' || c == '\t')) + break; + cnt++; + psave(c | quoted); + } + /* + * Unless at end-of-file, we will form a new word here if there were + * characters in the word, or in any case when we take text literally. + * If we didn't make empty words here when literal was set then we + * would lose blank lines. + */ + if (c != -1 && (cnt || literal)) + pword(); + hadnl = 0; + } while (c >= 0); + (void) close(pvec[0]); + pwait(); + prestjob(); } +static void psave(c) - char c; + int c; { - - if (--pnleft <= 0) - error("Word too long"); - *pargcp++ = c; + if (--pnleft <= 0) + stderror(ERR_WTOOLONG); + *pargcp++ = c; } +static void pword() { + psave(0); + if (pargc == pargsiz - 1) { + pargsiz += GLOBSPACE; + pargv = (Char **) xrealloc((ptr_t) pargv, + (size_t) pargsiz * sizeof(Char *)); + } + pargv[pargc++] = Strsave(pargs); + pargv[pargc] = NULL; + pargcp = pargs; + pnleft = MAXPATHLEN - 4; +} + +int +Gmatch(string, pattern) + register Char *string, *pattern; +{ + register Char stringc, patternc; + int match; + Char rangec; + + for (;; ++string) { + stringc = *string & TRIM; + patternc = *pattern++; + switch (patternc) { + case 0: + return (stringc == 0); + case '?': + if (stringc == 0) + return (0); + break; + case '*': + if (!*pattern) + return (1); + while (*string) + if (Gmatch(string++, pattern)) + return (1); + return (0); + case '[': + match = 0; + while (rangec = *pattern++) { + if (rangec == ']') + if (match) + break; + else + return (0); + if (match) + continue; + if (rangec == '-' && *(pattern - 2) != '[' && *pattern != ']') { + match = (stringc <= (*pattern & TRIM) && + (*(pattern - 2) & TRIM) <= stringc); + pattern++; + } + else + match = (stringc == rangec); + } + if (rangec == 0) + stderror(ERR_NAME | ERR_MISSING, ']'); + break; + default: + if ((patternc & TRIM) != stringc) + return (0); + break; + + } + } +} + +void +Gcat(s1, s2) + Char *s1, *s2; +{ + register Char *p, *q; + int n; + + for (p = s1; *p++;); + for (q = s2; *q++;); + n = (p - s1) + (q - s2) - 1; + if (++gargc >= gargsiz) { + gargsiz += GLOBSPACE; + gargv = (Char **) xrealloc((ptr_t) gargv, + (size_t) gargsiz * sizeof(Char *)); + } + gargv[gargc] = 0; + p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char)); + for (q = s1; *p++ = *q++;); + for (p--, q = s2; *p++ = *q++;); +} + +#ifdef FILEC +int +sortscmp(a, b) + register Char **a, **b; +{ +#if defined(NLS) && !defined(NOSTRCOLL) + char buf[2048]; + +#endif - psave(0); - if (pargc == GAVSIZ) - error("Too many words from ``"); - pargv[pargc++] = savestr(pargs); - pargv[pargc] = NOSTR; -#ifdef GDEBUG - printf("got word %s\n", pargv[pargc-1]); + if (!a) /* check for NULL */ + return (b ? 1 : 0); + if (!b) + return (-1); + + if (!*a) /* check for NULL */ + return (*b ? 1 : 0); + if (!*b) + return (-1); + +#if defined(NLS) && !defined(NOSTRCOLL) + (void) strcpy(buf, short2str(*a)); + return ((int) strcoll(buf, short2str(*b))); +#else + return ((int) Strcmp(*a, *b)); #endif - pargcp = pargs; - pnleft = BUFSIZ - 4; } +#endif /* FILEC */