rc: import 9front's improvements

This commit is contained in:
Giacomo Tesio 2017-10-18 01:10:06 +02:00
parent 26a2f0a1be
commit 085f5dfa34
26 changed files with 481 additions and 2133 deletions

View File

@ -31,10 +31,7 @@ int
morecode(void) morecode(void)
{ {
ncode+=100; ncode+=100;
codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]); codebuf = (code *)erealloc((char *)codebuf, ncode*sizeof codebuf[0]);
if(codebuf==0)
panic("Can't realloc %d bytes in morecode!",
ncode*sizeof codebuf[0]);
return 0; return 0;
} }
@ -55,7 +52,7 @@ compile(tree *t)
emiti(0); /* reference count */ emiti(0); /* reference count */
outcode(t, flag['e']?1:0); outcode(t, flag['e']?1:0);
if(nerror){ if(nerror){
efree((char *)codebuf); free(codebuf);
return 0; return 0;
} }
readhere(); readhere();
@ -68,7 +65,7 @@ void
cleanhere(char *f) cleanhere(char *f)
{ {
emitf(Xdelhere); emitf(Xdelhere);
emits(strdup(f)); emits(estrdup(f));
} }
char* char*
@ -120,13 +117,10 @@ outcode(tree *t, int eflag)
break; break;
case '&': case '&':
emitf(Xasync); emitf(Xasync);
if(havefork){ p = emiti(0);
p = emiti(0); outcode(c0, eflag);
outcode(c0, eflag); emitf(Xexit);
emitf(Xexit); stuffdot(p);
stuffdot(p);
} else
emits(fnstr(c0));
break; break;
case ';': case ';':
outcode(c0, eflag); outcode(c0, eflag);
@ -140,14 +134,21 @@ outcode(tree *t, int eflag)
emitf(Xconc); emitf(Xconc);
break; break;
case '`': case '`':
emitf(Xbackq); emitf(Xmark);
if(havefork){ if(c0){
p = emiti(0);
outcode(c0, 0); outcode(c0, 0);
emitf(Xexit); emitf(Xglob);
stuffdot(p); } else {
} else emitf(Xmark);
emits(fnstr(c0)); emitf(Xword);
emits(estrdup("ifs"));
emitf(Xdol);
}
emitf(Xbackq);
p = emiti(0);
outcode(c1, 0);
emitf(Xexit);
stuffdot(p);
break; break;
case ANDAND: case ANDAND:
outcode(c0, 0); outcode(c0, 0);
@ -223,13 +224,10 @@ outcode(tree *t, int eflag)
break; break;
case SUBSHELL: case SUBSHELL:
emitf(Xsubshell); emitf(Xsubshell);
if(havefork){ p = emiti(0);
p = emiti(0); outcode(c0, eflag);
outcode(c0, eflag); emitf(Xexit);
emitf(Xexit); stuffdot(p);
stuffdot(p);
} else
emits(fnstr(c0));
if(eflag) if(eflag)
emitf(Xeflag); emitf(Xeflag);
break; break;
@ -270,7 +268,7 @@ outcode(tree *t, int eflag)
else{ else{
emitf(Xmark); emitf(Xmark);
emitf(Xword); emitf(Xword);
emits(strdup("*")); emits(estrdup("*"));
emitf(Xdol); emitf(Xdol);
} }
emitf(Xmark); /* dummy value for Xlocal */ emitf(Xmark); /* dummy value for Xlocal */
@ -286,8 +284,19 @@ outcode(tree *t, int eflag)
emitf(Xunlocal); emitf(Xunlocal);
break; break;
case WORD: case WORD:
emitf(Xword); if(t->quoted){
emits(strdup(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){
@ -305,14 +314,10 @@ outcode(tree *t, int eflag)
case PIPEFD: case PIPEFD:
emitf(Xpipefd); emitf(Xpipefd);
emiti(t->rtype); emiti(t->rtype);
if(havefork){ p = emiti(0);
p = emiti(0); outcode(c0, eflag);
outcode(c0, eflag); emitf(Xexit);
emitf(Xexit); stuffdot(p);
stuffdot(p);
} else {
emits(fnstr(c0));
}
break; break;
case REDIR: case REDIR:
emitf(Xmark); emitf(Xmark);
@ -367,16 +372,11 @@ outcode(tree *t, int eflag)
emitf(Xpipe); emitf(Xpipe);
emiti(t->fd0); emiti(t->fd0);
emiti(t->fd1); emiti(t->fd1);
if(havefork){ p = emiti(0);
p = emiti(0); q = emiti(0);
q = emiti(0); outcode(c0, eflag);
outcode(c0, eflag); emitf(Xexit);
emitf(Xexit); stuffdot(p);
stuffdot(p);
} else {
emits(fnstr(c0));
q = emiti(0);
}
outcode(c1, eflag); outcode(c1, eflag);
emitf(Xreturn); emitf(Xreturn);
stuffdot(q); stuffdot(q);
@ -485,11 +485,12 @@ 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==Xword || p->f==Xdelhere) efree((++p)->s); else if(p->f==Xglobs) free(p[1].s), p+=2;
else if(p->f==Xword || p->f==Xdelhere) free((++p)->s);
else if(p->f==Xfn){ else if(p->f==Xfn){
efree(p[2].s); free(p[2].s);
p+=2; p+=2;
} }
} }
efree((char *)cp); free(cp);
} }

View File

