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