diff --git a/sys/src/cmd/rc/code.c b/sys/src/cmd/rc/code.c index 646b6a81a..9ec637988 100644 --- a/sys/src/cmd/rc/code.c +++ b/sys/src/cmd/rc/code.c @@ -108,13 +108,10 @@ outcode(tree *t, int eflag) break; case '&': emitf(Xasync); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); break; case ';': outcode(c0, eflag); @@ -129,13 +126,10 @@ outcode(tree *t, int eflag) break; case '`': emitf(Xbackq); - if(havefork){ - p = emiti(0); - outcode(c0, 0); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + outcode(c0, 0); + emitf(Xexit); + stuffdot(p); break; case ANDAND: outcode(c0, 0); @@ -211,13 +205,10 @@ outcode(tree *t, int eflag) break; case SUBSHELL: emitf(Xsubshell); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else - emits(fnstr(c0)); + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); if(eflag) emitf(Xeflag); break; @@ -304,14 +295,10 @@ outcode(tree *t, int eflag) case PIPEFD: emitf(Xpipefd); emiti(t->rtype); - if(havefork){ - p = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - } + p = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); break; case REDIR: emitf(Xmark); @@ -366,16 +353,11 @@ outcode(tree *t, int eflag) emitf(Xpipe); emiti(t->fd0); emiti(t->fd1); - if(havefork){ - p = emiti(0); - q = emiti(0); - outcode(c0, eflag); - emitf(Xexit); - stuffdot(p); - } else { - emits(fnstr(c0)); - q = emiti(0); - } + p = emiti(0); + q = emiti(0); + outcode(c0, eflag); + emitf(Xexit); + stuffdot(p); outcode(c1, eflag); emitf(Xreturn); stuffdot(q); diff --git a/sys/src/cmd/rc/compiling.on.unix b/sys/src/cmd/rc/compiling.on.unix deleted file mode 100644 index cd20c56c7..000000000 --- a/sys/src/cmd/rc/compiling.on.unix +++ /dev/null @@ -1,1866 +0,0 @@ -From geoff@collyer.net Fri Dec 19 01:21:40 EST 2003 -Received: from plan9.cs.bell-labs.com ([135.104.9.2]) by plan9; Fri Dec 19 01:21:39 EST 2003 -Received: from collyer.net ([63.192.14.226]) by plan9; Fri Dec 19 01:21:35 EST 2003 -Message-ID: -subject: rc on unix, part 1 -From: Geoff Collyer -Date: Thu, 18 Dec 2003 22:21:33 -0800 -To: presotto@plan9.bell-labs.com, rsc@plan9.bell-labs.com, geoff@collyer.net -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -Content-Transfer-Encoding: 7bit - -I got /sys/src/cmd/rc to compile under APE (in preparation for moving it -to Unixes) with the following changed files. I cadged some include files -from rsc but had to edit lib9.h slightly. I'll send the include files -separately. I can't tell if it works yet, but it does complain about -/usr/lib/rcmain being absent when I start it. Oh, and I haven't yet -simulated the effect of the OCEXEC bit. - - -# To unbundle, run this file -echo mkfile -sed 's/^X//' >mkfile <<'!' -X$test.out - -listing: -X pr mkfile $HFILES $FILES $FILES9 $FILESUNIX $YFILES|lp -du -! -echo simple.c -sed 's/^X//' >simple.c <<'!' -X/* -X * Maybe `simple' is a misnomer. -X */ -X#include "rc.h" -X#include "getflags.h" -X#include "exec.h" -X#include "io.h" -X#include "fns.h" -X/* -X * Search through the following code to see if we're just going to exit. -X */ -exitnext(void){ -X union code *c=&runq->code[runq->pc]; -X while(c->f==Xpopredir) c++; -X return c->f==Xexit; -X} - -void -XXsimple(void) -X{ -X word *a; -X thread *p = runq; -X var *v; -X struct builtin *bp; -X int pid; -X globlist(); -X a = runq->argv->words; -X if(a==0){ -X Xerror1("empty argument list"); -X return; -X } -X if(flag['x']) -X pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */ -X v = gvlook(a->word); -X if(v->fn) -X execfunc(v); -X else{ -X if(strcmp(a->word, "builtin")==0){ -X if(count(a)==1){ -X pfmt(err, "builtin: empty argument list\n"); -X setstatus("empty arg list"); -X poplist(); -X return; -X } -X a = a->next; -X popword(); -X } -X for(bp = Builtin;bp->name;bp++) -X if(strcmp(a->word, bp->name)==0){ -X (*bp->fnc)(); -X return; -X } -X if(exitnext()){ -X /* fork and wait is redundant */ -X pushword("exec"); -X execexec(); -X Xexit(); -X } -X else{ -X flush(err); -X Updenv(); /* necessary so changes don't go out again */ -X if((pid = execforkexec()) < 0){ -X Xerror("try again"); -X return; -X } - -X /* interrupts don't get us out */ -X poplist(); -X while(Waitfor(pid, 1) < 0) -X ; -X } -X } -X} -struct word nullpath = { "", 0}; - -void -doredir(redir *rp) -X{ -X if(rp){ -X doredir(rp->next); -X switch(rp->type){ -X case ROPEN: -X if(rp->from!=rp->to){ -X Dup(rp->from, rp->to); -X close(rp->from); -X } -X break; -X case RDUP: -X Dup(rp->from, rp->to); -X break; -X case RCLOSE: -X close(rp->from); -X break; -X } -X } -X} - -word* -searchpath(char *w) -X{ -X word *path; -X if(strncmp(w, "/", 1)==0 -X || strncmp(w, "#", 1)==0 -X || strncmp(w, "./", 2)==0 -X || strncmp(w, "../", 3)==0 -X || (path = vlook("path")->val)==0) -X path=&nullpath; -X return path; -X} - -void -execexec(void) -X{ -X popword(); /* "exec" */ -X if(runq->argv->words==0){ -X Xerror1("empty argument list"); -X return; -X } -X doredir(runq->redir); -X Execute(runq->argv->words, searchpath(runq->argv->words->word)); -X poplist(); -X} - -void -execfunc(var *func) -X{ -X word *starval; -X popword(); -X starval = runq->argv->words; -X runq->argv->words = 0; -X poplist(); -X start(func->fn, func->pc, (struct var *)0); -X runq->local = newvar(strdup("*"), runq->local); -X runq->local->val = starval; -X runq->local->changed = 1; -X} - -int -dochdir(char *word) -X{ -X /* report to /dev/wdir if it exists and we're interactive */ -X static int wdirfd = -2; -X if(chdir(word)<0) return -1; -X if(flag['i']!=0){ -X if(wdirfd==-2) /* try only once */ -X /* TODO: arrange close-on-exec on Unix */ -X wdirfd = open("/dev/wdir", OWRITE|OCEXEC); -X if(wdirfd>=0) -X write(wdirfd, word, strlen(word)); -X } -X return 1; -X} - -void -execcd(void) -X{ -X word *a = runq->argv->words; -X word *cdpath; -X char dir[512]; -X setstatus("can't cd"); -X cdpath = vlook("cdpath")->val; -X switch(count(a)){ -X default: -X pfmt(err, "Usage: cd [directory]\n"); -X break; -X case 2: -X if(a->next->word[0]=='/' || cdpath==0) -X cdpath=&nullpath; -X for(;cdpath;cdpath = cdpath->next){ -X strcpy(dir, cdpath->word); -X if(dir[0]) -X strcat(dir, "/"); -X strcat(dir, a->next->word); -X if(dochdir(dir)>=0){ -X if(strlen(cdpath->word) -X && strcmp(cdpath->word, ".")!=0) -X pfmt(err, "%s\n", dir); -X setstatus(""); -X break; -X } -X } -X if(cdpath==0) -X pfmt(err, "Can't cd %s: %r\n", a->next->word); -X break; -X case 1: -X a = vlook("home")->val; -X if(count(a)>=1){ -X if(dochdir(a->word)>=0) -X setstatus(""); -X else -X pfmt(err, "Can't cd %s: %r\n", a->word); -X } -X else -X pfmt(err, "Can't cd -- $home empty\n"); -X break; -X } -X poplist(); -X} - -void -execexit(void) -X{ -X switch(count(runq->argv->words)){ -X default: -X pfmt(err, "Usage: exit [status]\nExiting anyway\n"); -X case 2: -X setstatus(runq->argv->words->next->word); -X case 1: Xexit(); -X } -X} - -void -execshift(void) -X{ -X int n; -X word *a; -X var *star; -X switch(count(runq->argv->words)){ -X default: -X pfmt(err, "Usage: shift [n]\n"); -X setstatus("shift usage"); -X poplist(); -X return; -X case 2: -X n = atoi(runq->argv->words->next->word); -X break; -X case 1: -X n = 1; -X break; -X } -X star = vlook("*"); -X for(;n && star->val;--n){ -X a = star->val->next; -X efree(star->val->word); -X efree((char *)star->val); -X star->val = a; -X star->changed = 1; -X } -X setstatus(""); -X poplist(); -X} - -int -octal(char *s) -X{ -X int n = 0; -X while(*s==' ' || *s=='\t' || *s=='\n') s++; -X while('0'<=*s && *s<='7') n = n*8+*s++-'0'; -X return n; -X} - -int -mapfd(int fd) -X{ -X redir *rp; -X for(rp = runq->redir;rp;rp = rp->next){ -X switch(rp->type){ -X case RCLOSE: -X if(rp->from==fd) -X fd=-1; -X break; -X case RDUP: -X case ROPEN: -X if(rp->to==fd) -X fd = rp->from; -X break; -X } -X } -X return fd; -X} -union code rdcmds[4]; - -void -execcmds(io *f) -X{ -X static int first = 1; -X if(first){ -X rdcmds[0].i = 1; -X rdcmds[1].f = Xrdcmds; -X rdcmds[2].f = Xreturn; -X first = 0; -X } -X start(rdcmds, 1, runq->local); -X runq->cmdfd = f; -X runq->iflast = 0; -X} - -void -execeval(void) -X{ -X char *cmdline, *s, *t; -X int len = 0; -X word *ap; -X if(count(runq->argv->words)<=1){ -X Xerror1("Usage: eval cmd ..."); -X return; -X } -X eflagok = 1; -X for(ap = runq->argv->words->next;ap;ap = ap->next) -X len+=1+strlen(ap->word); -X cmdline = emalloc(len); -X s = cmdline; -X for(ap = runq->argv->words->next;ap;ap = ap->next){ -X for(t = ap->word;*t;) *s++=*t++; -X *s++=' '; -X } -X s[-1]='\n'; -X poplist(); -X execcmds(opencore(cmdline, len)); -X efree(cmdline); -X} -union code dotcmds[14]; - -void -execdot(void) -X{ -X int iflag = 0; -X int fd; -X list *av; -X thread *p = runq; -X char *zero; -X static int first = 1; -X char file[512]; -X word *path; -X if(first){ -X dotcmds[0].i = 1; -X dotcmds[1].f = Xmark; -X dotcmds[2].f = Xword; -X dotcmds[3].s="0"; -X dotcmds[4].f = Xlocal; -X dotcmds[5].f = Xmark; -X dotcmds[6].f = Xword; -X dotcmds[7].s="*"; -X dotcmds[8].f = Xlocal; -X dotcmds[9].f = Xrdcmds; -X dotcmds[10].f = Xunlocal; -X dotcmds[11].f = Xunlocal; -X dotcmds[12].f = Xreturn; -X first = 0; -X } -X else -X eflagok = 1; -X popword(); -X if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){ -X iflag = 1; -X popword(); -X } -X /* get input file */ -X if(p->argv->words==0){ -X Xerror1("Usage: . [-i] file [arg ...]"); -X return; -X } -X zero = strdup(p->argv->words->word); -X popword(); -X fd=-1; -X for(path = searchpath(zero);path;path = path->next){ -X strcpy(file, path->word); -X if(file[0]) -X strcat(file, "/"); -X strcat(file, zero); -X if((fd = open(file, 0))>=0) break; -X if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */ -X fd = Dup1(0); -X if(fd>=0) -X break; -X } -X } -X if(fd<0){ -X pfmt(err, "%s: ", zero); -X setstatus("can't open"); -X Xerror(".: can't open"); -X return; -X } -X /* set up for a new command loop */ -X start(dotcmds, 1, (struct var *)0); -X pushredir(RCLOSE, fd, 0); -X runq->cmdfile = zero; -X runq->cmdfd = openfd(fd); -X runq->iflag = iflag; -X runq->iflast = 0; -X /* push $* value */ -X pushlist(); -X runq->argv->words = p->argv->words; -X /* free caller's copy of $* */ -X av = p->argv; -X p->argv = av->next; -X efree((char *)av); -X /* push $0 value */ -X pushlist(); -X pushword(zero); -X ndot++; -X} - -void -execflag(void) -X{ -X char *letter, *val; -X switch(count(runq->argv->words)){ -X case 2: -X setstatus(flag[runq->argv->words->next->word[0]]?"":"flag not set"); -X break; -X case 3: -X letter = runq->argv->words->next->word; -X val = runq->argv->words->next->next->word; -X if(strlen(letter)==1){ -X if(strcmp(val, "+")==0){ -X flag[letter[0]] = flagset; -X break; -X } -X if(strcmp(val, "-")==0){ -X flag[letter[0]] = 0; -X break; -X } -X } -X default: -X Xerror1("Usage: flag [letter] [+-]"); -X return; -X } -X poplist(); -X} - -void -execwhatis(void){ /* mildly wrong -- should fork before writing */ -X word *a, *b, *path; -X var *v; -X struct builtin *bp; -X char file[512]; -X struct io out[1]; -X int found, sep; -X a = runq->argv->words->next; -X if(a==0){ -X Xerror1("Usage: whatis name ..."); -X return; -X } -X setstatus(""); -X out->fd = mapfd(1); -X out->bufp = out->buf; -X out->ebuf = &out->buf[NBUF]; -X out->strp = 0; -X for(;a;a = a->next){ -X v = vlook(a->word); -X if(v->val){ -X pfmt(out, "%s=", a->word); -X if(v->val->next==0) -X pfmt(out, "%q\n", v->val->word); -X else{ -X sep='('; -X for(b = v->val;b && b->word;b = b->next){ -X pfmt(out, "%c%q", sep, b->word); -X sep=' '; -X } -X pfmt(out, ")\n"); -X } -X found = 1; -X } -X else -X found = 0; -X v = gvlook(a->word); -X if(v->fn) -X pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s); -X else{ -X for(bp = Builtin;bp->name;bp++) -X if(strcmp(a->word, bp->name)==0){ -X pfmt(out, "builtin %s\n", a->word); -X break; -X } -X if(!bp->name){ -X for(path = searchpath(a->word);path;path = path->next){ -X strcpy(file, path->word); -X if(file[0]) -X strcat(file, "/"); -X strcat(file, a->word); -X if(Executable(file)){ -X pfmt(out, "%s\n", file); -X break; -X } -X } -X if(!path && !found){ -X pfmt(err, "%s: not found\n", a->word); -X setstatus("not found"); -X } -X } -X } -X } -X poplist(); -X flush(err); -X} - -void -execwait(void) -X{ -X switch(count(runq->argv->words)){ -X default: -X Xerror1("Usage: wait [pid]"); -X return; -X case 2: -X Waitfor(atoi(runq->argv->words->next->word), 0); -X break; -X case 1: -X Waitfor(-1, 0); -X break; -X } -X poplist(); -X} -! -echo havefork.c -sed 's/^X//' >havefork.c <<'!' -X#include "rc.h" -X#include "getflags.h" -X#include "exec.h" -X#include "io.h" -X#include "fns.h" - -int havefork = 1; - -void -XXasync(void) -X{ -X int null = open("/dev/null", 0); -X int pid; -X char npid[10]; -X if(null<0){ -X Xerror("Can't open /dev/null\n"); -X return; -X } -X#ifdef Unix -X pid = fork(); -X#else -X pid = rfork(RFFDG|RFPROC|RFNOTEG); -X#endif -X switch(pid){ -X case -1: -X close(null); -X Xerror("try again"); -X break; -X case 0: -X pushredir(ROPEN, null, 0); -X start(runq->code, runq->pc+1, runq->local); -X runq->ret = 0; -X break; -X default: -X close(null); -X runq->pc = runq->code[runq->pc].i; -X inttoascii(npid, pid); -X setvar("apid", newword(npid, (word *)0)); -X break; -X } -X} - -void -XXpipe(void) -X{ -X struct thread *p = runq; -X int pc = p->pc, forkid; -X int lfd = p->code[pc++].i; -X int rfd = p->code[pc++].i; -X int pfd[2]; -X if(pipe(pfd)<0){ -X Xerror("can't get pipe"); -X return; -X } -X switch(forkid = fork()){ -X case -1: -X Xerror("try again"); -X break; -X case 0: -X start(p->code, pc+2, runq->local); -X runq->ret = 0; -X close(pfd[PRD]); -X pushredir(ROPEN, pfd[PWR], lfd); -X break; -X default: -X start(p->code, p->code[pc].i, runq->local); -X close(pfd[PWR]); -X pushredir(ROPEN, pfd[PRD], rfd); -X p->pc = p->code[pc+1].i; -X p->pid = forkid; -X break; -X } -X} - -X/* -X * Who should wait for the exit from the fork? -X */ -void -XXbackq(void) -X{ -X char wd[8193]; -X int c; -X char *s, *ewd=&wd[8192], *stop; -X struct io *f; -X var *ifs = vlook("ifs"); -X word *v, *nextv; -X int pfd[2]; -X int pid; -X stop = ifs->val?ifs->val->word:""; -X if(pipe(pfd)<0){ -X Xerror("can't make pipe"); -X return; -X } -X switch(pid = fork()){ -X case -1: -X Xerror("try again"); -X close(pfd[PRD]); -X close(pfd[PWR]); -X return; -X case 0: -X close(pfd[PRD]); -X start(runq->code, runq->pc+1, runq->local); -X pushredir(ROPEN, pfd[PWR], 1); -X return; -X default: -X close(pfd[PWR]); -X f = openfd(pfd[PRD]); -X s = wd; -X v = 0; -X while((c = rchr(f))!=EOF){ -X if(strchr(stop, c) || s==ewd){ -X if(s!=wd){ -X *s='\0'; -X v = newword(wd, v); -X s = wd; -X } -X } -X else *s++=c; -X } -X if(s!=wd){ -X *s='\0'; -X v = newword(wd, v); -X } -X closeio(f); -X Waitfor(pid, 0); -X /* v points to reversed arglist -- reverse it onto argv */ -X while(v){ -X nextv = v->next; -X v->next = runq->argv->words; -X runq->argv->words = v; -X v = nextv; -X } -X runq->pc = runq->code[runq->pc].i; -X return; -X } -X} - -void -XXpipefd(void) -X{ -X struct thread *p = runq; -X int pc = p->pc; -X char name[40]; -X int pfd[2]; -X int sidefd, mainfd; -X if(pipe(pfd)<0){ -X Xerror("can't get pipe"); -X return; -X } -X if(p->code[pc].i==READ){ -X sidefd = pfd[PWR]; -X mainfd = pfd[PRD]; -X } -X else{ -X sidefd = pfd[PRD]; -X mainfd = pfd[PWR]; -X } -X switch(fork()){ -X case -1: -X Xerror("try again"); -X break; -X case 0: -X start(p->code, pc+2, runq->local); -X close(mainfd); -X pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0); -X runq->ret = 0; -X break; -X default: -X close(sidefd); -X pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */ -X strcpy(name, Fdprefix); -X inttoascii(name+strlen(name), mainfd); -X pushword(name); -X p->pc = p->code[pc+1].i; -X break; -X } -X} - -void -XXsubshell(void) -X{ -X int pid; -X switch(pid = fork()){ -X case -1: -X Xerror("try again"); -X break; -X case 0: -X start(runq->code, runq->pc+1, runq->local); -X runq->ret = 0; -X break; -X default: -X Waitfor(pid, 1); -X runq->pc = runq->code[runq->pc].i; -X break; -X } -X} - -int -execforkexec(void) -X{ -X int pid; -X int n; -X char buf[ERRMAX]; - -X switch(pid = fork()){ -X case -1: -X return -1; -X case 0: -X pushword("exec"); -X execexec(); -X strcpy(buf, "can't exec: "); -X n = strlen(buf); -X errstr(buf+n, ERRMAX-n); -X Exit(buf); -X } -X return pid; -X} -! -echo rc.h -sed 's/^X//' >rc.h <<'!' -X/* -X * Plan9 is defined for plan 9 -X * V9 is defined for 9th edition -X * Sun is defined for sun-os -X * Please don't litter the code with ifdefs. The three below should be enough. -X */ -X#define Unix - -X#ifdef Plan9 -X#include -X#include -X#define NSIG 32 -X#define SIGINT 2 -X#define SIGQUIT 3 -X#endif - -X#ifdef Unix -X#define _POSIX_SOURCE -X#define _BSD_EXTENSION - -X#include -X#include -X#include -X#include -X#include -X#include -X#include -X#endif - -X#ifndef ERRMAX -X#define ERRMAX 128 -X#endif - -X#define YYMAXDEPTH 500 -X#ifndef PAREN -X#include "x.tab.h" -X#endif -typedef struct tree tree; -typedef struct word word; -typedef struct io io; -typedef union code code; -typedef struct var var; -typedef struct list list; -typedef struct redir redir; -typedef struct thread thread; -typedef struct builtin builtin; - -struct tree{ -X int type; -X int rtype, fd0, fd1; /* details of REDIR PIPE DUP tokens */ -X char *str; -X int quoted; -X int iskw; -X tree *child[3]; -X tree *next; -X}; -tree *newtree(void); -tree *token(char*, int), *klook(char*), *tree1(int, tree*); -tree *tree2(int, tree*, tree*), *tree3(int, tree*, tree*, tree*); -tree *mung1(tree*, tree*), *mung2(tree*, tree*, tree*); -tree *mung3(tree*, tree*, tree*, tree*), *epimung(tree*, tree*); -tree *simplemung(tree*), *heredoc(tree*); -void freetree(tree*); -tree *cmdtree; -X/* -X * The first word of any code vector is a reference count. -X * Always create a new reference to a code vector by calling codecopy(.). -X * Always call codefree(.) when deleting a reference. -X */ -union code{ -X void (*f)(void); -X int i; -X char *s; -X}; -char *promptstr; -int doprompt; -X#define NTOK 8192 -char tok[NTOK]; -X#define APPEND 1 -X#define WRITE 2 -X#define READ 3 -X#define HERE 4 -X#define DUPFD 5 -X#define CLOSE 6 -struct var{ -X char *name; /* ascii name */ -X word *val; /* value */ -X int changed; -X code *fn; /* pointer to function's code vector */ -X int fnchanged; -X int pc; /* pc of start of function */ -X var *next; /* next on hash or local list */ -X}; -var *vlook(char*), *gvlook(char*), *newvar(char*, var*); -X#define NVAR 521 -var *gvar[NVAR]; /* hash for globals */ -X#define new(type) ((type *)emalloc(sizeof(type))) -char *emalloc(long); -void *Malloc(ulong); -void efree(char*); -X#define NOFILE 128 /* should come from */ -struct here{ -X tree *tag; -X char *name; -X struct here *next; -X}; -int mypid; -X/* -X * Glob character escape in strings: -X * In a string, GLOB must be followed by *?[ or GLOB. -X * GLOB* matches any string -X * GLOB? matches any single character -X * GLOB[...] matches anything in the brackets -X * GLOBGLOB matches GLOB -X */ -X#define GLOB ((char)0x01) -X/* -X * onebyte(c), twobyte(c), threebyte(c) -X * Is c the first character of a one- two- or three-byte utf sequence? -X */ -X#define onebyte(c) ((c&0x80)==0x00) -X#define twobyte(c) ((c&0xe0)==0xc0) -X#define threebyte(c) ((c&0xf0)==0xe0) -char **argp; -char **args; -int nerror; /* number of errors encountered during compilation */ -int doprompt; /* is it time for a prompt? */ -X/* -X * Which fds are the reading/writing end of a pipe? -X * Unfortunately, this can vary from system to system. -X * 9th edition Unix doesn't care, the following defines -X * work on plan 9. -X */ -X#define PRD 0 -X#define PWR 1 -char Rcmain[], Fdprefix[]; -X#define register -X/* -X * How many dot commands have we executed? -X * Used to ensure that -v flag doesn't print rcmain. -X */ -int ndot; -char *getstatus(void); -int lastc; -int lastword; -! -echo unix.c -sed 's/^X//' >unix.c <<'!' -X/* -X * Unix versions of system-specific functions -X * By convention, exported routines herein have names beginning with an -X * upper case letter. -X */ -X#include "rc.h" -X#include "io.h" -X#include "exec.h" -X#include "getflags.h" -X#include - -char Rcmain[]="/usr/lib/rcmain"; -char Fdprefix[]="/dev/fd/"; - -void execfinit(void); - -struct builtin Builtin[] = { -X "cd", execcd, -X "whatis", execwhatis, -X "eval", execeval, -X "exec", execexec, /* but with popword first */ -X "exit", execexit, -X "shift", execshift, -X "wait", execwait, -X "umask", execumask, -X ".", execdot, -X "finit", execfinit, -X "flag", execflag, -X 0 -X}; -X#define SEP '\1' -char **environp; - -struct word* -enval(s) -register char *s; -X{ -X char *t, c; -X struct word *v; -X for(t = s;*t && *t!=SEP;t++); -X c=*t; -X *t='\0'; -X v = newword(s, c=='\0'?(struct word *)0:enval(t+1)); -X *t = c; -X return v; -X} - -void -Vinit(void) -X{ -X extern char **environ; -X char *s; -X char **env = environ; -X environp = env; -X for(;*env;env++){ -X for(s=*env;*s && *s!='(' && *s!='=';s++); -X switch(*s){ -X case '\0': -X pfmt(err, "environment %q?\n", *env); -X break; -X case '=': -X *s='\0'; -X setvar(*env, enval(s+1)); -X *s='='; -X break; -X case '(': /* ignore functions for now */ -X break; -X } -X } -X} - -char **envp; - -void -XXrdfn(void) -X{ -X char *s; -X int len; -X for(;*envp;envp++){ -X for(s=*envp;*s && *s!='(' && *s!='=';s++); -X switch(*s){ -X case '\0': -X pfmt(err, "environment %q?\n", *envp); -X break; -X case '=': /* ignore variables */ -X break; -X case '(': /* Bourne again */ -X s=*envp+3; -X envp++; -X len = strlen(s); -X s[len]='\n'; -X execcmds(opencore(s, len+1)); -X s[len]='\0'; -X return; -X } -X } -X Xreturn(); -X} - -union code rdfns[4]; - -void -execfinit(void) -X{ -X static int first = 1; -X if(first){ -X rdfns[0].i = 1; -X rdfns[1].f = Xrdfn; -X rdfns[2].f = Xjump; -X rdfns[3].i = 1; -X first = 0; -X } -X Xpopm(); -X envp = environp; -X start(rdfns, 1, runq->local); -X} - -int -cmpenv(const void *aa, const void *ab) -X{ -X char **a = aa, **b = ab; - -X return strcmp(*a, *b); -X} - -char ** -mkenv(void) -X{ -X char **env, **ep, *p, *q; -X struct var **h, *v; -X struct word *a; -X int nvar = 0, nchr = 0, sep; - -X /* -X * Slightly kludgy loops look at locals then globals. -X * locals no longer exist - geoff -X */ -X for(h = gvar-1; h != &gvar[NVAR]; h++) -X for(v = h >= gvar? *h: runq->local; v ;v = v->next){ -X if((v==vlook(v->name)) && v->val){ -X nvar++; -X nchr+=strlen(v->name)+1; -X for(a = v->val;a;a = a->next) -X nchr+=strlen(a->word)+1; -X } -X if(v->fn){ -X nvar++; -X nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; -X } -X } -X env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr); -X ep = env; -X p = (char *)&env[nvar+1]; -X for(h = gvar-1; h != &gvar[NVAR]; h++) -X for(v = h >= gvar? *h: runq->local;v;v = v->next){ -X if((v==vlook(v->name)) && v->val){ -X *ep++=p; -X q = v->name; -X while(*q) *p++=*q++; -X sep='='; -X for(a = v->val;a;a = a->next){ -X *p++=sep; -X sep = SEP; -X q = a->word; -X while(*q) *p++=*q++; -X } -X *p++='\0'; -X } -X if(v->fn){ -X *ep++=p; -X *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ -X *p++='f'; *p++='n'; *p++=' '; -X q = v->name; -X while(*q) *p++=*q++; -X *p++=' '; -X q = v->fn[v->pc-1].s; -X while(*q) *p++=*q++; -X *p++='\0'; -X } -X } -X *ep = 0; -X qsort((void *)env, nvar, sizeof ep[0], cmpenv); -X return env; -X} -char *sigmsg[] = { -X/* 0 normal */ 0, -X/* 1 SIGHUP */ "Hangup", -X/* 2 SIGINT */ 0, -X/* 3 SIGQUIT */ "Quit", -X/* 4 SIGILL */ "Illegal instruction", -X/* 5 SIGTRAP */ "Trace/BPT trap", -X/* 6 SIGIOT */ "abort", -X/* 7 SIGEMT */ "EMT trap", -X/* 8 SIGFPE */ "Floating exception", -X/* 9 SIGKILL */ "Killed", -X/* 10 SIGBUS */ "Bus error", -X/* 11 SIGSEGV */ "Memory fault", -X/* 12 SIGSYS */ "Bad system call", -X/* 13 SIGPIPE */ 0, -X/* 14 SIGALRM */ "Alarm call", -X/* 15 SIGTERM */ "Terminated", -X/* 16 unused */ "signal 16", -X/* 17 SIGSTOP */ "Process stopped", -X/* 18 unused */ "signal 18", -X/* 19 SIGCONT */ "Process continued", -X/* 20 SIGCHLD */ "Child death", -X}; - -void -Waitfor(int pid, int persist) -X{ -X int wpid, sig; -X struct thread *p; -X int wstat; -X char wstatstr[12]; - -X for(;;){ -X errno = 0; -X wpid = wait(&wstat); -X if(errno==EINTR && persist) -X continue; -X if(wpid==-1) -X break; -X sig = wstat&0177; -X if(sig==0177){ -X pfmt(err, "trace: "); -X sig = (wstat>>8)&0177; -X } -X if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){ -X if(pid!=wpid) -X pfmt(err, "%d: ", wpid); -X if(sig<=(sizeof sigmsg/sizeof sigmsg[0])) -X pfmt(err, "%s", sigmsg[sig]); -X else if(sig==0177) pfmt(err, "stopped by ptrace"); -X else pfmt(err, "signal %d", sig); -X if(wstat&0200)pfmt(err, " -- core dumped"); -X pfmt(err, "\n"); -X } -X wstat = sig?sig+1000:(wstat>>8)&0xFF; -X if(wpid==pid){ -X inttoascii(wstatstr, wstat); -X setstatus(wstatstr); -X break; -X } -X else{ -X for(p = runq->ret;p;p = p->ret) -X if(p->pid==wpid){ -X p->pid=-1; -X inttoascii(p->status, wstat); -X break; -X } -X } -X } -X} - -char ** -mkargv(a) -register struct word *a; -X{ -X char **argv = (char **)emalloc((count(a)+2)*sizeof(char *)); -X char **argp = argv+1; /* leave one at front for runcoms */ - -X for(;a;a = a->next) -X *argp++=a->word; -X *argp = 0; -X return argv; -X} - -void -Updenv(void) -X{ -X} - -void -Execute(struct word *args, struct word *path) -X{ -X char *msg="not found"; -X#ifdef ETXTBSY -X int txtbusy = 0; -X#endif -X char **env = mkenv(); -X char **argv = mkargv(args); -X char file[512]; - -X for(;path;path = path->next){ -X strcpy(file, path->word); -X if(file[0]) -X strcat(file, "/"); -X strcat(file, argv[1]); -X#ifdef ETXTBSY -ReExec: -X#endif -X execve(file, argv+1, env); -X switch(errno){ -X case ENOEXEC: -X pfmt(err, "%s: Bourne again\n", argv[1]); -X argv[0]="sh"; -X argv[1] = strdup(file); -X execve("/bin/sh", argv, env); -X goto Bad; -X#ifdef ETXTBSY -X case ETXTBSY: -X if(++txtbusy!=5){ -X sleep(txtbusy); -X goto ReExec; -X } -X msg="text busy"; goto Bad; -X#endif -X case EACCES: -X msg="no access"; -X break; -X case ENOMEM: -X msg="not enough memory"; goto Bad; -X case E2BIG: -X msg="too big"; goto Bad; -X } -X } -Bad: -X pfmt(err, "%s: %s\n", argv[1], msg); -X efree((char *)env); -X efree((char *)argv); -X} - -X#define NDIR 14 /* should get this from param.h */ - -Globsize(p) -register char *p; -X{ -X int isglob = 0, globlen = NDIR+1; -X for(;*p;p++){ -X if(*p==GLOB){ -X p++; -X if(*p!=GLOB) -X isglob++; -X globlen+=*p=='*'?NDIR:1; -X } -X else -X globlen++; -X } -X return isglob?globlen:0; -X} - -X#include -X#include - -X#define NDIRLIST 50 - -DIR *dirlist[NDIRLIST]; - -Opendir(name) -char *name; -X{ -X DIR **dp; -X for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++) -X if(*dp==0){ -X *dp = opendir(name); -X return *dp?dp-dirlist:-1; -X } -X return -1; -X} - -int -Readdir(int f, char *p, int /* onlydirs */ ) -X{ -X struct dirent *dp = readdir(dirlist[f]); - -X if(dp==0) -X return 0; -X strcpy(p, dp->d_name); -X return 1; -X} - -void -Closedir(int f) -X{ -X closedir(dirlist[f]); -X dirlist[f] = 0; -X} - -char *Signame[] = { -X "sigexit", "sighup", "sigint", "sigquit", -X "sigill", "sigtrap", "sigiot", "sigemt", -X "sigfpe", "sigkill", "sigbus", "sigsegv", -X "sigsys", "sigpipe", "sigalrm", "sigterm", -X "sig16", "sigstop", "sigtstp", "sigcont", -X "sigchld", "sigttin", "sigttou", "sigtint", -X "sigxcpu", "sigxfsz", "sig26", "sig27", -X "sig28", "sig29", "sig30", "sig31", -X 0, -X}; - -void -gettrap(int sig) -X{ -X signal(sig, gettrap); -X trap[sig]++; -X ntrap++; -X if(ntrap>=NSIG){ -X pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig); -X signal(SIGABRT, (void (*)())0); -X kill(getpid(), SIGABRT); -X } -X} - -void -Trapinit(void) -X{ -X int i; -X void (*sig)(); - -X if(1 || flag['d']){ /* wrong!!! */ -X sig = signal(SIGINT, gettrap); -X if(sig==SIG_IGN) -X signal(SIGINT, SIG_IGN); -X } -X else{ -X for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){ -X sig = signal(i, gettrap); -X if(sig==SIG_IGN) -X signal(i, SIG_IGN); -X } -X } -X} - -Unlink(name) -char *name; -X{ -X return unlink(name); -X} -Write(fd, buf, cnt) -char *buf; -X{ -X return write(fd, buf, cnt); -X} -Read(fd, buf, cnt) -char *buf; -X{ -X return read(fd, buf, cnt); -X} -Seek(fd, cnt, whence) -long cnt; -X{ -X return lseek(fd, cnt, whence); -X} -Executable(file) -char *file; -X{ -X return(access(file, 01)==0); -X} -Creat(file) -char *file; -X{ -X return creat(file, 0666); -X} -Dup(a, b){ -X return dup2(a, b); -X} -Dup1(a){ -X return dup(a); -X} -X/* -X * Wrong: should go through components of a|b|c and return the maximum. -X */ -void -Exit(char *stat) -X{ -X int n = 0; - -X while(*stat){ -X if(*stat!='|'){ -X if(*stat<'0' || '9'<*stat) -X exit(1); -X else n = n*10+*stat-'0'; -X } -X stat++; -X } -X exit(n); -X} -Eintr(){ -X return errno==EINTR; -X} - -void -Noerror() -X{ -X errno = 0; -X} -Isatty(fd){ -X return isatty(fd); -X} - -void -Abort() -X{ -X abort(); -X} - -void -execumask(void) /* wrong -- should fork before writing */ -X{ -X int m; -X struct io out[1]; -X switch(count(runq->argv->words)){ -X default: -X pfmt(err, "Usage: umask [umask]\n"); -X setstatus("umask usage"); -X poplist(); -X return; -X case 2: -X umask(octal(runq->argv->words->next->word)); -X break; -X case 1: -X umask(m = umask(0)); -X out->fd = mapfd(1); -X out->bufp = out->buf; -X out->ebuf=&out->buf[NBUF]; -X out->strp = 0; -X pfmt(out, "%o\n", m); -X break; -X } -X setstatus(""); -X poplist(); -X} - -void -Memcpy(a, b, n) -char *a, *b; -X{ -X memmove(a, b, n); -X} - -void* -Malloc(unsigned long n) -X{ -X return (void *)malloc(n); -X} - -void -errstr(char *buf, int len) -X{ -X strncpy(buf, strerror(errno), len); -X} -! - -From geoff@collyer.net Fri Dec 19 01:23:26 EST 2003 -Received: from plan9.cs.bell-labs.com ([135.104.9.2]) by plan9; Fri Dec 19 01:23:25 EST 2003 -Received: from collyer.net ([63.192.14.226]) by plan9; Fri Dec 19 01:23:22 EST 2003 -Message-ID: <0b5ea130198a21a49139759d00d69939@collyer.net> -subject: rc on unix, part 2 -From: Geoff Collyer -Date: Thu, 18 Dec 2003 22:23:21 -0800 -To: presotto@plan9.bell-labs.com, rsc@plan9.bell-labs.com, geoff@collyer.net -MIME-Version: 1.0 -Content-Type: text/plain; charset="US-ASCII" -Content-Transfer-Encoding: 7bit - -These are the include files I used to emulate plan 9's include -files on Unix (APE). - - -# To unbundle, run this file -mkdir include -echo include/bio.h -sed 's/^X//' >include/bio.h <<'!' -X#ifndef _BIOH_ -X#define _BIOH_ 1 - -X#include /* for off_t */ -X#include /* for O_RDONLY, O_WRONLY */ - -typedef struct Biobuf Biobuf; - -enum -X{ -X Bsize = 8*1024, -X Bungetsize = 4, /* space for ungetc */ -X Bmagic = 0x314159, -X Beof = -1, -X Bbad = -2, - -X Binactive = 0, /* states */ -X Bractive, -X Bwactive, -X Bracteof, - -X Bend -X}; - -struct Biobuf -X{ -X int icount; /* neg num of bytes at eob */ -X int ocount; /* num of bytes at bob */ -X int rdline; /* num of bytes after rdline */ -X int runesize; /* num of bytes of last getrune */ -X int state; /* r/w/inactive */ -X int fid; /* open file */ -X int flag; /* magic if malloc'ed */ -X off_t offset; /* offset of buffer in file */ -X int bsize; /* size of buffer */ -X unsigned char* bbuf; /* pointer to beginning of buffer */ -X unsigned char* ebuf; /* pointer to end of buffer */ -X unsigned char* gbuf; /* pointer to good data in buf */ -X unsigned char b[Bungetsize+Bsize]; -X}; - -X#define BGETC(bp)\ -X ((bp)->icount?(bp)->bbuf[(bp)->bsize+(bp)->icount++]:Bgetc((bp))) -X#define BPUTC(bp,c)\ -X ((bp)->ocount?(bp)->bbuf[(bp)->bsize+(bp)->ocount++]=(c),0:Bputc((bp),(c))) -X#define BOFFSET(bp)\ -X (((bp)->state==Bractive)?\ -X (bp)->offset + (bp)->icount:\ -X (((bp)->state==Bwactive)?\ -X (bp)->offset + ((bp)->bsize + (bp)->ocount):\ -X -1)) -X#define BLINELEN(bp)\ -X (bp)->rdline -X#define BFILDES(bp)\ -X (bp)->fid - -int Bbuffered(Biobuf*); -int Bfildes(Biobuf*); -int Bflush(Biobuf*); -int Bgetc(Biobuf*); -int Bgetd(Biobuf*, double*); -int Binit(Biobuf*, int, int); -int Binits(Biobuf*, int, int, unsigned char*, int); -int Blinelen(Biobuf*); -off_t Boffset(Biobuf*); -Biobuf* Bopen(char*, int); -int Bprint(Biobuf*, char*, ...); -int Bputc(Biobuf*, int); -void* Brdline(Biobuf*, int); -long Bread(Biobuf*, void*, long); -off_t Bseek(Biobuf*, off_t, int); -int Bterm(Biobuf*); -int Bungetc(Biobuf*); -long Bwrite(Biobuf*, void*, long); - -long Bgetrune(Biobuf*); -int Bputrune(Biobuf*, long); -int Bungetrune(Biobuf*); - -X#endif -! -echo include/fmt.h -sed 's/^X//' >include/fmt.h <<'!' - -X/* -X * The authors of this software are Rob Pike and Ken Thompson. -X * Copyright (c) 2002 by Lucent Technologies. -X * Permission to use, copy, modify, and distribute this software for any -X * purpose without fee is hereby granted, provided that this entire notice -X * is included in all copies of any software which is or includes a copy -X * or modification of this software and in all copies of the supporting -X * documentation for such software. -X * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED -X * WARRANTY. IN PARTICULAR, NEITHER THE AUTHORS NOR LUCENT TECHNOLOGIES MAKE ANY -X * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY -X * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. -X */ - -X#ifndef _FMTH_ -X#define _FMTH_ 1 - -X#include - -X#ifndef _UTFH_ -X#include -X#endif - -typedef struct Fmt Fmt; -struct Fmt{ -X unsigned char runes; /* output buffer is runes or chars? */ -X void *start; /* of buffer */ -X void *to; /* current place in the buffer */ -X void *stop; /* end of the buffer; overwritten if flush fails */ -X int (*flush)(Fmt *); /* called when to == stop */ -X void *farg; /* to make flush a closure */ -X int nfmt; /* num chars formatted so far */ -X va_list args; /* args passed to dofmt */ -X int r; /* % format Rune */ -X int width; -X int prec; -X unsigned long flags; -X}; - -enum{ -X FmtWidth = 1, -X FmtLeft = FmtWidth << 1, -X FmtPrec = FmtLeft << 1, -X FmtSharp = FmtPrec << 1, -X FmtSpace = FmtSharp << 1, -X FmtSign = FmtSpace << 1, -X FmtZero = FmtSign << 1, -X FmtUnsigned = FmtZero << 1, -X FmtShort = FmtUnsigned << 1, -X FmtLong = FmtShort << 1, -X FmtVLong = FmtLong << 1, -X FmtComma = FmtVLong << 1, -X FmtByte = FmtComma << 1, -X FmtLDouble = FmtByte << 1, - -X FmtFlag = FmtLDouble << 1 -X}; - -extern int print(char*, ...); -extern char* seprint(char*, char*, char*, ...); -extern char* vseprint(char*, char*, char*, va_list); -extern int snprint(char*, int, char*, ...); -extern int vsnprint(char*, int, char*, va_list); -extern char* smprint(char*, ...); -extern char* vsmprint(char*, va_list); -extern int sprint(char*, char*, ...); -extern int fprint(int, char*, ...); -extern int vfprint(int, char*, va_list); - -extern int runesprint(Rune*, char*, ...); -extern int runesnprint(Rune*, int, char*, ...); -extern int runevsnprint(Rune*, int, char*, va_list); -extern Rune* runeseprint(Rune*, Rune*, char*, ...); -extern Rune* runevseprint(Rune*, Rune*, char*, va_list); -extern Rune* runesmprint(char*, ...); -extern Rune* runevsmprint(char*, va_list); - -extern int fmtfdinit(Fmt*, int, char*, int); -extern int fmtfdflush(Fmt*); -extern int fmtstrinit(Fmt*); -extern char* fmtstrflush(Fmt*); - -extern int quotestrfmt(Fmt *f); -extern void quotefmtinstall(void); -extern int (*fmtdoquote)(int); - - -extern int fmtinstall(int, int (*)(Fmt*)); -extern int dofmt(Fmt*, char*); -extern int fmtprint(Fmt*, char*, ...); -extern int fmtvprint(Fmt*, char*, va_list); -extern int fmtrune(Fmt*, int); -extern int fmtstrcpy(Fmt*, char*); - -extern double fmtstrtod(const char *, char **); -extern double fmtcharstod(int(*)(void*), void*); - -X#endif -! -echo include/lib9.h -sed 's/^X//' >include/lib9.h <<'!' -X#include -X#include "utf.h" - -X#define nil ((void*)0) - -X#define uchar _fmtuchar -X#define ushort _fmtushort -X#define uint _fmtuint -X#define ulong _fmtulong -X#define vlong _fmtvlong -X#define uvlong _fmtuvlong - -typedef unsigned char uchar; -typedef unsigned short ushort; -typedef unsigned int uint; -typedef unsigned long ulong; - -X#define OREAD O_RDONLY -X#define OWRITE O_WRONLY -X#define ORDWR O_RDWR -X#define OCEXEC 0 -! -echo include/regexp9.h -sed 's/^X//' >include/regexp9.h <<'!' -X#ifndef _REGEXP9H_ - -X#define _REGEXP9H_ 1 -X#include - -typedef struct Resub Resub; -typedef struct Reclass Reclass; -typedef struct Reinst Reinst; -typedef struct Reprog Reprog; - -X/* -X * Sub expression matches -X */ -struct Resub{ -X union -X { -X char *sp; -X Rune *rsp; -X }s; -X union -X { -X char *ep; -X Rune *rep; -X }e; -X}; - -X/* -X * character class, each pair of rune's defines a range -X */ -struct Reclass{ -X Rune *end; -X Rune spans[64]; -X}; - -X/* -X * Machine instructions -X */ -struct Reinst{ -X int type; -X union { -X Reclass *cp; /* class pointer */ -X Rune r; /* character */ -X int subid; /* sub-expression id for RBRA and LBRA */ -X Reinst *right; /* right child of OR */ -X }u1; -X union { /* regexp relies on these two being in the same union */ -X Reinst *left; /* left child of OR */ -X Reinst *next; /* next instruction for CAT & LBRA */ -X }u2; -X}; - -X/* -X * Reprogram definition -X */ -struct Reprog{ -X Reinst *startinst; /* start pc */ -X Reclass class[16]; /* .data */ -X Reinst firstinst[5]; /* .text */ -X}; - -extern Reprog *regcomp(char*); -extern Reprog *regcomplit(char*); -extern Reprog *regcompnl(char*); -extern void regerror(char*); -extern int regexec(Reprog*, char*, Resub*, int); -extern void regsub(char*, char*, int, Resub*, int); - -extern int rregexec(Reprog*, Rune*, Resub*, int); -extern void rregsub(Rune*, Rune*, Resub*, int); - -X#endif -! -echo include/utf.h -sed 's/^X//' >include/utf.h <<'!' -X#ifndef _UTFH_ -X#define _UTFH_ 1 - -typedef unsigned short Rune; /* 16 bits */ - -enum -X{ -X UTFmax = 3, /* maximum bytes per rune */ -X Runesync = 0x80, /* cannot represent part of a UTF sequence (<) */ -X Runeself = 0x80, /* rune and UTF sequences are the same (<) */ -X Runeerror = 0x80, /* decoding error in UTF */ -X}; - -X/* -X * rune routines -X */ -extern int runetochar(char*, Rune*); -extern int chartorune(Rune*, char*); -extern int runelen(long); -extern int runenlen(Rune*, int); -extern int fullrune(char*, int); -extern int utflen(char*); -extern int utfnlen(char*, long); -extern char* utfrune(char*, long); -extern char* utfrrune(char*, long); -extern char* utfutf(char*, char*); -extern char* utfecpy(char*, char*, char*); - -extern Rune* runestrcat(Rune*, Rune*); -extern Rune* runestrchr(Rune*, Rune); -extern int runestrcmp(Rune*, Rune*); -extern Rune* runestrcpy(Rune*, Rune*); -extern Rune* runestrncpy(Rune*, Rune*, long); -extern Rune* runestrecpy(Rune*, Rune*, Rune*); -extern Rune* runestrdup(Rune*); -extern Rune* runestrncat(Rune*, Rune*, long); -extern int runestrncmp(Rune*, Rune*, long); -extern Rune* runestrrchr(Rune*, Rune); -extern long runestrlen(Rune*); -extern Rune* runestrstr(Rune*, Rune*); - -extern Rune tolowerrune(Rune); -extern Rune totitlerune(Rune); -extern Rune toupperrune(Rune); -extern int isalpharune(Rune); -extern int islowerrune(Rune); -extern int isspacerune(Rune); -extern int istitlerune(Rune); -extern int isupperrune(Rune); - -X#endif -! - diff --git a/sys/src/cmd/rc/exec.h b/sys/src/cmd/rc/exec.h index f7fefed17..cc24dc961 100644 --- a/sys/src/cmd/rc/exec.h +++ b/sys/src/cmd/rc/exec.h @@ -68,7 +68,6 @@ struct builtin{ }; extern struct builtin Builtin[]; int eflagok; /* kludge flag so that -e doesn't exit in startup */ -int havefork; void execcd(void), execwhatis(void), execeval(void), execexec(void); int execforkexec(void); diff --git a/sys/src/cmd/rc/havefork.c b/sys/src/cmd/rc/havefork.c index 322ec0ce7..7f359423b 100644 --- a/sys/src/cmd/rc/havefork.c +++ b/sys/src/cmd/rc/havefork.c @@ -4,8 +4,6 @@ #include "io.h" #include "fns.h" -int havefork = 1; - void Xasync(void) { diff --git a/sys/src/cmd/rc/haventfork.c b/sys/src/cmd/rc/haventfork.c deleted file mode 100644 index 1e5aa0dc9..000000000 --- a/sys/src/cmd/rc/haventfork.c +++ /dev/null @@ -1,217 +0,0 @@ -#include "rc.h" -#include "getflags.h" -#include "exec.h" -#include "io.h" -#include "fns.h" - -int havefork = 0; - -static char ** -rcargv(char *s) -{ - int argc; - char **argv; - word *p; - - p = vlook("*")->val; - argv = emalloc((count(p)+6)*sizeof(char*)); - argc = 0; - argv[argc++] = argv0; - if(flag['e']) - argv[argc++] = "-Se"; - else - argv[argc++] = "-S"; - argv[argc++] = "-c"; - argv[argc++] = s; - for(p = vlook("*")->val; p; p = p->next) - argv[argc++] = p->word; - argv[argc] = 0; - return argv; -} - -void -Xasync(void) -{ - uint pid; - char buf[20], **argv; - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); - free(argv); - - if(pid == 0) { - Xerror("proc failed"); - return; - } - - runq->pc++; - sprint(buf, "%d", pid); - setvar("apid", newword(buf, (word *)0)); -} - -enum { Stralloc = 100, }; - -void -Xbackq(void) -{ - char **argv; - int c, l; - char *s, *wd, *ewd, *stop; - struct io *f; - var *ifs = vlook("ifs"); - word *v, *nextv; - int pfd[2]; - int pid; - - stop = ifs->val?ifs->val->word:""; - if(pipe(pfd)<0){ - Xerror("can't make pipe"); - return; - } - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, pfd[1], 2); - free(argv); - - close(pfd[1]); - - if(pid == 0) { - Xerror("proc failed"); - close(pfd[0]); - return; - } - - f = openfd(pfd[0]); - s = wd = ewd = 0; - v = 0; - while((c=rchr(f))!=EOF){ - if(s==ewd){ - l = s-wd; - wd = erealloc(wd, l+Stralloc); - ewd = wd+l+Stralloc-1; - s = wd+l; - } - if(strchr(stop, c)){ - if(s!=wd){ - *s='\0'; - v = newword(wd, v); - s = wd; - } - } - else *s++=c; - } - if(s!=wd){ - *s='\0'; - v=newword(wd, v); - } - free(wd); - closeio(f); - Waitfor(pid, 1); - /* v points to reversed arglist -- reverse it onto argv */ - while(v){ - nextv=v->next; - v->next=runq->argv->words; - runq->argv->words=v; - v=nextv; - } - runq->pc++; -} - -void -Xpipe(void) -{ - thread *p=runq; - int pc=p->pc, pid; - int rfd=p->code[pc+1].i; - int pfd[2]; - char **argv; - - if(pipe(pfd)<0){ - Xerror1("can't get pipe"); - return; - } - - Updenv(); - - argv = rcargv(runq->code[pc+2].s); - pid = ForkExecute(argv0, argv, 0, pfd[1], 2); - free(argv); - close(pfd[1]); - - if(pid == 0) { - Xerror("proc failed"); - close(pfd[0]); - return; - } - - start(p->code, pc+4, runq->local); - pushredir(ROPEN, pfd[0], rfd); - p->pc=p->code[pc+3].i; - p->pid=pid; -} - -void -Xpipefd(void) -{ - Abort(); -} - -void -Xsubshell(void) -{ - char **argv; - int pid; - - Updenv(); - - argv = rcargv(runq->code[runq->pc].s); - pid = ForkExecute(argv0, argv, -1, 1, 2); - free(argv); - - if(pid < 0) { - Xerror("proc failed"); - return; - } - - Waitfor(pid, 1); - runq->pc++; -} - -/* - * start a process running the cmd on the stack and return its pid. - */ -int -execforkexec(void) -{ - char **argv; - char file[1024]; - int nc, mc; - word *path; - int pid; - - if(runq->argv->words==0) - return -1; - argv = mkargv(runq->argv->words); - mc = strlen(argv[1])+1; - for(path = searchpath(runq->argv->words->word);path;path = path->next){ - nc = strlen(path->word); - if(nc + mc >= sizeof file - 1) /* 1 for / */ - continue; - if(nc > 0){ - memmove(file, path->word, nc); - file[nc++] = '/'; - } - memmove(file+nc, argv[1], mc); - pid = ForkExecute(file, argv+1, mapfd(0), mapfd(1), mapfd(2)); - if(pid >= 0){ - free(argv); - return pid; - } - } - free(argv); - return -1; -} diff --git a/sys/src/cmd/rc/mkfile b/sys/src/cmd/rc/mkfile index b2ea3c5eb..de6e8c2e7 100644 --- a/sys/src/cmd/rc/mkfile +++ b/sys/src/cmd/rc/mkfile @@ -1,7 +1,7 @@ $test.out - -listing: - pr mkfile $HFILES $FILES $FILES9 $FILESUNIX $YFILES|lp -du diff --git a/sys/src/cmd/rc/unix.c b/sys/src/cmd/rc/unix.c deleted file mode 100644 index 905bbbbd5..000000000 --- a/sys/src/cmd/rc/unix.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Unix versions of system-specific functions - * By convention, exported routines herein have names beginning with an - * upper case letter. - */ -#include "rc.h" -#include "exec.h" -#include -char Rcmain[]="/usr/lib/rcmain"; -char Fdprefix[]="/dev/fd/"; -int execumask(), execfinit(); -struct builtin Builtin[] = { - "cd", execcd, - "whatis", execwhatis, - "eval", execeval, - "exec", execexec, /* but with popword first */ - "exit", execexit, - "shift", execshift, - "wait", execwait, - "umask", execumask, - ".", execdot, - "finit", execfinit, - "flag", execflag, - 0 -}; -#define SEP '\1' -char **environp; - -struct word* -enval(s) -register char *s; -{ - char *t, c; - struct word *v; - for(t = s;*t && *t!=SEP;t++); - c=*t; - *t='\0'; - v = newword(s, c=='\0'?(struct word *)0:enval(t+1)); - *t = c; - return v; -} -Vinit(){ - extern char **environ; - char *s; - char **env = environ; - environp = env; - for(;*env;env++){ - for(s=*env;*s && *s!='(' && *s!='=';s++); - switch(*s){ - case '\0': - pfmt(err, "environment %q?\n", *env); - break; - case '=': - *s='\0'; - setvar(*env, enval(s+1)); - *s='='; - break; - case '(': /* ignore functions for now */ - break; - } - } -} -char **envp; -Xrdfn(){ - char *s; - int len; - for(;*envp;envp++){ - for(s=*envp;*s && *s!='(' && *s!='=';s++); - switch(*s){ - case '\0': - pfmt(err, "environment %q?\n", *envp); - break; - case '=': /* ignore variables */ - break; - case '(': /* Bourne again */ - s=*envp+3; - envp++; - len = strlen(s); - s[len]='\n'; - execcmds(opencore(s, len+1)); - s[len]='\0'; - return; - } - } - Xreturn(); -} -union code rdfns[4]; -execfinit(){ - static int first = 1; - if(first){ - rdfns[0].i = 1; - rdfns[1].f = Xrdfn; - rdfns[2].f = Xjump; - rdfns[3].i = 1; - first = 0; - } - Xpopm(); - envp = environp; - start(rdfns, 1, runq->local); -} -cmpenv(a, b) -char **a, **b; -{ - return strcmp(*a, *b); -} - -char* -*mkenv() -{ - char **env, **ep, *p, *q; - struct var **h, *v; - struct word *a; - int nvar = 0, nchr = 0, sep; - /* - * Slightly kludgy loops look at locals then globals - */ - for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){ - if((v==vlook(v->name)) && v->val){ - nvar++; - nchr+=strlen(v->name)+1; - for(a = v->val;a;a = a->next) - nchr+=strlen(a->word)+1; - } - if(v->fn){ - nvar++; - nchr+=strlen(v->name)+strlen(v->fn[v->pc-1].s)+8; - } - } - env = (char **)emalloc((nvar+1)*sizeof(char *)+nchr); - ep = env; - p = (char *)&env[nvar+1]; - for(h = var-1;h!=&var[NVAR];h++) for(v = h>=var?*h:runq->local;v;v = v->next){ - if((v==vlook(v->name)) && v->val){ - *ep++=p; - q = v->name; - while(*q) *p++=*q++; - sep='='; - for(a = v->val;a;a = a->next){ - *p++=sep; - sep = SEP; - q = a->word; - while(*q) *p++=*q++; - } - *p++='\0'; - } - if(v->fn){ - *ep++=p; - *p++='#'; *p++='('; *p++=')'; /* to fool Bourne */ - *p++='f'; *p++='n'; *p++=' '; - q = v->name; - while(*q) *p++=*q++; - *p++=' '; - q = v->fn[v->pc-1].s; - while(*q) *p++=*q++; - *p++='\0'; - } - } - *ep = 0; - qsort((char *)env, nvar, sizeof ep[0], cmpenv); - return env; -} -char *sigmsg[] = { -/* 0 normal */ 0, -/* 1 SIGHUP */ "Hangup", -/* 2 SIGINT */ 0, -/* 3 SIGQUIT */ "Quit", -/* 4 SIGILL */ "Illegal instruction", -/* 5 SIGTRAP */ "Trace/BPT trap", -/* 6 SIGIOT */ "abort", -/* 7 SIGEMT */ "EMT trap", -/* 8 SIGFPE */ "Floating exception", -/* 9 SIGKILL */ "Killed", -/* 10 SIGBUS */ "Bus error", -/* 11 SIGSEGV */ "Memory fault", -/* 12 SIGSYS */ "Bad system call", -/* 13 SIGPIPE */ 0, -/* 14 SIGALRM */ "Alarm call", -/* 15 SIGTERM */ "Terminated", -/* 16 unused */ "signal 16", -/* 17 SIGSTOP */ "Process stopped", -/* 18 unused */ "signal 18", -/* 19 SIGCONT */ "Process continued", -/* 20 SIGCHLD */ "Child death", -}; -Waitfor(pid, persist){ - int wpid, sig; - struct thread *p; - int wstat; - char wstatstr[12]; - for(;;){ - errno = 0; - wpid = wait(&wstat); - if(errno==EINTR && persist) - continue; - if(wpid==-1) - break; - sig = wstat&0177; - if(sig==0177){ - pfmt(err, "trace: "); - sig = (wstat>>8)&0177; - } - if(sig>(sizeof sigmsg/sizeof sigmsg[0]) || sigmsg[sig]){ - if(pid!=wpid) - pfmt(err, "%d: ", wpid); - if(sig<=(sizeof sigmsg/sizeof sigmsg[0])) - pfmt(err, "%s", sigmsg[sig]); - else if(sig==0177) pfmt(err, "stopped by ptrace"); - else pfmt(err, "signal %d", sig); - if(wstat&0200)pfmt(err, " -- core dumped"); - pfmt(err, "\n"); - } - wstat = sig?sig+1000:(wstat>>8)&0xFF; - if(wpid==pid){ - inttoascii(wstatstr, wstat); - setstatus(wstatstr); - break; - } - else{ - for(p = runq->ret;p;p = p->ret) - if(p->pid==wpid){ - p->pid=-1; - inttoascii(p->status, wstat); - break; - } - } - } -} - -char* -*mkargv(a) -register struct word *a; -{ - char **argv = (char **)emalloc((count(a)+2)*sizeof(char *)); - char **argp = argv+1; /* leave one at front for runcoms */ - for(;a;a = a->next) *argp++=a->word; - *argp = 0; - return argv; -} -Updenv(){} -Execute(args, path) -register struct word *args, *path; -{ - char *msg="not found"; - int txtbusy = 0; - char **env = mkenv(); - char **argv = mkargv(args); - char file[512]; - for(;path;path = path->next){ - strcpy(file, path->word); - if(file[0]) - strcat(file, "/"); - strcat(file, argv[1]); - ReExec: - execve(file, argv+1, env); - switch(errno){ - case ENOEXEC: - pfmt(err, "%s: Bourne again\n", argv[1]); - argv[0]="sh"; - argv[1] = estrdup(file); - execve("/bin/sh", argv, env); - goto Bad; - case ETXTBSY: - if(++txtbusy!=5){ - sleep(txtbusy); - goto ReExec; - } - msg="text busy"; goto Bad; - case EACCES: - msg="no access"; - break; - case ENOMEM: - msg="not enough memory"; goto Bad; - case E2BIG: - msg="too big"; goto Bad; - } - } -Bad: - setstatus(msg); - pfmt(err, "%s: %s\n", argv[1], msg); - free(env); - free(argv); -} -#define NDIR 14 /* should get this from param.h */ -Globsize(p) -register char *p; -{ - int isglob = 0, globlen = NDIR+1; - for(;*p;p++){ - if(*p==GLOB){ - p++; - if(*p!=GLOB) - isglob++; - globlen+=*p=='*'?NDIR:1; - } - else - globlen++; - } - return isglob?globlen:0; -} -#include -#include -#define NDIRLIST 50 -DIR *dirlist[NDIRLIST]; -Opendir(name) -char *name; -{ - DIR **dp; - for(dp = dirlist;dp!=&dirlist[NDIRLIST];dp++) - if(*dp==0){ - *dp = opendir(name); - return *dp?dp-dirlist:-1; - } - return -1; -} -Readdir(f, p, onlydirs) -int f; -void *p; -int onlydirs; /* ignored, just advisory */ -{ - struct direct *dp = readdir(dirlist[f]); - if(dp==0) - return 0; - strncpy(p, dp->d_name, NDIR); - return 1; -} -Closedir(f){ - closedir(dirlist[f]); - dirlist[f] = 0; -} -char *Signame[] = { - "sigexit", "sighup", "sigint", "sigquit", - "sigill", "sigtrap", "sigiot", "sigemt", - "sigfpe", "sigkill", "sigbus", "sigsegv", - "sigsys", "sigpipe", "sigalrm", "sigterm", - "sig16", "sigstop", "sigtstp", "sigcont", - "sigchld", "sigttin", "sigttou", "sigtint", - "sigxcpu", "sigxfsz", "sig26", "sig27", - "sig28", "sig29", "sig30", "sig31", - 0, -}; - -int -gettrap(sig) -{ - signal(sig, gettrap); - trap[sig]++; - ntrap++; - if(ntrap>=NSIG){ - pfmt(err, "rc: Too many traps (trap %d), dumping core\n", sig); - signal(SIGIOT, (int (*)())0); - kill(getpid(), SIGIOT); - } -} -Trapinit(){ - int i; - int (*sig)(); - if(1 || flag['d']){ /* wrong!!! */ - sig = signal(SIGINT, gettrap); - if(sig==SIG_IGN) - signal(SIGINT, SIG_IGN); - } - else{ - for(i = 1;i<=NSIG;i++) if(i!=SIGCHLD){ - sig = signal(i, gettrap); - if(sig==SIG_IGN) - signal(i, SIG_IGN); - } - } -} -Unlink(name) -char *name; -{ - return unlink(name); -} -Write(fd, buf, cnt) -void *buf; -{ - return write(fd, buf, cnt); -} -Read(fd, buf, cnt) -void *buf; -{ - return read(fd, buf, cnt); -} -Seek(fd, cnt, whence) -long cnt; -{ - return lseek(fd, cnt, whence); -} -Executable(file) -char *file; -{ - return(access(file, 01)==0); -} -Creat(file) -char *file; -{ - return creat(file, 0666); -} -Dup(a, b){ - return dup2(a, b); -} -Dup1(a){ - return dup(a); -} -/* - * Wrong: should go through components of a|b|c and return the maximum. - */ -Exit(stat) -register char *stat; -{ - int n = 0; - while(*stat){ - if(*stat!='|'){ - if(*stat<'0' || '9'<*stat) - exit(1); - else n = n*10+*stat-'0'; - } - stat++; - } - exit(n); -} -Eintr(){ - return errno==EINTR; -} -Noerror(){ - errno = 0; -} -Isatty(fd){ - return isatty(fd); -} -Abort(){ - abort(); -} -static int -octal(char *s) -{ - int n = 0; - while(*s==' ' || *s=='\t' || *s=='\n') s++; - while('0'<=*s && *s<='7') n = n*8+*s++-'0'; - return n; -} -execumask(){ /* wrong -- should fork before writing */ - int m; - struct io out[1]; - switch(count(runq->argv->words)){ - default: - pfmt(err, "Usage: umask [umask]\n"); - setstatus("umask usage"); - poplist(); - return; - case 2: - umask(octal(runq->argv->words->next->word)); - break; - case 1: - umask(m = umask(0)); - out->fd = mapfd(1); - out->bufp = out->buf; - out->ebuf=&out->buf[NBUF]; - out->strp = 0; - pfmt(out, "%o\n", m); - break; - } - setstatus(""); - poplist(); -} diff --git a/sys/src/cmd/rc/win32.c b/sys/src/cmd/rc/win32.c deleted file mode 100644 index b33f8b545..000000000 --- a/sys/src/cmd/rc/win32.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Plan 9 versions of system-specific functions - * By convention, exported routines herein have names beginning with an - * upper case letter. - */ -#include "rc.h" -#include "exec.h" -#include "io.h" -#include "fns.h" -#include "getflags.h" -char *Signame[] = { - "sigexit", "sighup", "sigint", "sigquit", - "sigalrm", "sigkill", "sigfpe", "sigterm", - 0 -}; -char *syssigname[] = { - "exit", /* can't happen */ - "hangup", - "interrupt", - "quit", /* can't happen */ - "alarm", - "kill", - "sys: fp: ", - "term", - 0 -}; -char Rcmain[]="/rc/lib/rcmain"; -char Fdprefix[]="/fd/"; -void execfinit(void); -void execbind(void); - -builtin Builtin[] = { - "cd", execcd, - "whatis", execwhatis, - "eval", execeval, - "exec", execexec, /* but with popword first */ - "exit", execexit, - "shift", execshift, - "wait", execwait, - ".", execdot, - "finit", execfinit, - "flag", execflag, - 0 -}; - -void -Vinit(void) -{ - int dir, f, len; - word *val; - char *buf, *s; - Dir *ent; - int i, nent; - char envname[256]; - dir = open("/env", OREAD); - if(dir<0){ - pfmt(err, "rc: can't open /env: %r\n"); - return; - } - ent = nil; - for(;;){ - nent = dirread(dir, &ent); - if(nent <= 0) - break; - for(i = 0; i=0){ - buf = emalloc((int)len+1); - read(f, buf, (long)len); - val = 0; - /* Charitably add a 0 at the end if need be */ - if(buf[len-1]) - buf[len++]='\0'; - s = buf+len-1; - for(;;){ - while(s!=buf && s[-1]!='\0') --s; - val = newword(s, val); - if(s==buf) - break; - --s; - } - setvar(ent[i].name, val); - vlook(ent[i].name)->changed = 0; - close(f); - free(buf); - } - } - } - free(ent); - } - close(dir); -} -int envdir; - -void -Xrdfn(void) -{ - int f, len; - static Dir *ent, *allocent; - static int nent; - Dir *e; - char envname[256]; - - for(;;){ - if(nent == 0){ - free(allocent); - nent = dirread(envdir, &allocent); - ent = allocent; - } - if(nent <= 0) - break; - while(nent){ - e = ent++; - nent--; - len = e->length; - if(len && strncmp(e->name, "fn#", 3)==0){ - snprint(envname, sizeof envname, "/env/%s", e->name); - if((f = open(envname, 0))>=0){ - execcmds(openfd(f)); - return; - } - } - } - } - close(envdir); - Xreturn(); -} -union code rdfns[4]; - -void -execfinit(void) -{ - static int first = 1; - if(first){ - rdfns[0].i = 1; - rdfns[1].f = Xrdfn; - rdfns[2].f = Xjump; - rdfns[3].i = 1; - first = 0; - } - Xpopm(); - envdir = open("/env", 0); - if(envdir<0){ - pfmt(err, "rc: can't open /env: %r\n"); - return; - } - start(rdfns, 1, runq->local); -} - -int -Waitfor(int pid, int persist) -{ - thread *p; - Waitmsg *w; - char errbuf[ERRMAX]; - - while((w = wait()) != nil){ - if(w->pid==pid){ - setstatus(w->msg); - free(w); - return 0; - } - for(p = runq->ret;p;p = p->ret) - if(p->pid==w->pid){ - p->pid=-1; - strcpy(p->status, w->msg); - } - free(w); - } - - errstr(errbuf, sizeof errbuf); - if(strcmp(errbuf, "interrupted")==0) return -1; - return 0; -} - -char* -*mkargv(word *a) -{ - char **argv = (char **)emalloc((count(a)+2)*sizeof(char *)); - char **argp = argv+1; /* leave one at front for runcoms */ - for(;a;a = a->next) *argp++=a->word; - *argp = 0; - return argv; -} - -void -addenv(var *v) -{ - char envname[256]; - word *w; - int f; - io *fd; - if(v->changed){ - v->changed = 0; - snprint(envname, sizeof envname, "/env/%s", v->name); - if((f = Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ - for(w = v->val;w;w = w->next) - write(f, w->word, strlen(w->word)+1L); - close(f); - } - } - if(v->fnchanged){ - v->fnchanged = 0; - snprint(envname, sizeof envname, "/env/fn#%s", v->name); - if((f = Creat(envname))<0) - pfmt(err, "rc: can't open %s: %r\n", envname); - else{ - if(v->fn){ - fd = openfd(f); - pfmt(fd, "fn %q %s\n", v->name, v->fn[v->pc-1].s); - closeio(fd); - } - close(f); - } - } -} - -void -updenvlocal(var *v) -{ - if(v){ - updenvlocal(v->next); - addenv(v); - } -} - -void -Updenv(void) -{ - var *v, **h; - for(h = gvar;h!=&gvar[NVAR];h++) - for(v=*h;v;v = v->next) - addenv(v); - if(runq) - updenvlocal(runq->local); -} - -int -ForkExecute(char *file, char **argv, int sin, int sout, int serr) -{ - int pid; - -{int i; -fprint(2, "forkexec %s", file); -for(i = 0; argv[i]; i++)fprint(2, " %s", argv[i]); -fprint(2, " %d %d %d\n", sin, sout, serr); -} - if(access(file, 1) != 0) - return -1; -fprint(2, "forking\n"); - switch(pid = fork()){ - case -1: - return -1; - case 0: - if(sin >= 0) - dup(sin, 0); - else - close(0); - if(sout >= 0) - dup(sout, 1); - else - close(1); - if(serr >= 0) - dup(serr, 2); - else - close(2); -fprint(2, "execing\n"); - exec(file, argv); -fprint(2, "exec: %r\n"); - exits(file); - } - return pid; -} - -void -Execute(word *args, word *path) -{ - char **argv = mkargv(args); - char file[1024]; - int nc; - Updenv(); - for(;path;path = path->next){ - nc = strlen(path->word); - if(nc<1024){ - strcpy(file, path->word); - if(file[0]){ - strcat(file, "/"); - nc++; - } - if(nc+strlen(argv[1])<1024){ - strcat(file, argv[1]); - exec(file, argv+1); - } - else werrstr("command name too long"); - } - } - rerrstr(file, sizeof file); - setstatus(file); - pfmt(err, "%s: %s\n", argv[1], file); - free(argv); -} -#define NDIR 256 /* shoud be a better way */ - -int -Globsize(char *p) -{ - int isglob = 0, globlen = NDIR+1; - for(;*p;p++){ - if(*p==GLOB){ - p++; - if(*p!=GLOB) - isglob++; - globlen+=*p=='*'?NDIR:1; - } - else - globlen++; - } - return isglob?globlen:0; -} -#define NFD 50 -#define NDBUF 32 -struct{ - Dir *dbuf; - int i; - int n; -}dir[NFD]; - -int -Opendir(char *name) -{ - Dir *db; - int f; - f = open(name, 0); - if(f==-1) - return f; - db = dirfstat(f); - if(db!=nil && (db->mode&DMDIR)){ - if(f=NFD) - return 0; -Again: - if(dir[f].i==dir[f].n){ /* read */ - free(dir[f].dbuf); - dir[f].dbuf = 0; - n = dirread(f, &dir[f].dbuf); - if(n>0){ - if(onlydirs){ - n = trimdirs(dir[f].dbuf, n); - if(n == 0) - goto Again; - } - dir[f].n = n; - }else - dir[f].n = 0; - dir[f].i = 0; - } - if(dir[f].i == dir[f].n) - return 0; - strncpy(p, dir[f].dbuf[dir[f].i].name, NDIR); - dir[f].i++; - return 1; -} - -void -Closedir(int f) -{ - if(f>=0 && f=32){ /* rc is probably in a trap loop */ - pfmt(err, "rc: Too many traps (trap %s), aborting\n", s); - abort(); - } - noted(NCONT); -} - -void -Trapinit(void) -{ - notify(notifyf); -} - -void -Unlink(char *name) -{ - remove(name); -} - -long -Write(int fd, void *buf, long cnt) -{ - return write(fd, buf, (long)cnt); -} - -long -Read(int fd, void *buf, long cnt) -{ - return read(fd, buf, cnt); -} - -long -Seek(int fd, long cnt, long whence) -{ - return seek(fd, cnt, whence); -} - -int -Executable(char *file) -{ - Dir *statbuf; - int ret; - - statbuf = dirstat(file); - if(statbuf == nil) - return 0; - ret = ((statbuf->mode&0111)!=0 && (statbuf->mode&DMDIR)==0); - free(statbuf); - return ret; -} - -int -Creat(char *file) -{ - return create(file, 1, 0666L); -} - -int -Dup(int a, int b) -{ - return dup(a, b); -} - -int -Dup1(int) -{ - return -1; -} - -void -Exit(char *stat) -{ - Updenv(); - setstatus(stat); - exits(truestatus()?"":getstatus()); -} - -int -Eintr(void) -{ - return interrupted; -} - -void -Noerror(void) -{ - interrupted = 0; -} - -int -Isatty(int fd) -{ - Dir *d1, *d2; - int ret; - - d1 = dirfstat(fd); - if(d1 == nil) - return 0; - if(strncmp(d1->name, "ptty", 4)==0){ /* fwd complaints to philw */ - free(d1); - return 1; - } - d2 = dirstat("/dev/cons"); - if(d2 == nil){ - free(d1); - return 0; - } - ret = (d1->type==d2->type&&d1->dev==d2->dev&&d1->qid.path==d2->qid.path); - free(d1); - free(d2); - return ret; -} - -void -Abort(void) -{ - pfmt(err, "aborting\n"); - flush(err); - Exit("aborting"); -}