📄 compiling.on.unix
字号:
From geoff@collyer.net Fri Dec 19 01:21:40 EST 2003Received: from plan9.cs.bell-labs.com ([135.104.9.2]) by plan9; Fri Dec 19 01:21:39 EST 2003Received: from collyer.net ([63.192.14.226]) by plan9; Fri Dec 19 01:21:35 EST 2003Message-ID: <c790d8b1e06b3918ad2c7848a3ae0ec7@collyer.net>subject: rc on unix, part 1From: Geoff Collyer <geoff@collyer.net>Date: Thu, 18 Dec 2003 22:21:33 -0800To: presotto@plan9.bell-labs.com, rsc@plan9.bell-labs.com, geoff@collyer.netMIME-Version: 1.0Content-Type: text/plain; charset="US-ASCII"Content-Transfer-Encoding: 7bitI got /sys/src/cmd/rc to compile under APE (in preparation for moving itto Unixes) with the following changed files. I cadged some include filesfrom rsc but had to edit lib9.h slightly. I'll send the include filesseparately. 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 yetsimulated the effect of the OCEXEC bit.# To unbundle, run this fileecho mkfilesed 's/^X//' >mkfile <<'!'X</$objtype/mkfileTARG=rcCOMMONOFILES=\X code.$O\X exec.$O\X getflags.$O\X glob.$O\X here.$O\X io.$O\X lex.$O\X pcmd.$O\X pfnc.$O\X simple.$O\X subr.$O\X trap.$O\X tree.$O\X var.$O\X havefork.$O\PLAN9OFILES=plan9.$O\UNIXOFILES=unix.$O\OFILES=$COMMONOFILES $UNIXOFILES y.tab.$OHFILES=rc.h\X x.tab.h\X io.h\X exec.h\X fns.h\YFILES=syn.yBIN=/$objtype/binUPDATE=\X mkfile\X $HFILES\X ${COMMONOFILES:%.$O=%.c}\X ${UNIXOFILES:%.$O=%.c}\X ${PLAN9OFILES:%.$O=%.c}\X $YFILES\X ${TARG:%=/386/bin/%}\CC=pcc -c -B -I../includeLD=pccX</sys/src/cmd/mkonex.tab.h: y.tab.hX cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.hclean:V:X rm -f [$OS].out *.[$OS] [xy].tab.? y.debug $TARGregress: $O.outX cd testX mkunregress:V:X for(test in test/*.test) rc $test >$test.outlisting:X pr mkfile $HFILES $FILES $FILES9 $FILESUNIX $YFILES|lp -du!echo simple.csed '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}voidXXsimple(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};voiddoredir(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)==0X || strncmp(w, "#", 1)==0X || strncmp(w, "./", 2)==0X || strncmp(w, "../", 3)==0X || (path = vlook("path")->val)==0)X path=&nullpath;X return path;X}voidexecexec(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}voidexecfunc(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}intdochdir(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}voidexeccd(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 elseX pfmt(err, "Can't cd %s: %r\n", a->word);X }X elseX pfmt(err, "Can't cd -- $home empty\n");X break;X }X poplist();X}voidexecexit(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}voidexecshift(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}intoctal(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}intmapfd(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];voidexeccmds(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}voidexeceval(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];voidexecdot(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 elseX 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}voidexecflag(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}voidexecwhatis(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 elseX 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}voidexecwait(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.csed '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;voidXXasync(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 UnixX pid = fork();X#elseX pid = rfork(RFFDG|RFPROC|RFNOTEG);X#endifX switch(pid){X case -1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -