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().
This commit is contained in:
parent
81f867f4fb
commit
7717051e3c
11 changed files with 169 additions and 173 deletions
|
@ -274,8 +274,19 @@ outcode(tree *t, int eflag)
|
||||||
emitf(Xunlocal);
|
emitf(Xunlocal);
|
||||||
break;
|
break;
|
||||||
case WORD:
|
case WORD:
|
||||||
emitf(Xword);
|
if(t->quoted){
|
||||||
emits(estrdup(t->str));
|
emitf(Xword);
|
||||||
|
emits(estrdup(t->str));
|
||||||
|
} else {
|
||||||
|
if((q = Globsize(t->str)) > 0){
|
||||||
|
emitf(Xglobs);
|
||||||
|
emits(estrdup(t->str));
|
||||||
|
emiti(q);
|
||||||
|
} else {
|
||||||
|
emitf(Xword);
|
||||||
|
emits(deglob(estrdup(t->str)));
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case DUP:
|
case DUP:
|
||||||
if(t->rtype==DUPFD){
|
if(t->rtype==DUPFD){
|
||||||
|
@ -473,6 +484,7 @@ codefree(code *cp)
|
||||||
|| p->f==Xsubshell || p->f==Xtrue) p++;
|
|| p->f==Xsubshell || p->f==Xtrue) p++;
|
||||||
else if(p->f==Xdup || p->f==Xpipefd) p+=2;
|
else if(p->f==Xdup || p->f==Xpipefd) p+=2;
|
||||||
else if(p->f==Xpipe) p+=4;
|
else if(p->f==Xpipe) p+=4;
|
||||||
|
else if(p->f==Xglobs) efree(p[1].s), p+=2;
|
||||||
else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s);
|
else if(p->f==Xword || p->f==Xdelhere) efree((++p)->s);
|
||||||
else if(p->f==Xfn){
|
else if(p->f==Xfn){
|
||||||
efree(p[2].s);
|
efree(p[2].s);
|
||||||
|
|
|
@ -33,14 +33,18 @@ Newword(char *wd, word *next)
|
||||||
word *p = new(word);
|
word *p = new(word);
|
||||||
p->word = wd;
|
p->word = wd;
|
||||||
p->next = next;
|
p->next = next;
|
||||||
|
p->glob = 0;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
void
|
word*
|
||||||
Pushword(char *wd)
|
Pushword(char *wd)
|
||||||
{
|
{
|
||||||
|
word *w;
|
||||||
if(runq->argv==0)
|
if(runq->argv==0)
|
||||||
panic("pushword but no argv!", 0);
|
panic("pushword but no argv!", 0);
|
||||||
runq->argv->words = Newword(wd, runq->argv->words);
|
w = Newword(wd, runq->argv->words);
|
||||||
|
runq->argv->words = w;
|
||||||
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
word*
|
word*
|
||||||
|
@ -48,10 +52,10 @@ newword(char *wd, word *next)
|
||||||
{
|
{
|
||||||
return Newword(estrdup(wd), next);
|
return Newword(estrdup(wd), next);
|
||||||
}
|
}
|
||||||
void
|
word*
|
||||||
pushword(char *wd)
|
pushword(char *wd)
|
||||||
{
|
{
|
||||||
Pushword(estrdup(wd));
|
return Pushword(estrdup(wd));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -220,6 +224,7 @@ main(int argc, char *argv[])
|
||||||
* Xfalse{...} execute {} if false
|
* Xfalse{...} execute {} if false
|
||||||
* Xfn(name){... Xreturn} define function
|
* Xfn(name){... Xreturn} define function
|
||||||
* Xfor(var, list){... Xreturn} for loop
|
* Xfor(var, list){... Xreturn} for loop
|
||||||
|
* Xglobs[string globsize] push globbing string
|
||||||
* Xjump[addr] goto
|
* Xjump[addr] goto
|
||||||
* Xlocal(name, val) create local variable, assign value
|
* Xlocal(name, val) create local variable, assign value
|
||||||
* Xmark mark stack
|
* Xmark mark stack
|
||||||
|
@ -471,6 +476,13 @@ Xword(void)
|
||||||
pushword(runq->code[runq->pc++].s);
|
pushword(runq->code[runq->pc++].s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Xglobs(void)
|
||||||
|
{
|
||||||
|
word *w = pushword(runq->code[runq->pc++].s);
|
||||||
|
w->glob = runq->code[runq->pc++].i;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Xwrite(void)
|
Xwrite(void)
|
||||||
{
|
{
|
||||||
|
@ -566,6 +578,8 @@ conclist(word *lp, word *rp, word *tail)
|
||||||
p = Newword(emalloc(ln+rn+1), (word *)0);
|
p = Newword(emalloc(ln+rn+1), (word *)0);
|
||||||
Memcpy(p->word, lp->word, ln);
|
Memcpy(p->word, lp->word, ln);
|
||||||
Memcpy(p->word+ln, rp->word, rn+1);
|
Memcpy(p->word+ln, rp->word, rn+1);
|
||||||
|
if(lp->glob || rp->glob)
|
||||||
|
p->glob = Globsize(p->word);
|
||||||
*end = p, end = &p->next;
|
*end = p, end = &p->next;
|
||||||
if(lp->next == 0 && rp->next == 0)
|
if(lp->next == 0 && rp->next == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -599,6 +613,17 @@ Xconc(void)
|
||||||
runq->argv->words = vp;
|
runq->argv->words = vp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char*
|
||||||
|
Str(word *a)
|
||||||
|
{
|
||||||
|
char *s = a->word;
|
||||||
|
if(a->glob){
|
||||||
|
a->glob = 0;
|
||||||
|
deglob(s);
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Xassign(void)
|
Xassign(void)
|
||||||
{
|
{
|
||||||
|
@ -607,12 +632,10 @@ Xassign(void)
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deglob(runq->argv->words->word);
|
v = vlook(Str(runq->argv->words));
|
||||||
v = vlook(runq->argv->words->word);
|
|
||||||
poplist();
|
poplist();
|
||||||
globlist();
|
|
||||||
freewords(v->val);
|
freewords(v->val);
|
||||||
v->val = runq->argv->words;
|
v->val = globlist(runq->argv->words);
|
||||||
v->changed = 1;
|
v->changed = 1;
|
||||||
runq->argv->words = 0;
|
runq->argv->words = 0;
|
||||||
poplist();
|
poplist();
|
||||||
|
@ -641,8 +664,7 @@ Xdol(void)
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s = runq->argv->words->word;
|
s = Str(runq->argv->words);
|
||||||
deglob(s);
|
|
||||||
n = 0;
|
n = 0;
|
||||||
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
|
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
|
||||||
a = runq->argv->next->words;
|
a = runq->argv->next->words;
|
||||||
|
@ -668,8 +690,7 @@ Xqdol(void)
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s = runq->argv->words->word;
|
s = Str(runq->argv->words);
|
||||||
deglob(s);
|
|
||||||
a = vlook(s)->val;
|
a = vlook(s)->val;
|
||||||
poplist();
|
poplist();
|
||||||
Pushword(list2str(a));
|
Pushword(list2str(a));
|
||||||
|
@ -699,8 +720,7 @@ subwords(word *val, int len, word *sub, word *a)
|
||||||
if(!sub)
|
if(!sub)
|
||||||
return a;
|
return a;
|
||||||
a = subwords(val, len, sub->next, a);
|
a = subwords(val, len, sub->next, a);
|
||||||
s = sub->word;
|
s = Str(sub);
|
||||||
deglob(s);
|
|
||||||
m = 0;
|
m = 0;
|
||||||
n = 0;
|
n = 0;
|
||||||
while('0'<=*s && *s<='9')
|
while('0'<=*s && *s<='9')
|
||||||
|
@ -732,8 +752,7 @@ Xsub(void)
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s = runq->argv->next->words->word;
|
s = Str(runq->argv->next->words);
|
||||||
deglob(s);
|
|
||||||
a = runq->argv->next->next->words;
|
a = runq->argv->next->next->words;
|
||||||
v = vlook(s)->val;
|
v = vlook(s)->val;
|
||||||
a = subwords(v, count(v), runq->argv->words, a);
|
a = subwords(v, count(v), runq->argv->words, a);
|
||||||
|
@ -753,8 +772,7 @@ Xcount(void)
|
||||||
Xerror1("variable name not singleton!");
|
Xerror1("variable name not singleton!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s = runq->argv->words->word;
|
s = Str(runq->argv->words);
|
||||||
deglob(s);
|
|
||||||
n = 0;
|
n = 0;
|
||||||
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
|
for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
|
||||||
if(n==0 || *t){
|
if(n==0 || *t){
|
||||||
|
@ -776,11 +794,9 @@ Xlocal(void)
|
||||||
Xerror1("variable name must be singleton\n");
|
Xerror1("variable name must be singleton\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
deglob(runq->argv->words->word);
|
runq->local = newvar(Str(runq->argv->words), runq->local);
|
||||||
runq->local = newvar(runq->argv->words->word, runq->local);
|
|
||||||
poplist();
|
poplist();
|
||||||
globlist();
|
runq->local->val = globlist(runq->argv->words);
|
||||||
runq->local->val = runq->argv->words;
|
|
||||||
runq->local->changed = 1;
|
runq->local->changed = 1;
|
||||||
runq->argv->words = 0;
|
runq->argv->words = 0;
|
||||||
poplist();
|
poplist();
|
||||||
|
@ -819,8 +835,7 @@ Xfn(void)
|
||||||
word *a;
|
word *a;
|
||||||
int end;
|
int end;
|
||||||
end = runq->code[runq->pc].i;
|
end = runq->code[runq->pc].i;
|
||||||
globlist();
|
for(a = globlist(runq->argv->words);a;a = a->next){
|
||||||
for(a = runq->argv->words;a;a = a->next){
|
|
||||||
v = gvlook(a->word);
|
v = gvlook(a->word);
|
||||||
if(v->fn)
|
if(v->fn)
|
||||||
codefree(v->fn);
|
codefree(v->fn);
|
||||||
|
@ -989,5 +1004,5 @@ Xfor(void)
|
||||||
void
|
void
|
||||||
Xglob(void)
|
Xglob(void)
|
||||||
{
|
{
|
||||||
globlist();
|
globlist(runq->argv->words);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
|
||||||
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
|
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
|
||||||
extern void Xrdwr(void);
|
extern void Xrdwr(void);
|
||||||
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
|
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
|
||||||
extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void);
|
extern void Xtrue(void), Xword(void), Xglobs(void), Xwrite(void), Xpipefd(void), Xcase(void);
|
||||||
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
|
||||||
extern void Xrdcmds(void), Xwastrue(void), Xif(void), Xifnot(void), Xpipewait(void);
|
extern void Xrdcmds(void), Xwastrue(void), Xif(void), Xifnot(void), Xpipewait(void);
|
||||||
extern void Xdelhere(void), Xpopredir(void), Xsub(void), Xeflag(void), Xsettrue(void);
|
extern void Xdelhere(void), Xpopredir(void), Xsub(void), Xeflag(void), Xsettrue(void);
|
||||||
|
@ -20,6 +20,7 @@ extern void Xerror1(char*);
|
||||||
struct word{
|
struct word{
|
||||||
char *word;
|
char *word;
|
||||||
word *next;
|
word *next;
|
||||||
|
int glob; /* Globsize(word) */
|
||||||
};
|
};
|
||||||
struct list{
|
struct list{
|
||||||
word *words;
|
word *words;
|
||||||
|
|
|
@ -30,19 +30,18 @@ void codefree(code*);
|
||||||
int compile(tree*);
|
int compile(tree*);
|
||||||
char * list2str(word*);
|
char * list2str(word*);
|
||||||
int count(word*);
|
int count(word*);
|
||||||
void deglob(void*);
|
char* deglob(char*);
|
||||||
void delwaitpid(int);
|
void delwaitpid(int);
|
||||||
void dotrap(void);
|
void dotrap(void);
|
||||||
void freenodes(void);
|
void freenodes(void);
|
||||||
void freewords(word*);
|
void freewords(word*);
|
||||||
void globlist(void);
|
word* globlist(word*);
|
||||||
int havewaitpid(int);
|
int havewaitpid(int);
|
||||||
int idchr(int);
|
int idchr(int);
|
||||||
void inttoascii(char*, long);
|
void inttoascii(char*, long);
|
||||||
void kinit(void);
|
void kinit(void);
|
||||||
int mapfd(int);
|
int mapfd(int);
|
||||||
int match(void*, void*, int);
|
int match(char*, char*, int);
|
||||||
int matchfn(void*, void*);
|
|
||||||
char** mkargv(word*);
|
char** mkargv(word*);
|
||||||
void clearwaitpids(void);
|
void clearwaitpids(void);
|
||||||
void panic(char*, int);
|
void panic(char*, int);
|
||||||
|
@ -52,7 +51,7 @@ void popword(void);
|
||||||
void pprompt(void);
|
void pprompt(void);
|
||||||
void pushlist(void);
|
void pushlist(void);
|
||||||
void pushredir(int, int, int);
|
void pushredir(int, int, int);
|
||||||
void pushword(char*);
|
word* pushword(char*);
|
||||||
void readhere(void);
|
void readhere(void);
|
||||||
word* searchpath(char*);
|
word* searchpath(char*);
|
||||||
void setstatus(char*);
|
void setstatus(char*);
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
#include "rc.h"
|
#include "rc.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "fns.h"
|
#include "fns.h"
|
||||||
char *globname;
|
|
||||||
struct word *globv;
|
|
||||||
/*
|
/*
|
||||||
* delete all the GLOB marks from s, in place
|
* delete all the GLOB marks from s, in place
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
char*
|
||||||
deglob(void *as)
|
deglob(char *s)
|
||||||
{
|
{
|
||||||
char *s = as;
|
char *b = s;
|
||||||
char *t = s;
|
char *t = s;
|
||||||
do{
|
do{
|
||||||
if(*t==GLOB)
|
if(*t==GLOB)
|
||||||
t++;
|
t++;
|
||||||
*s++=*t;
|
*s++=*t;
|
||||||
}while(*t++);
|
}while(*t++);
|
||||||
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
static int
|
||||||
globcmp(const void *s, const void *t)
|
globcmp(void *s, void *t)
|
||||||
{
|
{
|
||||||
return strcmp(*(char**)s, *(char**)t);
|
return strcmp(*(char**)s, *(char**)t);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
globsort(word *left, word *right)
|
globsort(word *left, word *right)
|
||||||
{
|
{
|
||||||
char **list;
|
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];
|
for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
|
||||||
efree((char *)list);
|
efree((char *)list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Push names prefixed by globname and suffixed by a match of p onto the astack.
|
* Does the string s match the pattern p
|
||||||
* namep points to the end of the prefix in globname.
|
* . and .. are only matched by patterns starting with .
|
||||||
|
* * matches any sequence of characters
|
||||||
|
* ? matches any single character
|
||||||
|
* [...] matches the enclosed list of characters
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static int
|
||||||
globdir(uchar *p, uchar *namep)
|
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;
|
int f;
|
||||||
/* scan the pattern looking for a component with a metacharacter in it */
|
/* scan the pattern looking for a component with a metacharacter in it */
|
||||||
if(*p=='\0'){
|
if(*p=='\0')
|
||||||
globv = newword(globname, globv);
|
return newword(name, list);
|
||||||
return;
|
|
||||||
}
|
|
||||||
t = namep;
|
t = namep;
|
||||||
newp = p;
|
newp = p;
|
||||||
while(*newp){
|
while(*newp){
|
||||||
|
@ -67,65 +77,63 @@ globdir(uchar *p, uchar *namep)
|
||||||
/* If we ran out of pattern, append the name if accessible */
|
/* If we ran out of pattern, append the name if accessible */
|
||||||
if(*newp=='\0'){
|
if(*newp=='\0'){
|
||||||
*t='\0';
|
*t='\0';
|
||||||
if(access(globname, 0)==0)
|
if(access(name, 0)==0)
|
||||||
globv = newword(globname, globv);
|
list = newword(name, list);
|
||||||
return;
|
return list;
|
||||||
}
|
}
|
||||||
/* read the directory and recur for any entry that matches */
|
/* read the directory and recur for any entry that matches */
|
||||||
*namep='\0';
|
*namep='\0';
|
||||||
if((f = Opendir(globname[0]?globname:"."))<0) return;
|
if((f = Opendir(name[0]?name:".")) >= 0){
|
||||||
while(*newp!='/' && *newp!='\0') newp++;
|
while(*newp!='/' && *newp!='\0') newp++;
|
||||||
while(Readdir(f, namep, *newp=='/')){
|
while(Readdir(f, namep, *newp=='/')){
|
||||||
if(matchfn(namep, p)){
|
if(matchfn(namep, p)){
|
||||||
for(t = namep;*t;t++);
|
for(t = namep;*t;t++);
|
||||||
globdir(newp, 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.
|
* Subsitute a word with its glob in place.
|
||||||
* If there are no matches, the list consists of p.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
static void
|
||||||
glob(void *ap)
|
globword(word *w)
|
||||||
{
|
{
|
||||||
uchar *p = ap;
|
word *left, *right;
|
||||||
word *svglobv = globv;
|
char *name;
|
||||||
int globlen = Globsize(ap);
|
|
||||||
|
|
||||||
if(!globlen){
|
if(w->glob == 0)
|
||||||
deglob(p);
|
|
||||||
globv = newword((char *)p, globv);
|
|
||||||
return;
|
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
|
word*
|
||||||
equtf(uchar *p, uchar *q)
|
globlist(word *l)
|
||||||
{
|
{
|
||||||
Rune pr, qr;
|
word *p, *q;
|
||||||
|
|
||||||
if(*p!=*q)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
chartorune(&pr, (char*)p);
|
for(p=l;p;p=q){
|
||||||
chartorune(&qr, (char*)q);
|
q = p->next;
|
||||||
return pr == qr;
|
globword(p);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -133,50 +141,43 @@ equtf(uchar *p, uchar *q)
|
||||||
* not jumping past nuls in broken utf codes!
|
* not jumping past nuls in broken utf codes!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uchar*
|
static char*
|
||||||
nextutf(uchar *p)
|
nextutf(char *p)
|
||||||
{
|
{
|
||||||
Rune dummy;
|
Rune dummy;
|
||||||
|
|
||||||
return p + chartorune(&dummy, (char*)p);
|
return p + chartorune(&dummy, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Convert the utf code at *p to a unicode value
|
* Convert the utf code at *p to a unicode value
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
static int
|
||||||
unicode(uchar *p)
|
unicode(char *p)
|
||||||
{
|
{
|
||||||
Rune r;
|
Rune r;
|
||||||
|
|
||||||
chartorune(&r, (char*)p);
|
chartorune(&r, p);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Does the string s match the pattern p
|
* Do p and q point at equal utf codes
|
||||||
* . and .. are only matched by patterns starting with .
|
|
||||||
* * matches any sequence of characters
|
|
||||||
* ? matches any single character
|
|
||||||
* [...] matches the enclosed list of characters
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
static int
|
||||||
matchfn(void *as, void *ap)
|
equtf(char *p, char *q)
|
||||||
{
|
{
|
||||||
uchar *s = as, *p = ap;
|
if(*p!=*q)
|
||||||
|
return 0;
|
||||||
if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
|
return unicode(p) == unicode(q);
|
||||||
return 0;
|
|
||||||
return match(s, p, '/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
match(void *as, void *ap, int stop)
|
match(char *s, char *p, int stop)
|
||||||
{
|
{
|
||||||
int compl, hit, lo, hi, t, c;
|
int compl, hit, lo, hi, t, c;
|
||||||
uchar *s = as, *p = ap;
|
|
||||||
|
|
||||||
for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){
|
for(; *p!=stop && *p!='\0'; s = nextutf(s), p = nextutf(p)){
|
||||||
if(*p!=GLOB){
|
if(*p!=GLOB){
|
||||||
|
@ -235,27 +236,3 @@ match(void *as, void *ap, int stop)
|
||||||
}
|
}
|
||||||
return *s=='\0';
|
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -366,8 +366,7 @@ yylex(void)
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
for(;;){
|
for(;;){
|
||||||
/* next line should have (char)c==GLOB, but ken's compiler is broken */
|
if(c=='*' || c=='[' || c=='?' || c==GLOB)
|
||||||
if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
|
|
||||||
w = addtok(w, GLOB);
|
w = addtok(w, GLOB);
|
||||||
w = addutf(w, c);
|
w = addutf(w, c);
|
||||||
c = nextc();
|
c = nextc();
|
||||||
|
|
|
@ -38,6 +38,7 @@ struct{
|
||||||
Xdelfn, "Xdelfn",
|
Xdelfn, "Xdelfn",
|
||||||
Xpipe, "Xpipe",
|
Xpipe, "Xpipe",
|
||||||
Xpipewait, "Xpipewait",
|
Xpipewait, "Xpipewait",
|
||||||
|
Xpopredir, "Xpopredir",
|
||||||
Xrdcmds, "Xrdcmds",
|
Xrdcmds, "Xrdcmds",
|
||||||
(void (*)(void))Xerror, "Xerror",
|
(void (*)(void))Xerror, "Xerror",
|
||||||
Xbackq, "Xbackq",
|
Xbackq, "Xbackq",
|
||||||
|
@ -46,6 +47,7 @@ struct{
|
||||||
Xdelhere, "Xdelhere",
|
Xdelhere, "Xdelhere",
|
||||||
Xfor, "Xfor",
|
Xfor, "Xfor",
|
||||||
Xglob, "Xglob",
|
Xglob, "Xglob",
|
||||||
|
Xglobs, "Xglobs",
|
||||||
Xrdfn, "Xrdfn",
|
Xrdfn, "Xrdfn",
|
||||||
Xsimple, "Xsimple",
|
Xsimple, "Xsimple",
|
||||||
Xrdfn, "Xrdfn",
|
Xrdfn, "Xrdfn",
|
||||||
|
|
|
@ -20,18 +20,17 @@ void
|
||||||
Xsimple(void)
|
Xsimple(void)
|
||||||
{
|
{
|
||||||
word *a;
|
word *a;
|
||||||
thread *p = runq;
|
|
||||||
var *v;
|
var *v;
|
||||||
struct builtin *bp;
|
struct builtin *bp;
|
||||||
int pid;
|
int pid;
|
||||||
globlist();
|
|
||||||
a = runq->argv->words;
|
a = globlist(runq->argv->words);
|
||||||
if(a==0){
|
if(a==0){
|
||||||
Xerror1("empty argument list");
|
Xerror1("empty argument list");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(flag['x'])
|
if(flag['x'])
|
||||||
pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
|
pfmt(err, "%v\n", a); /* wrong, should do redirs */
|
||||||
v = gvlook(a->word);
|
v = gvlook(a->word);
|
||||||
if(v->fn)
|
if(v->fn)
|
||||||
execfunc(v);
|
execfunc(v);
|
||||||
|
@ -140,9 +139,9 @@ int
|
||||||
dochdir(char *word)
|
dochdir(char *word)
|
||||||
{
|
{
|
||||||
/* report to /dev/wdir if it exists and we're interactive */
|
/* report to /dev/wdir if it exists and we're interactive */
|
||||||
static int wdirfd = -2;
|
|
||||||
if(chdir(word)<0) return -1;
|
if(chdir(word)<0) return -1;
|
||||||
if(flag['i']!=0){
|
if(flag['i']!=0){
|
||||||
|
static int wdirfd = -2;
|
||||||
if(wdirfd==-2) /* try only once */
|
if(wdirfd==-2) /* try only once */
|
||||||
wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
|
wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
|
||||||
if(wdirfd>=0)
|
if(wdirfd>=0)
|
||||||
|
@ -234,10 +233,10 @@ execshift(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
star = vlook("*");
|
star = vlook("*");
|
||||||
for(;n && star->val;--n){
|
for(;star->val;--n){
|
||||||
a = star->val->next;
|
a = star->val->next;
|
||||||
efree(star->val->word);
|
efree(star->val->word);
|
||||||
efree((char *)star->val);
|
efree(star->val);
|
||||||
star->val = a;
|
star->val = a;
|
||||||
star->changed = 1;
|
star->changed = 1;
|
||||||
}
|
}
|
||||||
|
@ -245,15 +244,6 @@ execshift(void)
|
||||||
poplist();
|
poplist();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
octal(char *s)
|
|
||||||
{
|
|
||||||
int n = 0;
|
|
||||||
while(*s==' ' || *s=='\t' || *s=='\n') s++;
|
|
||||||
while('0'<=*s && *s<='7') n = n*8+*s++-'0';
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
mapfd(int fd)
|
mapfd(int fd)
|
||||||
{
|
{
|
||||||
|
@ -293,25 +283,18 @@ execcmds(io *f)
|
||||||
void
|
void
|
||||||
execeval(void)
|
execeval(void)
|
||||||
{
|
{
|
||||||
char *cmdline, *s, *t;
|
char *cmdline;
|
||||||
int len = 0;
|
int len;
|
||||||
word *ap;
|
|
||||||
if(count(runq->argv->words)<=1){
|
if(count(runq->argv->words)<=1){
|
||||||
Xerror1("Usage: eval cmd ...");
|
Xerror1("Usage: eval cmd ...");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
eflagok = 1;
|
eflagok = 1;
|
||||||
for(ap = runq->argv->words->next;ap;ap = ap->next)
|
cmdline = list2str(runq->argv->words->next);
|
||||||
len+=1+strlen(ap->word);
|
len = strlen(cmdline);
|
||||||
cmdline = emalloc(len);
|
cmdline[len] = '\n';
|
||||||
s = cmdline;
|
|
||||||
for(ap = runq->argv->words->next;ap;ap = ap->next){
|
|
||||||
for(t = ap->word;*t;) *s++=*t++;
|
|
||||||
*s++=' ';
|
|
||||||
}
|
|
||||||
s[-1]='\n';
|
|
||||||
poplist();
|
poplist();
|
||||||
execcmds(opencore(cmdline, len));
|
execcmds(opencore(cmdline, len+1));
|
||||||
efree(cmdline);
|
efree(cmdline);
|
||||||
}
|
}
|
||||||
union code dotcmds[14];
|
union code dotcmds[14];
|
||||||
|
@ -393,7 +376,7 @@ execdot(void)
|
||||||
/* free caller's copy of $* */
|
/* free caller's copy of $* */
|
||||||
av = p->argv;
|
av = p->argv;
|
||||||
p->argv = av->next;
|
p->argv = av->next;
|
||||||
efree((char *)av);
|
efree(av);
|
||||||
/* push $0 value */
|
/* push $0 value */
|
||||||
pushlist();
|
pushlist();
|
||||||
pushword(zero);
|
pushword(zero);
|
||||||
|
|
|
@ -28,7 +28,7 @@ freenodes(void)
|
||||||
u = t->next;
|
u = t->next;
|
||||||
if(t->str)
|
if(t->str)
|
||||||
efree(t->str);
|
efree(t->str);
|
||||||
efree((char *)t);
|
efree(t);
|
||||||
}
|
}
|
||||||
treenodes = 0;
|
treenodes = 0;
|
||||||
}
|
}
|
||||||
|
@ -144,5 +144,5 @@ freetree(tree *p)
|
||||||
freetree(p->child[2]);
|
freetree(p->child[2]);
|
||||||
if(p->str)
|
if(p->str)
|
||||||
efree(p->str);
|
efree(p->str);
|
||||||
efree((char *)p);
|
efree(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,8 +277,8 @@ register struct word *args, *path;
|
||||||
Bad:
|
Bad:
|
||||||
setstatus(msg);
|
setstatus(msg);
|
||||||
pfmt(err, "%s: %s\n", argv[1], msg);
|
pfmt(err, "%s: %s\n", argv[1], msg);
|
||||||
efree((char *)env);
|
efree(env);
|
||||||
efree((char *)argv);
|
efree(argv);
|
||||||
}
|
}
|
||||||
#define NDIR 14 /* should get this from param.h */
|
#define NDIR 14 /* should get this from param.h */
|
||||||
Globsize(p)
|
Globsize(p)
|
||||||
|
@ -432,6 +432,14 @@ Isatty(fd){
|
||||||
Abort(){
|
Abort(){
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
static int
|
||||||
|
octal(char *s)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
while(*s==' ' || *s=='\t' || *s=='\n') s++;
|
||||||
|
while('0'<=*s && *s<='7') n = n*8+*s++-'0';
|
||||||
|
return n;
|
||||||
|
}
|
||||||
execumask(){ /* wrong -- should fork before writing */
|
execumask(){ /* wrong -- should fork before writing */
|
||||||
int m;
|
int m;
|
||||||
struct io out[1];
|
struct io out[1];
|
||||||
|
|
|
@ -301,7 +301,7 @@ Execute(word *args, word *path)
|
||||||
rerrstr(file, sizeof file);
|
rerrstr(file, sizeof file);
|
||||||
setstatus(file);
|
setstatus(file);
|
||||||
pfmt(err, "%s: %s\n", argv[1], file);
|
pfmt(err, "%s: %s\n", argv[1], file);
|
||||||
efree((char *)argv);
|
efree(argv);
|
||||||
}
|
}
|
||||||
#define NDIR 256 /* shoud be a better way */
|
#define NDIR 256 /* shoud be a better way */
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue