13e12c5d1SDavid du Colombier #include "rc.h" 23e12c5d1SDavid du Colombier #include "getflags.h" 33e12c5d1SDavid du Colombier #include "exec.h" 43e12c5d1SDavid du Colombier #include "io.h" 53e12c5d1SDavid du Colombier #include "fns.h" 63e12c5d1SDavid du Colombier /* 73e12c5d1SDavid du Colombier * Start executing the given code at the given pc with the given redirection 83e12c5d1SDavid du Colombier */ 93e12c5d1SDavid du Colombier void start(code *c, int pc, var *local) 103e12c5d1SDavid du Colombier { 113e12c5d1SDavid du Colombier struct thread *p=new(struct thread); 123e12c5d1SDavid du Colombier p->code=codecopy(c); 133e12c5d1SDavid du Colombier p->pc=pc; 143e12c5d1SDavid du Colombier p->argv=0; 153e12c5d1SDavid du Colombier p->redir=p->startredir=runq?runq->redir:0; 163e12c5d1SDavid du Colombier p->local=local; 173e12c5d1SDavid du Colombier p->cmdfile=0; 183e12c5d1SDavid du Colombier p->cmdfd=0; 193e12c5d1SDavid du Colombier p->eof=0; 203e12c5d1SDavid du Colombier p->iflag=0; 213e12c5d1SDavid du Colombier p->lineno=1; 223e12c5d1SDavid du Colombier p->ret=runq; 233e12c5d1SDavid du Colombier runq=p; 243e12c5d1SDavid du Colombier } 253e12c5d1SDavid du Colombier word *newword(char *wd, word *next) 263e12c5d1SDavid du Colombier { 273e12c5d1SDavid du Colombier word *p=new(word); 283e12c5d1SDavid du Colombier p->word=strdup(wd); 293e12c5d1SDavid du Colombier p->next=next; 303e12c5d1SDavid du Colombier return p; 313e12c5d1SDavid du Colombier } 323e12c5d1SDavid du Colombier void pushword(char *wd) 333e12c5d1SDavid du Colombier { 343e12c5d1SDavid du Colombier if(runq->argv==0) panic("pushword but no argv!", 0); 353e12c5d1SDavid du Colombier runq->argv->words=newword(wd, runq->argv->words); 363e12c5d1SDavid du Colombier } 373e12c5d1SDavid du Colombier void popword(void){ 383e12c5d1SDavid du Colombier word *p; 393e12c5d1SDavid du Colombier if(runq->argv==0) panic("popword but no argv!", 0); 403e12c5d1SDavid du Colombier p=runq->argv->words; 413e12c5d1SDavid du Colombier if(p==0) panic("popword but no word!", 0); 423e12c5d1SDavid du Colombier runq->argv->words=p->next; 433e12c5d1SDavid du Colombier efree(p->word); 443e12c5d1SDavid du Colombier efree((char *)p); 453e12c5d1SDavid du Colombier } 463e12c5d1SDavid du Colombier void freelist(word *w) 473e12c5d1SDavid du Colombier { 483e12c5d1SDavid du Colombier word *nw; 493e12c5d1SDavid du Colombier while(w){ 503e12c5d1SDavid du Colombier nw=w->next; 513e12c5d1SDavid du Colombier efree(w->word); 523e12c5d1SDavid du Colombier efree((char *)w); 533e12c5d1SDavid du Colombier w=nw; 543e12c5d1SDavid du Colombier } 553e12c5d1SDavid du Colombier } 563e12c5d1SDavid du Colombier void pushlist(void){ 573e12c5d1SDavid du Colombier list *p=new(list); 583e12c5d1SDavid du Colombier p->next=runq->argv; 593e12c5d1SDavid du Colombier p->words=0; 603e12c5d1SDavid du Colombier runq->argv=p; 613e12c5d1SDavid du Colombier } 623e12c5d1SDavid du Colombier void poplist(void){ 633e12c5d1SDavid du Colombier list *p=runq->argv; 643e12c5d1SDavid du Colombier if(p==0) panic("poplist but no argv", 0); 653e12c5d1SDavid du Colombier freelist(p->words); 663e12c5d1SDavid du Colombier runq->argv=p->next; 673e12c5d1SDavid du Colombier efree((char *)p); 683e12c5d1SDavid du Colombier } 693e12c5d1SDavid du Colombier int count(word *w) 703e12c5d1SDavid du Colombier { 713e12c5d1SDavid du Colombier int n; 723e12c5d1SDavid du Colombier for(n=0;w;n++) w=w->next; 733e12c5d1SDavid du Colombier return n; 743e12c5d1SDavid du Colombier } 753e12c5d1SDavid du Colombier void pushredir(int type, int from, int to){ 763e12c5d1SDavid du Colombier redir * rp=new(redir); 773e12c5d1SDavid du Colombier rp->type=type; 783e12c5d1SDavid du Colombier rp->from=from; 793e12c5d1SDavid du Colombier rp->to=to; 803e12c5d1SDavid du Colombier rp->next=runq->redir; 813e12c5d1SDavid du Colombier runq->redir=rp; 823e12c5d1SDavid du Colombier } 833e12c5d1SDavid du Colombier var *newvar(char *name, var *next) 843e12c5d1SDavid du Colombier { 853e12c5d1SDavid du Colombier var *v=new(var); 863e12c5d1SDavid du Colombier v->name=name; 873e12c5d1SDavid du Colombier v->val=0; 883e12c5d1SDavid du Colombier v->fn=0; 893e12c5d1SDavid du Colombier v->changed=0; 903e12c5d1SDavid du Colombier v->fnchanged=0; 913e12c5d1SDavid du Colombier v->next=next; 923e12c5d1SDavid du Colombier return v; 933e12c5d1SDavid du Colombier } 943e12c5d1SDavid du Colombier /* 953e12c5d1SDavid du Colombier * get command line flags, initialize keywords & traps. 963e12c5d1SDavid du Colombier * get values from environment. 973e12c5d1SDavid du Colombier * set $pid, $cflag, $* 983e12c5d1SDavid du Colombier * fabricate bootstrap code and start it (*=(argv);. /usr/lib/rcmain $*) 993e12c5d1SDavid du Colombier * start interpreting code 1003e12c5d1SDavid du Colombier */ 101*7dd7cddfSDavid du Colombier void main(int argc, char *argv[]) 1023e12c5d1SDavid du Colombier { 1033e12c5d1SDavid du Colombier code bootstrap[17]; 1043e12c5d1SDavid du Colombier char num[12]; 1053e12c5d1SDavid du Colombier int i; 1063e12c5d1SDavid du Colombier argc=getflags(argc, argv, "srdiIlxepvVc:1[command]", 1); 1073e12c5d1SDavid du Colombier if(argc==-1) usage("[file [arg ...]]"); 1083e12c5d1SDavid du Colombier if(argv[0][0]=='-') flag['l']=flagset; 1093e12c5d1SDavid du Colombier if(flag['I']) flag['i'] = 0; 110*7dd7cddfSDavid du Colombier else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset; 1113e12c5d1SDavid du Colombier err=openfd(2); 1123e12c5d1SDavid du Colombier kinit(); 1133e12c5d1SDavid du Colombier Trapinit(); 1143e12c5d1SDavid du Colombier Vinit(); 1153e12c5d1SDavid du Colombier itoa(num, mypid=getpid()); 1163e12c5d1SDavid du Colombier setvar("pid", newword(num, (word *)0)); 1173e12c5d1SDavid du Colombier setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0) 1183e12c5d1SDavid du Colombier :(word *)0); 119219b2ee8SDavid du Colombier setvar("rcname", newword(argv[0], (word *)0)); 1203e12c5d1SDavid du Colombier i=0; 1213e12c5d1SDavid du Colombier bootstrap[i++].i=1; 1223e12c5d1SDavid du Colombier bootstrap[i++].f=Xmark; 1233e12c5d1SDavid du Colombier bootstrap[i++].f=Xword; 1243e12c5d1SDavid du Colombier bootstrap[i++].s="*"; 1253e12c5d1SDavid du Colombier bootstrap[i++].f=Xassign; 1263e12c5d1SDavid du Colombier bootstrap[i++].f=Xmark; 1273e12c5d1SDavid du Colombier bootstrap[i++].f=Xmark; 1283e12c5d1SDavid du Colombier bootstrap[i++].f=Xword; 1293e12c5d1SDavid du Colombier bootstrap[i++].s="*"; 1303e12c5d1SDavid du Colombier bootstrap[i++].f=Xdol; 1313e12c5d1SDavid du Colombier bootstrap[i++].f=Xword; 1323e12c5d1SDavid du Colombier bootstrap[i++].s=Rcmain; 1333e12c5d1SDavid du Colombier bootstrap[i++].f=Xword; 1343e12c5d1SDavid du Colombier bootstrap[i++].s="."; 1353e12c5d1SDavid du Colombier bootstrap[i++].f=Xsimple; 1363e12c5d1SDavid du Colombier bootstrap[i++].f=Xexit; 1373e12c5d1SDavid du Colombier bootstrap[i].i=0; 1383e12c5d1SDavid du Colombier start(bootstrap, 1, (var *)0); 1393e12c5d1SDavid du Colombier /* prime bootstrap argv */ 1403e12c5d1SDavid du Colombier pushlist(); 1413e12c5d1SDavid du Colombier for(i=argc-1;i!=0;--i) pushword(argv[i]); 1423e12c5d1SDavid du Colombier for(;;){ 1433e12c5d1SDavid du Colombier if(flag['r']) pfnc(err, runq); 1443e12c5d1SDavid du Colombier runq->pc++; 1453e12c5d1SDavid du Colombier (*runq->code[runq->pc-1].f)(); 1463e12c5d1SDavid du Colombier if(ntrap) dotrap(); 1473e12c5d1SDavid du Colombier } 1483e12c5d1SDavid du Colombier } 1493e12c5d1SDavid du Colombier /* 1503e12c5d1SDavid du Colombier * Opcode routines 1513e12c5d1SDavid du Colombier * Arguments on stack (...) 1523e12c5d1SDavid du Colombier * Arguments in line [...] 1533e12c5d1SDavid du Colombier * Code in line with jump around {...} 1543e12c5d1SDavid du Colombier * 1553e12c5d1SDavid du Colombier * Xappend(file)[fd] open file to append 1563e12c5d1SDavid du Colombier * Xassign(name, val) assign val to name 1573e12c5d1SDavid du Colombier * Xasync{... Xexit} make thread for {}, no wait 1583e12c5d1SDavid du Colombier * Xbackq{... Xreturn} make thread for {}, push stdout 1593e12c5d1SDavid du Colombier * Xbang complement condition 1603e12c5d1SDavid du Colombier * Xcase(pat, value){...} exec code on match, leave (value) on 1613e12c5d1SDavid du Colombier * stack 1623e12c5d1SDavid du Colombier * Xclose[i] close file descriptor 1633e12c5d1SDavid du Colombier * Xconc(left, right) concatenate, push results 1643e12c5d1SDavid du Colombier * Xcount(name) push var count 1653e12c5d1SDavid du Colombier * Xdelfn(name) delete function definition 1663e12c5d1SDavid du Colombier * Xdeltraps(names) delete named traps 1673e12c5d1SDavid du Colombier * Xdol(name) get variable value 1683e12c5d1SDavid du Colombier * Xqdol(name) concatenate variable components 1693e12c5d1SDavid du Colombier * Xdup[i j] dup file descriptor 1703e12c5d1SDavid du Colombier * Xexit rc exits with status 1713e12c5d1SDavid du Colombier * Xfalse{...} execute {} if false 1723e12c5d1SDavid du Colombier * Xfn(name){... Xreturn} define function 1733e12c5d1SDavid du Colombier * Xfor(var, list){... Xreturn} for loop 1743e12c5d1SDavid du Colombier * Xjump[addr] goto 1753e12c5d1SDavid du Colombier * Xlocal(name, val) create local variable, assign value 1763e12c5d1SDavid du Colombier * Xmark mark stack 1773e12c5d1SDavid du Colombier * Xmatch(pat, str) match pattern, set status 1783e12c5d1SDavid du Colombier * Xpipe[i j]{... Xreturn}{... Xreturn} construct a pipe between 2 new threads, 1793e12c5d1SDavid du Colombier * wait for both 1803e12c5d1SDavid du Colombier * Xpipefd[type]{... Xreturn} connect {} to pipe (input or output, 1813e12c5d1SDavid du Colombier * depending on type), push /dev/fd/?? 1823e12c5d1SDavid du Colombier * Xpopm(value) pop value from stack 1833e12c5d1SDavid du Colombier * Xread(file)[fd] open file to read 1843e12c5d1SDavid du Colombier * Xsettraps(names){... Xreturn} define trap functions 1853e12c5d1SDavid du Colombier * Xshowtraps print trap list 1863e12c5d1SDavid du Colombier * Xsimple(args) run command and wait 1873e12c5d1SDavid du Colombier * Xreturn kill thread 1883e12c5d1SDavid du Colombier * Xsubshell{... Xexit} execute {} in a subshell and wait 1893e12c5d1SDavid du Colombier * Xtrue{...} execute {} if true 1903e12c5d1SDavid du Colombier * Xunlocal delete local variable 1913e12c5d1SDavid du Colombier * Xword[string] push string 1923e12c5d1SDavid du Colombier * Xwrite(file)[fd] open file to write 1933e12c5d1SDavid du Colombier */ 1943e12c5d1SDavid du Colombier void Xappend(void){ 1953e12c5d1SDavid du Colombier char *file; 1963e12c5d1SDavid du Colombier int f; 1973e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 1983e12c5d1SDavid du Colombier default: Xerror(">> requires singleton"); return; 1993e12c5d1SDavid du Colombier case 0: Xerror(">> requires file"); return; 2003e12c5d1SDavid du Colombier case 1: break; 2013e12c5d1SDavid du Colombier } 2023e12c5d1SDavid du Colombier file=runq->argv->words->word; 2033e12c5d1SDavid du Colombier if((f=open(file, 1))<0 && (f=Creat(file))<0){ 204*7dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 205*7dd7cddfSDavid du Colombier Xerror("can't open"); 2063e12c5d1SDavid du Colombier return; 2073e12c5d1SDavid du Colombier } 2083e12c5d1SDavid du Colombier Seek(f, 0L, 2); 2093e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 2103e12c5d1SDavid du Colombier runq->pc++; 2113e12c5d1SDavid du Colombier poplist(); 2123e12c5d1SDavid du Colombier } 2133e12c5d1SDavid du Colombier void Xasync(void){ 2143e12c5d1SDavid du Colombier int null=open("/dev/null", 0); 2153e12c5d1SDavid du Colombier int pid; 2163e12c5d1SDavid du Colombier char npid[10]; 2173e12c5d1SDavid du Colombier if(null<0){ 218*7dd7cddfSDavid du Colombier Xerror("Can't open /dev/null\n"); 2193e12c5d1SDavid du Colombier return; 2203e12c5d1SDavid du Colombier } 221219b2ee8SDavid du Colombier switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){ 2223e12c5d1SDavid du Colombier case -1: 2233e12c5d1SDavid du Colombier close(null); 224*7dd7cddfSDavid du Colombier Xerror("try again"); 2253e12c5d1SDavid du Colombier break; 2263e12c5d1SDavid du Colombier case 0: 2273e12c5d1SDavid du Colombier pushredir(ROPEN, null, 0); 2283e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 2293e12c5d1SDavid du Colombier runq->ret=0; 2303e12c5d1SDavid du Colombier break; 2313e12c5d1SDavid du Colombier default: 2323e12c5d1SDavid du Colombier close(null); 2333e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2343e12c5d1SDavid du Colombier itoa(npid, pid); 2353e12c5d1SDavid du Colombier setvar("apid", newword(npid, (word *)0)); 2363e12c5d1SDavid du Colombier break; 2373e12c5d1SDavid du Colombier } 2383e12c5d1SDavid du Colombier } 239219b2ee8SDavid du Colombier void Xsettrue(void){ 240219b2ee8SDavid du Colombier setstatus(""); 241219b2ee8SDavid du Colombier } 2423e12c5d1SDavid du Colombier void Xbang(void){ 2433e12c5d1SDavid du Colombier setstatus(truestatus()?"false":""); 2443e12c5d1SDavid du Colombier } 2453e12c5d1SDavid du Colombier void Xclose(void){ 2463e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0); 2473e12c5d1SDavid du Colombier runq->pc++; 2483e12c5d1SDavid du Colombier } 2493e12c5d1SDavid du Colombier void Xdup(void){ 2503e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); 2513e12c5d1SDavid du Colombier runq->pc+=2; 2523e12c5d1SDavid du Colombier } 253219b2ee8SDavid du Colombier void Xeflag(void){ 254219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit(); 255219b2ee8SDavid du Colombier } 2563e12c5d1SDavid du Colombier void Xexit(void){ 2573e12c5d1SDavid du Colombier struct var *trapreq; 2583e12c5d1SDavid du Colombier struct word *starval; 2593e12c5d1SDavid du Colombier static int beenhere=0; 2603e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){ 2613e12c5d1SDavid du Colombier trapreq=vlook("sigexit"); 2623e12c5d1SDavid du Colombier if(trapreq->fn){ 2633e12c5d1SDavid du Colombier beenhere=1; 2643e12c5d1SDavid du Colombier --runq->pc; 265219b2ee8SDavid du Colombier starval=vlook("*")->val; 2663e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0); 2673e12c5d1SDavid du Colombier runq->local=newvar(strdup("*"), runq->local); 2683e12c5d1SDavid du Colombier runq->local->val=copywords(starval, (struct word *)0); 2693e12c5d1SDavid du Colombier runq->local->changed=1; 2703e12c5d1SDavid du Colombier runq->redir=runq->startredir=0; 2713e12c5d1SDavid du Colombier return; 2723e12c5d1SDavid du Colombier } 2733e12c5d1SDavid du Colombier } 2743e12c5d1SDavid du Colombier Exit(getstatus()); 2753e12c5d1SDavid du Colombier } 2763e12c5d1SDavid du Colombier void Xfalse(void){ 2773e12c5d1SDavid du Colombier if(truestatus()) runq->pc=runq->code[runq->pc].i; 2783e12c5d1SDavid du Colombier else runq->pc++; 2793e12c5d1SDavid du Colombier } 2803e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */ 2813e12c5d1SDavid du Colombier void Xifnot(void){ 2823e12c5d1SDavid du Colombier if(ifnot) 2833e12c5d1SDavid du Colombier runq->pc++; 2843e12c5d1SDavid du Colombier else 2853e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2863e12c5d1SDavid du Colombier } 2873e12c5d1SDavid du Colombier void Xjump(void){ 2883e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2893e12c5d1SDavid du Colombier } 2903e12c5d1SDavid du Colombier void Xmark(void){ 2913e12c5d1SDavid du Colombier pushlist(); 2923e12c5d1SDavid du Colombier } 2933e12c5d1SDavid du Colombier void Xpopm(void){ 2943e12c5d1SDavid du Colombier poplist(); 2953e12c5d1SDavid du Colombier } 2963e12c5d1SDavid du Colombier void Xread(void){ 2973e12c5d1SDavid du Colombier char *file; 2983e12c5d1SDavid du Colombier int f; 2993e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 3003e12c5d1SDavid du Colombier default: Xerror("< requires singleton\n"); return; 3013e12c5d1SDavid du Colombier case 0: Xerror("< requires file\n"); return; 3023e12c5d1SDavid du Colombier case 1: break; 3033e12c5d1SDavid du Colombier } 3043e12c5d1SDavid du Colombier file=runq->argv->words->word; 3053e12c5d1SDavid du Colombier if((f=open(file, 0))<0){ 306*7dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 307*7dd7cddfSDavid du Colombier Xerror("can't open"); 3083e12c5d1SDavid du Colombier return; 3093e12c5d1SDavid du Colombier } 3103e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3113e12c5d1SDavid du Colombier runq->pc++; 3123e12c5d1SDavid du Colombier poplist(); 3133e12c5d1SDavid du Colombier } 3143e12c5d1SDavid du Colombier void turfredir(void){ 3153e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir) 3163e12c5d1SDavid du Colombier Xpopredir(); 3173e12c5d1SDavid du Colombier } 3183e12c5d1SDavid du Colombier void Xpopredir(void){ 3193e12c5d1SDavid du Colombier struct redir *rp=runq->redir; 3203e12c5d1SDavid du Colombier if(rp==0) panic("turfredir null!", 0); 3213e12c5d1SDavid du Colombier runq->redir=rp->next; 3223e12c5d1SDavid du Colombier if(rp->type==ROPEN) close(rp->from); 3233e12c5d1SDavid du Colombier efree((char *)rp); 3243e12c5d1SDavid du Colombier } 3253e12c5d1SDavid du Colombier void Xreturn(void){ 3263e12c5d1SDavid du Colombier struct thread *p=runq; 3273e12c5d1SDavid du Colombier turfredir(); 3283e12c5d1SDavid du Colombier while(p->argv) poplist(); 3293e12c5d1SDavid du Colombier codefree(p->code); 3303e12c5d1SDavid du Colombier runq=p->ret; 3313e12c5d1SDavid du Colombier efree((char *)p); 3323e12c5d1SDavid du Colombier if(runq==0) Exit(getstatus()); 3333e12c5d1SDavid du Colombier } 3343e12c5d1SDavid du Colombier void Xtrue(void){ 3353e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 3363e12c5d1SDavid du Colombier else runq->pc=runq->code[runq->pc].i; 3373e12c5d1SDavid du Colombier } 3383e12c5d1SDavid du Colombier void Xif(void){ 3393e12c5d1SDavid du Colombier ifnot=1; 3403e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 3413e12c5d1SDavid du Colombier else runq->pc=runq->code[runq->pc].i; 3423e12c5d1SDavid du Colombier } 3433e12c5d1SDavid du Colombier void Xwastrue(void){ 3443e12c5d1SDavid du Colombier ifnot=0; 3453e12c5d1SDavid du Colombier } 3463e12c5d1SDavid du Colombier void Xword(void){ 3473e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s); 3483e12c5d1SDavid du Colombier } 3493e12c5d1SDavid du Colombier void Xwrite(void){ 3503e12c5d1SDavid du Colombier char *file; 3513e12c5d1SDavid du Colombier int f; 3523e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 3533e12c5d1SDavid du Colombier default: Xerror("> requires singleton\n"); return; 3543e12c5d1SDavid du Colombier case 0: Xerror("> requires file\n"); return; 3553e12c5d1SDavid du Colombier case 1: break; 3563e12c5d1SDavid du Colombier } 3573e12c5d1SDavid du Colombier file=runq->argv->words->word; 3583e12c5d1SDavid du Colombier if((f=Creat(file))<0){ 359*7dd7cddfSDavid du Colombier pfmt(err, "%s: ", file); 360*7dd7cddfSDavid du Colombier Xerror("can't open"); 3613e12c5d1SDavid du Colombier return; 3623e12c5d1SDavid du Colombier } 3633e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3643e12c5d1SDavid du Colombier runq->pc++; 3653e12c5d1SDavid du Colombier poplist(); 3663e12c5d1SDavid du Colombier } 3673e12c5d1SDavid du Colombier char *list2str(word *words){ 3683e12c5d1SDavid du Colombier char *value, *s, *t; 3693e12c5d1SDavid du Colombier int len=0; 3703e12c5d1SDavid du Colombier word *ap; 3713e12c5d1SDavid du Colombier for(ap=words;ap;ap=ap->next) 3723e12c5d1SDavid du Colombier len+=1+strlen(ap->word); 3733e12c5d1SDavid du Colombier value=emalloc(len+1); 3743e12c5d1SDavid du Colombier s=value; 3753e12c5d1SDavid du Colombier for(ap=words;ap;ap=ap->next){ 3763e12c5d1SDavid du Colombier for(t=ap->word;*t;) *s++=*t++; 3773e12c5d1SDavid du Colombier *s++=' '; 3783e12c5d1SDavid du Colombier } 3793e12c5d1SDavid du Colombier if(s==value) *s='\0'; 3803e12c5d1SDavid du Colombier else s[-1]='\0'; 3813e12c5d1SDavid du Colombier return value; 3823e12c5d1SDavid du Colombier } 3833e12c5d1SDavid du Colombier void Xmatch(void){ 3843e12c5d1SDavid du Colombier word *p; 3853e12c5d1SDavid du Colombier char *subject; 3863e12c5d1SDavid du Colombier subject=list2str(runq->argv->words); 3873e12c5d1SDavid du Colombier setstatus("no match"); 3883e12c5d1SDavid du Colombier for(p=runq->argv->next->words;p;p=p->next) 3893e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){ 3903e12c5d1SDavid du Colombier setstatus(""); 3913e12c5d1SDavid du Colombier break; 3923e12c5d1SDavid du Colombier } 3933e12c5d1SDavid du Colombier efree(subject); 3943e12c5d1SDavid du Colombier poplist(); 3953e12c5d1SDavid du Colombier poplist(); 3963e12c5d1SDavid du Colombier } 3973e12c5d1SDavid du Colombier void Xcase(void){ 3983e12c5d1SDavid du Colombier word *p; 3993e12c5d1SDavid du Colombier char *s; 4003e12c5d1SDavid du Colombier int ok=0; 4013e12c5d1SDavid du Colombier s=list2str(runq->argv->next->words); 4023e12c5d1SDavid du Colombier for(p=runq->argv->words;p;p=p->next){ 4033e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){ 4043e12c5d1SDavid du Colombier ok=1; 4053e12c5d1SDavid du Colombier break; 4063e12c5d1SDavid du Colombier } 4073e12c5d1SDavid du Colombier } 4083e12c5d1SDavid du Colombier efree(s); 4093e12c5d1SDavid du Colombier if(ok) 4103e12c5d1SDavid du Colombier runq->pc++; 4113e12c5d1SDavid du Colombier else 4123e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 4133e12c5d1SDavid du Colombier poplist(); 4143e12c5d1SDavid du Colombier } 4153e12c5d1SDavid du Colombier word *conclist(word *lp, word *rp, word *tail) 4163e12c5d1SDavid du Colombier { 4173e12c5d1SDavid du Colombier char *buf; 4183e12c5d1SDavid du Colombier word *v; 4193e12c5d1SDavid du Colombier if(lp->next || rp->next) 4203e12c5d1SDavid du Colombier tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next, 4213e12c5d1SDavid du Colombier tail); 4223e12c5d1SDavid du Colombier buf=emalloc(strlen(lp->word)+strlen(rp->word)+1); 4233e12c5d1SDavid du Colombier strcpy(buf, lp->word); 4243e12c5d1SDavid du Colombier strcat(buf, rp->word); 4253e12c5d1SDavid du Colombier v=newword(buf, tail); 4263e12c5d1SDavid du Colombier efree(buf); 4273e12c5d1SDavid du Colombier return v; 4283e12c5d1SDavid du Colombier } 4293e12c5d1SDavid du Colombier void Xconc(void){ 4303e12c5d1SDavid du Colombier word *lp=runq->argv->words; 4313e12c5d1SDavid du Colombier word *rp=runq->argv->next->words; 4323e12c5d1SDavid du Colombier word *vp=runq->argv->next->next->words; 4333e12c5d1SDavid du Colombier int lc=count(lp), rc=count(rp); 4343e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){ 4353e12c5d1SDavid du Colombier if(lc==0 || rc==0){ 4363e12c5d1SDavid du Colombier Xerror("null list in concatenation"); 4373e12c5d1SDavid du Colombier return; 4383e12c5d1SDavid du Colombier } 4393e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){ 4403e12c5d1SDavid du Colombier Xerror("mismatched list lengths in concatenation"); 4413e12c5d1SDavid du Colombier return; 4423e12c5d1SDavid du Colombier } 4433e12c5d1SDavid du Colombier vp=conclist(lp, rp, vp); 4443e12c5d1SDavid du Colombier } 4453e12c5d1SDavid du Colombier poplist(); 4463e12c5d1SDavid du Colombier poplist(); 4473e12c5d1SDavid du Colombier runq->argv->words=vp; 4483e12c5d1SDavid du Colombier } 4493e12c5d1SDavid du Colombier void Xassign(void){ 4503e12c5d1SDavid du Colombier var *v; 4513e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 4523e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 4533e12c5d1SDavid du Colombier return; 4543e12c5d1SDavid du Colombier } 4553e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 4563e12c5d1SDavid du Colombier v=vlook(runq->argv->words->word); 4573e12c5d1SDavid du Colombier poplist(); 4583e12c5d1SDavid du Colombier globlist(); 4593e12c5d1SDavid du Colombier freewords(v->val); 4603e12c5d1SDavid du Colombier v->val=runq->argv->words; 4613e12c5d1SDavid du Colombier v->changed=1; 4623e12c5d1SDavid du Colombier runq->argv->words=0; 4633e12c5d1SDavid du Colombier poplist(); 4643e12c5d1SDavid du Colombier } 4653e12c5d1SDavid du Colombier /* 4663e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail 4673e12c5d1SDavid du Colombier */ 4683e12c5d1SDavid du Colombier word *copywords(word *a, word *tail) 4693e12c5d1SDavid du Colombier { 4703e12c5d1SDavid du Colombier word *v=0, **end; 4713e12c5d1SDavid du Colombier for(end=&v;a;a=a->next,end=&(*end)->next) 4723e12c5d1SDavid du Colombier *end=newword(a->word, 0); 4733e12c5d1SDavid du Colombier *end=tail; 4743e12c5d1SDavid du Colombier return v; 4753e12c5d1SDavid du Colombier } 4763e12c5d1SDavid du Colombier void Xdol(void){ 4773e12c5d1SDavid du Colombier word *a, *star; 4783e12c5d1SDavid du Colombier char *s, *t; 4793e12c5d1SDavid du Colombier int n; 4803e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 4813e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 4823e12c5d1SDavid du Colombier return; 4833e12c5d1SDavid du Colombier } 4843e12c5d1SDavid du Colombier s=runq->argv->words->word; 4853e12c5d1SDavid du Colombier deglob(s); 4863e12c5d1SDavid du Colombier n=0; 4873e12c5d1SDavid du Colombier for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; 4883e12c5d1SDavid du Colombier a=runq->argv->next->words; 4893e12c5d1SDavid du Colombier if(n==0 || *t) 4903e12c5d1SDavid du Colombier a=copywords(vlook(s)->val, a); 4913e12c5d1SDavid du Colombier else{ 4923e12c5d1SDavid du Colombier star=vlook("*")->val; 4933e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){ 4943e12c5d1SDavid du Colombier while(--n) star=star->next; 4953e12c5d1SDavid du Colombier a=newword(star->word, a); 4963e12c5d1SDavid du Colombier } 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier poplist(); 4993e12c5d1SDavid du Colombier runq->argv->words=a; 5003e12c5d1SDavid du Colombier } 5013e12c5d1SDavid du Colombier void Xqdol(void){ 5023e12c5d1SDavid du Colombier word *a, *p; 5033e12c5d1SDavid du Colombier char *s; 5043e12c5d1SDavid du Colombier int n; 5053e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5063e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5073e12c5d1SDavid du Colombier return; 5083e12c5d1SDavid du Colombier } 5093e12c5d1SDavid du Colombier s=runq->argv->words->word; 5103e12c5d1SDavid du Colombier deglob(s); 5113e12c5d1SDavid du Colombier a=vlook(s)->val; 5123e12c5d1SDavid du Colombier poplist(); 5133e12c5d1SDavid du Colombier n=count(a); 5143e12c5d1SDavid du Colombier if(n==0){ 5153e12c5d1SDavid du Colombier pushword(""); 5163e12c5d1SDavid du Colombier return; 5173e12c5d1SDavid du Colombier } 5183e12c5d1SDavid du Colombier for(p=a;p;p=p->next) n+=strlen(p->word); 5193e12c5d1SDavid du Colombier s=emalloc(n); 5203e12c5d1SDavid du Colombier if(a){ 5213e12c5d1SDavid du Colombier strcpy(s, a->word); 5223e12c5d1SDavid du Colombier for(p=a->next;p;p=p->next){ 5233e12c5d1SDavid du Colombier strcat(s, " "); 5243e12c5d1SDavid du Colombier strcat(s, p->word); 5253e12c5d1SDavid du Colombier } 5263e12c5d1SDavid du Colombier } 5273e12c5d1SDavid du Colombier else 5283e12c5d1SDavid du Colombier s[0]='\0'; 5293e12c5d1SDavid du Colombier pushword(s); 5303e12c5d1SDavid du Colombier efree(s); 5313e12c5d1SDavid du Colombier } 5323e12c5d1SDavid du Colombier word *subwords(word *val, int len, word *sub, word *a) 5333e12c5d1SDavid du Colombier { 5343e12c5d1SDavid du Colombier int n; 5353e12c5d1SDavid du Colombier char *s; 5363e12c5d1SDavid du Colombier if(!sub) return a; 5373e12c5d1SDavid du Colombier a=subwords(val, len, sub->next, a); 5383e12c5d1SDavid du Colombier s=sub->word; 5393e12c5d1SDavid du Colombier deglob(s); 5403e12c5d1SDavid du Colombier n=0; 5413e12c5d1SDavid du Colombier while('0'<=*s && *s<='9') n=n*10+ *s++ -'0'; 5423e12c5d1SDavid du Colombier if(n<1 || len<n) return a; 5433e12c5d1SDavid du Colombier for(;n!=1;--n) val=val->next; 5443e12c5d1SDavid du Colombier return newword(val->word, a); 5453e12c5d1SDavid du Colombier } 5463e12c5d1SDavid du Colombier void Xsub(void){ 5473e12c5d1SDavid du Colombier word *a, *v; 5483e12c5d1SDavid du Colombier char *s; 5493e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){ 5503e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5513e12c5d1SDavid du Colombier return; 5523e12c5d1SDavid du Colombier } 5533e12c5d1SDavid du Colombier s=runq->argv->next->words->word; 5543e12c5d1SDavid du Colombier deglob(s); 5553e12c5d1SDavid du Colombier a=runq->argv->next->next->words; 5563e12c5d1SDavid du Colombier v=vlook(s)->val; 5573e12c5d1SDavid du Colombier a=subwords(v, count(v), runq->argv->words, a); 5583e12c5d1SDavid du Colombier poplist(); 5593e12c5d1SDavid du Colombier poplist(); 5603e12c5d1SDavid du Colombier runq->argv->words=a; 5613e12c5d1SDavid du Colombier } 5623e12c5d1SDavid du Colombier void Xcount(void){ 5633e12c5d1SDavid du Colombier word *a; 5643e12c5d1SDavid du Colombier char *s, *t; 5653e12c5d1SDavid du Colombier int n; 5663e12c5d1SDavid du Colombier char num[12]; 5673e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5683e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5693e12c5d1SDavid du Colombier return; 5703e12c5d1SDavid du Colombier } 5713e12c5d1SDavid du Colombier s=runq->argv->words->word; 5723e12c5d1SDavid du Colombier deglob(s); 5733e12c5d1SDavid du Colombier n=0; 5743e12c5d1SDavid du Colombier for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; 5753e12c5d1SDavid du Colombier if(n==0 || *t){ 5763e12c5d1SDavid du Colombier a=vlook(s)->val; 5773e12c5d1SDavid du Colombier itoa(num, count(a)); 5783e12c5d1SDavid du Colombier } 5793e12c5d1SDavid du Colombier else{ 5803e12c5d1SDavid du Colombier a=vlook("*")->val; 5813e12c5d1SDavid du Colombier itoa(num, a && 1<=n && n<=count(a)?1:0); 5823e12c5d1SDavid du Colombier } 5833e12c5d1SDavid du Colombier poplist(); 5843e12c5d1SDavid du Colombier pushword(num); 5853e12c5d1SDavid du Colombier } 5863e12c5d1SDavid du Colombier void Xlocal(void){ 5873e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5883e12c5d1SDavid du Colombier Xerror("variable name must be singleton\n"); 5893e12c5d1SDavid du Colombier return; 5903e12c5d1SDavid du Colombier } 5913e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 5923e12c5d1SDavid du Colombier runq->local=newvar(strdup(runq->argv->words->word), runq->local); 5933e12c5d1SDavid du Colombier runq->local->val=copywords(runq->argv->next->words, (word *)0); 5943e12c5d1SDavid du Colombier runq->local->changed=1; 5953e12c5d1SDavid du Colombier poplist(); 5963e12c5d1SDavid du Colombier poplist(); 5973e12c5d1SDavid du Colombier } 5983e12c5d1SDavid du Colombier void Xunlocal(void){ 5993e12c5d1SDavid du Colombier var *v=runq->local, *hid; 6003e12c5d1SDavid du Colombier if(v==0) panic("Xunlocal: no locals!", 0); 6013e12c5d1SDavid du Colombier runq->local=v->next; 6023e12c5d1SDavid du Colombier hid=vlook(v->name); 6033e12c5d1SDavid du Colombier hid->changed=1; 6043e12c5d1SDavid du Colombier efree(v->name); 6053e12c5d1SDavid du Colombier freewords(v->val); 6063e12c5d1SDavid du Colombier efree((char *)v); 6073e12c5d1SDavid du Colombier } 6083e12c5d1SDavid du Colombier void freewords(word *w) 6093e12c5d1SDavid du Colombier { 6103e12c5d1SDavid du Colombier word *nw; 6113e12c5d1SDavid du Colombier while(w){ 6123e12c5d1SDavid du Colombier efree(w->word); 6133e12c5d1SDavid du Colombier nw=w->next; 6143e12c5d1SDavid du Colombier efree((char *)w); 6153e12c5d1SDavid du Colombier w=nw; 6163e12c5d1SDavid du Colombier } 6173e12c5d1SDavid du Colombier } 6183e12c5d1SDavid du Colombier void Xfn(void){ 6193e12c5d1SDavid du Colombier var *v; 6203e12c5d1SDavid du Colombier word *a; 6213e12c5d1SDavid du Colombier int end; 6223e12c5d1SDavid du Colombier end=runq->code[runq->pc].i; 6233e12c5d1SDavid du Colombier for(a=runq->argv->words;a;a=a->next){ 6243e12c5d1SDavid du Colombier v=gvlook(a->word); 6253e12c5d1SDavid du Colombier if(v->fn) codefree(v->fn); 6263e12c5d1SDavid du Colombier v->fn=codecopy(runq->code); 6273e12c5d1SDavid du Colombier v->pc=runq->pc+2; 6283e12c5d1SDavid du Colombier v->fnchanged=1; 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier runq->pc=end; 6313e12c5d1SDavid du Colombier poplist(); 6323e12c5d1SDavid du Colombier } 6333e12c5d1SDavid du Colombier void Xdelfn(void){ 6343e12c5d1SDavid du Colombier var *v; 6353e12c5d1SDavid du Colombier word *a; 6363e12c5d1SDavid du Colombier for(a=runq->argv->words;a;a=a->next){ 6373e12c5d1SDavid du Colombier v=gvlook(a->word); 6383e12c5d1SDavid du Colombier if(v->fn) codefree(v->fn); 6393e12c5d1SDavid du Colombier v->fn=0; 6403e12c5d1SDavid du Colombier v->fnchanged=1; 6413e12c5d1SDavid du Colombier } 6423e12c5d1SDavid du Colombier poplist(); 6433e12c5d1SDavid du Colombier } 6443e12c5d1SDavid du Colombier void Xpipe(void){ 6453e12c5d1SDavid du Colombier struct thread *p=runq; 6463e12c5d1SDavid du Colombier int pc=p->pc, forkid; 6473e12c5d1SDavid du Colombier int lfd=p->code[pc++].i; 6483e12c5d1SDavid du Colombier int rfd=p->code[pc++].i; 6493e12c5d1SDavid du Colombier int pfd[2]; 6503e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 651*7dd7cddfSDavid du Colombier Xerror("can't get pipe"); 6523e12c5d1SDavid du Colombier return; 6533e12c5d1SDavid du Colombier } 6543e12c5d1SDavid du Colombier switch(forkid=fork()){ 6553e12c5d1SDavid du Colombier case -1: 656*7dd7cddfSDavid du Colombier Xerror("try again"); 6573e12c5d1SDavid du Colombier break; 6583e12c5d1SDavid du Colombier case 0: 6593e12c5d1SDavid du Colombier start(p->code, pc+2, runq->local); 6603e12c5d1SDavid du Colombier runq->ret=0; 6613e12c5d1SDavid du Colombier close(pfd[PRD]); 6623e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PWR], lfd); 6633e12c5d1SDavid du Colombier break; 6643e12c5d1SDavid du Colombier default: 6653e12c5d1SDavid du Colombier start(p->code, p->code[pc].i, runq->local); 6663e12c5d1SDavid du Colombier close(pfd[PWR]); 6673e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PRD], rfd); 6683e12c5d1SDavid du Colombier p->pc=p->code[pc+1].i; 6693e12c5d1SDavid du Colombier p->pid=forkid; 6703e12c5d1SDavid du Colombier break; 6713e12c5d1SDavid du Colombier } 6723e12c5d1SDavid du Colombier } 6733e12c5d1SDavid du Colombier char *concstatus(char *s, char *t) 6743e12c5d1SDavid du Colombier { 6753e12c5d1SDavid du Colombier static char v[NSTATUS+1]; 6763e12c5d1SDavid du Colombier int n=strlen(s); 6773e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS); 6783e12c5d1SDavid du Colombier if(n<NSTATUS){ 6793e12c5d1SDavid du Colombier v[n]='|'; 6803e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1); 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier v[NSTATUS]='\0'; 6833e12c5d1SDavid du Colombier return v; 6843e12c5d1SDavid du Colombier } 6853e12c5d1SDavid du Colombier void Xpipewait(void){ 6863e12c5d1SDavid du Colombier char status[NSTATUS+1]; 6873e12c5d1SDavid du Colombier if(runq->pid==-1) 6883e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus())); 6893e12c5d1SDavid du Colombier else{ 6903e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS); 6913e12c5d1SDavid du Colombier status[NSTATUS]='\0'; 6923e12c5d1SDavid du Colombier Waitfor(runq->pid, 1); 6933e12c5d1SDavid du Colombier runq->pid=-1; 6943e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status)); 6953e12c5d1SDavid du Colombier } 6963e12c5d1SDavid du Colombier } 6973e12c5d1SDavid du Colombier void Xrdcmds(void){ 6983e12c5d1SDavid du Colombier struct thread *p=runq; 6993e12c5d1SDavid du Colombier word *prompt; 7003e12c5d1SDavid du Colombier flush(err); 7013e12c5d1SDavid du Colombier nerror=0; 7023e12c5d1SDavid du Colombier if(flag['s'] && !truestatus()) 7033e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val); 7043e12c5d1SDavid du Colombier if(runq->iflag){ 7053e12c5d1SDavid du Colombier prompt=vlook("prompt")->val; 7063e12c5d1SDavid du Colombier if(prompt) 7073e12c5d1SDavid du Colombier promptstr=prompt->word; 7083e12c5d1SDavid du Colombier else 7093e12c5d1SDavid du Colombier promptstr="% "; 7103e12c5d1SDavid du Colombier } 7113e12c5d1SDavid du Colombier Noerror(); 7123e12c5d1SDavid du Colombier if(yyparse()){ 7133e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){ 7143e12c5d1SDavid du Colombier if(p->cmdfile) efree(p->cmdfile); 7153e12c5d1SDavid du Colombier closeio(p->cmdfd); 7163e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */ 7173e12c5d1SDavid du Colombier } 7183e12c5d1SDavid du Colombier else{ 7193e12c5d1SDavid du Colombier if(Eintr()){ 7203e12c5d1SDavid du Colombier pchr(err, '\n'); 7213e12c5d1SDavid du Colombier p->eof=0; 7223e12c5d1SDavid du Colombier } 7233e12c5d1SDavid du Colombier --p->pc; /* go back for next command */ 7243e12c5d1SDavid du Colombier } 7253e12c5d1SDavid du Colombier } 7263e12c5d1SDavid du Colombier else{ 727*7dd7cddfSDavid du Colombier ntrap = 0; /* avoid double-interrupts during blocked writes */ 7283e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */ 7293e12c5d1SDavid du Colombier start(codebuf, 1, runq->local); 7303e12c5d1SDavid du Colombier } 7313e12c5d1SDavid du Colombier freenodes(); 7323e12c5d1SDavid du Colombier } 7333e12c5d1SDavid du Colombier void Xerror(char *s) 7343e12c5d1SDavid du Colombier { 7353e12c5d1SDavid du Colombier pfmt(err, "rc: %s\n", s); 7363e12c5d1SDavid du Colombier flush(err); 7373e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn(); 7383e12c5d1SDavid du Colombier } 7393e12c5d1SDavid du Colombier void Xbackq(void){ 7403e12c5d1SDavid du Colombier char wd[8193]; 7413e12c5d1SDavid du Colombier int c; 7423e12c5d1SDavid du Colombier char *s, *ewd=&wd[8192], *stop; 7433e12c5d1SDavid du Colombier struct io *f; 7443e12c5d1SDavid du Colombier var *ifs=vlook("ifs"); 7453e12c5d1SDavid du Colombier word *v, *nextv; 7463e12c5d1SDavid du Colombier int pfd[2]; 7473e12c5d1SDavid du Colombier int pid; 7483e12c5d1SDavid du Colombier stop=ifs->val?ifs->val->word:""; 7493e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 7503e12c5d1SDavid du Colombier Xerror("can't make pipe"); 7513e12c5d1SDavid du Colombier return; 7523e12c5d1SDavid du Colombier } 7533e12c5d1SDavid du Colombier switch(pid=fork()){ 7543e12c5d1SDavid du Colombier case -1: Xerror("try again"); 7553e12c5d1SDavid du Colombier close(pfd[PRD]); 7563e12c5d1SDavid du Colombier close(pfd[PWR]); 7573e12c5d1SDavid du Colombier return; 7583e12c5d1SDavid du Colombier case 0: 7593e12c5d1SDavid du Colombier close(pfd[PRD]); 7603e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 7613e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PWR], 1); 7623e12c5d1SDavid du Colombier return; 7633e12c5d1SDavid du Colombier default: 7643e12c5d1SDavid du Colombier close(pfd[PWR]); 7653e12c5d1SDavid du Colombier f=openfd(pfd[PRD]); 7663e12c5d1SDavid du Colombier s=wd; 7673e12c5d1SDavid du Colombier v=0; 7683e12c5d1SDavid du Colombier while((c=rchr(f))!=EOF){ 7693e12c5d1SDavid du Colombier if(strchr(stop, c) || s==ewd){ 7703e12c5d1SDavid du Colombier if(s!=wd){ 7713e12c5d1SDavid du Colombier *s='\0'; 7723e12c5d1SDavid du Colombier v=newword(wd, v); 7733e12c5d1SDavid du Colombier s=wd; 7743e12c5d1SDavid du Colombier } 7753e12c5d1SDavid du Colombier } 7763e12c5d1SDavid du Colombier else *s++=c; 7773e12c5d1SDavid du Colombier } 7783e12c5d1SDavid du Colombier if(s!=wd){ 7793e12c5d1SDavid du Colombier *s='\0'; 7803e12c5d1SDavid du Colombier v=newword(wd, v); 7813e12c5d1SDavid du Colombier } 7823e12c5d1SDavid du Colombier closeio(f); 7833e12c5d1SDavid du Colombier Waitfor(pid, 0); 7843e12c5d1SDavid du Colombier /* v points to reversed arglist -- reverse it onto argv */ 7853e12c5d1SDavid du Colombier while(v){ 7863e12c5d1SDavid du Colombier nextv=v->next; 7873e12c5d1SDavid du Colombier v->next=runq->argv->words; 7883e12c5d1SDavid du Colombier runq->argv->words=v; 7893e12c5d1SDavid du Colombier v=nextv; 7903e12c5d1SDavid du Colombier } 7913e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 7923e12c5d1SDavid du Colombier return; 7933e12c5d1SDavid du Colombier } 7943e12c5d1SDavid du Colombier } 7953e12c5d1SDavid du Colombier /* 7963e12c5d1SDavid du Colombier * Who should wait for the exit from the fork? 7973e12c5d1SDavid du Colombier */ 7983e12c5d1SDavid du Colombier void Xpipefd(void){ 7993e12c5d1SDavid du Colombier struct thread *p=runq; 8003e12c5d1SDavid du Colombier int pc=p->pc; 8013e12c5d1SDavid du Colombier char name[40]; 8023e12c5d1SDavid du Colombier int pfd[2]; 8033e12c5d1SDavid du Colombier int sidefd, mainfd; 8043e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 8053e12c5d1SDavid du Colombier Xerror("can't get pipe"); 8063e12c5d1SDavid du Colombier return; 8073e12c5d1SDavid du Colombier } 8083e12c5d1SDavid du Colombier if(p->code[pc].i==READ){ 8093e12c5d1SDavid du Colombier sidefd=pfd[PWR]; 8103e12c5d1SDavid du Colombier mainfd=pfd[PRD]; 8113e12c5d1SDavid du Colombier } 8123e12c5d1SDavid du Colombier else{ 8133e12c5d1SDavid du Colombier sidefd=pfd[PRD]; 8143e12c5d1SDavid du Colombier mainfd=pfd[PWR]; 8153e12c5d1SDavid du Colombier } 8163e12c5d1SDavid du Colombier switch(fork()){ 8173e12c5d1SDavid du Colombier case -1: 8183e12c5d1SDavid du Colombier Xerror("try again"); 8193e12c5d1SDavid du Colombier break; 8203e12c5d1SDavid du Colombier case 0: 8213e12c5d1SDavid du Colombier start(p->code, pc+2, runq->local); 8223e12c5d1SDavid du Colombier close(mainfd); 8233e12c5d1SDavid du Colombier pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); 8243e12c5d1SDavid du Colombier runq->ret=0; 8253e12c5d1SDavid du Colombier break; 8263e12c5d1SDavid du Colombier default: 8273e12c5d1SDavid du Colombier close(sidefd); 8283e12c5d1SDavid du Colombier pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ 8293e12c5d1SDavid du Colombier strcpy(name, Fdprefix); 8303e12c5d1SDavid du Colombier itoa(name+strlen(name), mainfd); 8313e12c5d1SDavid du Colombier pushword(name); 8323e12c5d1SDavid du Colombier p->pc=p->code[pc+1].i; 8333e12c5d1SDavid du Colombier break; 8343e12c5d1SDavid du Colombier } 8353e12c5d1SDavid du Colombier } 8363e12c5d1SDavid du Colombier void Xsubshell(void){ 8373e12c5d1SDavid du Colombier int pid; 8383e12c5d1SDavid du Colombier switch(pid=fork()){ 8393e12c5d1SDavid du Colombier case -1: 8403e12c5d1SDavid du Colombier Xerror("try again"); 8413e12c5d1SDavid du Colombier break; 8423e12c5d1SDavid du Colombier case 0: 8433e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 8443e12c5d1SDavid du Colombier runq->ret=0; 8453e12c5d1SDavid du Colombier break; 8463e12c5d1SDavid du Colombier default: 8473e12c5d1SDavid du Colombier Waitfor(pid, 1); 8483e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 8493e12c5d1SDavid du Colombier break; 8503e12c5d1SDavid du Colombier } 8513e12c5d1SDavid du Colombier } 8523e12c5d1SDavid du Colombier void setstatus(char *s) 8533e12c5d1SDavid du Colombier { 8543e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0)); 8553e12c5d1SDavid du Colombier } 8563e12c5d1SDavid du Colombier char *getstatus(void){ 8573e12c5d1SDavid du Colombier var *status=vlook("status"); 8583e12c5d1SDavid du Colombier return status->val?status->val->word:""; 8593e12c5d1SDavid du Colombier } 8603e12c5d1SDavid du Colombier int truestatus(void){ 8613e12c5d1SDavid du Colombier char *s; 8623e12c5d1SDavid du Colombier for(s=getstatus();*s;s++) 8633e12c5d1SDavid du Colombier if(*s!='|' && *s!='0') return 0; 8643e12c5d1SDavid du Colombier return 1; 8653e12c5d1SDavid du Colombier } 8663e12c5d1SDavid du Colombier void Xdelhere(void){ 8673e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s); 8683e12c5d1SDavid du Colombier } 8693e12c5d1SDavid du Colombier void Xfor(void){ 8703e12c5d1SDavid du Colombier if(runq->argv->words==0){ 8713e12c5d1SDavid du Colombier poplist(); 8723e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 8733e12c5d1SDavid du Colombier } 8743e12c5d1SDavid du Colombier else{ 8753e12c5d1SDavid du Colombier freelist(runq->local->val); 8763e12c5d1SDavid du Colombier runq->local->val=runq->argv->words; 8773e12c5d1SDavid du Colombier runq->local->changed=1; 8783e12c5d1SDavid du Colombier runq->argv->words=runq->argv->words->next; 8793e12c5d1SDavid du Colombier runq->local->val->next=0; 8803e12c5d1SDavid du Colombier runq->pc++; 8813e12c5d1SDavid du Colombier } 8823e12c5d1SDavid du Colombier } 8833e12c5d1SDavid du Colombier void Xglob(void){ 8843e12c5d1SDavid du Colombier globlist(); 8853e12c5d1SDavid du Colombier } 886