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 */ 1013e12c5d1SDavid du Colombier 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(argc==1 && Isatty(0)) flag['i']=flagset; 1093e12c5d1SDavid du Colombier if(argv[0][0]=='-') flag['l']=flagset; 1103e12c5d1SDavid du Colombier if(flag['I']) flag['i']=0; 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); 119*219b2ee8SDavid 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*219b2ee8SDavid du Colombier Xperror(file); 2053e12c5d1SDavid du Colombier return; 2063e12c5d1SDavid du Colombier } 2073e12c5d1SDavid du Colombier Seek(f, 0L, 2); 2083e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 2093e12c5d1SDavid du Colombier runq->pc++; 2103e12c5d1SDavid du Colombier poplist(); 2113e12c5d1SDavid du Colombier } 2123e12c5d1SDavid du Colombier void Xasync(void){ 2133e12c5d1SDavid du Colombier int null=open("/dev/null", 0); 2143e12c5d1SDavid du Colombier int pid; 2153e12c5d1SDavid du Colombier char npid[10]; 2163e12c5d1SDavid du Colombier if(null<0){ 217*219b2ee8SDavid du Colombier Xperror("/dev/null"); 2183e12c5d1SDavid du Colombier return; 2193e12c5d1SDavid du Colombier } 220*219b2ee8SDavid du Colombier switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){ 2213e12c5d1SDavid du Colombier case -1: 2223e12c5d1SDavid du Colombier close(null); 223*219b2ee8SDavid du Colombier Xperror("rfork"); 2243e12c5d1SDavid du Colombier break; 2253e12c5d1SDavid du Colombier case 0: 2263e12c5d1SDavid du Colombier pushredir(ROPEN, null, 0); 2273e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 2283e12c5d1SDavid du Colombier runq->ret=0; 2293e12c5d1SDavid du Colombier break; 2303e12c5d1SDavid du Colombier default: 2313e12c5d1SDavid du Colombier close(null); 2323e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2333e12c5d1SDavid du Colombier itoa(npid, pid); 2343e12c5d1SDavid du Colombier setvar("apid", newword(npid, (word *)0)); 2353e12c5d1SDavid du Colombier break; 2363e12c5d1SDavid du Colombier } 2373e12c5d1SDavid du Colombier } 238*219b2ee8SDavid du Colombier void Xsettrue(void){ 239*219b2ee8SDavid du Colombier setstatus(""); 240*219b2ee8SDavid du Colombier } 2413e12c5d1SDavid du Colombier void Xbang(void){ 2423e12c5d1SDavid du Colombier setstatus(truestatus()?"false":""); 2433e12c5d1SDavid du Colombier } 2443e12c5d1SDavid du Colombier void Xclose(void){ 2453e12c5d1SDavid du Colombier pushredir(RCLOSE, runq->code[runq->pc].i, 0); 2463e12c5d1SDavid du Colombier runq->pc++; 2473e12c5d1SDavid du Colombier } 2483e12c5d1SDavid du Colombier void Xdup(void){ 2493e12c5d1SDavid du Colombier pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i); 2503e12c5d1SDavid du Colombier runq->pc+=2; 2513e12c5d1SDavid du Colombier } 252*219b2ee8SDavid du Colombier void Xeflag(void){ 253*219b2ee8SDavid du Colombier if(eflagok && !truestatus()) Xexit(); 254*219b2ee8SDavid du Colombier } 2553e12c5d1SDavid du Colombier void Xexit(void){ 2563e12c5d1SDavid du Colombier struct var *trapreq; 2573e12c5d1SDavid du Colombier struct word *starval; 2583e12c5d1SDavid du Colombier static int beenhere=0; 2593e12c5d1SDavid du Colombier if(getpid()==mypid && !beenhere){ 2603e12c5d1SDavid du Colombier trapreq=vlook("sigexit"); 2613e12c5d1SDavid du Colombier if(trapreq->fn){ 2623e12c5d1SDavid du Colombier beenhere=1; 2633e12c5d1SDavid du Colombier --runq->pc; 264*219b2ee8SDavid du Colombier starval=vlook("*")->val; 2653e12c5d1SDavid du Colombier start(trapreq->fn, trapreq->pc, (struct var *)0); 2663e12c5d1SDavid du Colombier runq->local=newvar(strdup("*"), runq->local); 2673e12c5d1SDavid du Colombier runq->local->val=copywords(starval, (struct word *)0); 2683e12c5d1SDavid du Colombier runq->local->changed=1; 2693e12c5d1SDavid du Colombier runq->redir=runq->startredir=0; 2703e12c5d1SDavid du Colombier return; 2713e12c5d1SDavid du Colombier } 2723e12c5d1SDavid du Colombier } 2733e12c5d1SDavid du Colombier Exit(getstatus()); 2743e12c5d1SDavid du Colombier } 2753e12c5d1SDavid du Colombier void Xfalse(void){ 2763e12c5d1SDavid du Colombier if(truestatus()) runq->pc=runq->code[runq->pc].i; 2773e12c5d1SDavid du Colombier else runq->pc++; 2783e12c5d1SDavid du Colombier } 2793e12c5d1SDavid du Colombier int ifnot; /* dynamic if not flag */ 2803e12c5d1SDavid du Colombier void Xifnot(void){ 2813e12c5d1SDavid du Colombier if(ifnot) 2823e12c5d1SDavid du Colombier runq->pc++; 2833e12c5d1SDavid du Colombier else 2843e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2853e12c5d1SDavid du Colombier } 2863e12c5d1SDavid du Colombier void Xjump(void){ 2873e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 2883e12c5d1SDavid du Colombier } 2893e12c5d1SDavid du Colombier void Xmark(void){ 2903e12c5d1SDavid du Colombier pushlist(); 2913e12c5d1SDavid du Colombier } 2923e12c5d1SDavid du Colombier void Xpopm(void){ 2933e12c5d1SDavid du Colombier poplist(); 2943e12c5d1SDavid du Colombier } 2953e12c5d1SDavid du Colombier void Xread(void){ 2963e12c5d1SDavid du Colombier char *file; 2973e12c5d1SDavid du Colombier int f; 2983e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 2993e12c5d1SDavid du Colombier default: Xerror("< requires singleton\n"); return; 3003e12c5d1SDavid du Colombier case 0: Xerror("< requires file\n"); return; 3013e12c5d1SDavid du Colombier case 1: break; 3023e12c5d1SDavid du Colombier } 3033e12c5d1SDavid du Colombier file=runq->argv->words->word; 3043e12c5d1SDavid du Colombier if((f=open(file, 0))<0){ 305*219b2ee8SDavid du Colombier Xperror(file); 3063e12c5d1SDavid du Colombier return; 3073e12c5d1SDavid du Colombier } 3083e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3093e12c5d1SDavid du Colombier runq->pc++; 3103e12c5d1SDavid du Colombier poplist(); 3113e12c5d1SDavid du Colombier } 3123e12c5d1SDavid du Colombier void turfredir(void){ 3133e12c5d1SDavid du Colombier while(runq->redir!=runq->startredir) 3143e12c5d1SDavid du Colombier Xpopredir(); 3153e12c5d1SDavid du Colombier } 3163e12c5d1SDavid du Colombier void Xpopredir(void){ 3173e12c5d1SDavid du Colombier struct redir *rp=runq->redir; 3183e12c5d1SDavid du Colombier if(rp==0) panic("turfredir null!", 0); 3193e12c5d1SDavid du Colombier runq->redir=rp->next; 3203e12c5d1SDavid du Colombier if(rp->type==ROPEN) close(rp->from); 3213e12c5d1SDavid du Colombier efree((char *)rp); 3223e12c5d1SDavid du Colombier } 3233e12c5d1SDavid du Colombier void Xreturn(void){ 3243e12c5d1SDavid du Colombier struct thread *p=runq; 3253e12c5d1SDavid du Colombier turfredir(); 3263e12c5d1SDavid du Colombier while(p->argv) poplist(); 3273e12c5d1SDavid du Colombier codefree(p->code); 3283e12c5d1SDavid du Colombier runq=p->ret; 3293e12c5d1SDavid du Colombier efree((char *)p); 3303e12c5d1SDavid du Colombier if(runq==0) Exit(getstatus()); 3313e12c5d1SDavid du Colombier } 3323e12c5d1SDavid du Colombier void Xtrue(void){ 3333e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 3343e12c5d1SDavid du Colombier else runq->pc=runq->code[runq->pc].i; 3353e12c5d1SDavid du Colombier } 3363e12c5d1SDavid du Colombier void Xif(void){ 3373e12c5d1SDavid du Colombier ifnot=1; 3383e12c5d1SDavid du Colombier if(truestatus()) runq->pc++; 3393e12c5d1SDavid du Colombier else runq->pc=runq->code[runq->pc].i; 3403e12c5d1SDavid du Colombier } 3413e12c5d1SDavid du Colombier void Xwastrue(void){ 3423e12c5d1SDavid du Colombier ifnot=0; 3433e12c5d1SDavid du Colombier } 3443e12c5d1SDavid du Colombier void Xword(void){ 3453e12c5d1SDavid du Colombier pushword(runq->code[runq->pc++].s); 3463e12c5d1SDavid du Colombier } 3473e12c5d1SDavid du Colombier void Xwrite(void){ 3483e12c5d1SDavid du Colombier char *file; 3493e12c5d1SDavid du Colombier int f; 3503e12c5d1SDavid du Colombier switch(count(runq->argv->words)){ 3513e12c5d1SDavid du Colombier default: Xerror("> requires singleton\n"); return; 3523e12c5d1SDavid du Colombier case 0: Xerror("> requires file\n"); return; 3533e12c5d1SDavid du Colombier case 1: break; 3543e12c5d1SDavid du Colombier } 3553e12c5d1SDavid du Colombier file=runq->argv->words->word; 3563e12c5d1SDavid du Colombier if((f=Creat(file))<0){ 357*219b2ee8SDavid du Colombier Xperror(file); 3583e12c5d1SDavid du Colombier return; 3593e12c5d1SDavid du Colombier } 3603e12c5d1SDavid du Colombier pushredir(ROPEN, f, runq->code[runq->pc].i); 3613e12c5d1SDavid du Colombier runq->pc++; 3623e12c5d1SDavid du Colombier poplist(); 3633e12c5d1SDavid du Colombier } 3643e12c5d1SDavid du Colombier char *list2str(word *words){ 3653e12c5d1SDavid du Colombier char *value, *s, *t; 3663e12c5d1SDavid du Colombier int len=0; 3673e12c5d1SDavid du Colombier word *ap; 3683e12c5d1SDavid du Colombier for(ap=words;ap;ap=ap->next) 3693e12c5d1SDavid du Colombier len+=1+strlen(ap->word); 3703e12c5d1SDavid du Colombier value=emalloc(len+1); 3713e12c5d1SDavid du Colombier s=value; 3723e12c5d1SDavid du Colombier for(ap=words;ap;ap=ap->next){ 3733e12c5d1SDavid du Colombier for(t=ap->word;*t;) *s++=*t++; 3743e12c5d1SDavid du Colombier *s++=' '; 3753e12c5d1SDavid du Colombier } 3763e12c5d1SDavid du Colombier if(s==value) *s='\0'; 3773e12c5d1SDavid du Colombier else s[-1]='\0'; 3783e12c5d1SDavid du Colombier return value; 3793e12c5d1SDavid du Colombier } 3803e12c5d1SDavid du Colombier void Xmatch(void){ 3813e12c5d1SDavid du Colombier word *p; 3823e12c5d1SDavid du Colombier char *subject; 3833e12c5d1SDavid du Colombier subject=list2str(runq->argv->words); 3843e12c5d1SDavid du Colombier setstatus("no match"); 3853e12c5d1SDavid du Colombier for(p=runq->argv->next->words;p;p=p->next) 3863e12c5d1SDavid du Colombier if(match(subject, p->word, '\0')){ 3873e12c5d1SDavid du Colombier setstatus(""); 3883e12c5d1SDavid du Colombier break; 3893e12c5d1SDavid du Colombier } 3903e12c5d1SDavid du Colombier efree(subject); 3913e12c5d1SDavid du Colombier poplist(); 3923e12c5d1SDavid du Colombier poplist(); 3933e12c5d1SDavid du Colombier } 3943e12c5d1SDavid du Colombier void Xcase(void){ 3953e12c5d1SDavid du Colombier word *p; 3963e12c5d1SDavid du Colombier char *s; 3973e12c5d1SDavid du Colombier int ok=0; 3983e12c5d1SDavid du Colombier s=list2str(runq->argv->next->words); 3993e12c5d1SDavid du Colombier for(p=runq->argv->words;p;p=p->next){ 4003e12c5d1SDavid du Colombier if(match(s, p->word, '\0')){ 4013e12c5d1SDavid du Colombier ok=1; 4023e12c5d1SDavid du Colombier break; 4033e12c5d1SDavid du Colombier } 4043e12c5d1SDavid du Colombier } 4053e12c5d1SDavid du Colombier efree(s); 4063e12c5d1SDavid du Colombier if(ok) 4073e12c5d1SDavid du Colombier runq->pc++; 4083e12c5d1SDavid du Colombier else 4093e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 4103e12c5d1SDavid du Colombier poplist(); 4113e12c5d1SDavid du Colombier } 4123e12c5d1SDavid du Colombier word *conclist(word *lp, word *rp, word *tail) 4133e12c5d1SDavid du Colombier { 4143e12c5d1SDavid du Colombier char *buf; 4153e12c5d1SDavid du Colombier word *v; 4163e12c5d1SDavid du Colombier if(lp->next || rp->next) 4173e12c5d1SDavid du Colombier tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next, 4183e12c5d1SDavid du Colombier tail); 4193e12c5d1SDavid du Colombier buf=emalloc(strlen(lp->word)+strlen(rp->word)+1); 4203e12c5d1SDavid du Colombier strcpy(buf, lp->word); 4213e12c5d1SDavid du Colombier strcat(buf, rp->word); 4223e12c5d1SDavid du Colombier v=newword(buf, tail); 4233e12c5d1SDavid du Colombier efree(buf); 4243e12c5d1SDavid du Colombier return v; 4253e12c5d1SDavid du Colombier } 4263e12c5d1SDavid du Colombier void Xconc(void){ 4273e12c5d1SDavid du Colombier word *lp=runq->argv->words; 4283e12c5d1SDavid du Colombier word *rp=runq->argv->next->words; 4293e12c5d1SDavid du Colombier word *vp=runq->argv->next->next->words; 4303e12c5d1SDavid du Colombier int lc=count(lp), rc=count(rp); 4313e12c5d1SDavid du Colombier if(lc!=0 || rc!=0){ 4323e12c5d1SDavid du Colombier if(lc==0 || rc==0){ 4333e12c5d1SDavid du Colombier Xerror("null list in concatenation"); 4343e12c5d1SDavid du Colombier return; 4353e12c5d1SDavid du Colombier } 4363e12c5d1SDavid du Colombier if(lc!=1 && rc!=1 && lc!=rc){ 4373e12c5d1SDavid du Colombier Xerror("mismatched list lengths in concatenation"); 4383e12c5d1SDavid du Colombier return; 4393e12c5d1SDavid du Colombier } 4403e12c5d1SDavid du Colombier vp=conclist(lp, rp, vp); 4413e12c5d1SDavid du Colombier } 4423e12c5d1SDavid du Colombier poplist(); 4433e12c5d1SDavid du Colombier poplist(); 4443e12c5d1SDavid du Colombier runq->argv->words=vp; 4453e12c5d1SDavid du Colombier } 4463e12c5d1SDavid du Colombier void Xassign(void){ 4473e12c5d1SDavid du Colombier var *v; 4483e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 4493e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 4503e12c5d1SDavid du Colombier return; 4513e12c5d1SDavid du Colombier } 4523e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 4533e12c5d1SDavid du Colombier v=vlook(runq->argv->words->word); 4543e12c5d1SDavid du Colombier poplist(); 4553e12c5d1SDavid du Colombier globlist(); 4563e12c5d1SDavid du Colombier freewords(v->val); 4573e12c5d1SDavid du Colombier v->val=runq->argv->words; 4583e12c5d1SDavid du Colombier v->changed=1; 4593e12c5d1SDavid du Colombier runq->argv->words=0; 4603e12c5d1SDavid du Colombier poplist(); 4613e12c5d1SDavid du Colombier } 4623e12c5d1SDavid du Colombier /* 4633e12c5d1SDavid du Colombier * copy arglist a, adding the copy to the front of tail 4643e12c5d1SDavid du Colombier */ 4653e12c5d1SDavid du Colombier word *copywords(word *a, word *tail) 4663e12c5d1SDavid du Colombier { 4673e12c5d1SDavid du Colombier word *v=0, **end; 4683e12c5d1SDavid du Colombier for(end=&v;a;a=a->next,end=&(*end)->next) 4693e12c5d1SDavid du Colombier *end=newword(a->word, 0); 4703e12c5d1SDavid du Colombier *end=tail; 4713e12c5d1SDavid du Colombier return v; 4723e12c5d1SDavid du Colombier } 4733e12c5d1SDavid du Colombier void Xdol(void){ 4743e12c5d1SDavid du Colombier word *a, *star; 4753e12c5d1SDavid du Colombier char *s, *t; 4763e12c5d1SDavid du Colombier int n; 4773e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 4783e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 4793e12c5d1SDavid du Colombier return; 4803e12c5d1SDavid du Colombier } 4813e12c5d1SDavid du Colombier s=runq->argv->words->word; 4823e12c5d1SDavid du Colombier deglob(s); 4833e12c5d1SDavid du Colombier n=0; 4843e12c5d1SDavid du Colombier for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; 4853e12c5d1SDavid du Colombier a=runq->argv->next->words; 4863e12c5d1SDavid du Colombier if(n==0 || *t) 4873e12c5d1SDavid du Colombier a=copywords(vlook(s)->val, a); 4883e12c5d1SDavid du Colombier else{ 4893e12c5d1SDavid du Colombier star=vlook("*")->val; 4903e12c5d1SDavid du Colombier if(star && 1<=n && n<=count(star)){ 4913e12c5d1SDavid du Colombier while(--n) star=star->next; 4923e12c5d1SDavid du Colombier a=newword(star->word, a); 4933e12c5d1SDavid du Colombier } 4943e12c5d1SDavid du Colombier } 4953e12c5d1SDavid du Colombier poplist(); 4963e12c5d1SDavid du Colombier runq->argv->words=a; 4973e12c5d1SDavid du Colombier } 4983e12c5d1SDavid du Colombier void Xqdol(void){ 4993e12c5d1SDavid du Colombier word *a, *p; 5003e12c5d1SDavid du Colombier char *s; 5013e12c5d1SDavid du Colombier int n; 5023e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5033e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5043e12c5d1SDavid du Colombier return; 5053e12c5d1SDavid du Colombier } 5063e12c5d1SDavid du Colombier s=runq->argv->words->word; 5073e12c5d1SDavid du Colombier deglob(s); 5083e12c5d1SDavid du Colombier a=vlook(s)->val; 5093e12c5d1SDavid du Colombier poplist(); 5103e12c5d1SDavid du Colombier n=count(a); 5113e12c5d1SDavid du Colombier if(n==0){ 5123e12c5d1SDavid du Colombier pushword(""); 5133e12c5d1SDavid du Colombier return; 5143e12c5d1SDavid du Colombier } 5153e12c5d1SDavid du Colombier for(p=a;p;p=p->next) n+=strlen(p->word); 5163e12c5d1SDavid du Colombier s=emalloc(n); 5173e12c5d1SDavid du Colombier if(a){ 5183e12c5d1SDavid du Colombier strcpy(s, a->word); 5193e12c5d1SDavid du Colombier for(p=a->next;p;p=p->next){ 5203e12c5d1SDavid du Colombier strcat(s, " "); 5213e12c5d1SDavid du Colombier strcat(s, p->word); 5223e12c5d1SDavid du Colombier } 5233e12c5d1SDavid du Colombier } 5243e12c5d1SDavid du Colombier else 5253e12c5d1SDavid du Colombier s[0]='\0'; 5263e12c5d1SDavid du Colombier pushword(s); 5273e12c5d1SDavid du Colombier efree(s); 5283e12c5d1SDavid du Colombier } 5293e12c5d1SDavid du Colombier word *subwords(word *val, int len, word *sub, word *a) 5303e12c5d1SDavid du Colombier { 5313e12c5d1SDavid du Colombier int n; 5323e12c5d1SDavid du Colombier char *s; 5333e12c5d1SDavid du Colombier if(!sub) return a; 5343e12c5d1SDavid du Colombier a=subwords(val, len, sub->next, a); 5353e12c5d1SDavid du Colombier s=sub->word; 5363e12c5d1SDavid du Colombier deglob(s); 5373e12c5d1SDavid du Colombier n=0; 5383e12c5d1SDavid du Colombier while('0'<=*s && *s<='9') n=n*10+ *s++ -'0'; 5393e12c5d1SDavid du Colombier if(n<1 || len<n) return a; 5403e12c5d1SDavid du Colombier for(;n!=1;--n) val=val->next; 5413e12c5d1SDavid du Colombier return newword(val->word, a); 5423e12c5d1SDavid du Colombier } 5433e12c5d1SDavid du Colombier void Xsub(void){ 5443e12c5d1SDavid du Colombier word *a, *v; 5453e12c5d1SDavid du Colombier char *s; 5463e12c5d1SDavid du Colombier if(count(runq->argv->next->words)!=1){ 5473e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5483e12c5d1SDavid du Colombier return; 5493e12c5d1SDavid du Colombier } 5503e12c5d1SDavid du Colombier s=runq->argv->next->words->word; 5513e12c5d1SDavid du Colombier deglob(s); 5523e12c5d1SDavid du Colombier a=runq->argv->next->next->words; 5533e12c5d1SDavid du Colombier v=vlook(s)->val; 5543e12c5d1SDavid du Colombier a=subwords(v, count(v), runq->argv->words, a); 5553e12c5d1SDavid du Colombier poplist(); 5563e12c5d1SDavid du Colombier poplist(); 5573e12c5d1SDavid du Colombier runq->argv->words=a; 5583e12c5d1SDavid du Colombier } 5593e12c5d1SDavid du Colombier void Xcount(void){ 5603e12c5d1SDavid du Colombier word *a; 5613e12c5d1SDavid du Colombier char *s, *t; 5623e12c5d1SDavid du Colombier int n; 5633e12c5d1SDavid du Colombier char num[12]; 5643e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5653e12c5d1SDavid du Colombier Xerror("variable name not singleton!"); 5663e12c5d1SDavid du Colombier return; 5673e12c5d1SDavid du Colombier } 5683e12c5d1SDavid du Colombier s=runq->argv->words->word; 5693e12c5d1SDavid du Colombier deglob(s); 5703e12c5d1SDavid du Colombier n=0; 5713e12c5d1SDavid du Colombier for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0'; 5723e12c5d1SDavid du Colombier if(n==0 || *t){ 5733e12c5d1SDavid du Colombier a=vlook(s)->val; 5743e12c5d1SDavid du Colombier itoa(num, count(a)); 5753e12c5d1SDavid du Colombier } 5763e12c5d1SDavid du Colombier else{ 5773e12c5d1SDavid du Colombier a=vlook("*")->val; 5783e12c5d1SDavid du Colombier itoa(num, a && 1<=n && n<=count(a)?1:0); 5793e12c5d1SDavid du Colombier } 5803e12c5d1SDavid du Colombier poplist(); 5813e12c5d1SDavid du Colombier pushword(num); 5823e12c5d1SDavid du Colombier } 5833e12c5d1SDavid du Colombier void Xlocal(void){ 5843e12c5d1SDavid du Colombier if(count(runq->argv->words)!=1){ 5853e12c5d1SDavid du Colombier Xerror("variable name must be singleton\n"); 5863e12c5d1SDavid du Colombier return; 5873e12c5d1SDavid du Colombier } 5883e12c5d1SDavid du Colombier deglob(runq->argv->words->word); 5893e12c5d1SDavid du Colombier runq->local=newvar(strdup(runq->argv->words->word), runq->local); 5903e12c5d1SDavid du Colombier runq->local->val=copywords(runq->argv->next->words, (word *)0); 5913e12c5d1SDavid du Colombier runq->local->changed=1; 5923e12c5d1SDavid du Colombier poplist(); 5933e12c5d1SDavid du Colombier poplist(); 5943e12c5d1SDavid du Colombier } 5953e12c5d1SDavid du Colombier void Xunlocal(void){ 5963e12c5d1SDavid du Colombier var *v=runq->local, *hid; 5973e12c5d1SDavid du Colombier if(v==0) panic("Xunlocal: no locals!", 0); 5983e12c5d1SDavid du Colombier runq->local=v->next; 5993e12c5d1SDavid du Colombier hid=vlook(v->name); 6003e12c5d1SDavid du Colombier hid->changed=1; 6013e12c5d1SDavid du Colombier efree(v->name); 6023e12c5d1SDavid du Colombier freewords(v->val); 6033e12c5d1SDavid du Colombier efree((char *)v); 6043e12c5d1SDavid du Colombier } 6053e12c5d1SDavid du Colombier void freewords(word *w) 6063e12c5d1SDavid du Colombier { 6073e12c5d1SDavid du Colombier word *nw; 6083e12c5d1SDavid du Colombier while(w){ 6093e12c5d1SDavid du Colombier efree(w->word); 6103e12c5d1SDavid du Colombier nw=w->next; 6113e12c5d1SDavid du Colombier efree((char *)w); 6123e12c5d1SDavid du Colombier w=nw; 6133e12c5d1SDavid du Colombier } 6143e12c5d1SDavid du Colombier } 6153e12c5d1SDavid du Colombier void Xfn(void){ 6163e12c5d1SDavid du Colombier var *v; 6173e12c5d1SDavid du Colombier word *a; 6183e12c5d1SDavid du Colombier int end; 6193e12c5d1SDavid du Colombier end=runq->code[runq->pc].i; 6203e12c5d1SDavid du Colombier for(a=runq->argv->words;a;a=a->next){ 6213e12c5d1SDavid du Colombier v=gvlook(a->word); 6223e12c5d1SDavid du Colombier if(v->fn) codefree(v->fn); 6233e12c5d1SDavid du Colombier v->fn=codecopy(runq->code); 6243e12c5d1SDavid du Colombier v->pc=runq->pc+2; 6253e12c5d1SDavid du Colombier v->fnchanged=1; 6263e12c5d1SDavid du Colombier } 6273e12c5d1SDavid du Colombier runq->pc=end; 6283e12c5d1SDavid du Colombier poplist(); 6293e12c5d1SDavid du Colombier } 6303e12c5d1SDavid du Colombier void Xdelfn(void){ 6313e12c5d1SDavid du Colombier var *v; 6323e12c5d1SDavid du Colombier word *a; 6333e12c5d1SDavid du Colombier for(a=runq->argv->words;a;a=a->next){ 6343e12c5d1SDavid du Colombier v=gvlook(a->word); 6353e12c5d1SDavid du Colombier if(v->fn) codefree(v->fn); 6363e12c5d1SDavid du Colombier v->fn=0; 6373e12c5d1SDavid du Colombier v->fnchanged=1; 6383e12c5d1SDavid du Colombier } 6393e12c5d1SDavid du Colombier poplist(); 6403e12c5d1SDavid du Colombier } 6413e12c5d1SDavid du Colombier void Xpipe(void){ 6423e12c5d1SDavid du Colombier struct thread *p=runq; 6433e12c5d1SDavid du Colombier int pc=p->pc, forkid; 6443e12c5d1SDavid du Colombier int lfd=p->code[pc++].i; 6453e12c5d1SDavid du Colombier int rfd=p->code[pc++].i; 6463e12c5d1SDavid du Colombier int pfd[2]; 6473e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 648*219b2ee8SDavid du Colombier Xperror("can't get pipe"); 6493e12c5d1SDavid du Colombier return; 6503e12c5d1SDavid du Colombier } 6513e12c5d1SDavid du Colombier switch(forkid=fork()){ 6523e12c5d1SDavid du Colombier case -1: 653*219b2ee8SDavid du Colombier Xperror("can't fork"); 6543e12c5d1SDavid du Colombier break; 6553e12c5d1SDavid du Colombier case 0: 6563e12c5d1SDavid du Colombier start(p->code, pc+2, runq->local); 6573e12c5d1SDavid du Colombier runq->ret=0; 6583e12c5d1SDavid du Colombier close(pfd[PRD]); 6593e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PWR], lfd); 6603e12c5d1SDavid du Colombier break; 6613e12c5d1SDavid du Colombier default: 6623e12c5d1SDavid du Colombier start(p->code, p->code[pc].i, runq->local); 6633e12c5d1SDavid du Colombier close(pfd[PWR]); 6643e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PRD], rfd); 6653e12c5d1SDavid du Colombier p->pc=p->code[pc+1].i; 6663e12c5d1SDavid du Colombier p->pid=forkid; 6673e12c5d1SDavid du Colombier break; 6683e12c5d1SDavid du Colombier } 6693e12c5d1SDavid du Colombier } 6703e12c5d1SDavid du Colombier char *concstatus(char *s, char *t) 6713e12c5d1SDavid du Colombier { 6723e12c5d1SDavid du Colombier static char v[NSTATUS+1]; 6733e12c5d1SDavid du Colombier int n=strlen(s); 6743e12c5d1SDavid du Colombier strncpy(v, s, NSTATUS); 6753e12c5d1SDavid du Colombier if(n<NSTATUS){ 6763e12c5d1SDavid du Colombier v[n]='|'; 6773e12c5d1SDavid du Colombier strncpy(v+n+1, t, NSTATUS-n-1); 6783e12c5d1SDavid du Colombier } 6793e12c5d1SDavid du Colombier v[NSTATUS]='\0'; 6803e12c5d1SDavid du Colombier return v; 6813e12c5d1SDavid du Colombier } 6823e12c5d1SDavid du Colombier void Xpipewait(void){ 6833e12c5d1SDavid du Colombier char status[NSTATUS+1]; 6843e12c5d1SDavid du Colombier if(runq->pid==-1) 6853e12c5d1SDavid du Colombier setstatus(concstatus(runq->status, getstatus())); 6863e12c5d1SDavid du Colombier else{ 6873e12c5d1SDavid du Colombier strncpy(status, getstatus(), NSTATUS); 6883e12c5d1SDavid du Colombier status[NSTATUS]='\0'; 6893e12c5d1SDavid du Colombier Waitfor(runq->pid, 1); 6903e12c5d1SDavid du Colombier runq->pid=-1; 6913e12c5d1SDavid du Colombier setstatus(concstatus(getstatus(), status)); 6923e12c5d1SDavid du Colombier } 6933e12c5d1SDavid du Colombier } 6943e12c5d1SDavid du Colombier void Xrdcmds(void){ 6953e12c5d1SDavid du Colombier struct thread *p=runq; 6963e12c5d1SDavid du Colombier word *prompt; 6973e12c5d1SDavid du Colombier flush(err); 6983e12c5d1SDavid du Colombier nerror=0; 6993e12c5d1SDavid du Colombier if(flag['s'] && !truestatus()) 7003e12c5d1SDavid du Colombier pfmt(err, "status=%v\n", vlook("status")->val); 7013e12c5d1SDavid du Colombier if(runq->iflag){ 7023e12c5d1SDavid du Colombier prompt=vlook("prompt")->val; 7033e12c5d1SDavid du Colombier if(prompt) 7043e12c5d1SDavid du Colombier promptstr=prompt->word; 7053e12c5d1SDavid du Colombier else 7063e12c5d1SDavid du Colombier promptstr="% "; 7073e12c5d1SDavid du Colombier } 7083e12c5d1SDavid du Colombier Noerror(); 7093e12c5d1SDavid du Colombier if(yyparse()){ 7103e12c5d1SDavid du Colombier if(!p->iflag || p->eof && !Eintr()){ 7113e12c5d1SDavid du Colombier if(p->cmdfile) efree(p->cmdfile); 7123e12c5d1SDavid du Colombier closeio(p->cmdfd); 7133e12c5d1SDavid du Colombier Xreturn(); /* should this be omitted? */ 7143e12c5d1SDavid du Colombier } 7153e12c5d1SDavid du Colombier else{ 7163e12c5d1SDavid du Colombier if(Eintr()){ 7173e12c5d1SDavid du Colombier pchr(err, '\n'); 7183e12c5d1SDavid du Colombier p->eof=0; 7193e12c5d1SDavid du Colombier } 7203e12c5d1SDavid du Colombier --p->pc; /* go back for next command */ 7213e12c5d1SDavid du Colombier } 7223e12c5d1SDavid du Colombier } 7233e12c5d1SDavid du Colombier else{ 7243e12c5d1SDavid du Colombier --p->pc; /* re-execute Xrdcmds after codebuf runs */ 7253e12c5d1SDavid du Colombier start(codebuf, 1, runq->local); 7263e12c5d1SDavid du Colombier } 7273e12c5d1SDavid du Colombier freenodes(); 7283e12c5d1SDavid du Colombier } 7293e12c5d1SDavid du Colombier void Xerror(char *s) 7303e12c5d1SDavid du Colombier { 7313e12c5d1SDavid du Colombier pfmt(err, "rc: %s\n", s); 7323e12c5d1SDavid du Colombier flush(err); 7333e12c5d1SDavid du Colombier while(!runq->iflag) Xreturn(); 7343e12c5d1SDavid du Colombier } 735*219b2ee8SDavid du Colombier void Xperror(char *s) 736*219b2ee8SDavid du Colombier { 737*219b2ee8SDavid du Colombier pfmt(err, "rc: %s: %s\n", s, Geterrstr()); 738*219b2ee8SDavid du Colombier flush(err); 739*219b2ee8SDavid du Colombier while(!runq->iflag) Xreturn(); 740*219b2ee8SDavid du Colombier } 7413e12c5d1SDavid du Colombier void Xbackq(void){ 7423e12c5d1SDavid du Colombier char wd[8193]; 7433e12c5d1SDavid du Colombier int c; 7443e12c5d1SDavid du Colombier char *s, *ewd=&wd[8192], *stop; 7453e12c5d1SDavid du Colombier struct io *f; 7463e12c5d1SDavid du Colombier var *ifs=vlook("ifs"); 7473e12c5d1SDavid du Colombier word *v, *nextv; 7483e12c5d1SDavid du Colombier int pfd[2]; 7493e12c5d1SDavid du Colombier int pid; 7503e12c5d1SDavid du Colombier stop=ifs->val?ifs->val->word:""; 7513e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 7523e12c5d1SDavid du Colombier Xerror("can't make pipe"); 7533e12c5d1SDavid du Colombier return; 7543e12c5d1SDavid du Colombier } 7553e12c5d1SDavid du Colombier switch(pid=fork()){ 7563e12c5d1SDavid du Colombier case -1: Xerror("try again"); 7573e12c5d1SDavid du Colombier close(pfd[PRD]); 7583e12c5d1SDavid du Colombier close(pfd[PWR]); 7593e12c5d1SDavid du Colombier return; 7603e12c5d1SDavid du Colombier case 0: 7613e12c5d1SDavid du Colombier close(pfd[PRD]); 7623e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 7633e12c5d1SDavid du Colombier pushredir(ROPEN, pfd[PWR], 1); 7643e12c5d1SDavid du Colombier return; 7653e12c5d1SDavid du Colombier default: 7663e12c5d1SDavid du Colombier close(pfd[PWR]); 7673e12c5d1SDavid du Colombier f=openfd(pfd[PRD]); 7683e12c5d1SDavid du Colombier s=wd; 7693e12c5d1SDavid du Colombier v=0; 7703e12c5d1SDavid du Colombier while((c=rchr(f))!=EOF){ 7713e12c5d1SDavid du Colombier if(strchr(stop, c) || s==ewd){ 7723e12c5d1SDavid du Colombier if(s!=wd){ 7733e12c5d1SDavid du Colombier *s='\0'; 7743e12c5d1SDavid du Colombier v=newword(wd, v); 7753e12c5d1SDavid du Colombier s=wd; 7763e12c5d1SDavid du Colombier } 7773e12c5d1SDavid du Colombier } 7783e12c5d1SDavid du Colombier else *s++=c; 7793e12c5d1SDavid du Colombier } 7803e12c5d1SDavid du Colombier if(s!=wd){ 7813e12c5d1SDavid du Colombier *s='\0'; 7823e12c5d1SDavid du Colombier v=newword(wd, v); 7833e12c5d1SDavid du Colombier } 7843e12c5d1SDavid du Colombier closeio(f); 7853e12c5d1SDavid du Colombier Waitfor(pid, 0); 7863e12c5d1SDavid du Colombier /* v points to reversed arglist -- reverse it onto argv */ 7873e12c5d1SDavid du Colombier while(v){ 7883e12c5d1SDavid du Colombier nextv=v->next; 7893e12c5d1SDavid du Colombier v->next=runq->argv->words; 7903e12c5d1SDavid du Colombier runq->argv->words=v; 7913e12c5d1SDavid du Colombier v=nextv; 7923e12c5d1SDavid du Colombier } 7933e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 7943e12c5d1SDavid du Colombier return; 7953e12c5d1SDavid du Colombier } 7963e12c5d1SDavid du Colombier } 7973e12c5d1SDavid du Colombier /* 7983e12c5d1SDavid du Colombier * Who should wait for the exit from the fork? 7993e12c5d1SDavid du Colombier */ 8003e12c5d1SDavid du Colombier void Xpipefd(void){ 8013e12c5d1SDavid du Colombier struct thread *p=runq; 8023e12c5d1SDavid du Colombier int pc=p->pc; 8033e12c5d1SDavid du Colombier char name[40]; 8043e12c5d1SDavid du Colombier int pfd[2]; 8053e12c5d1SDavid du Colombier int sidefd, mainfd; 8063e12c5d1SDavid du Colombier if(pipe(pfd)<0){ 8073e12c5d1SDavid du Colombier Xerror("can't get pipe"); 8083e12c5d1SDavid du Colombier return; 8093e12c5d1SDavid du Colombier } 8103e12c5d1SDavid du Colombier if(p->code[pc].i==READ){ 8113e12c5d1SDavid du Colombier sidefd=pfd[PWR]; 8123e12c5d1SDavid du Colombier mainfd=pfd[PRD]; 8133e12c5d1SDavid du Colombier } 8143e12c5d1SDavid du Colombier else{ 8153e12c5d1SDavid du Colombier sidefd=pfd[PRD]; 8163e12c5d1SDavid du Colombier mainfd=pfd[PWR]; 8173e12c5d1SDavid du Colombier } 8183e12c5d1SDavid du Colombier switch(fork()){ 8193e12c5d1SDavid du Colombier case -1: 8203e12c5d1SDavid du Colombier Xerror("try again"); 8213e12c5d1SDavid du Colombier break; 8223e12c5d1SDavid du Colombier case 0: 8233e12c5d1SDavid du Colombier start(p->code, pc+2, runq->local); 8243e12c5d1SDavid du Colombier close(mainfd); 8253e12c5d1SDavid du Colombier pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); 8263e12c5d1SDavid du Colombier runq->ret=0; 8273e12c5d1SDavid du Colombier break; 8283e12c5d1SDavid du Colombier default: 8293e12c5d1SDavid du Colombier close(sidefd); 8303e12c5d1SDavid du Colombier pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ 8313e12c5d1SDavid du Colombier strcpy(name, Fdprefix); 8323e12c5d1SDavid du Colombier itoa(name+strlen(name), mainfd); 8333e12c5d1SDavid du Colombier pushword(name); 8343e12c5d1SDavid du Colombier p->pc=p->code[pc+1].i; 8353e12c5d1SDavid du Colombier break; 8363e12c5d1SDavid du Colombier } 8373e12c5d1SDavid du Colombier } 8383e12c5d1SDavid du Colombier void Xsubshell(void){ 8393e12c5d1SDavid du Colombier int pid; 8403e12c5d1SDavid du Colombier switch(pid=fork()){ 8413e12c5d1SDavid du Colombier case -1: 8423e12c5d1SDavid du Colombier Xerror("try again"); 8433e12c5d1SDavid du Colombier break; 8443e12c5d1SDavid du Colombier case 0: 8453e12c5d1SDavid du Colombier start(runq->code, runq->pc+1, runq->local); 8463e12c5d1SDavid du Colombier runq->ret=0; 8473e12c5d1SDavid du Colombier break; 8483e12c5d1SDavid du Colombier default: 8493e12c5d1SDavid du Colombier Waitfor(pid, 1); 8503e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 8513e12c5d1SDavid du Colombier break; 8523e12c5d1SDavid du Colombier } 8533e12c5d1SDavid du Colombier } 8543e12c5d1SDavid du Colombier void setstatus(char *s) 8553e12c5d1SDavid du Colombier { 8563e12c5d1SDavid du Colombier setvar("status", newword(s, (word *)0)); 8573e12c5d1SDavid du Colombier } 8583e12c5d1SDavid du Colombier char *getstatus(void){ 8593e12c5d1SDavid du Colombier var *status=vlook("status"); 8603e12c5d1SDavid du Colombier return status->val?status->val->word:""; 8613e12c5d1SDavid du Colombier } 8623e12c5d1SDavid du Colombier int truestatus(void){ 8633e12c5d1SDavid du Colombier char *s; 8643e12c5d1SDavid du Colombier for(s=getstatus();*s;s++) 8653e12c5d1SDavid du Colombier if(*s!='|' && *s!='0') return 0; 8663e12c5d1SDavid du Colombier return 1; 8673e12c5d1SDavid du Colombier } 8683e12c5d1SDavid du Colombier void Xdelhere(void){ 8693e12c5d1SDavid du Colombier Unlink(runq->code[runq->pc++].s); 8703e12c5d1SDavid du Colombier } 8713e12c5d1SDavid du Colombier void Xfor(void){ 8723e12c5d1SDavid du Colombier if(runq->argv->words==0){ 8733e12c5d1SDavid du Colombier poplist(); 8743e12c5d1SDavid du Colombier runq->pc=runq->code[runq->pc].i; 8753e12c5d1SDavid du Colombier } 8763e12c5d1SDavid du Colombier else{ 8773e12c5d1SDavid du Colombier freelist(runq->local->val); 8783e12c5d1SDavid du Colombier runq->local->val=runq->argv->words; 8793e12c5d1SDavid du Colombier runq->local->changed=1; 8803e12c5d1SDavid du Colombier runq->argv->words=runq->argv->words->next; 8813e12c5d1SDavid du Colombier runq->local->val->next=0; 8823e12c5d1SDavid du Colombier runq->pc++; 8833e12c5d1SDavid du Colombier } 8843e12c5d1SDavid du Colombier } 8853e12c5d1SDavid du Colombier void Xglob(void){ 8863e12c5d1SDavid du Colombier globlist(); 8873e12c5d1SDavid du Colombier } 888