diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-05-15 19:10:37 +0200 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2016-05-15 19:10:37 +0200 |
commit | 7717051e3ce062fbdb8415e4befa5205d25e80bb (patch) | |
tree | 029df0be93da100936c772c5f6a83f0874930cef /sys/src/cmd/rc/glob.c | |
parent | 81f867f4fb3d7fd495be3282a01d2e4a9b1a56fd (diff) |
rc: fix inband globbing bugs, cleanup
add glob information to the word structure so we wont accidently
deglob quoted strings containing the GLOB. we store Globsize(word)
in in word->glob which avoids recalculating that values and the
check if a word should be globbed quick.
globlist() now substitutes the word inplace avoiding the copying
when all words are literals and avoids recursion.
minor cleanups: use list2str() in execeval(), move octal() to
unix.c, remove the (char*) casts to efree().
Diffstat (limited to 'sys/src/cmd/rc/glob.c')
-rw-r--r-- | sys/src/cmd/rc/glob.c | 183 |
1 files changed, 80 insertions, 103 deletions
diff --git a/sys/src/cmd/rc/glob.c b/sys/src/cmd/rc/glob.c index 90513243d..10dff0421 100644 --- a/sys/src/cmd/rc/glob.c +++ b/sys/src/cmd/rc/glob.c @@ -1,31 +1,31 @@ #include "rc.h" #include "exec.h" #include "fns.h" -char *globname; -struct word *globv; + /* * delete all the GLOB marks from s, in place */ -void -deglob(void *as) +char* +deglob(char *s) { - char *s = as; + char *b = s; char *t = s; do{ if(*t==GLOB) t++; *s++=*t; }while(*t++); + return b; } -int -globcmp(const void *s, const void *t) +static int +globcmp(void *s, void *t) { return strcmp(*(char**)s, *(char**)t); } -void +static void globsort(word *left, word *right) { char **list; @@ -38,21 +38,31 @@ globsort(word *left, word *right) for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n]; efree((char *)list); } + /* - * Push names prefixed by globname and suffixed by a match of p onto the astack. - * namep points to the end of the prefix in globname. + * Does the string s match the pattern p + * . and .. are only matched by patterns starting with . + * * matches any sequence of characters + * ? matches any single character + * [...] matches the enclosed list of characters */ -void -globdir(uchar *p, uchar *namep) +static int +matchfn(char *s, char *p) { - uchar *t, *newp; + if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') + return 0; + return match(s, p, '/'); +} + +static word* +globdir(word *list, char *p, char *name, char *namep) +{ + char *t, *newp; int f; /* scan the pattern looking for a component with a metacharacter in it */ - if(*p=='\0'){ - globv = newword(globname, globv); - return; - } + if(*p=='\0') + return newword(name, list); t = namep; newp = p; while(*newp){ @@ -67,65 +77,63 @@ globdir(uchar *p, uchar *namep) /* If we ran out of pattern, append the name if accessible */ if(*newp=='\0'){ *t='\0'; - if(access(globname, 0)==0) - globv = newword(globname, globv); - return; + if(access(name, 0)==0) + list = newword(name, list); + return list; } /* read the directory and recur for any entry that matches */ *namep='\0'; - if((f = Opendir(globname[0]?globname:"."))<0) return; - while(*newp!='/' && *newp!='\0') newp++; - while(Readdir(f, namep, *newp=='/')){ - if(matchfn(namep, p)){ - for(t = namep;*t;t++); - globdir(newp, t); + if((f = Opendir(name[0]?name:".")) >= 0){ + while(*newp!='/' && *newp!='\0') newp++; + while(Readdir(f, namep, *newp=='/')){ + if(matchfn(namep, p)){ + for(t = namep;*t;t++); + list = globdir(list, newp, name, t); + } } + Closedir(f); } - Closedir(f); + return list; } + /* - * Push all file names matched by p on the current thread's stack. - * If there are no matches, the list consists of p. + * Subsitute a word with its glob in place. */ -void -glob(void *ap) +static void +globword(word *w) { - uchar *p = ap; - word *svglobv = globv; - int globlen = Globsize(ap); + word *left, *right; + char *name; - if(!globlen){ - deglob(p); - globv = newword((char *)p, globv); + if(w->glob == 0) return; + name = emalloc(w->glob); + memset(name, 0, w->glob); + right = w->next; + left = globdir(right, w->word, name, name); + efree(name); + if(left == right) { + deglob(w->word); + w->glob = 0; + } else { + efree(w->word); + globsort(left, right); + *w = *left; + efree(left); } - globname = emalloc(globlen); - memset(globname, 0, globlen); - globdir(p, (uchar *)globname); - efree(globname); - if(svglobv==globv){ - deglob(p); - globv = newword((char *)p, globv); - } - else - globsort(globv, svglobv); } -/* - * Do p and q point at equal utf codes - */ -int -equtf(uchar *p, uchar *q) +word* +globlist(word *l) { - Rune pr, qr; - - if(*p!=*q) - return 0; + word *p, *q; - chartorune(&pr, (char*)p); - chartorune(&qr, (char*)q); - return pr == qr; + for(p=l;p;p=q){ + q = p->next; + globword(p); + } + return l; } /* @@ -133,50 +141,43 @@ equtf(uchar *p, uchar *q) * not jumping past nuls in broken utf codes! */ -uchar* -nextutf(uchar *p) +static char* +nextutf(char *p) { Rune dummy; - return p + chartorune(&dummy, (char*)p); + return p + chartorune(&dummy, p); } /* * Convert the utf code at *p to a unicode value */ -int -unicode(uchar *p) +static int +unicode(char *p) { Rune r; - chartorune(&r, (char*)p); + chartorune(&r, p); return r; } /* - * Does the string s match the pattern p - * . and .. are only matched by patterns starting with . - * * matches any sequence of characters - * ? matches any single character - * [...] matches the enclosed list of characters + * Do p and q point at equal utf codes */ -int -matchfn(void *as, void *ap) +static int +equtf(char *p, char *q) { - uchar *s = as, *p = ap; - - if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.') - return 0; - return match(s, p, '/'); + if(*p!=*q) + return 0; + return unicode(p) == unicode(q); } int -match(void *as, void *ap, int stop) +match(char *s, char *p, int stop) { int compl, hit, lo, hi, t, c; - uchar *s = as, *p = ap; for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){ if(*p!=GLOB){ @@ -235,27 +236,3 @@ match(void *as, void *ap, int stop) } return *s=='\0'; } - -void -globlist1(word *gl) -{ - if(gl){ - globlist1(gl->next); - glob(gl->word); - } -} - -void -globlist(void) -{ - word *a; - globv = 0; - globlist1(runq->argv->words); - poplist(); - pushlist(); - if(globv){ - for(a = globv;a->next;a = a->next); - a->next = runq->argv->words; - runq->argv->words = globv; - } -} |