#include "rc.h" int flag[256]; Io *err; Channel *wchan; Thread *runq; int ndot; void initpath(void) { char *p; char *PATH; Word *path, *v; if(vlook("path")->val != nil) return; v = vlook("PATH")->val; if(v == nil) return; PATH = strdup(v->word); if(PATH == nil) return; path = nil; while((p = strrchr(PATH, ':')) != nil){ *p++ = '\0'; path = newword(p, path); } path = newword(PATH, path); setvar("path", path); } void threadmain(int argc, char *argv[]) { int i; Code bootstrap[17]; char *cflag; char rcmain[200]; Var *pmroot; cflag = 0; /* default to interactive mode */ flag['i']++; ARGBEGIN{ default: fprint(2, "usage: %s: [-seiIlvxr] [-c string] [file [args]]\n", argv0); threadexitsall("usage"); case 'D': pm_debug = ~0; break; case 'e': flag['e']++; break; case 'c': cflag = ARGF(); break; case 'i': flag['i']++; break; case 'I': flag['i'] = 0; break; case 'l': flag['l']++; break; case 'r': flag['r']++; break; case 's': flag['s']++; break; case 'S': flag['S']++; break; /* sub shell */ case 'v': flag['v']++; break; case 'V': flag['V']++; break; case 'x': flag['x']++; break; }ARGEND wchan = threadwaitchan(); err = openfd(2); kinit(); vinit(); notify(notifyf); initpath(); pmroot = vlook("9pm"); if(pmroot->val == 0) pmroot = vlook("9PM"); if(pmroot->val == 0) pmroot = vlook("ninepm"); if(pmroot->val == 0) pmroot = vlook("NINEPM"); if(pmroot->val == 0) sysfatal("$9pm not set"); sprint(rcmain, "%s/lib/rcmain", pmroot->val->word); setvar("rcname", newword(argv0, 0)); if(cflag) setvar("cflag", newword(cflag, 0)); else setvar("cflag", 0); /* bootstrap == . rcmain $* */ i=0; bootstrap[i++].i=1; bootstrap[i++].f=Xmark; bootstrap[i++].f=Xword; bootstrap[i++].s="*"; bootstrap[i++].f=Xassign; bootstrap[i++].f=Xmark; bootstrap[i++].f=Xmark; bootstrap[i++].f=Xword; bootstrap[i++].s="*"; bootstrap[i++].f=Xdol; bootstrap[i++].f=Xword; bootstrap[i++].s=rcmain; bootstrap[i++].f=Xword; bootstrap[i++].s="."; bootstrap[i++].f=Xsimple; bootstrap[i++].f=Xexit; bootstrap[i].i=0; start(bootstrap, 1, 0); pushlist(); for(i=argc-1;i>=0;i--) pushword(argv[i]); for(;;){ if(flag['r']) pfnc(err, runq); runq->pc++; (*runq->code[runq->pc-1].f)(); if(ntrap.ref) { dotrap(); } } } void panic(char *s, int n) { pfmt(err, "rcsh: "); pfmt(err, s, n); pchr(err, '\n'); flush(err); pfmt(err, "aborting\n"); flush(err); threadexitsall("aborting"); } void setstatus(char *s) { setvar("status", newword(s, 0)); } char * getstatus(void) { Var *status=vlook("status"); return status->val?status->val->word:""; } int truestatus(void) { char *s; for(s=getstatus();*s;s++) if(*s!='|' && *s!='0') return 0; return 1; } char * concstatus(char *s, char *t) { static char v[NSTATUS+1]; int n=strlen(s); strncpy(v, s, NSTATUS); if(ncode = codecopy(c); p->pc = pc; if(runq) { p->redir = runq->redir; p->startredir = runq->redir; } p->local = local; p->lineno = 1; p->ret = runq; runq=p; //fprint(2, "start runq=%p\n", runq); } void execcmds(Io *f) { static Code rdcmds[4]; static int first=1; if(first){ rdcmds[0].i=1; rdcmds[1].f=Xrdcmds; rdcmds[2].f=Xreturn; first=0; } start(rdcmds, 1, runq->local); runq->cmdfd=f; runq->iflast=0; } void waitfor(uint pid) { Thread *p; Waitmsg *w; char errbuf[ERRMAX]; Again: while((w = recvp(wchan)) != nil){ if(w->pid==pid){ setstatus(w->msg); free(w); return; } for(p=runq->ret;p;p=p->ret) if(p->pid==w->pid){ p->pid=-1; strcpy(p->status, w->msg); } free(w); } rerrstr(errbuf, sizeof errbuf); //fprint(2, "wait: err %s\n", errbuf); if(strcmp(errbuf, "interrupted")==0) goto Again; } char ** procargv(char *s0, char *s1, char *s2, char *s3, Word *w) { int n, i; Word *p; char **argv; for(p=w,n=5; p; p=p->next,n++); ; argv = malloc(n*sizeof(char*)); i = 0; if(s0) argv[i++] = s0; if(s1) argv[i++] = s1; if(s2) argv[i++] = s2; if(s3) argv[i++] = s3; for(p=w; p; p=p->next) argv[i++] = p->word; argv[i] = 0; return argv; }