123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900 |
- #include "rc.h"
- #include "getflags.h"
- #include "exec.h"
- #include "io.h"
- #include "fns.h"
- /*
- * Start executing the given code at the given pc with the given redirection
- */
- char *argv0="rc";
- void start(code *c, int pc, var *local)
- {
- struct thread *p=new(struct thread);
- p->code=codecopy(c);
- p->pc=pc;
- p->argv=0;
- p->redir=p->startredir=runq?runq->redir:0;
- p->local=local;
- p->cmdfile=0;
- p->cmdfd=0;
- p->eof=0;
- p->iflag=0;
- p->lineno=1;
- p->ret=runq;
- runq=p;
- }
- word *newword(char *wd, word *next)
- {
- word *p=new(word);
- p->word=strdup(wd);
- p->next=next;
- return p;
- }
- void pushword(char *wd)
- {
- if(runq->argv==0) panic("pushword but no argv!", 0);
- runq->argv->words=newword(wd, runq->argv->words);
- }
- void popword(void){
- word *p;
- if(runq->argv==0) panic("popword but no argv!", 0);
- p=runq->argv->words;
- if(p==0) panic("popword but no word!", 0);
- runq->argv->words=p->next;
- efree(p->word);
- efree((char *)p);
- }
- void freelist(word *w)
- {
- word *nw;
- while(w){
- nw=w->next;
- efree(w->word);
- efree((char *)w);
- w=nw;
- }
- }
- void pushlist(void){
- list *p=new(list);
- p->next=runq->argv;
- p->words=0;
- runq->argv=p;
- }
- void poplist(void){
- list *p=runq->argv;
- if(p==0) panic("poplist but no argv", 0);
- freelist(p->words);
- runq->argv=p->next;
- efree((char *)p);
- }
- int count(word *w)
- {
- int n;
- for(n=0;w;n++) w=w->next;
- return n;
- }
- void pushredir(int type, int from, int to){
- redir * rp=new(redir);
- rp->type=type;
- rp->from=from;
- rp->to=to;
- rp->next=runq->redir;
- runq->redir=rp;
- }
- var *newvar(char *name, var *next)
- {
- var *v=new(var);
- v->name=name;
- v->val=0;
- v->fn=0;
- v->changed=0;
- v->fnchanged=0;
- v->next=next;
- return v;
- }
- /*
- * get command line flags, initialize keywords & traps.
- * get values from environment.
- * set $pid, $cflag, $*
- * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*)
- * start interpreting code
- */
- void main(int argc, char *argv[])
- {
- code bootstrap[17];
- char num[12], *rcmain;
- int i;
- argc=getflags(argc, argv, "srdiIlxepvVc:1m:1[command]", 1);
- if(argc==-1) usage("[file [arg ...]]");
- if(argv[0][0]=='-') flag['l']=flagset;
- if(flag['I']) flag['i'] = 0;
- else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
- rcmain=flag['m']?flag['m'][0]:Rcmain;
- err=openfd(2);
- kinit();
- Trapinit();
- Vinit();
- itoa(num, mypid=getpid());
- setvar("pid", newword(num, (word *)0));
- setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
- :(word *)0);
- setvar("rcname", newword(argv[0], (word *)0));
- i=0;
- bootstrap[i++].i=1;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f=Xassign;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xword;
- bootstrap[i++].s="*";
- bootstrap[i++].f=Xdol;
- bootstrap[i++].f=Xword;
- bootstrap[i++].s=rcmain;
- bootstrap[i++].f=Xword;
- bootstrap[i++].s=".";
- bootstrap[i++].f=Xsimple;
- bootstrap[i++].f=Xexit;
- bootstrap[i].i=0;
- start(bootstrap, 1, (var *)0);
- /* prime bootstrap argv */
- pushlist();
- argv0 = strdup(argv[0]);
- for(i=argc-1;i!=0;--i) pushword(argv[i]);
- for(;;){
- if(flag['r']) pfnc(err, runq);
- runq->pc++;
- (*runq->code[runq->pc-1].f)();
- if(ntrap) dotrap();
- }
- }
- /*
- * Opcode routines
- * Arguments on stack (...)
- * Arguments in line [...]
- * Code in line with jump around {...}
- *
- * Xappend(file)[fd] open file to append
- * Xassign(name, val) assign val to name
- * Xasync{... Xexit} make thread for {}, no wait
- * Xbackq{... Xreturn} make thread for {}, push stdout
- * Xbang complement condition
- * Xcase(pat, value){...} exec code on match, leave (value) on
- * stack
- * Xclose[i] close file descriptor
- * Xconc(left, right) concatenate, push results
- * Xcount(name) push var count
- * Xdelfn(name) delete function definition
- * Xdeltraps(names) delete named traps
- * Xdol(name) get variable value
- * Xqdol(name) concatenate variable components
- * Xdup[i j] dup file descriptor
- * Xexit rc exits with status
- * Xfalse{...} execute {} if false
- * Xfn(name){... Xreturn} define function
- * Xfor(var, list){... Xreturn} for loop
- * Xjump[addr] goto
- * Xlocal(name, val) create local variable, assign value
- * Xmark mark stack
- * Xmatch(pat, str) match pattern, set status
- * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads,
- * wait for both
- * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
- * depending on type), push /dev/fd/??
- * Xpopm(value) pop value from stack
- * Xread(file)[fd] open file to read
- * Xsettraps(names){... Xreturn} define trap functions
- * Xshowtraps print trap list
- * Xsimple(args) run command and wait
- * Xreturn kill thread
- * Xsubshell{... Xexit} execute {} in a subshell and wait
- * Xtrue{...} execute {} if true
- * Xunlocal delete local variable
- * Xword[string] push string
- * Xwrite(file)[fd] open file to write
- */
- void Xappend(void){
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default: Xerror1(">> requires singleton"); return;
- case 0: Xerror1(">> requires file"); return;
- case 1: break;
- }
- file=runq->argv->words->word;
- if((f=open(file, 1))<0 && (f=Creat(file))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- Seek(f, 0L, 2);
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- void Xasync(void){
- int null=open("/dev/null", 0);
- int pid;
- char npid[10];
- if(null<0){
- Xerror("Can't open /dev/null\n");
- return;
- }
- switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
- case -1:
- close(null);
- Xerror("try again");
- break;
- case 0:
- pushredir(ROPEN, null, 0);
- start(runq->code, runq->pc+1, runq->local);
- runq->ret=0;
- break;
- default:
- close(null);
- runq->pc=runq->code[runq->pc].i;
- itoa(npid, pid);
- setvar("apid", newword(npid, (word *)0));
- break;
- }
- }
- void Xsettrue(void){
- setstatus("");
- }
- void Xbang(void){
- setstatus(truestatus()?"false":"");
- }
- void Xclose(void){
- pushredir(RCLOSE, runq->code[runq->pc].i, 0);
- runq->pc++;
- }
- void Xdup(void){
- pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
- runq->pc+=2;
- }
- void Xeflag(void){
- if(eflagok && !truestatus()) Xexit();
- }
- void Xexit(void){
- struct var *trapreq;
- struct word *starval;
- static int beenhere=0;
- if(getpid()==mypid && !beenhere){
- trapreq=vlook("sigexit");
- if(trapreq->fn){
- beenhere=1;
- --runq->pc;
- starval=vlook("*")->val;
- start(trapreq->fn, trapreq->pc, (struct var *)0);
- runq->local=newvar(strdup("*"), runq->local);
- runq->local->val=copywords(starval, (struct word *)0);
- runq->local->changed=1;
- runq->redir=runq->startredir=0;
- return;
- }
- }
- Exit(getstatus());
- }
- void Xfalse(void){
- if(truestatus()) runq->pc=runq->code[runq->pc].i;
- else runq->pc++;
- }
- int ifnot; /* dynamic if not flag */
- void Xifnot(void){
- if(ifnot)
- runq->pc++;
- else
- runq->pc=runq->code[runq->pc].i;
- }
- void Xjump(void){
- runq->pc=runq->code[runq->pc].i;
- }
- void Xmark(void){
- pushlist();
- }
- void Xpopm(void){
- poplist();
- }
- void Xread(void){
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default: Xerror1("< requires singleton\n"); return;
- case 0: Xerror1("< requires file\n"); return;
- case 1: break;
- }
- file=runq->argv->words->word;
- if((f=open(file, 0))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- void turfredir(void){
- while(runq->redir!=runq->startredir)
- Xpopredir();
- }
- void Xpopredir(void){
- struct redir *rp=runq->redir;
- if(rp==0) panic("turfredir null!", 0);
- runq->redir=rp->next;
- if(rp->type==ROPEN) close(rp->from);
- efree((char *)rp);
- }
- void Xreturn(void){
- struct thread *p=runq;
- turfredir();
- while(p->argv) poplist();
- codefree(p->code);
- runq=p->ret;
- efree((char *)p);
- if(runq==0) Exit(getstatus());
- }
- void Xtrue(void){
- if(truestatus()) runq->pc++;
- else runq->pc=runq->code[runq->pc].i;
- }
- void Xif(void){
- ifnot=1;
- if(truestatus()) runq->pc++;
- else runq->pc=runq->code[runq->pc].i;
- }
- void Xwastrue(void){
- ifnot=0;
- }
- void Xword(void){
- pushword(runq->code[runq->pc++].s);
- }
- void Xwrite(void){
- char *file;
- int f;
- switch(count(runq->argv->words)){
- default: Xerror1("> requires singleton\n"); return;
- case 0: Xerror1("> requires file\n"); return;
- case 1: break;
- }
- file=runq->argv->words->word;
- if((f=Creat(file))<0){
- pfmt(err, "%s: ", file);
- Xerror("can't open");
- return;
- }
- pushredir(ROPEN, f, runq->code[runq->pc].i);
- runq->pc++;
- poplist();
- }
- char *list2str(word *words){
- char *value, *s, *t;
- int len=0;
- word *ap;
- for(ap=words;ap;ap=ap->next)
- len+=1+strlen(ap->word);
- value=emalloc(len+1);
- s=value;
- for(ap=words;ap;ap=ap->next){
- for(t=ap->word;*t;) *s++=*t++;
- *s++=' ';
- }
- if(s==value) *s='\0';
- else s[-1]='\0';
- return value;
- }
- void Xmatch(void){
- word *p;
- char *subject;
- subject=list2str(runq->argv->words);
- setstatus("no match");
- for(p=runq->argv->next->words;p;p=p->next)
- if(match(subject, p->word, '\0')){
- setstatus("");
- break;
- }
- efree(subject);
- poplist();
- poplist();
- }
- void Xcase(void){
- word *p;
- char *s;
- int ok=0;
- s=list2str(runq->argv->next->words);
- for(p=runq->argv->words;p;p=p->next){
- if(match(s, p->word, '\0')){
- ok=1;
- break;
- }
- }
- efree(s);
- if(ok)
- runq->pc++;
- else
- runq->pc=runq->code[runq->pc].i;
- poplist();
- }
- word *conclist(word *lp, word *rp, word *tail)
- {
- char *buf;
- word *v;
- if(lp->next || rp->next)
- tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
- tail);
- buf=emalloc(strlen(lp->word)+strlen(rp->word)+1);
- strcpy(buf, lp->word);
- strcat(buf, rp->word);
- v=newword(buf, tail);
- efree(buf);
- return v;
- }
- void Xconc(void){
- word *lp=runq->argv->words;
- word *rp=runq->argv->next->words;
- word *vp=runq->argv->next->next->words;
- int lc=count(lp), rc=count(rp);
- if(lc!=0 || rc!=0){
- if(lc==0 || rc==0){
- Xerror1("null list in concatenation");
- return;
- }
- if(lc!=1 && rc!=1 && lc!=rc){
- Xerror1("mismatched list lengths in concatenation");
- return;
- }
- vp=conclist(lp, rp, vp);
- }
- poplist();
- poplist();
- runq->argv->words=vp;
- }
- void Xassign(void){
- var *v;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- deglob(runq->argv->words->word);
- v=vlook(runq->argv->words->word);
- poplist();
- globlist();
- freewords(v->val);
- v->val=runq->argv->words;
- v->changed=1;
- runq->argv->words=0;
- poplist();
- }
- /*
- * copy arglist a, adding the copy to the front of tail
- */
- word *copywords(word *a, word *tail)
- {
- word *v=0, **end;
- for(end=&v;a;a=a->next,end=&(*end)->next)
- *end=newword(a->word, 0);
- *end=tail;
- return v;
- }
- void Xdol(void){
- word *a, *star;
- char *s, *t;
- int n;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s=runq->argv->words->word;
- deglob(s);
- n=0;
- for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
- a=runq->argv->next->words;
- if(n==0 || *t)
- a=copywords(vlook(s)->val, a);
- else{
- star=vlook("*")->val;
- if(star && 1<=n && n<=count(star)){
- while(--n) star=star->next;
- a=newword(star->word, a);
- }
- }
- poplist();
- runq->argv->words=a;
- }
- void Xqdol(void){
- word *a, *p;
- char *s;
- int n;
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s=runq->argv->words->word;
- deglob(s);
- a=vlook(s)->val;
- poplist();
- n=count(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 *subwords(word *val, int len, word *sub, word *a)
- {
- int n;
- char *s;
- if(!sub) return a;
- a=subwords(val, len, sub->next, a);
- s=sub->word;
- deglob(s);
- n=0;
- while('0'<=*s && *s<='9') n=n*10+ *s++ -'0';
- if(n<1 || len<n) return a;
- for(;n!=1;--n) val=val->next;
- return newword(val->word, a);
- }
- void Xsub(void){
- word *a, *v;
- char *s;
- if(count(runq->argv->next->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s=runq->argv->next->words->word;
- deglob(s);
- a=runq->argv->next->next->words;
- v=vlook(s)->val;
- a=subwords(v, count(v), runq->argv->words, a);
- poplist();
- poplist();
- runq->argv->words=a;
- }
- void Xcount(void){
- word *a;
- char *s, *t;
- int n;
- char num[12];
- if(count(runq->argv->words)!=1){
- Xerror1("variable name not singleton!");
- return;
- }
- s=runq->argv->words->word;
- deglob(s);
- n=0;
- for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
- if(n==0 || *t){
- a=vlook(s)->val;
- itoa(num, count(a));
- }
- else{
- a=vlook("*")->val;
- itoa(num, a && 1<=n && n<=count(a)?1:0);
- }
- poplist();
- pushword(num);
- }
- void Xlocal(void){
- if(count(runq->argv->words)!=1){
- Xerror1("variable name must be singleton\n");
- return;
- }
- deglob(runq->argv->words->word);
- runq->local=newvar(strdup(runq->argv->words->word), runq->local);
- runq->local->val=copywords(runq->argv->next->words, (word *)0);
- runq->local->changed=1;
- poplist();
- poplist();
- }
- void Xunlocal(void){
- var *v=runq->local, *hid;
- if(v==0) panic("Xunlocal: no locals!", 0);
- runq->local=v->next;
- hid=vlook(v->name);
- hid->changed=1;
- efree(v->name);
- freewords(v->val);
- efree((char *)v);
- }
- void freewords(word *w)
- {
- word *nw;
- while(w){
- efree(w->word);
- nw=w->next;
- efree((char *)w);
- w=nw;
- }
- }
- void Xfn(void){
- var *v;
- word *a;
- int end;
- end=runq->code[runq->pc].i;
- for(a=runq->argv->words;a;a=a->next){
- v=gvlook(a->word);
- if(v->fn) codefree(v->fn);
- v->fn=codecopy(runq->code);
- v->pc=runq->pc+2;
- v->fnchanged=1;
- }
- runq->pc=end;
- poplist();
- }
- void Xdelfn(void){
- var *v;
- word *a;
- for(a=runq->argv->words;a;a=a->next){
- v=gvlook(a->word);
- if(v->fn) codefree(v->fn);
- v->fn=0;
- v->fnchanged=1;
- }
- poplist();
- }
- void Xpipe(void){
- struct thread *p=runq;
- int pc=p->pc, forkid;
- int lfd=p->code[pc++].i;
- int rfd=p->code[pc++].i;
- int pfd[2];
- if(pipe(pfd)<0){
- Xerror("can't get pipe");
- return;
- }
- switch(forkid=fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(p->code, pc+2, runq->local);
- runq->ret=0;
- close(pfd[PRD]);
- pushredir(ROPEN, pfd[PWR], lfd);
- break;
- default:
- start(p->code, p->code[pc].i, runq->local);
- close(pfd[PWR]);
- pushredir(ROPEN, pfd[PRD], rfd);
- p->pc=p->code[pc+1].i;
- p->pid=forkid;
- break;
- }
- }
- char *concstatus(char *s, char *t)
- {
- static char v[NSTATUS+1];
- int n=strlen(s);
- strncpy(v, s, NSTATUS);
- if(n<NSTATUS){
- v[n]='|';
- strncpy(v+n+1, t, NSTATUS-n-1);
- }
- v[NSTATUS]='\0';
- return v;
- }
- void Xpipewait(void){
- char status[NSTATUS+1];
- if(runq->pid==-1)
- setstatus(concstatus(runq->status, getstatus()));
- else{
- strncpy(status, getstatus(), NSTATUS);
- status[NSTATUS]='\0';
- Waitfor(runq->pid, 1);
- runq->pid=-1;
- setstatus(concstatus(getstatus(), status));
- }
- }
- void Xrdcmds(void){
- struct thread *p=runq;
- word *prompt;
- flush(err);
- nerror=0;
- if(flag['s'] && !truestatus())
- pfmt(err, "status=%v\n", vlook("status")->val);
- if(runq->iflag){
- prompt=vlook("prompt")->val;
- if(prompt)
- promptstr=prompt->word;
- else
- promptstr="% ";
- }
- Noerror();
- if(yyparse()){
- if(!p->iflag || p->eof && !Eintr()){
- if(p->cmdfile) efree(p->cmdfile);
- closeio(p->cmdfd);
- Xreturn(); /* should this be omitted? */
- }
- else{
- if(Eintr()){
- pchr(err, '\n');
- p->eof=0;
- }
- --p->pc; /* go back for next command */
- }
- }
- else{
- ntrap = 0; /* avoid double-interrupts during blocked writes */
- --p->pc; /* re-execute Xrdcmds after codebuf runs */
- start(codebuf, 1, runq->local);
- }
- freenodes();
- }
- void Xerror(char *s)
- {
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s: %r\n", s);
- else
- pfmt(err, "rc (%s): %s: %r\n", argv0, s);
- flush(err);
- while(!runq->iflag) Xreturn();
- }
- void Xerror1(char *s)
- {
- if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
- pfmt(err, "rc: %s\n", s);
- else
- pfmt(err, "rc (%s): %s\n", argv0, s);
- flush(err);
- while(!runq->iflag) Xreturn();
- }
- void Xbackq(void){
- char wd[8193];
- 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;
- }
- switch(pid=fork()){
- case -1: Xerror("try again");
- close(pfd[PRD]);
- close(pfd[PWR]);
- return;
- case 0:
- close(pfd[PRD]);
- start(runq->code, runq->pc+1, runq->local);
- pushredir(ROPEN, pfd[PWR], 1);
- return;
- default:
- close(pfd[PWR]);
- f=openfd(pfd[PRD]);
- 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, 0);
- /* 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=runq->code[runq->pc].i;
- return;
- }
- }
- /*
- * Who should wait for the exit from the fork?
- */
- void Xpipefd(void){
- struct thread *p=runq;
- int pc=p->pc;
- char name[40];
- int pfd[2];
- int sidefd, mainfd;
- if(pipe(pfd)<0){
- Xerror("can't get pipe");
- return;
- }
- if(p->code[pc].i==READ){
- sidefd=pfd[PWR];
- mainfd=pfd[PRD];
- }
- else{
- sidefd=pfd[PRD];
- mainfd=pfd[PWR];
- }
- switch(fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(p->code, pc+2, runq->local);
- close(mainfd);
- pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
- runq->ret=0;
- break;
- default:
- close(sidefd);
- pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
- strcpy(name, Fdprefix);
- itoa(name+strlen(name), mainfd);
- pushword(name);
- p->pc=p->code[pc+1].i;
- break;
- }
- }
- void Xsubshell(void){
- int pid;
- switch(pid=fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(runq->code, runq->pc+1, runq->local);
- runq->ret=0;
- break;
- default:
- Waitfor(pid, 1);
- runq->pc=runq->code[runq->pc].i;
- break;
- }
- }
- void setstatus(char *s)
- {
- setvar("status", newword(s, (word *)0));
- }
- char *getstatus(void){
- var *status=vlook("status");
- return status->val?status->val->word:"";
- }
- int truestatus(void){
- char *s;
- for(s=getstatus();*s;s++)
- if(*s!='|' && *s!='0') return 0;
- return 1;
- }
- void Xdelhere(void){
- Unlink(runq->code[runq->pc++].s);
- }
- void Xfor(void){
- if(runq->argv->words==0){
- poplist();
- runq->pc=runq->code[runq->pc].i;
- }
- else{
- freelist(runq->local->val);
- runq->local->val=runq->argv->words;
- runq->local->changed=1;
- runq->argv->words=runq->argv->words->next;
- runq->local->val->next=0;
- runq->pc++;
- }
- }
- void Xglob(void){
- globlist();
- }
|