summaryrefslogtreecommitdiff
path: root/sys/src/cmd/rc/glob.c
diff options
context:
space:
mode:
authorcinap_lenrek <cinap_lenrek@felloff.net>2016-05-15 19:10:37 +0200
committercinap_lenrek <cinap_lenrek@felloff.net>2016-05-15 19:10:37 +0200
commit7717051e3ce062fbdb8415e4befa5205d25e80bb (patch)
tree029df0be93da100936c772c5f6a83f0874930cef /sys/src/cmd/rc/glob.c
parent81f867f4fb3d7fd495be3282a01d2e4a9b1a56fd (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.c183
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;
- }
-}