@ -37,20 +37,34 @@ start(code *c, int pc, var *local)
} }
word* word*
newword(char *wd, word *next) Newword(char *wd, word *next)
{ {
word *p = new(word); word *p = new(word);
p->word = strdup(wd); p->word = wd;
p->next = next; p->next = next;
p->glob = 0;
return p; return p;
} }
word*
void 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*
newword(char *wd, word *next)
{
return Newword(estrdup(wd), next);
}
word*
pushword(char *wd)
{
return Pushword(estrdup(wd));
} }
void void
@ -63,8 +77,8 @@ popword(void)
if(p==0) if(p==0)
panic("popword but no word!", 0); panic("popword but no word!", 0);
runq->argv->words = p->next; runq->argv->words = p->next;
efree(p->word); free(p->word);
efree((char *)p); free(p);
} }
void void
@ -73,8 +87,8 @@ freelist(word *w)
word *nw; word *nw;
while(w){ while(w){
nw = w->next; nw = w->next;
efree(w->word); free(w->word);
efree((char *)w); free(w);
w = nw; w = nw;
} }
} }
@ -96,7 +110,7 @@ poplist(void)
panic("poplist but no argv", 0); panic("poplist but no argv", 0);
freelist(p->words); freelist(p->words);
runq->argv = p->next; runq->argv = p->next;
efree((char *)p); free(p);
} }
int int
@ -122,7 +136,7 @@ var*
newvar(char *name, var *next) newvar(char *name, var *next)
{ {
var *v = new(var); var *v = new(var);
v->name = name; v->name = estrdup(name);
v->val = 0; v->val = 0;
v->fn = 0; v->fn = 0;
v->changed = 0; v->changed = 0;
@ -166,7 +180,6 @@ main(int argc, char *argv[])
:(word *)0); :(word *)0);
setvar("rcname", newword(argv[0], (word *)0)); setvar("rcname", newword(argv[0], (word *)0));
i = 0; i = 0;
memset(bootstrap, 0, sizeof bootstrap);
bootstrap[i++].i = 1; bootstrap[i++].i = 1;
bootstrap[i++].f = Xmark; bootstrap[i++].f = Xmark;
bootstrap[i++].f = Xword; bootstrap[i++].f = Xword;
@ -187,8 +200,9 @@ main(int argc, char *argv[])
start(bootstrap, 1, (var *)0); start(bootstrap, 1, (var *)0);
/* prime bootstrap argv */ /* prime bootstrap argv */
pushlist(); pushlist();
argv0 = strdup(argv[0]); argv0 = estrdup(argvcopy[0]);
for(i = argc-1;i!=0;--i) pushword(argv[i]); for(i = argc-1; i != 0; --i)
pushword(argv[i]);
for(;;){ for(;;){
if(flag['r']) if(flag['r'])
pfnc(err, runq); pfnc(err, runq);
@ -207,7 +221,7 @@ main(int argc, char *argv[])
* Xappend(file)[fd] open file to append * Xappend(file)[fd] open file to append
* Xassign(name, val) assign val to name * Xassign(name, val) assign val to name
* Xasync{... Xexit} make thread for {}, no wait * Xasync{... Xexit} make thread for {}, no wait
* Xbackq{... Xreturn} make thread for {}, push stdout * Xbackq(split){... Xreturn} make thread for {}, push stdout
* Xbang complement condition * Xbang complement condition
* Xcase(pat, value){...} exec code on match, leave (value) on * Xcase(pat, value){...} exec code on match, leave (value) on
* stack * stack
@ -215,18 +229,15 @@ main(int argc, char *argv[])
* Xconc(left, right) concatenate, push results * Xconc(left, right) concatenate, push results
* Xcount(name) push var count * Xcount(name) push var count
* Xdelfn(name) delete function definition * Xdelfn(name) delete function definition
* Xdelhere * Xdeltraps(names) delete named traps
* Xdol(name) get variable value * Xdol(name) get variable value
* Xqdol(name) concatenate variable components
* Xdup[i j] dup file descriptor * Xdup[i j] dup file descriptor
* Xeflag
* Xerror
* Xexit rc exits with status * Xexit rc exits with status
* 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
* Xglob * Xglobs[string globsize] push globbing string
* Xif
* Xifnot
* 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
@ -235,21 +246,16 @@ main(int argc, char *argv[])
* wait for both * wait for both
* Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
* depending on type), push /dev/fd/?? * depending on type), push /dev/fd/??
* Xpipewait
* Xpopm(value) pop value from stack * Xpopm(value) pop value from stack
* Xpopredir
* Xrdcmds
* Xrdfn
* Xrdwr(file)[fd] open file for reading and writing * Xrdwr(file)[fd] open file for reading and writing
* Xread(file)[fd] open file to read * Xread(file)[fd] open file to read
* Xqdol(name) concatenate variable components * Xsettraps(names){... Xreturn} define trap functions
* Xreturn kill thread * Xshowtraps print trap list
* Xsimple(args) run command and wait * Xsimple(args) run command and wait
* Xsub * Xreturn kill thread
* Xsubshell{... Xexit} execute {} in a subshell and wait * Xsubshell{... Xexit} execute {} in a subshell and wait
* Xtrue{...} execute {} if true * Xtrue{...} execute {} if true
* Xunlocal delete local variable * Xunlocal delete local variable
* Xwastrue
* Xword[string] push string * Xword[string] push string
* Xwrite(file)[fd] open file to write * Xwrite(file)[fd] open file to write
*/ */
@ -326,7 +332,7 @@ Xexit(void)
--runq->pc; --runq->pc;
starval = vlook("*")->val; starval = vlook("*")->val;
start(trapreq->fn, trapreq->pc, (struct var *)0); start(trapreq->fn, trapreq->pc, (struct var *)0);
runq->local = newvar(strdup("*"), runq->local); runq->local = newvar("*", runq->local);
runq->local->val = copywords(starval, (struct word *)0); runq->local->val = copywords(starval, (struct word *)0);
runq->local->changed = 1; runq->local->changed = 1;
runq->redir = runq->startredir = 0; runq->redir = runq->startredir = 0;
@ -440,7 +446,7 @@ Xpopredir(void)
runq->redir = rp->next; runq->redir = rp->next;
if(rp->type==ROPEN) if(rp->type==ROPEN)
close(rp->from); close(rp->from);
efree((char *)rp); free(rp);
} }
void void
@ -451,7 +457,7 @@ Xreturn(void)
while(p->argv) poplist(); while(p->argv) poplist();
codefree(p->code); codefree(p->code);
runq = p->ret; runq = p->ret;
efree((char *)p); free(p);
if(runq==0) if(runq==0)
Exit(getstatus()); Exit(getstatus());
} }
@ -483,6 +489,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)
{ {
@ -541,7 +554,7 @@ Xmatch(void)
setstatus(""); setstatus("");
break; break;
} }
efree(subject); free(subject);
poplist(); poplist();
poplist(); poplist();
} }
@ -559,7 +572,7 @@ Xcase(void)
break; break;
} }
} }
efree(s); free(s);
if(ok) if(ok)
runq->pc++; runq->pc++;
else else
@ -570,16 +583,25 @@ Xcase(void)
word* word*
conclist(word *lp, word *rp, word *tail) conclist(word *lp, word *rp, word *tail)
{ {
char *buf; word *v, *p, **end;
word *v; int ln, rn;
if(lp->next || rp->next)
tail = conclist(lp->next==0? lp: lp->next, for(end = &v;;){
rp->next==0? rp: rp->next, tail); ln = strlen(lp->word), rn = strlen(rp->word);
buf = emalloc(strlen(lp->word)+strlen((char *)rp->word)+1); p = Newword(emalloc(ln+rn+1), (word *)0);
strcpy(buf, lp->word); memmove(p->word, lp->word, ln);
strcat(buf, rp->word); memmove(p->word+ln, rp->word, rn+1);
v = newword(buf, tail); if(lp->glob || rp->glob)
efree(buf); p->glob = Globsize(p->word);
*end = p, end = &p->next;
if(lp->next == 0 && rp->next == 0)
break;
if(lp->next)
lp = lp->next;
if(rp->next)
rp = rp->next;
}
*end = tail;
return v; return v;
} }
@ -606,6 +628,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)
{ {
@ -614,12 +647,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();
@ -648,8 +679,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;
@ -669,35 +699,17 @@ Xdol(void)
void void
Xqdol(void) Xqdol(void)
{ {
word *a, *p; word *a;
char *s; char *s;
int n;
if(count(runq->argv->words)!=1){ if(count(runq->argv->words)!=1){
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();
n = count(a); Pushword(list2str(a));
if(n==0){
pushword("");
return;
}
for(p = a;p;p = p->next) n+=strlen(p->word);
s = emalloc(n);
if(a){
strcpy(s, a->word);
for(p = a->next;p;p = p->next){
strcat(s, " ");
strcat(s, p->word);
}
}
else
s[0]='\0';
pushword(s);
efree(s);
} }
word* word*
@ -724,8 +736,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')
@ -757,8 +768,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);
@ -801,11 +811,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(strdup(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();
@ -820,9 +828,9 @@ Xunlocal(void)
runq->local = v->next; runq->local = v->next;
hid = vlook(v->name); hid = vlook(v->name);
hid->changed = 1; hid->changed = 1;
efree(v->name); free(v->name);
freewords(v->val); freewords(v->val);
efree((char *)v); free(v);
} }
void void
@ -830,9 +838,9 @@ freewords(word *w)
{ {
word *nw; word *nw;
while(w){ while(w){
efree(w->word); free(w->word);
nw = w->next; nw = w->next;
efree((char *)w); free(w);
w = nw; w = nw;
} }
} }
@ -844,8 +852,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);
@ -921,7 +928,7 @@ Xrdcmds(void)
if(yyparse()){ if(yyparse()){
if(!p->iflag || p->eof && !Eintr()){ if(!p->iflag || p->eof && !Eintr()){
if(p->cmdfile) if(p->cmdfile)
efree(p->cmdfile); free(p->cmdfile);
closeio(p->cmdfd); closeio(p->cmdfd);
Xreturn(); /* should this be omitted? */ Xreturn(); /* should this be omitted? */
} }
@ -1014,5 +1021,5 @@ Xfor(void)
void void
Xglob(void) Xglob(void)
{ {
globlist(); globlist(runq->argv->words);
} }

View File

@ -16,7 +16,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);
@ -29,6 +29,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;
@ -76,7 +77,6 @@ struct builtin{
}; };
extern struct builtin Builtin[]; extern struct builtin Builtin[];
int eflagok; /* kludge flag so that -e doesn't exit in startup */ int eflagok; /* kludge flag so that -e doesn't exit in startup */
int havefork;
void execcd(void), execwhatis(void), execeval(void), execexec(void); void execcd(void), execwhatis(void), execeval(void), execexec(void);
int execforkexec(void); int execforkexec(void);

View File

@ -19,18 +19,17 @@ void Exit(char*);
int ForkExecute(char*, char**, int, int, int); int ForkExecute(char*, char**, int, int, int);
int Globsize(char*); int Globsize(char*);
int Isatty(int); int Isatty(int);
void Memcpy(void*, void*, int32_t);
void Noerror(void); void Noerror(void);
int Opendir(char*); int Opendir(char*);
int32_t Read(int, void*, int32_t); int Read(int, void*, int);
int Readdir(int, void*, int); int Readdir(int, void*, int);
int32_t Seek(int, int32_t, int32_t); int Seek(int, int, int);
void Trapinit(void); void Trapinit(void);
void Unlink(char*); void Unlink(char*);
void Updenv(void); void Updenv(void);
void Vinit(void); void Vinit(void);
int Waitfor(int, int); int Waitfor(int, int);
int32_t Write(int, void*, int32_t); int Write(int, void*, int);
void addwaitpid(int); void addwaitpid(int);
int advance(void); int advance(void);
int back(int); int back(int);
@ -39,19 +38,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*, int32_t); void inttoascii(char*, int);
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);
@ -61,7 +59,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*);

View File

