1 /* $Header: /p/tcsh/cvsroot/tcsh/sh.glob.c,v 3.95 2016/08/01 16:21:09 christos Exp $ */
3 * sh.glob.c: Regular expression expansion
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. 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.
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
35 RCSID("$tcsh: sh.glob.c,v 3.95 2016/08/01 16:21:09 christos Exp $")
45 #define G_NONE 0 /* No globbing needed */
46 #define G_GLOB 1 /* string contains *?[] characters */
47 #define G_CSH 2 /* string contains ~`{ characters */
49 #define GLOBSPACE 100 /* Alloc increment */
59 * globbing is now done in two stages. In the first pass we expand
60 * csh globbing idioms ~`{ and then we proceed doing the normal
61 * globbing if needed ?*[
63 * Csh type globbing is handled in globexpand() and the rest is
64 * handled in glob() which is part of the 4.4BSD libc.
67 static Char *globtilde (Char *);
68 static Char *handleone (Char *, Char **, int);
69 static Char **libglob (Char **);
70 static Char **globexpand (Char **, int);
71 static int globbrace (const Char *, Char ***);
72 static void expbrace (Char ***, Char ***, int);
73 static void pword (struct blk_buf *, struct Strbuf *);
74 static void backeval (struct blk_buf *, struct Strbuf *, Char *,
79 Char *name, *u, *home, *res;
82 for (s++; *s && *s != '/' && *s != ':'; s++)
84 name = Strnsave(u + 1, s - (u + 1));
85 cleanup_push(name, xfree);
88 if (adrof(STRnonomatch)) {
93 stderror(ERR_UNKUSER, short2str(name));
98 if (home[0] == '/' && home[1] == '\0' && s[0] == '/')
101 res = Strspl(home, s);
107 /* Returns a newly allocated string, old or NULL */
116 * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names
117 * in stack. PWP: let =foobar pass through (for X windows)
119 if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) {
121 const Char *olddir = varval (STRowd);
123 if (olddir && *olddir &&
124 !dcwd->di_next->di_name && !dcwd->di_prev->di_name)
125 return Strspl(olddir, &old[2]);
129 else if (Isdigit(old[1])) {
132 for (b = &old[2]; Isdigit(*b); b++)
133 dig = dig * 10 + (*b - '0');
134 if (*b != '\0' && *b != '/')
135 /* =<number>foobar */
145 return Strspl(dir, b);
149 globbrace(const Char *s, Char ***bl)
151 struct Strbuf gbuf = Strbuf_INIT;
152 struct blk_buf bb = BLK_BUF_INIT;
154 const Char *p, *pm, *pe, *pl;
157 /* copy part up to the brace */
158 for (p = s; *p != LBRC; p++)
162 /* check for balanced braces */
163 for (i = 0, pe = ++p; *pe; pe++)
165 /* Ignore everything between [] */
166 for (++pe; *pe != RBRK && *pe != EOS; pe++)
171 else if (*pe == LBRC)
173 else if (*pe == RBRC) {
179 if (i != 0 || *pe == '\0')
182 Strbuf_appendn(&gbuf, s, prefix_len);
184 for (i = 0, pl = pm = p; pm <= pe; pm++)
187 for (++pm; *pm != RBRK && *pm != EOS; pm++)
208 gbuf.len = prefix_len;
209 Strbuf_appendn(&gbuf, pl, pm - pl);
210 Strbuf_append(&gbuf, pe + 1);
211 Strbuf_terminate(&gbuf);
212 bb_append(&bb, Strsave(gbuf.s));
219 *bl = bb_finish(&bb);
226 expbrace(Char ***nvp, Char ***elp, int size)
228 Char **vl, **el, **nv, *s;
234 el = vl + blklen(vl);
236 for (s = *vl; s; s = *++vl) {
239 /* leave {} untouched for find */
240 if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0')))
242 if (Strchr(s, '{') != NULL) {
246 if ((len = globbrace(s, &bl)) < 0)
247 stderror(ERR_MISSING, -len);
254 if (&el[len] >= &nv[size]) {
256 l = &el[len] - &nv[size];
257 size += GLOBSPACE > l ? GLOBSPACE : l;
260 nv = xrealloc(nv, size * sizeof(Char *));
261 *nvp = nv; /* To keep cleanups working */
274 for (bp = el; bp != vp; bp--)
284 for (bp = bl + 1; *bp; *vp++ = *bp++)
295 globexpand(Char **v, int noglob)
298 Char ***fnv, **vl, **el;
299 int size = GLOBSPACE;
302 fnv = xmalloc(sizeof(Char ***));
303 *fnv = vl = xmalloc(sizeof(Char *) * size);
305 cleanup_push(fnv, blk_indirect_cleanup);
308 * Step 1: expand backquotes.
310 while ((s = *v++) != '\0') {
311 if (Strchr(s, '`')) {
315 expanded = dobackp(s, 0);
316 for (i = 0; expanded[i] != NULL; i++) {
318 if (vl == &(*fnv)[size]) {
320 *fnv = xrealloc(*fnv, size * sizeof(Char *));
321 vl = &(*fnv)[size - GLOBSPACE];
328 if (vl == &(*fnv)[size]) {
330 *fnv = xrealloc(*fnv, size * sizeof(Char *));
331 vl = &(*fnv)[size - GLOBSPACE];
341 * Step 2: expand braces
344 expbrace(fnv, &el, size);
351 for (s = *vl; s; s = *++vl)
358 if ((ns = globequal(s)) == NULL) {
359 if (!adrof(STRnonomatch))
360 stderror(ERR_DEEP); /* Error */
363 /* Expansion succeeded */
374 * Step 4: expand .. if the variable symlinks==expand is set
376 if (symlinks == SYM_EXPAND) {
377 for (s = *vl; s; s = *++vl) {
378 *vl = dnormalize(s, 1);
392 handleone(Char *str, Char **vl, int action)
399 setname(short2str(str));
401 stderror(ERR_NAME | ERR_AMBIG);
405 for (t = vl; (p = *t++) != NULL; chars++)
407 str = xmalloc(chars * sizeof(Char));
408 for (t = vl, strp = str; (p = *t++) != '\0'; chars++) {
410 *strp++ = *p++ & TRIM;
417 str = Strsave(strip(*vl));
429 int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT;
432 int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0;
434 if (adrof(STRglobdot))
437 if (adrof(STRglobstar))
448 gflgs |= GLOB_NOCHECK;
451 ptr = short2qstr(*vl);
452 switch (glob(ptr, gflgs, 0, &globv)) {
456 stderror(ERR_NAME | ERR_GLOB);
465 if (globv.gl_flags & GLOB_MAGCHAR) {
466 match |= (globv.gl_matchc != 0);
469 gflgs |= GLOB_APPEND;
472 vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ?
473 NULL : blk2short(globv.gl_pathv);
479 globone(Char *str, int action)
481 Char *v[2], **vl, **vo;
484 noglob = adrof(STRnoglob) != 0;
489 return (strip(Strsave(str)));
493 * Expand back-quote, tilde and brace
495 vo = globexpand(v, noglob);
496 if (noglob || (gflg & G_GLOB) == 0) {
500 cleanup_push(vo, blk_cleanup);
502 else if (noglob || (gflg & G_GLOB) == 0)
503 return (strip(Strsave(str)));
515 setname(short2str(str));
516 stderror(ERR_NAME | ERR_NOMATCH);
519 if (vl && vl[0] == NULL) {
521 return (Strsave(STRNULL));
524 return (handleone(str, vl, action));
533 globall(Char **v, int gflg)
541 noglob = adrof(STRnoglob) != 0;
545 * Expand back-quote, tilde and brace
547 vl = vo = globexpand(v, noglob);
549 vl = vo = saveblk(v);
551 if (!noglob && (gflg & G_GLOB)) {
552 cleanup_push(vo, blk_cleanup);
565 glob_all_or_error(Char **v)
571 v = globall(v, gflag);
573 stderror(ERR_NAME | ERR_NOMATCH);
582 rscan(Char **t, void (*f) (Char))
586 while ((p = *t++) != '\0')
596 while ((p = *t++) != '\0')
598 #if INVALID_BYTE != 0
599 if ((*p & INVALID_BYTE) != INVALID_BYTE) /* *p < INVALID_BYTE */
613 while ((p = *t++) != '\0') {
614 if (*p == '~' || *p == '=')
616 else if (*p == '{' &&
617 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0')))
624 * We do want to expand echo `echo '*'`, so we don't\
625 * use this piece of code anymore.
628 while (*p && *p != '`')
630 if (*p) /* Quoted chars */
635 if (!*p) /* The matching ` */
643 else if (symlinks == SYM_EXPAND &&
644 p[1] && ISDOTDOT(p) && (p == *(t-1) || *(p-1) == '/') )
653 * Command substitute cp. If literal, then this is a substitution from a
654 * << redirection, and so we should not crunch blanks and tabs, separating
655 * words only at newlines.
658 dobackp(Char *cp, int literal)
660 struct Strbuf word = Strbuf_INIT;
661 struct blk_buf bb = BLK_BUF_INIT;
664 cleanup_push(&bb, bb_cleanup);
665 cleanup_push(&word, Strbuf_cleanup);
667 for (lp = cp; *lp != '\0' && *lp != '`'; lp++)
669 Strbuf_appendn(&word, cp, lp - cp);
673 for (rp = lp; *rp && *rp != '`'; rp++)
682 stderror(ERR_UNMATCHED, '`');
684 ep = Strnsave(lp, rp - lp);
685 cleanup_push(ep, xfree);
686 backeval(&bb, &word, ep, literal);
694 return bb_finish(&bb);
699 backeval(struct blk_buf *bb, struct Strbuf *word, Char *cp, int literal)
703 struct command faket;
706 Char *fakecom[2], ibuf[BUFSIZE];
711 for (ip = cp; (*ip & QUOTE) != 0; ip++)
713 quoted = *ip == '\0';
716 faket.t_dtyp = NODE_COMMAND;
717 faket.t_dflg = F_BACKQ;
721 faket.t_dcom = fakecom;
722 fakecom[0] = STRfakecom1;
726 * We do the psave job to temporarily change the current job so that the
727 * following fork is considered a separate job. This is so that when
728 * backquotes are used in a builtin function that calls glob the "current
729 * job" is not corrupted. We only need one level of pushed jobs as long as
730 * we are sure to fork here.
733 cleanup_push(&faket, psavejob_cleanup); /* faket is only a marker */
736 * It would be nicer if we could integrate this redirection more with the
737 * routines in sh.sem.c by doing a fake execute on a builtin function that
741 cleanup_push(&pvec[0], open_cleanup);
742 cleanup_push(&pvec[1], open_cleanup);
743 if (pfork(&faket, -1) == 0) {
749 (void) dmove(pvec[1], 1);
750 (void) dmove(SHDIAG, 2);
754 for (arginp = cp; *cp; cp++) {
756 if (is_set(STRcsubstnonl) && (*cp == '\n' || *cp == '\r'))
761 * In the child ``forget'' everything about current aliases or
769 omark = cleanup_push_mark();
772 struct wordent paraml1;
781 cleanup_pop_mark(omark);
791 (void) lex(¶ml1);
792 cleanup_push(¶ml1, lex_cleanup);
796 t = syntax(paraml1.next, ¶ml1, 0);
797 cleanup_push(t, syntax_cleanup);
798 /* The F_BACKQ flag must set so the job output is correct if
799 * printexitvalue is set. If it's not set, the job output
800 * will have "Exit N" appended where N is the exit status. */
802 t->t_dflg = F_BACKQ|F_NOFORK;
806 signal(SIGTSTP, SIG_IGN);
809 signal(SIGTTIN, SIG_IGN);
812 signal(SIGTTOU, SIG_IGN);
814 execute(t, -1, NULL, NULL, TRUE);
816 cleanup_until(¶ml1);
819 cleanup_until(&pvec[1]);
828 icnt = wide_read(pvec[0], ibuf, BUFSIZE, 0);
838 #if defined(WINNT_NATIVE) || defined(__CYGWIN__)
841 #endif /* WINNT_NATIVE || __CYGWIN__ */
844 * Continue around the loop one more time, so that we can eat
845 * the last newline without terminating this word.
850 if (!quoted && (c == ' ' || c == '\t'))
853 if (c == '\\' || quoted)
855 Strbuf_append1(word, c);
858 * Unless at end-of-file, we will form a new word here if there were
859 * characters in the word, or in any case when we take text literally.
860 * If we didn't make empty words here when literal was set then we
861 * would lose blank lines.
863 if (c != 0 && (cnt || literal))
868 cleanup_until(&pvec[0]);
870 cleanup_until(&faket); /* psavejob_cleanup(); */
874 pword(struct blk_buf *bb, struct Strbuf *word)
878 s = Strbuf_finish(word);
884 Gmatch(const Char *string, const Char *pattern)
886 return Gnmatch(string, pattern, NULL);
890 Gnmatch(const Char *string, const Char *pattern, const Char **endstr)
893 const Char *tstring = string;
894 int gpol = 1, gres = 0;
896 if (*pattern == '^') {
901 fblk = xmalloc(sizeof(Char ***));
902 *fblk = xmalloc(GLOBSPACE * sizeof(Char *));
903 (*fblk)[0] = Strsave(pattern);
906 cleanup_push(fblk, blk_indirect_cleanup);
907 expbrace(fblk, NULL, GLOBSPACE);
910 /* Exact matches only */
911 for (p = *fblk; *p; p++)
912 gres |= t_pmatch(string, *p, &tstring, 1) == 2 ? 1 : 0;
916 /* partial matches */
917 end = Strend(string);
918 for (p = *fblk; *p; p++)
919 if (t_pmatch(string, *p, &tstring, 1) != 0) {
928 return(gres == gpol);
932 * Return 2 on exact match,
933 * Return 1 on substring match.
934 * Return 0 on no match.
935 * *estr will point to the end of the longest exact or substring match.
938 t_pmatch(const Char *string, const Char *pattern, const Char **estr, int cs)
940 Char stringc, patternc, rangec;
941 int match, negate_range;
942 const Char *pestr, *nstring;
944 for (nstring = string;; string = nstring) {
945 stringc = *nstring++ & TRIM;
946 patternc = *pattern++ & TRIM;
950 return (stringc == '\0' ? 2 : 1);
957 *estr = Strend(string);
963 switch(t_pmatch(string, pattern, estr, cs)) {
967 pestr = *estr;/*FIXME: does not guarantee longest match */
972 abort(); /* Cannot happen */
974 stringc = *string++ & TRIM;
988 if ((negate_range = (*pattern == '^')) != 0)
990 while ((rangec = *pattern++ & TRIM) != '\0') {
995 if (*pattern == '-' && pattern[1] != ']') {
998 rangec2 = *pattern++ & TRIM;
999 match = (globcharcoll(stringc, rangec2, 0) <= 0 &&
1000 globcharcoll(rangec, stringc, 0) <= 0);
1003 match = (stringc == rangec);
1006 stderror(ERR_NAME | ERR_MISSING, ']');
1007 if ((!match) && (stringc == '\0'))
1009 if (match == negate_range)
1013 if (cs ? patternc != stringc
1014 : Tolower(patternc) != Tolower(stringc))