@ -10,22 +10,22 @@
#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 int
@ -45,23 +45,33 @@ globsort(word *left, word *right)
for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word; for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
qsort((void *)list, n, sizeof(void *), globcmp); qsort((void *)list, n, sizeof(void *), globcmp);
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); free(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(uint8_t *p, uint8_t *namep) matchfn(char *s, char *p)
{ {
uint8_t *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){
@ -76,64 +86,63 @@ globdir(uint8_t *p, uint8_t *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, AEXIST)==0) if(access(name, AEXIST)==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)
{ {
uint8_t *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);
free(name);
if(left == right) {
deglob(w->word);
w->glob = 0;
} else {
free(w->word);
globsort(left, right);
*w = *left;
free(left);
} }
globname = emalloc(globlen);
globname[0]='\0';
globdir(p, (uint8_t *)globname);
efree(globname);
if(svglobv==globv){
deglob(p);
globv = newword((char *)p, globv);
}
else
globsort(globv, svglobv);
} }
/* word*
* Do p and q point at equal utf codes globlist(word *l)
*/
int
equtf(uint8_t *p, uint8_t *q)
{ {
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;
} }
/* /*
@ -141,49 +150,43 @@ equtf(uint8_t *p, uint8_t *q)
* not jumping past nuls in broken utf codes! * not jumping past nuls in broken utf codes!
*/ */
uint8_t* static char*
nextutf(uint8_t *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(uint8_t *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)
{ {
uint8_t *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;
uint8_t *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){
@ -242,27 +245,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;
}
}

View File

@ -12,9 +12,6 @@
#include "exec.h" #include "exec.h"
#include "io.h" #include "io.h"
#include "fns.h" #include "fns.h"
#include <String.h>
int havefork = 1;
void void
Xasync(void) Xasync(void)
@ -22,10 +19,12 @@ Xasync(void)
int null = open("/dev/null", OREAD); int null = open("/dev/null", OREAD);
int pid; int pid;
char npid[10]; char npid[10];
if(null<0){ if(null<0){
Xerror("Can't open /dev/null\n"); Xerror("Can't open /dev/null\n");
return; return;
} }
Updenv();
switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){ switch(pid = rfork(RFFDG|RFPROC|RFNOTEG)){
case -1: case -1:
close(null); close(null);
@ -55,10 +54,12 @@ Xpipe(void)
int lfd = p->code[pc++].i; int lfd = p->code[pc++].i;
int rfd = p->code[pc++].i; int rfd = p->code[pc++].i;
int pfd[2]; int pfd[2];
if(pipe(pfd)<0){ if(pipe(pfd)<0){
Xerror("can't get pipe"); Xerror("can't get pipe");
return; return;
} }
Updenv();
switch(forkid = fork()){ switch(forkid = fork()){
case -1: case -1:
Xerror("try again"); Xerror("try again");
@ -84,25 +85,25 @@ Xpipe(void)
/* /*
* Who should wait for the exit from the fork? * Who should wait for the exit from the fork?
*/ */
enum { Stralloc = 100, };
void void
Xbackq(void) Xbackq(void)
{ {
int n, pid; int c, l, pid;
int pfd[2]; int pfd[2];
char *stop; char *s, *wd, *ewd, *stop;
char utf[UTFmax+1];
struct io *f; struct io *f;
var *ifs = vlook("ifs");
word *v, *nextv; word *v, *nextv;
Rune r;
String *word;
stop = ifs->val? ifs->val->word: ""; stop = "";
if(runq->argv && runq->argv->words)
stop = runq->argv->words->word;
if(pipe(pfd)<0){ if(pipe(pfd)<0){
Xerror("can't make pipe"); Xerror("can't make pipe");
return; return;
} }
Updenv();
switch(pid = fork()){ switch(pid = fork()){
case -1: case -1:
Xerror("try again"); Xerror("try again");
@ -119,28 +120,32 @@ Xbackq(void)
addwaitpid(pid); addwaitpid(pid);
close(pfd[PWR]); close(pfd[PWR]);
f = openfd(pfd[PRD]); f = openfd(pfd[PRD]);
word = s_new(); s = wd = ewd = 0;
v = nil; v = 0;
/* rutf requires at least UTFmax+1 bytes in utf */ while((c = rchr(f))!=EOF){
while((n = rutf(f, utf, &r)) != EOF){ if(s==ewd){
utf[n] = '\0'; l = s-wd;
if(utfutf(stop, utf) == nil) wd = erealloc(wd, l+Stralloc);
s_nappend(word, utf, n); ewd = wd+l+Stralloc-1;
else s = wd+l;
/* }
* utf/r is an ifs rune (e.g., \t, \n), thus if(strchr(stop, c)){
* ends the current word, if any. if(s!=wd){
*/ *s='\0';
if(s_len(word) > 0){ v = newword(wd, v);
v = newword(s_to_c(word), v); s = wd;
s_reset(word);
} }
}
else *s++=c;
} }
if(s_len(word) > 0) if(s!=wd){
v = newword(s_to_c(word), v); *s='\0';
s_free(word); v = newword(wd, v);
}
free(wd);
closeio(f); closeio(f);
Waitfor(pid, 0); Waitfor(pid, 0);
poplist(); /* ditch split in "stop" */
/* v points to reversed arglist -- reverse it onto argv */ /* v points to reversed arglist -- reverse it onto argv */
while(v){ while(v){
nextv = v->next; nextv = v->next;
@ -161,6 +166,7 @@ Xpipefd(void)
char name[40]; char name[40];
int pfd[2]; int pfd[2];
int sidefd, mainfd; int sidefd, mainfd;
if(pipe(pfd)<0){ if(pipe(pfd)<0){
Xerror("can't get pipe"); Xerror("can't get pipe");
return; return;
@ -173,6 +179,7 @@ Xpipefd(void)
sidefd = pfd[PRD]; sidefd = pfd[PRD];
mainfd = pfd[PWR]; mainfd = pfd[PWR];
} }
Updenv();
switch(pid = fork()){ switch(pid = fork()){
case -1: case -1:
Xerror("try again"); Xerror("try again");
@ -200,6 +207,8 @@ void
Xsubshell(void) Xsubshell(void)
{ {
int pid; int pid;
Updenv();
switch(pid = fork()){ switch(pid = fork()){
case -1: case -1:
Xerror("try again"); Xerror("try again");

View File

@ -1,220 +0,0 @@
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#include "rc.h"
#include "getflags.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
int havefork = 0;
static char **
rcargv(char *s)
{
int argc;
char **argv;
word *p;
p = vlook("*")->val;
argv = emalloc((count(p)+6)*sizeof(char*));
argc = 0;
argv[argc++] = argv0;
if(flag['e'])
argv[argc++] = "-Se";
else
argv[argc++] = "-S";
argv[argc++] = "-c";
argv[argc++] = s;
for(p = vlook("*")->val; p; p = p->next)
argv[argc++] = p->word;
argv[argc] = 0;
return argv;
}
void
Xasync(void)
{
uint32_t pid;
char buf[20], **argv;
Updenv();
argv = rcargv(runq->code[runq->pc].s);
pid = ForkExecute(argv0, argv, -1, 1, 2);
free(argv);
if(pid == 0) {
Xerror("proc failed");
return;
}
runq->pc++;
sprint(buf, "%d", pid);
setvar("apid", newword(buf, (word *)0));
}
void
Xbackq(void)
{
char wd[8193], **argv;
int c;
char *s, *ewd=&wd[8192], *stop;
struct io *f;
var *ifs = vlook("ifs");
word *v, *nextv;
int pfd[2];
int pid;
stop = ifs->val?ifs->val->word:"";
if(pipe(pfd)<0){
Xerror("can't make pipe");
return;
}
Updenv();
argv = rcargv(runq->code[runq->pc].s);
pid = ForkExecute(argv0, argv, -1, pfd[1], 2);
free(argv);
close(pfd[1]);
if(pid == 0) {
Xerror("proc failed");
close(pfd[0]);
return;
}
f = openfd(pfd[0]);
s = wd;
v = 0;
while((c=rchr(f))!=EOF){
if(strchr(stop, c) || s==ewd){
if(s!=wd){
*s='\0';
v=newword(wd, v);
s=wd;
}
}
else *s++=c;
}
if(s!=wd){
*s='\0';
v=newword(wd, v);
}
closeio(f);
Waitfor(pid, 1);
/* v points to reversed arglist -- reverse it onto argv */
while(v){
nextv=v->next;
v->next=runq->argv->words;
runq->argv->words=v;
v=nextv;
}
runq->pc++;
}
void
Xpipe(void)
{
thread *p=runq;
int pc=p->pc, pid;
int rfd=p->code[pc+1].i;
int pfd[2];
char **argv;
if(pipe(pfd)<0){
Xerror1("can't get pipe");
return;
}
Updenv();
argv = rcargv(runq->code[pc+2].s);
pid = ForkExecute(argv0, argv, 0, pfd[1], 2);
free(argv);
close(pfd[1]);
if(pid == 0) {
Xerror("proc failed");
close(pfd[0]);
return;
}
start(p->code, pc+4, runq->local);
pushredir(ROPEN, pfd[0], rfd);
p->pc=p->code[pc+3].i;
p->pid=pid;
}
void
Xpipefd(void)
{
Abort();
}
void
Xsubshell(void)
{
char **argv;
int pid;
Updenv();
argv = rcargv(runq->code[runq->pc].s);
pid = ForkExecute(argv0, argv, -1, 1, 2);
free(argv);
if(pid < 0) {
Xerror("proc failed");
return;
}
Waitfor(pid, 1);
runq->pc++;
}
/*
* start a process running the cmd on the stack and return its pid.
*/
int
execforkexec(void)
{
char **argv;
char file[1024];
int nc;
word *path;
int pid;
if(runq->argv->words==0)
return -1;
argv = mkargv(runq->argv->words);
for(path = searchpath(runq->argv->words->word);path;path = path->next){
nc = strlen(path->word);
if(nc < sizeof file - 1){ /* 1 for / */
strcpy(file, path->word);
if(file[0]){
strcat(file, "/");
nc++;
}
if(nc+strlen(argv[1])<sizeof(file)){
strcat(file, argv[1]);
pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2));
if(pid >= 0){
free(argv);
return pid;
}
}
}
}
free(argv);
return -1;
}

View File

@ -14,8 +14,8 @@
struct here *here, **ehere; struct here *here, **ehere;
int ser = 0; int ser = 0;
char tmp[] = "/tmp/here0000.0000"; char tmp[]="/tmp/here0000.0000";
char hex[] = "0123456789abcdef"; char hex[]="0123456789abcdef";
void psubst(io*, uint8_t*); void psubst(io*, uint8_t*);
void pstrs(io*, word*); void pstrs(io*, word*);
@ -45,7 +45,7 @@ heredoc(tree *tag)
h->tag = tag; h->tag = tag;
hexnum(&tmp[9], getpid()); hexnum(&tmp[9], getpid());
hexnum(&tmp[14], ser++); hexnum(&tmp[14], ser++);
h->name = strdup(tmp); h->name = estrdup(tmp);
return token(tmp, WORD); return token(tmp, WORD);
} }
@ -58,25 +58,24 @@ heredoc(tree *tag)
void void
readhere(void) readhere(void)
{ {
int c, subst;
char *s, *tag;
char line[NLINE+1];
io *f;
struct here *h, *nexth; struct here *h, *nexth;
io *f;
for(h = here; h; h = nexth){ char *s, *tag;
subst = !h->tag->quoted; int c, subst;
char line[NLINE+1];
for(h = here;h;h = nexth){
subst=!h->tag->quoted;
tag = h->tag->str; tag = h->tag->str;
c = Creat(h->name); c = Creat(h->name);
if(c < 0) if(c<0)
yyerror("can't create here document"); yyerror("can't create here document");
f = openfd(c); f = openfd(c);
s = line; s = line;
pprompt(); pprompt();
while((c = rchr(runq->cmdfd)) != EOF){ while((c = rchr(runq->cmdfd)) != EOF){
if(c == '\n' || s == &line[NLINE]){ if(c == '\n' || s == &line[NLINE]){
*s = '\0'; *s='\0';
if(tag && strcmp(line, tag) == 0) if(tag && strcmp(line, tag)==0)
break; break;
if(subst) if(subst)
psubst(f, (uint8_t *)line); psubst(f, (uint8_t *)line);
@ -95,7 +94,7 @@ readhere(void)
closeio(f); closeio(f);
cleanhere(h->name); cleanhere(h->name);
nexth = h->next; nexth = h->next;
efree((char *)h); free(h);
} }
here = 0; here = 0;
doprompt = 1; doprompt = 1;
@ -106,19 +105,26 @@ psubst(io *f, uint8_t *s)
{ {
int savec, n; int savec, n;
uint8_t *t, *u; uint8_t *t, *u;
Rune r;
word *star; word *star;
while(*s){ while(*s){
if(*s != '$'){ /* copy plain text rune */ if(*s != '$'){
if(*s < Runeself) if(0xa0 <= *s && *s <= 0xf5){
pchr(f, *s++); pchr(f, *s++);
else{ if(*s == '\0')
n = chartorune(&r, (char *)s); break;
while(n-- > 0)
pchr(f, *s++);
} }
}else{ /* $something -- perform substitution */ else if(0xf6 <= *s && *s <= 0xf7){
pchr(f, *s++);
if(*s == '\0')
break;
pchr(f, *s++);
if(*s == '\0')
break;
}
pchr(f, *s++);
}
else{
t = ++s; t = ++s;
if(*t == '$') if(*t == '$')
pchr(f, *t++); pchr(f, *t++);
@ -130,14 +136,15 @@ psubst(io *f, uint8_t *s)
n = 0; n = 0;
for(u = s; *u && '0' <= *u && *u <= '9'; u++) for(u = s; *u && '0' <= *u && *u <= '9'; u++)
n = n*10 + *u - '0'; n = n*10 + *u - '0';
if(n && *u == '\0'){ if(n && *u=='\0'){
star = vlook("*")->val; star = vlook("*")->val;
if(star && 1 <= n && n <= count(star)){ if(star && 1 <= n && n <= count(star)){
while(--n) while(--n)
star = star->next; star = star->next;
pstr(f, star->word); pstr(f, star->word);
} }
}else }
else
pstrs(f, vlook((char *)s)->val); pstrs(f, vlook((char *)s)->val);
*t = savec; *t = savec;
if(savec == '^') if(savec == '^')

View File

@ -88,35 +88,6 @@ rchr(io *b)
return *b->bufp++; return *b->bufp++;
} }
int
rutf(io *b, char *buf, Rune *r)
{
int n, i, c;
c = rchr(b);
if(c == EOF)
return EOF;
*buf = c;
if(c < Runesync){
*r = c;
return 1;
}
for(i = 1; (c = rchr(b)) != EOF; ){
buf[i++] = c;
buf[i] = 0;
if(fullrune(buf, i)){
n = chartorune(r, buf);
b->bufp -= i - n; /* push back unconsumed bytes */
assert(b->fd == -1 || b->bufp > b->buf);
return n;
}
}
/* at eof */
b->bufp -= i - 1; /* consume 1 byte */
*r = Runeerror;
return runetochar(buf, r);
}
void void
pquo(io *f, char *s) pquo(io *f, char *s)
{ {
@ -216,9 +187,7 @@ flush(io *f)
if(f->strp){ if(f->strp){
n = f->ebuf - f->strp; n = f->ebuf - f->strp;
f->strp = realloc(f->strp, n+Stralloc+1); f->strp = erealloc(f->strp, n+Stralloc+1);
if(f->strp==0)
panic("Can't realloc %d bytes in flush!", n+Stralloc+1);
f->bufp = f->strp + n; f->bufp = f->strp + n;
f->ebuf = f->bufp + Stralloc; f->ebuf = f->bufp + Stralloc;
memset(f->bufp, '\0', Stralloc+1); memset(f->bufp, '\0', Stralloc+1);
@ -270,7 +239,7 @@ opencore(char *s, int len)
f->fd = -1 /*open("/dev/null", OREAD)*/; f->fd = -1 /*open("/dev/null", OREAD)*/;
f->bufp = f->strp = buf; f->bufp = f->strp = buf;
f->ebuf = buf+len; f->ebuf = buf+len;
Memcpy(buf, s, len); memmove(buf, s, len);
return f; return f;
} }
@ -288,11 +257,11 @@ rewind(io *io)
void void
closeio(io *io) closeio(io *io)
{ {
if(io->fd>=0) if(io->fd >= 0)
close(io->fd); close(io->fd);
if(io->strp) if(io->strp)
efree(io->strp); free(io->strp);
efree(io); free(io);
} }
int int

View File

@ -21,7 +21,6 @@ io *openfd(int), *openstr(void), *opencore(char *, int);
int emptybuf(io*); int emptybuf(io*);
void pchr(io*, int); void pchr(io*, int);
int rchr(io*); int rchr(io*);
int rutf(io*, char*, Rune*);
void closeio(io*); void closeio(io*);
void flush(io*); void flush(io*);
int fullbuf(io*, int); int fullbuf(io*, int);

View File

@ -101,6 +101,16 @@ pprompt(void)
if(runq->iflag){ if(runq->iflag){
pstr(err, promptstr); pstr(err, promptstr);
flush(err); flush(err);
if(newwdir){
char dir[4096];
int fd;
if((fd=open("/dev/wdir", OWRITE))>=0){
getwd(dir, sizeof(dir));
write(fd, dir, strlen(dir));
close(fd);
}
newwdir = 0;
}
prompt = vlook("prompt"); prompt = vlook("prompt");
if(prompt->val && prompt->val->next) if(prompt->val && prompt->val->next)
promptstr = prompt->val->next->word; promptstr = prompt->val->next->word;
@ -163,7 +173,7 @@ addtok(char *p, int val)
{ {
if(p==0) if(p==0)
return 0; return 0;
if(p >= &tok[NTOK]){ if(p == &tok[NTOK-1]){
*p = 0; *p = 0;
yyerror("token buffer too short"); yyerror("token buffer too short");
return 0; return 0;
@ -179,7 +189,7 @@ addutf(char *p, int c)
int i; int i;
p = addtok(p, c); /* 1-byte UTF runes are special */ p = addtok(p, c); /* 1-byte UTF runes are special */
if(c < Runeself) if(onebyte(c))
return p; return p;
m = 0xc0; m = 0xc0;

View File

@ -30,7 +30,6 @@ pcmd(io *f, tree *t)
{ {
if(t==0) if(t==0)
return; return;
assert(f != nil);
switch(t->type){ switch(t->type){
default: pfmt(f, "bad cmd %d %p %p %p", t->type, c0, c1, c2); default: pfmt(f, "bad cmd %d %p %p %p", t->type, c0, c1, c2);
break; break;
@ -42,7 +41,7 @@ pcmd(io *f, tree *t)
break; break;
case '^': pfmt(f, "%t^%t", c0, c1); case '^': pfmt(f, "%t^%t", c0, c1);
break; break;
case '`': pfmt(f, "`%t", c0); case '`': pfmt(f, "`%t%t", c0, c1);
break; break;
case ANDAND: pfmt(f, "%t && %t", c0, c1); case ANDAND: pfmt(f, "%t && %t", c0, c1);
break; break;

View File

@ -17,52 +17,51 @@ struct{
char *name; char *name;
} fname[] = { } fname[] = {
Xappend, "Xappend", Xappend, "Xappend",
Xassign, "Xassign",
Xasync, "Xasync", Xasync, "Xasync",
Xbackq, "Xbackq",
Xbang, "Xbang", Xbang, "Xbang",
Xcase, "Xcase",
Xclose, "Xclose", Xclose, "Xclose",
Xconc, "Xconc",
Xcount, "Xcount",
Xdelfn, "Xdelfn",
Xdelhere, "Xdelhere",
Xdol, "Xdol",
Xdup, "Xdup", Xdup, "Xdup",
Xeflag, "Xeflag", Xeflag, "Xeflag",
(void (*)(void))Xerror, "Xerror",
Xexit, "Xexit", Xexit, "Xexit",
Xfalse, "Xfalse", Xfalse, "Xfalse",
Xfn, "Xfn",
Xfor, "Xfor",
Xglob, "Xglob",
Xif, "Xif",
Xifnot, "Xifnot", Xifnot, "Xifnot",
Xjump, "Xjump", Xjump, "Xjump",
Xlocal, "Xlocal",
Xmark, "Xmark", Xmark, "Xmark",
Xmatch, "Xmatch",
Xpipe, "Xpipe",
Xpipefd, "Xpipefd",
Xpipewait, "Xpipewait",
Xpopm, "Xpopm", Xpopm, "Xpopm",
Xpopredir, "Xpopredir",
Xqdol, "Xqdol",
Xrdcmds, "Xrdcmds",
Xrdfn, "Xrdfn",
Xrdwr, "Xrdwr", Xrdwr, "Xrdwr",
Xread, "Xread", Xread, "Xread",
Xreturn, "Xreturn", Xreturn, "Xreturn",
Xsimple, "Xsimple",
Xsub, "Xsub",
Xsubshell, "Xsubshell",
Xtrue, "Xtrue", Xtrue, "Xtrue",
Xunlocal, "Xunlocal", Xif, "Xif",
Xwastrue, "Xwastrue", Xwastrue, "Xwastrue",
Xword, "Xword", Xword, "Xword",
Xwrite, "Xwrite", Xwrite, "Xwrite",
0 Xmatch, "Xmatch",
}; Xcase, "Xcase",
Xconc, "Xconc",
Xassign, "Xassign",
Xdol, "Xdol",
Xcount, "Xcount",
Xlocal, "Xlocal",
Xunlocal, "Xunlocal",
Xfn, "Xfn",
Xdelfn, "Xdelfn",
Xpipe, "Xpipe",
Xpipewait, "Xpipewait",
Xpopredir, "Xpopredir",
Xrdcmds, "Xrdcmds",
(void (*)(void))Xerror, "Xerror",
Xbackq, "Xbackq",
Xpipefd, "Xpipefd",
Xsubshell, "Xsubshell",
Xdelhere, "Xdelhere",
Xfor, "Xfor",
Xglob, "Xglob",
Xglobs, "Xglobs",
Xrdfn, "Xrdfn",
Xsimple, "Xsimple",
Xqdol, "Xqdol",
0};
void void
pfnc(io *fd, thread *t) pfnc(io *fd, thread *t)
@ -72,14 +71,14 @@ pfnc(io *fd, thread *t)
list *a; list *a;
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc); pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
for (i = 0; fname[i].f; i++) for(i = 0; fname[i].f; i++)
if (fname[i].f == fn) { if(fname[i].f == fn){
pstr(fd, fname[i].name); pstr(fd, fname[i].name);
break; break;
} }
if (!fname[i].f) if(!fname[i].f)
pfmt(fd, "%p", fn); pfmt(fd, "%p", fn);
for (a = t->argv; a; a = a->next) for(a = t->argv; a; a = a->next)
pfmt(fd, " (%v)", a->words); pfmt(fd, " (%v)", a->words);
pchr(fd, '\n'); pchr(fd, '\n');
flush(fd); flush(fd);

View File

@ -19,7 +19,7 @@
#include "getflags.h" #include "getflags.h"
enum { enum {
Maxenvname = 256, /* undocumented limit */ Maxenvname = 128, /* undocumented limit */
}; };
char *Signame[] = { char *Signame[] = {
@ -155,7 +155,7 @@ Vinit(void)
setvar(ent[i].name, val); setvar(ent[i].name, val);
vlook(ent[i].name)->changed = 0; vlook(ent[i].name)->changed = 0;
close(f); close(f);
efree(buf); free(buf);
} }
} }
} }
@ -163,42 +163,21 @@ Vinit(void)
} }
close(dir); close(dir);
} }
int envdir;
void void
Xrdfn(void) Xrdfn(void)
{ {
int f, len; if(runq->argv->words == 0)
Dir *e; poplist();
char envname[Maxenvname]; else {
static Dir *ent, *allocent; int f = open(runq->argv->words->word, OREAD);
static int nent; popword();
runq->pc--;
for(;;){ if(f >= 0)
if(nent == 0){ execcmds(openfd(f));
free(allocent);
nent = dirread(envdir, &allocent);
ent = allocent;
}
if(nent <= 0)
break;
while(nent){
e = ent++;
nent--;
len = e->length;
if(len && strncmp(e->name, "fn#", 3)==0){
snprint(envname, sizeof envname, "/env/%s", e->name);
if((f = open(envname, OREAD))>=0){
execcmds(openfd(f));
return;
}
}
}
} }
close(envdir);
Xreturn();
} }
union code rdfns[4]; union code rdfns[8];
void void
execfinit(void) execfinit(void)
@ -206,17 +185,15 @@ execfinit(void)
static int first = 1; static int first = 1;
if(first){ if(first){
rdfns[0].i = 1; rdfns[0].i = 1;
rdfns[1].f = Xrdfn; rdfns[1].f = Xmark;
rdfns[2].f = Xjump; rdfns[2].f = Xglobs;
rdfns[3].i = 1; rdfns[4].i = Globsize(rdfns[3].s = "/env/fn#\001*");
rdfns[5].f = Xglob;
rdfns[6].f = Xrdfn;
rdfns[7].f = Xreturn;
first = 0; first = 0;
} }
Xpopm(); poplist();
envdir = open("/env", OREAD);
if(envdir<0){
pfmt(err, "rc: can't open /env: %r\n");
return;
}
start(rdfns, 1, runq->local); start(rdfns, 1, runq->local);
} }
@ -284,12 +261,10 @@ addenv(var *v)
if((f = Creat(envname))<0) if((f = Creat(envname))<0)
pfmt(err, "rc: can't open %s: %r\n", envname); pfmt(err, "rc: can't open %s: %r\n", envname);
else{ else{
if(v->fn){ fd = openfd(f);
fd = openfd(f); if(v->fn)
pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s); pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
closeio(fd); closeio(fd);
}
close(f);
} }
} }
} }
@ -318,71 +293,35 @@ Updenv(void)
int int
ForkExecute(char *file, char **argv, int sin, int sout, int serr) ForkExecute(char *file, char **argv, int sin, int sout, int serr)
{ {
int pid; return -1;
if(access(file, AEXEC) != 0)
return -1;
switch(pid = fork()){
case -1:
return -1;
case 0:
if(sin >= 0)
dup(sin, 0);
else
close(0);
if(sout >= 0)
dup(sout, 1);
else
close(1);
if(serr >= 0)
dup(serr, 2);
else
close(2);
exec(file, argv);
exits(file);
}
return pid;
} }
void void
Execute(word *args, word *path) Execute(word *args, word *path)
{ {
char **argv = mkargv(args); char **argv = mkargv(args);
char file[1024], errstr[1024]; char file[1024];
int nc; int nc, mc;
Updenv(); Updenv();
errstr[0] = '\0'; mc = strlen(argv[1])+1;
for(;path;path = path->next){ for(;path;path = path->next){
nc = strlen(path->word); nc = strlen(path->word);
if(nc < sizeof file - 1){ /* 1 for / */ if(nc + mc >= sizeof file - 1){ /* 1 for / */
strcpy(file, path->word); werrstr("command path name too long");
if(file[0]){ continue;
strcat(file, "/");
nc++;
}
if(nc + strlen(argv[1]) < sizeof file){
strcat(file, argv[1]);
exec(file, argv+1);
rerrstr(errstr, sizeof errstr);
/*
* if file exists and is executable, exec should
* have worked, unless it's a directory or an
* executable for another architecture. in
* particular, if it failed due to lack of
* swap/vm (e.g., arg. list too long) or other
* allocation failure, stop searching and print
* the reason for failure.
*/
if (strstr(errstr, " allocat") != nil ||
strstr(errstr, " full") != nil)
break;
}
else werrstr("command name too long");
} }
if(nc > 0){
memmove(file, path->word, nc);
file[nc++] = '/';
}
memmove(file+nc, argv[1], mc);
exec(file, argv+1);
} }
pfmt(err, "%s: %s\n", argv[1], errstr); rerrstr(file, sizeof file);
efree((char *)argv); setstatus(file);
pfmt(err, "%s: %s\n", argv[1], file);
free(argv);
} }
#define NDIR 256 /* shoud be a better way */ #define NDIR 256 /* shoud be a better way */
@ -475,7 +414,7 @@ Again:
} }
if(dir[f].i == dir[f].n) if(dir[f].i == dir[f].n)
return 0; return 0;
strcpy(p, dir[f].dbuf[dir[f].i].name); strncpy((char*)p, dir[f].dbuf[dir[f].i].name, NDIR);
dir[f].i++; dir[f].i++;
return 1; return 1;
} }
@ -527,20 +466,20 @@ Unlink(char *name)
remove(name); remove(name);
} }
int32_t int
Write(int fd, void *buf, int32_t cnt) Write(int fd, void *buf, int cnt)
{ {
return write(fd, buf, cnt); return write(fd, buf, cnt);
} }
int32_t int
Read(int fd, void *buf, int32_t cnt) Read(int fd, void *buf, int cnt)
{ {
return read(fd, buf, cnt); return read(fd, buf, cnt);
} }
int32_t int
Seek(int fd, int32_t cnt, int32_t whence) Seek(int fd, int cnt, int whence)
{ {
return seek(fd, cnt, whence); return seek(fd, cnt, whence);
} }
@ -621,27 +560,13 @@ Abort(void)
Exit("aborting"); Exit("aborting");
} }
void
Memcpy(void *a, void *b, int32_t n)
{
memmove(a, b, n);
}
void*
Malloc(uint32_t n)
{
return mallocz(n, 1);
}
int *waitpids; int *waitpids;
int nwaitpids; int nwaitpids;
void void
addwaitpid(int pid) addwaitpid(int pid)
{ {
waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]); waitpids = erealloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
if(waitpids == 0)
panic("Can't realloc %d waitpids", nwaitpids+1);
waitpids[nwaitpids++] = pid; waitpids[nwaitpids++] = pid;
} }

View File

@ -6,14 +6,6 @@
* modified, propagated, or distributed except according to the terms contained * modified, propagated, or distributed except according to the terms contained
* in the LICENSE file. * in the LICENSE file.
*/ */
/*
* Assume plan 9 by default; if Unix is defined, assume unix.
* Please don't litter the code with ifdefs. The five below should be enough.
*/
#ifndef Unix
/* plan 9 */
#include <u.h> #include <u.h>
#include <lib9.h> #include <lib9.h>
@ -21,18 +13,6 @@
#define SIGINT 2 #define SIGINT 2
#define SIGQUIT 3 #define SIGQUIT 3
#define fcntl(fd, op, arg) /* unix compatibility */
#define F_SETFD
#define FD_CLOEXEC
#define YYSIZE_T size_t /* GNU Bison/yacc has hundred of types :( */
#else
#include "unix.h"
#endif
#ifndef ERRMAX
#define ERRMAX 128
#endif
#define YYMAXDEPTH 500 #define YYMAXDEPTH 500
#ifndef YYPREFIX #ifndef YYPREFIX
#ifndef PAREN #ifndef PAREN
@ -50,11 +30,6 @@ typedef struct redir redir;
typedef struct thread thread; typedef struct thread thread;
typedef struct builtin builtin; typedef struct builtin builtin;
#ifndef Unix
#pragma incomplete word
#pragma incomplete io
#endif
struct tree{ struct tree{
int type; int type;
int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */
@ -84,12 +59,13 @@ union code{
char *s; char *s;
}; };
int newwdir;
char *promptstr; char *promptstr;
int doprompt; int doprompt;
#define NTOK 8192 /* maximum bytes in a word (token) */ #define NTOK 8192 /* maximum bytes in a word (token) */
char tok[NTOK + UTFmax]; char tok[NTOK];
#define APPEND 1 #define APPEND 1
#define WRITE 2 #define WRITE 2
@ -116,9 +92,11 @@ var *gvar[NVAR]; /* hash for globals */
#define new(type) ((type *)emalloc(sizeof(type))) #define new(type) ((type *)emalloc(sizeof(type)))
void *emalloc(int32_t); void *emalloc(int);
void *Malloc(uint32_t); void *erealloc(void *, int);
void efree(void *); char *estrdup(char*);
#define NOFILE 128 /* should come from <param.h> */
struct here{ struct here{
tree *tag; tree *tag;
@ -135,7 +113,12 @@ int mypid;
* GLOB[...] matches anything in the brackets * GLOB[...] matches anything in the brackets
* GLOBGLOB matches GLOB * GLOBGLOB matches GLOB
*/ */
#define GLOB '\001' #define GLOB ((char)0x01)
/*
* onebyte(c)
* Is c the first character of a one-byte utf sequence?
*/
#define onebyte(c) ((c&0x80)==0x00)
char **argp; char **argp;
char **args; char **args;

View File

@ -1,34 +0,0 @@
# rcmain: unix version
if(~ $#home 0) home=$HOME
if(~ $#ifs 0) ifs='
'
switch($#prompt){
case 0
prompt=('% ' ' ')
case 1
prompt=($prompt ' ')
}
if(~ $rcname ?.out) prompt=('broken! ' ' ')
if(flag p) path=/cmd
if not {
finit
if(~ $#path 0) path=(. /cmd /usr/cmd /usr/local/bin)
}
fn sigexit
if(! ~ $#cflag 0){
if(flag l && test -r $home/lib/profile) . $home/lib/profile
status=''
eval $cflag
}
if not if(flag i){
if(flag l && test -r $home/lib/profile) . $home/lib/profile
status=''
if(! ~ $#* 0) . $*
. -i /dev/fd/0
}
if not if(~ $#* 0) . /dev/fd/0
if not{
status=''
. $*
}
exit $status

View File

@ -1,20 +0,0 @@
yacc -d syn.y
cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h
cc -DUnix -c -I. code.c
cc -DUnix -c -I. exec.c
cc -DUnix -c -I. getflags.c
cc -DUnix -c -I. glob.c
cc -DUnix -c -I. here.c
cc -DUnix -c -I. io.c
cc -DUnix -c -I. lex.c
cc -DUnix -c -I. pcmd.c
cc -DUnix -c -I. pfnc.c
cc -DUnix -c -I. simple.c
cc -DUnix -c -I. subr.c
cc -DUnix -c -I. trap.c
cc -DUnix -c -I. tree.c
cc -DUnix -c -I. var.c
cc -DUnix -c -I. havefork.c
cc -DUnix -c -I. unix.c
cc -DUnix -c -I. y.tab.c
cc -o rc code.o exec.o getflags.o glob.o here.o io.o lex.o pcmd.o pfnc.o simple.o subr.o trap.o tree.o var.o havefork.o unix.o y.tab.o

View File

@ -29,18 +29,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);
@ -64,7 +63,6 @@ Xsimple(void)
/* fork and wait is redundant */ /* fork and wait is redundant */
pushword("exec"); pushword("exec");
execexec(); execexec();
Xexit();
} }
else{ else{
flush(err); flush(err);
@ -129,6 +127,7 @@ execexec(void)
doredir(runq->redir); doredir(runq->redir);
Execute(runq->argv->words, searchpath(runq->argv->words->word)); Execute(runq->argv->words, searchpath(runq->argv->words->word));
poplist(); poplist();
Xexit();
} }
void void
@ -140,7 +139,7 @@ execfunc(var *func)
runq->argv->words = 0; runq->argv->words = 0;
poplist(); poplist();
start(func->fn, func->pc, runq->local); start(func->fn, func->pc, runq->local);
runq->local = newvar(strdup("*"), runq->local); runq->local = newvar("*", runq->local);
runq->local->val = starval; runq->local->val = starval;
runq->local->changed = 1; runq->local->changed = 1;
} }
@ -149,36 +148,12 @@ 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)
if(chdir(word)<0) return -1; return -1;
if(flag['i']!=0){ newwdir = 1;
if(wdirfd==-2) /* try only once */
wdirfd = open("/dev/wdir", OWRITE|OCEXEC);
if(wdirfd>=0) {
fcntl(wdirfd, F_SETFD, FD_CLOEXEC);
write(wdirfd, word, strlen(word));
}
}
return 1; return 1;
} }
static char *
appfile(char *dir, char *comp)
{
int dirlen, complen;
char *s, *p;
dirlen = strlen(dir);
complen = strlen(comp);
s = emalloc(dirlen + 1 + complen + 1);
memmove(s, dir, dirlen);
p = s + dirlen;
*p++ = '/';
memmove(p, comp, complen);
p[complen] = '\0';
return s;
}
void void
execcd(void) execcd(void)
{ {
@ -197,9 +172,10 @@ execcd(void)
cdpath = &nullpath; cdpath = &nullpath;
for(; cdpath; cdpath = cdpath->next){ for(; cdpath; cdpath = cdpath->next){
if(cdpath->word[0] != '\0') if(cdpath->word[0] != '\0')
dir = appfile(cdpath->word, a->next->word); dir = smprint("%s/%s", cdpath->word,
a->next->word);
else else
dir = strdup(a->next->word); dir = estrdup(a->next->word);
if(dochdir(dir) >= 0){ if(dochdir(dir) >= 0){
if(cdpath->word[0] != '\0' && if(cdpath->word[0] != '\0' &&
@ -261,10 +237,10 @@ execshift(void)
break; break;
} }
star = vlook("*"); star = vlook("*");
for(;n && star->val;--n){ for(;n>0 && star->val;--n){
a = star->val->next; a = star->val->next;
efree(star->val->word); free(star->val->word);
efree((char *)star->val); free(star->val);
star->val = a; star->val = a;
star->changed = 1; star->changed = 1;
} }
@ -272,15 +248,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)
{ {
@ -320,26 +287,19 @@ 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); free(cmdline);
} }
union code dotcmds[14]; union code dotcmds[14];
@ -382,14 +342,14 @@ execdot(void)
Xerror1("Usage: . [-i] file [arg ...]"); Xerror1("Usage: . [-i] file [arg ...]");
return; return;
} }
zero = strdup(p->argv->words->word); zero = estrdup(p->argv->words->word);
popword(); popword();
fd = -1; fd = -1;
for(path = searchpath(zero); path; path = path->next){ for(path = searchpath(zero); path; path = path->next){
if(path->word[0] != '\0') if(path->word[0] != '\0')
file = appfile(path->word, zero); file = smprint("%s/%s", path->word, zero);
else else
file = strdup(zero); file = estrdup(zero);
fd = open(file, OREAD); fd = open(file, OREAD);
free(file); free(file);
@ -420,7 +380,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); free(av);
/* push $0 value */ /* push $0 value */
pushlist(); pushlist();
pushword(zero); pushword(zero);
@ -469,7 +429,6 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */
return; return;
} }
setstatus(""); setstatus("");
memset(out, 0, sizeof out);
out->fd = mapfd(1); out->fd = mapfd(1);
out->bufp = out->buf; out->bufp = out->buf;
out->ebuf = &out->buf[NBUF]; out->ebuf = &out->buf[NBUF];
@ -505,10 +464,10 @@ execwhatis(void){ /* mildly wrong -- should fork before writing */
for(path = searchpath(a->word); path; for(path = searchpath(a->word); path;
path = path->next){ path = path->next){
if(path->word[0] != '\0') if(path->word[0] != '\0')
file = appfile(path->word, file = smprint("%s/%s",
a->word); path->word, a->word);
else else
file = strdup(a->word); file = estrdup(a->word);
if(Executable(file)){ if(Executable(file)){
pfmt(out, "%s\n", file); pfmt(out, "%s\n", file);
free(file); free(file);

View File

@ -13,24 +13,35 @@
#include "fns.h" #include "fns.h"
void * void *
emalloc(int32_t n) emalloc(int n)
{ {
void *p = Malloc(n); void *p = malloc(n);
if(p==0) if(p==0)
panic("Can't malloc %d bytes", n); panic("Can't malloc %d bytes", n);
/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } */
return p; return p;
} }
void void*
efree(void *p) erealloc(void *p, int n)
{ {
/* pfmt(err, "free %p\n", p); flush(err); */ p = realloc(p, n);
if(p) if(p==0 && n!=0)
free(p); panic("Can't realloc %d bytes\n", n);
else pfmt(err, "free 0\n"); return p;
} }
char*
estrdup(char *s)
{
char *d;
int n;
n = strlen(s)+1;
d = emalloc(n);
memmove(d, s, n);
return d;
}
extern int lastword, lastdol; extern int lastword, lastdol;
void void
@ -68,7 +79,7 @@ iacvt(int n)
} }
void void
inttoascii(char *s, int32_t n) inttoascii(char *s, int n)
{ {
bp = s; bp = s;
iacvt(n); iacvt(n);

View File

@ -83,7 +83,8 @@ comword: '$' word {$$=tree1('$', $2);}
| '"' word {$$=tree1('"', $2);} | '"' word {$$=tree1('"', $2);}
| COUNT word {$$=tree1(COUNT, $2);} | COUNT word {$$=tree1(COUNT, $2);}
| WORD | WORD
| '`' brace {$$=tree1('`', $2);} | '`' brace {$$=tree2('`', (struct tree*)0, $2);}
| '`' word brace {$$=tree2('`', $2, $3);}
| '(' words ')' {$$=tree1(PAREN, $2);} | '(' words ')' {$$=tree1(PAREN, $2);}
| REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;} | REDIR brace {$$=mung1($1, $2); $$->type=PIPEFD;}
keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN keyword: FOR|IN|WHILE|IF|NOT|TWIDDLE|BANG|SUBSHELL|SWITCH|FN

View File

@ -27,7 +27,7 @@ dotrap(void)
trapreq = vlook(Signame[i]); trapreq = vlook(Signame[i]);
if(trapreq->fn){ if(trapreq->fn){
start(trapreq->fn, trapreq->pc, (struct var *)0); start(trapreq->fn, trapreq->pc, (struct var *)0);
runq->local = newvar(strdup("*"), runq->local); runq->local = newvar("*", runq->local);
runq->local->val = copywords(starval, (struct word *)0); runq->local->val = copywords(starval, (struct word *)0);
runq->local->changed = 1; runq->local->changed = 1;
runq->redir = runq->startredir = 0; runq->redir = runq->startredir = 0;

View File

@ -36,8 +36,8 @@ freenodes(void)
for(t = treenodes;t;t = u){ for(t = treenodes;t;t = u){
u = t->next; u = t->next;
if(t->str) if(t->str)
efree(t->str); free(t->str);
efree((char *)t); free(t);
} }
treenodes = 0; treenodes = 0;
} }
@ -120,7 +120,7 @@ simplemung(tree *t)
t = tree1(SIMPLE, t); t = tree1(SIMPLE, t);
s = openstr(); s = openstr();
pfmt(s, "%t", t); pfmt(s, "%t", t);
t->str = strdup((char *)s->strp); t->str = estrdup((char *)s->strp);
closeio(s); closeio(s);
for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){ for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){
if(u->child[1]->type==DUP if(u->child[1]->type==DUP
@ -152,6 +152,6 @@ freetree(tree *p)
freetree(p->child[1]); freetree(p->child[1]);
freetree(p->child[2]); freetree(p->child[2]);
if(p->str) if(p->str)
efree(p->str); free(p->str);
efree((char *)p); free(p);
} }

View File

@ -1,601 +0,0 @@
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/*
* Unix versions of system-specific functions
* By convention, exported routines herein have names beginning with an
* upper case letter.
*/
#include "rc.h"
#include "io.h"
#include "exec.h"
#include "getflags.h"
#include <errno.h>
char *Rcmain = "/usr/lib/rcmain";
char *Fdprefix = "/dev/fd/";
void execfinit(void);
struct builtin Builtin[] = {
"cd", execcd,
"whatis", execwhatis,
"eval", execeval,
"exec", execexec, /* but with popword first */
"exit", execexit,
"shift", execshift,
"wait", execwait,
"umask", execumask,
".", execdot,
"finit", execfinit,
"flag", execflag,
0
};
#define SEP '\1'
char **environp;
struct word*
enval(s)
register char *s;
{
char *t, c;
struct word *v;
for(t = s;*t && *t!=SEP;t++);
c=*t;
*t='\0';
v = newword(s, c=='\0'?(struct word *)0:enval(t+1));
*t = c;
return v;
}
void
Vinit(void)
{
extern char **environ;
char *s;
char **env = environ;
environp = env;
for(;*env;env++){
for(s=*env;*s && *s!='(' && *s!='=';s++);
switch(*s){
case '\0':
pfmt(err, "environment %q?\n", *env);
break;
case '=':
*s='\0';
setvar(*env, enval(s+1));
*s='=';
break;
case '(': /* ignore functions for now */
break;
}
}
}
char **envp;
void
Xrdfn(void)
{
char *s;
int len;
for(;*envp;envp++){
for(s=*envp;*s && *s!='(' && *s!='=';s++);
switch(*s){
case '\0':
pfmt(err, "environment %q?\n", *envp);
break;
case '=': /* ignore variables */
break;
case '(': /* Bourne again */
s=*envp+3;
envp++;
len = strlen(s);
s[len]='\n';
execcmds(opencore(s, len+1));
s[len]='\0';
return;
}
}
Xreturn();
}
union code rdfns[4];
void
execfinit(void)
{
static int first = 1;
if(first){
rdfns[0].i = 1;
rdfns[1].f = Xrdfn;
rdfns[2].f = Xjump;
rdfns[3].i = 1;
first = 0;
}
Xpopm();
envp = environp;
start(rdfns, 1, runq->local);
}
int
cmpenv(const void *aa, const void *ab)
{
char **a = aa, **b = ab;
return strcmp(*a, *b);
}
char **
mkenv(void)
{
char **env, **ep, *p, *q;
struct var **h, *v;
struct word *a;
int nvar = 0, nchr = 0, sep;
/*
* Slightly kludgy loops look at locals then globals.
* locals no longer exist - geoff
*/
for(h = gvar-1; h != &gvar[NVAR]; h++)
for(v = h >= gvar? *h: runq->local; v ;v = v->next){
if((v==vlook(v->name)) && v->val){
nvar++;
nchr+=strlen(v->name)+1;
for(a = v->val;a;a = a->next)
nchr+=strlen(a->word)+1;
}
if(v->fn){
nvar++;
nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8;
}
}
env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr);
ep = env;
p = (char *)&env[nvar+1];
for(h = gvar-1; h != &gvar[NVAR]; h++)
for(v = h >= gvar? *h: runq->local;v;v = v->next){
if((v==vlook(v->name)) && v->val){
*ep++=p;
q = v->name;
while(*q) *p++=*q++;
sep='=';
for(a = v->val;a;a = a->next){
*p++=sep;
sep = SEP;
q = a->word;
while(*q) *p++=*q++;
}
*p++='\0';
}
if(v->fn){
*ep++=p;
*p++='#'; *p++='('; *p++=')'; /* to fool Bourne */
*p++='f'; *p++='n'; *p++=' ';
q = v->name;
while(*q) *p++=*q++;
*p++=' ';
q = v->fn[v->pc-1].s;
while(*q) *p++=*q++;
*p++='\0';
}
}
*ep = 0;
qsort((void *)env, nvar, sizeof ep[0], cmpenv);
return env;
}
char *sigmsg[] = {
/* 0 normal */ 0,
/* 1 SIGHUP */ "Hangup",
/* 2 SIGINT */ 0,
/* 3 SIGQUIT */ "Quit",
/* 4 SIGILL */ "Illegal instruction",
/* 5 SIGTRAP */ "Trace/BPT trap",
/* 6 SIGIOT */ "abort",
/* 7 SIGEMT */ "EMT trap",
/* 8 SIGFPE */ "Floating exception",
/* 9 SIGKILL */ "Killed",
/* 10 SIGBUS */ "Bus error",
/* 11 SIGSEGV */ "Memory fault",
/* 12 SIGSYS */ "Bad system call",
/* 13 SIGPIPE */ 0,
/* 14 SIGALRM */ "Alarm call",
/* 15 SIGTERM */ "Terminated",
/* 16 unused */ "signal 16",
/* 17 SIGSTOP */ "Process stopped",
/* 18 unused */ "signal 18",
/* 19 SIGCONT */ "Process continued",
/* 20 SIGCHLD */ "Child death",
};
void
Waitfor(int pid, int persist)
{
int wpid, sig;
struct thread *p;
int wstat;
char wstatstr[12];
for(;;){
errno = 0;
wpid = wait(&wstat);
if(errno==EINTR && persist)
continue;
if(wpid==-1)
break;
sig = wstat&0177;
if(sig==0177){
pfmt(err, "trace: ");
sig = (wstat>>8)&0177;
}
if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){
if(pid!=wpid)
pfmt(err, "%d: ", wpid);
if(sig<=(sizeof sigmsg/sizeof sigmsg[0]))
pfmt(err, "%s", sigmsg[sig]);
else if(sig==0177) pfmt(err, "stopped by ptrace");
else pfmt(err, "signal %d", sig);
if(wstat&0200)pfmt(err, " -- core dumped");
pfmt(err, "\n");
}
wstat = sig?sig+1000:(wstat>>8)&0xFF;
if(wpid==pid){
inttoascii(wstatstr, wstat);
setstatus(wstatstr);
break;
}
else{
for(p = runq->ret;p;p = p->ret)
if(p->pid==wpid){
p->pid=-1;
inttoascii(p->status, wstat);
break;
}
}
}
}
char **
mkargv(a)
register struct word *a;
{
char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
char **argp = argv+1; /* leave one at front for runcoms */
for(;a;a = a->next)
*argp++=a->word;
*argp = 0;
return argv;
}
void
Updenv(void)
{
}
void
Execute(struct word *args, struct word *path)
{
char *msg="not found";
int txtbusy = 0;
char **env = mkenv();
char **argv = mkargv(args);
char file[512];
for(;path;path = path->next){
strcpy(file, path->word);
if(file[0])
strcat(file, "/");
strcat(file, argv[1]);
ReExec:
execve(file, argv+1, env);
switch(errno){
case ENOEXEC:
pfmt(err, "%s: Bourne again\n", argv[1]);
argv[0]="sh";
argv[1] = strdup(file);
execve("/cmd/sh", argv, env);
goto Bad;
case ETXTBSY:
if(++txtbusy!=5){
sleep(txtbusy);
goto ReExec;
}
msg="text busy"; goto Bad;
case EACCES:
msg="no access";
break;
case ENOMEM:
msg="not enough memory"; goto Bad;
case E2BIG:
msg="too big"; goto Bad;
}
}
Bad:
pfmt(err, "%s: %s\n", argv[1], msg);
efree((char *)env);
efree((char *)argv);
}
#define NDIR 14 /* should get this from param.h */
Globsize(p)
register char *p;
{
int isglob = 0, globlen = NDIR+1;
for(;*p;p++){
if(*p==GLOB){
p++;
if(*p!=GLOB)
isglob++;
globlen+=*p=='*'?NDIR:1;
}
else
globlen++;
}
return isglob?globlen:0;
}
#include <sys/types.h>
#include <dirent.h>
#define NDIRLIST 50
DIR *dirlist[NDIRLIST];
Opendir(name)
char *name;
{
DIR **dp;
for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++)
if(*dp==0){
*dp = opendir(name);
return *dp?dp-dirlist:-1;
}
return -1;
}
int
Readdir(int f, char *p, int onlydirs)
{
struct dirent *dp = readdir(dirlist[f]);
if(dp==0)
return 0;
strcpy(p, dp->d_name);
return 1;
}
void
Closedir(int f)
{
closedir(dirlist[f]);
dirlist[f] = 0;
}
char *Signame[] = {
"sigexit", "sighup", "sigint", "sigquit",
"sigill", "sigtrap", "sigiot", "sigemt",
"sigfpe", "sigkill", "sigbus", "sigsegv",
"sigsys", "sigpipe", "sigalrm", "sigterm",
"sig16", "sigstop", "sigtstp", "sigcont",
"sigchld", "sigttin", "sigttou", "sigtint",
"sigxcpu", "sigxfsz", "sig26", "sig27",
"sig28", "sig29", "sig30", "sig31",
0,
};
void
gettrap(int sig)
{
signal(sig, gettrap);
trap[sig]++;
ntrap++;
if(ntrap>=NSIG){
pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig);
signal(SIGABRT, (void (*)())0);
kill(getpid(), SIGABRT);
}
}
void
Trapinit(void)
{
int i;
void (*sig)();
if(1 || flag['d']){ /* wrong!!! */
sig = signal(SIGINT, gettrap);
if(sig==SIG_IGN)
signal(SIGINT, SIG_IGN);
}
else{
for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){
sig = signal(i, gettrap);
if(sig==SIG_IGN)
signal(i, SIG_IGN);
}
}
}
Unlink(name)
char *name;
{
return unlink(name);
}
Write(fd, buf, cnt)
char *buf;
{
return write(fd, buf, cnt);
}
Read(fd, buf, cnt)
char *buf;
{
return read(fd, buf, cnt);
}
Seek(fd, cnt, whence)
int32_t cnt;
{
return lseek(fd, cnt, whence);
}
Executable(file)
char *file;
{
return(access(file, AEXEC)==0);
}
Creat(file)
char *file;
{
return creat(file, 0666);
}
Dup(a, b){
return dup2(a, b);
}
Dup1(a){
return dup(a);
}
/*
* Wrong: should go through components of a|b|c and return the maximum.
*/
void
Exit(char *stat)
{
int n = 0;
while(*stat){
if(*stat!='|'){
if(*stat<'0' || '9'<*stat)
exit(1);
else n = n*10+*stat-'0';
}
stat++;
}
exit(n);
}
Eintr(){
return errno==EINTR;
}
void
Noerror()
{
errno = 0;
}
Isatty(fd){
return isatty(fd);
}
void
Abort()
{
abort();
}
void
execumask(void) /* wrong -- should fork before writing */
{
int m;
struct io out[1];
switch(count(runq->argv->words)){
default:
pfmt(err, "Usage: umask [umask]\n");
setstatus("umask usage");
poplist();
return;
case 2:
umask(octal(runq->argv->words->next->word));
break;
case 1:
umask(m = umask(0));
out->fd = mapfd(1);
out->bufp = out->buf;
out->ebuf=&out->buf[NBUF];
out->strp = 0;
pfmt(out, "%o\n", m);
break;
}
setstatus("");
poplist();
}
void
Memcpy(a, b, n)
int8_t *a, *b;
{
memmove(a, b, n);
}
void*
Malloc(unsigned long n)
{
return (void *)malloc(n);
}
void
errstr(char *buf, int len)
{
strncpy(buf, strerror(errno), len);
}
int
needsrcquote(int c)
{
if(c <= ' ')
return 1;
if(strchr("`^#*[]=|\\?${}()'<>&;", c))
return 1;
return 0;
}
int
rfork(int bits)
{
return fork();
}
int *waitpids;
int nwaitpids;
void
addwaitpid(int pid)
{
waitpids = realloc(waitpids, (nwaitpids+1)*sizeof waitpids[0]);
if(waitpids == 0)
panic("Can't realloc %d waitpids", nwaitpids+1);
waitpids[nwaitpids++] = pid;
}
void
delwaitpid(int pid)
{
int r, w;
for(r=w=0; r<nwaitpids; r++)
if(waitpids[r] != pid)
waitpids[w++] = waitpids[r];
nwaitpids = w;
}
void
clearwaitpids(void)
{
nwaitpids = 0;
}
int
havewaitpid(int pid)
{
int i;
for(i=0; i<nwaitpids; i++)
if(waitpids[i] == pid)
return 1;
return 0;
}

View File

@ -1,62 +0,0 @@
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
#undef _BSD_EXTENSION /* avoid multiple def'n if predefined */
#undef _PLAN9_SOURCE
#undef _POSIX_SOURCE
#undef _RESEARCH_SOURCE
#undef _SUSV2_SOURCE
#define _BSD_EXTENSION
#define _PLAN9_SOURCE
#define _POSIX_SOURCE
#define _RESEARCH_SOURCE
#define _SUSV2_SOURCE
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <inttypes.h>
#ifndef NSIG
#define NSIG 32
#endif
/* plan 9 compatibility */
#define RFPROC 1
#define RFFDG 1
#define RFNOTEG 1
#define uintptr_t uintptr_t
char *strdup(const char *);
#define nil ((void*)0)
/* in case uchar, etc. are built-in types */
#define uchar _fmtuchar
#define ushort _fmtushort
#define uint32_t _fmtuint
#define ulong _fmtulong
#define vlong _fmtvlong
#define uvlong _fmtuvlong
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint32_t;
typedef unsigned long ulong;
typedef unsigned long long uvlong;
#define OREAD O_RDONLY
#define OWRITE O_WRONLY
#define ORDWR O_RDWR
#define OCEXEC 0

View File

@ -11,17 +11,14 @@
#include "exec.h" #include "exec.h"
#include "fns.h" #include "fns.h"
unsigned int
hash(char *as, int n) hash(char *s, int n)
{ {
int i = 1; int h = 0, i = 1;
unsigned h = 0; while(*s)
uint8_t *s;
s = (uint8_t *)as;
while (*s)
h += *s++ * i++; h += *s++ * i++;
return h % n; h%=n;
return h < 0 ? h+n : h;
} }
#define NKW 30 #define NKW 30
@ -76,8 +73,10 @@ gvlook(char *name)
{ {
int h = hash(name, NVAR); int h = hash(name, NVAR);
var *v; var *v;
for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v; for(v = gvar[h];v;v = v->next)
return gvar[h] = newvar(strdup(name), gvar[h]); if(strcmp(v->name, name)==0)
return v;
return gvar[h] = newvar(name, gvar[h]);
} }
var* var*

View File

@ -1,570 +0,0 @@
/*
* This file is part of the UCB release of Plan 9. It is subject to the license
* terms in the LICENSE file found in the top-level directory of this
* distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
* part of the UCB release of Plan 9, including this file, may be copied,
* modified, propagated, or distributed except according to the terms contained
* in the LICENSE file.
*/
/*
* Plan 9 versions of system-specific functions
* By convention, exported routines herein have names beginning with an
* upper case letter.
*/
#include "rc.h"
#include "exec.h"
#include "io.h"
#include "fns.h"
#include "getflags.h"
char *Signame[] = {
"sigexit", "sighup", "sigint", "sigquit",
"sigalrm", "sigkill", "sigfpe", "sigterm",
0
};
char *syssigname[] = {
"exit", /* can't happen */
"hangup",
"interrupt",
"quit", /* can't happen */
"alarm",
"kill",
"sys: fp: ",
"term",
0
};
char *Rcmain = "/rc/lib/rcmain";
char *Fdprefix = "/fd/";
void execfinit(void);
void execbind(void);
builtin Builtin[] = {
"cd", execcd,
"whatis", execwhatis,
"eval", execeval,
"exec", execexec, /* but with popword first */
"exit", execexit,
"shift", execshift,
"wait", execwait,
".", execdot,
"finit", execfinit,
"flag", execflag,
0
};
void
Vinit(void)
{
int dir, f, len;
word *val;
char *buf, *s;
Dir *ent;
int i, nent;
char envname[256];
dir = open("/env", OREAD);
if(dir<0){
pfmt(err, "rc: can't open /env: %r\n");
return;
}
ent = nil;
for(;;){
nent = dirread(dir, &ent);
if(nent <= 0)
break;
for(i = 0; i<nent; i++){
len = ent[i].length;
if(len && strncmp(ent[i].name, "fn#", 3)!=0){
snprint(envname, sizeof envname, "/env/%s", ent[i].name);
if((f = open(envname, OREAD))>=0){
buf = emalloc((int)len+1);
read(f, buf, (int32_t)len);
val = 0;
/* Charitably add a 0 at the end if need be */
if(buf[len-1])
buf[len++]='\0';
s = buf+len-1;
for(;;){
while(s!=buf && s[-1]!='\0') --s;
val = newword(s, val);
if(s==buf)
break;
--s;
}
setvar(ent[i].name, val);
vlook(ent[i].name)->changed = 0;
close(f);
efree(buf);
}
}
}
free(ent);
}
close(dir);
}
int envdir;
void
Xrdfn(void)
{
int f, len;
static Dir *ent, *allocent;
static int nent;
Dir *e;
char envname[256];
for(;;){
if(nent == 0){
free(allocent);
nent = dirread(envdir, &allocent);
ent = allocent;
}
if(nent <= 0)
break;
while(nent){
e = ent++;
nent--;
len = e->length;
if(len && strncmp(e->name, "fn#", 3)==0){
snprint(envname, sizeof envname, "/env/%s", e->name);
if((f = open(envname, OREAD))>=0){
execcmds(openfd(f));
return;
}
}
}
}
close(envdir);
Xreturn();
}
union code rdfns[4];
void
execfinit(void)
{
static int first = 1;
if(first){
rdfns[0].i = 1;
rdfns[1].f = Xrdfn;
rdfns[2].f = Xjump;
rdfns[3].i = 1;
first = 0;
}
Xpopm();
envdir = open("/env", OREAD);
if(envdir<0){
pfmt(err, "rc: can't open /env: %r\n");
return;
}
start(rdfns, 1, runq->local);
}
int
Waitfor(int pid, int persist)
{
thread *p;
Waitmsg *w;
char errbuf[ERRMAX];
while((w = wait()) != nil){
if(w->pid==pid){
setstatus(w->msg);
free(w);
return 0;
}
for(p = runq->ret;p;p = p->ret)
if(p->pid==w->pid){
p->pid=-1;
strcpy(p->status, w->msg);
}
free(w);
}
errstr(errbuf, sizeof errbuf);
if(strcmp(errbuf, "interrupted")==0) return -1;
return 0;
}
char*
*mkargv(word *a)
{
char **argv = (char **)emalloc((count(a)+2)*sizeof(char *));
char **argp = argv+1; /* leave one at front for runcoms */
for(;a;a = a->next) *argp++=a->word;
*argp = 0;
return argv;
}
void
addenv(var *v)
{
char envname[256];
word *w;
int f;
io *fd;
if(v->changed){
v->changed = 0;
snprint(envname, sizeof envname, "/env/%s", v->name);
if((f = Creat(envname))<0)
pfmt(err, "rc: can't open %s: %r\n", envname);
else{
for(w = v->val;w;w = w->next)
write(f, w->word, strlen(w->word)+1L);
close(f);
}
}
if(v->fnchanged){
v->fnchanged = 0;
snprint(envname, sizeof envname, "/env/fn#%s", v->name);
if((f = Creat(envname))<0)
pfmt(err, "rc: can't open %s: %r\n", envname);
else{
if(v->fn){
fd = openfd(f);
pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s);
closeio(fd);
}
close(f);
}
}
}
void
updenvlocal(var *v)
{
if(v){
updenvlocal(v->next);
addenv(v);
}
}
void
Updenv(void)
{
var *v, **h;
for(h = gvar;h!=&gvar[NVAR];h++)
for(v=*h;v;v = v->next)
addenv(v);
if(runq)
updenvlocal(runq->local);
}
int
ForkExecute(char *file, char **argv, int sin, int sout, int serr)
{
int pid;
{int i;
fprint(2, "forkexec %s", file);
for(i = 0; argv[i]; i++)fprint(2, " %s", argv[i]);
fprint(2, " %d %d %d\n", sin, sout, serr);
}
if(access(file, AEXEC) != 0)
return -1;
fprint(2, "forking\n");
switch(pid = fork()){
case -1:
return -1;
case 0:
if(sin >= 0)
dup(sin, 0);
else
close(0);
if(sout >= 0)
dup(sout, 1);
else
close(1);
if(serr >= 0)
dup(serr, 2);
else
close(2);
fprint(2, "execing\n");
exec(file, argv);
fprint(2, "exec: %r\n");
exits(file);
}
return pid;
}
void
Execute(word *args, word *path)
{
char **argv = mkargv(args);
char file[1024];
int nc;
Updenv();
for(;path;path = path->next){
nc = strlen(path->word);
if(nc<1024){
strcpy(file, path->word);
if(file[0]){
strcat(file, "/");
nc++;
}
if(nc+strlen(argv[1])<1024){
strcat(file, argv[1]);
exec(file, argv+1);
}
else werrstr("command name too long");
}
}
rerrstr(file, sizeof file);
pfmt(err, "%s: %s\n", argv[1], file);
efree((char *)argv);
}
#define NDIR 256 /* shoud be a better way */
int
Globsize(char *p)
{
int isglob = 0, globlen = NDIR+1;
for(;*p;p++){
if(*p==GLOB){
p++;
if(*p!=GLOB)
isglob++;
globlen+=*p=='*'?NDIR:1;
}
else
globlen++;
}
return isglob?globlen:0;
}
#define NFD 50
#define NDBUF 32
struct{
Dir *dbuf;
int i;
int n;
}dir[NFD];
int
Opendir(char *name)
{
Dir *db;
int f;
f = open(name, OREAD);
if(f==-1)
return f;
db = dirfstat(f);
if(db!=nil && (db->mode&DMDIR)){
if(f<NFD){
dir[f].i = 0;
dir[f].n = 0;
}
free(db);
return f;
}
free(db);
close(f);
return -1;
}
static int
trimdirs(Dir *d, int nd)
{
int r, w;
for(r=w=0; r<nd; r++)
if(d[r].mode&DMDIR)
d[w++] = d[r];
return w;
}
/*
* onlydirs is advisory -- it means you only
* need to return the directories. it's okay to
* return files too (e.g., on unix where you can't
* tell during the readdir), but that just makes
* the globber work harder.
*/
int
Readdir(int f, void *p, int onlydirs)
{
int n;
if(f<0 || f>=NFD)
return 0;
Again:
if(dir[f].i==dir[f].n){ /* read */
free(dir[f].dbuf);
dir[f].dbuf = 0;
n = dirread(f, &dir[f].dbuf);
if(n>0){
if(onlydirs){
n = trimdirs(dir[f].dbuf, n);
if(n == 0)
goto Again;
}
dir[f].n = n;
}else
dir[f].n = 0;
dir[f].i = 0;
}
if(dir[f].i == dir[f].n)
return 0;
strcpy(p, dir[f].dbuf[dir[f].i].name);
dir[f].i++;
return 1;
}
void
Closedir(int f)
{
if(f>=0 && f<NFD){
free(dir[f].dbuf);
dir[f].i = 0;
dir[f].n = 0;
dir[f].dbuf = 0;
}
close(f);
}
int interrupted = 0;
void
notifyf(void*, char *s)
{
int i;
for(i = 0;syssigname[i];i++) if(strncmp(s, syssigname[i], strlen(syssigname[i]))==0){
if(strncmp(s, "sys: ", 5)!=0) interrupted = 1;
goto Out;
}
pfmt(err, "rc: note: %s\n", s);
noted(NDFLT);
return;
Out:
if(strcmp(s, "interrupt")!=0 || trap[i]==0){
trap[i]++;
ntrap++;
}
if(ntrap>=32){ /* rc is probably in a trap loop */
pfmt(err, "rc: Too many traps (trap %s), aborting\n", s);
abort();
}
noted(NCONT);
}
void
Trapinit(void)
{
notify(notifyf);
}
void
Unlink(char *name)
{
remove(name);
}
int32_t
Write(int fd, void *buf, int32_t cnt)
{
return write(fd, buf, (int32_t)cnt);
}
int32_t
Read(int fd, void *buf, int32_t cnt)
{
return read(fd, buf, cnt);
}
int32_t
Seek(int fd, int32_t cnt, int32_t whence)
{
return seek(fd, cnt, whence);
}
int
Executable(char *file)
{
Dir *statbuf;
int ret;
statbuf = dirstat(file);
if(statbuf == nil)
return 0;
ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0);
free(statbuf);
return ret;
}
int
Creat(char *file)
{
return create(file, 1, 0666L);
}
int
Dup(int a, int b)
{
return dup(a, b);
}
int
Dup1(int)
{
return -1;
}
void
Exit(char *stat)
{
Updenv();
setstatus(stat);
exits(truestatus()?"":getstatus());
}
int
Eintr(void)
{
return interrupted;
}
void
Noerror(void)
{
interrupted = 0;
}
int
Isatty(int fd)
{
Dir *d1, *d2;
int ret;
d1 = dirfstat(fd);
if(d1 == nil)
return 0;
if(strncmp(d1->name, "ptty", 4)==0){ /* fwd complaints to philw */
free(d1);
return 1;
}
d2 = dirstat("/dev/cons");
if(d2 == nil){
free(d1);
return 0;
}
ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path);
free(d1);
free(d2);
return ret;
}
void
Abort(void)
{
pfmt(err, "aborting\n");
flush(err);
Exit("aborting");
}
void
Memcpy(void *a, void *b, int32_t n)
{
memmove(a, b, n);
}
void*
Malloc(uint32_t n)
{
return malloc(n);
}