diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-03 18:41:48 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-01-03 18:41:48 +0000 |
commit | 189731aad01e09db1807c78af421c615ed3a3242 (patch) | |
tree | 4cec623654b4e4e9da03bb00f36ea49755c8ca98 /sys/src/cmd/rc | |
parent | c51a5cfa06dd982da839c4cfcba1610259d27e38 (diff) |
rc: make it portable (for UNIX)
Fixup remaining Plan9 dependencies (chartorune()).
Add Makefile for UNIX-like systems (tested with Linux and APE).
Make error printing consistent, use Errstr() explicitely.
Get rid of NSTATUS buffer limit, just malloc it.
Diffstat (limited to 'sys/src/cmd/rc')
-rw-r--r-- | sys/src/cmd/rc/Makefile | 51 | ||||
-rw-r--r-- | sys/src/cmd/rc/code.c | 2 | ||||
-rw-r--r-- | sys/src/cmd/rc/exec.c | 159 | ||||
-rw-r--r-- | sys/src/cmd/rc/exec.h | 8 | ||||
-rw-r--r-- | sys/src/cmd/rc/fns.h | 8 | ||||
-rw-r--r-- | sys/src/cmd/rc/getflags.c | 3 | ||||
-rw-r--r-- | sys/src/cmd/rc/glob.c | 39 | ||||
-rw-r--r-- | sys/src/cmd/rc/havefork.c | 21 | ||||
-rw-r--r-- | sys/src/cmd/rc/here.c | 9 | ||||
-rw-r--r-- | sys/src/cmd/rc/io.c | 25 | ||||
-rw-r--r-- | sys/src/cmd/rc/io.h | 4 | ||||
-rw-r--r-- | sys/src/cmd/rc/lex.c | 19 | ||||
-rw-r--r-- | sys/src/cmd/rc/mkfile | 9 | ||||
-rw-r--r-- | sys/src/cmd/rc/plan9.c | 27 | ||||
-rw-r--r-- | sys/src/cmd/rc/rc.h | 32 | ||||
-rw-r--r-- | sys/src/cmd/rc/rcmain.plan9 | 41 | ||||
-rw-r--r-- | sys/src/cmd/rc/rcmain.unix | 38 | ||||
-rw-r--r-- | sys/src/cmd/rc/simple.c | 29 | ||||
-rw-r--r-- | sys/src/cmd/rc/subr.c | 4 | ||||
-rw-r--r-- | sys/src/cmd/rc/trap.c | 6 | ||||
-rw-r--r-- | sys/src/cmd/rc/unix.c | 420 |
21 files changed, 799 insertions, 155 deletions
diff --git a/sys/src/cmd/rc/Makefile b/sys/src/cmd/rc/Makefile new file mode 100644 index 000000000..43e3a05e1 --- /dev/null +++ b/sys/src/cmd/rc/Makefile @@ -0,0 +1,51 @@ +TARG=rc + +OFILES=\ + code.o\ + exec.o\ + getflags.o\ + glob.o\ + here.o\ + io.o\ + lex.o\ + pcmd.o\ + pfnc.o\ + simple.o\ + subr.o\ + trap.o\ + tree.o\ + var.o\ + havefork.o\ + unix.o\ + y.tab.o\ + +HFILES=rc.h\ + y.tab.h\ + io.h\ + exec.h\ + fns.h\ + getflags.h\ + +YFILES=syn.y + +PREFIX=/usr/local + +all: $(TARG) + +install: $(TARG) rcmain.unix + cp $(TARG) $(PREFIX)/bin/ + cp rcmain.unix $(PREFIX)/lib/rcmain + +$(TARG): $(OFILES) + $(CC) $(CFLAGS) $(LDFLAGS) -o $(TARG) $(OFILES) + +y.tab.h y.tab.c: $(YFILES) + $(YACC) -d $(YFILES) + +unix.o: unix.c + $(CC) $(CFLAGS) '-DPREFIX="$(PREFIX)"' -c unix.c + +$(OFILES): $(HFILES) + +clean: + rm -f $(OFILES) $(TARG) y.tab.? y.debug diff --git a/sys/src/cmd/rc/code.c b/sys/src/cmd/rc/code.c index f39b3a573..d5427aff5 100644 --- a/sys/src/cmd/rc/code.c +++ b/sys/src/cmd/rc/code.c @@ -460,7 +460,7 @@ codeswitch(tree *t, int eflag) int out; /* jump here to leave switch */ int nextcase; /* patch jump address to next case */ tree *tt; - if(c1->child[0]==nil + if(c1->child[0]==0 || c1->child[0]->type!=';' || !iscase(c1->child[0]->child[0])){ yyerror("case missing in switch"); diff --git a/sys/src/cmd/rc/exec.c b/sys/src/cmd/rc/exec.c index 7e2aaa95a..fa32a182b 100644 --- a/sys/src/cmd/rc/exec.c +++ b/sys/src/cmd/rc/exec.c @@ -19,6 +19,8 @@ start(code *c, int pc, var *local, redir *redir) p->lex = 0; p->local = local; p->iflag = 0; + p->pid = 0; + p->status = 0; p->ret = runq; runq = p; } @@ -42,6 +44,7 @@ popthread(void) runq = p->ret; if(p->lex) freelexer(p->lex); codefree(p->code); + free(p->status); free(p); } @@ -341,7 +344,7 @@ Xappend(void) } file = runq->argv->words->word; if((fd = Open(file, 1))<0 && (fd = Creat(file))<0){ - Xerror("can't open"); + Xerror3(">> can't open", file, Errstr()); return; } Seek(fd, 0L, 2); @@ -395,7 +398,7 @@ Xexit(void) return; } } - Exit(getstatus()); + Exit(); } void @@ -443,25 +446,51 @@ Xpush(void) runq->argv->words = h; } +static int +herefile(char *tmp) +{ + char *s = tmp+strlen(tmp)-1; + static int ser; + int fd, i; + + i = ser++; + while(*s == 'Y'){ + *s-- = (i%26) + 'A'; + i = i/26; + } + i = getpid(); + while(*s == 'X'){ + *s-- = (i%10) + '0'; + i = i/10; + } + s++; + for(i='a'; i<'z'; i++){ + if(access(tmp, 0)!=0 && (fd = Creat(tmp))>=0) + return fd; + *s = i; + } + return -1; +} + void Xhere(void) { - char file[] = "/tmp/here.XXXXXXXXXXX"; + char file[]="/tmp/hereXXXXXXXXXXYY"; int fd; io *io; - if((fd = Creat(mktemp(file)))<0){ - Xerror("can't open"); + if((fd = herefile(file))<0){ + Xerror3("<< can't get temp file", file, Errstr()); return; } io = openiofd(fd); - psubst(io, (uchar*)runq->code[runq->pc++].s); + psubst(io, (unsigned char*)runq->code[runq->pc++].s); flushio(io); closeio(io); /* open for reading and unlink */ if((fd = Open(file, 3))<0){ - Xerror("can't open"); + Xerror3("<< can't open", file, Errstr()); return; } pushredir(ROPEN, fd, runq->code[runq->pc++].i); @@ -470,11 +499,11 @@ Xhere(void) void Xhereq(void) { - char file[] = "/tmp/here.XXXXXXXXXXX", *body; + char file[]="/tmp/hereXXXXXXXXXXYY", *body; int fd; - if((fd = Creat(mktemp(file)))<0){ - Xerror("can't open"); + if((fd = herefile(file))<0){ + Xerror3("<< can't get temp file", file, Errstr()); return; } body = runq->code[runq->pc++].s; @@ -483,7 +512,7 @@ Xhereq(void) /* open for reading and unlink */ if((fd = Open(file, 3))<0){ - Xerror("can't open"); + Xerror3("<< can't open", file, Errstr()); return; } pushredir(ROPEN, fd, runq->code[runq->pc++].i); @@ -492,6 +521,7 @@ Xhereq(void) void Xread(void) { + char *file; int fd; switch(count(runq->argv->words)){ @@ -504,8 +534,9 @@ Xread(void) case 1: break; } - if((fd = Open(runq->argv->words->word, 0))<0){ - Xerror("can't open"); + file = runq->argv->words->word; + if((fd = Open(file, 0))<0){ + Xerror3("< can't open", file, Errstr()); return; } pushredir(ROPEN, fd, runq->code[runq->pc++].i); @@ -515,6 +546,7 @@ Xread(void) void Xrdwr(void) { + char *file; int fd; switch(count(runq->argv->words)){ @@ -527,8 +559,9 @@ Xrdwr(void) case 1: break; } - if((fd = Open(runq->argv->words->word, 2))<0){ - Xerror("can't open"); + file = runq->argv->words->word; + if((fd = Open(file, 2))<0){ + Xerror3("<> can't open", file, Errstr()); return; } pushredir(ROPEN, fd, runq->code[runq->pc++].i); @@ -555,7 +588,7 @@ Xreturn(void) Xpopredir(); popthread(); if(runq==0) - Exit(getstatus()); + Exit(); } void @@ -588,6 +621,7 @@ Xword(void) void Xwrite(void) { + char *file; int fd; switch(count(runq->argv->words)){ @@ -600,8 +634,9 @@ Xwrite(void) case 1: break; } - if((fd = Creat(runq->argv->words->word))<0){ - Xerror("can't open"); + file = runq->argv->words->word; + if((fd = Creat(file))<0){ + Xerror3("> can't create", file, Errstr()); return; } pushredir(ROPEN, fd, runq->code[runq->pc++].i); @@ -696,7 +731,7 @@ Xassign(void) var *v; if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("= variable name not singleton!"); return; } v = vlook(runq->argv->words->word); @@ -728,7 +763,7 @@ Xdol(void) int n; if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$ variable name not singleton!"); return; } n = 0; @@ -833,7 +868,7 @@ Xsub(void) char *s; if(count(runq->argv->next->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$() variable name not singleton!"); return; } s = runq->argv->next->words->word; @@ -853,7 +888,7 @@ Xcount(void) int n; if(count(runq->argv->words)!=1){ - Xerror1("variable name not singleton!"); + Xerror1("$# variable name not singleton!"); return; } n = 0; @@ -875,7 +910,7 @@ void Xlocal(void) { if(count(runq->argv->words)!=1){ - Xerror1("variable name must be singleton"); + Xerror1("local variable name must be singleton"); return; } runq->local = newvar(runq->argv->words->word, runq->local); @@ -932,29 +967,31 @@ Xdelfn(void) static char* concstatus(char *s, char *t) { - static char v[NSTATUS+1]; - int n = strlen(s); - strncpy(v, s, NSTATUS); - if(n<NSTATUS){ - v[n]='|'; - strncpy(v+n+1, t, NSTATUS-n-1); - } - v[NSTATUS]='\0'; - return v; + int n, m; + + if(t==0) return s; + if(s==0) return t; + n = strlen(s); + m = strlen(t); + s = erealloc(s, n+m+2); + if(n > 0) s[n++]='|'; + memmove(s+n, t, m+1); + free(t); + return s; } void Xpipewait(void) { - char status[NSTATUS+1]; - if(runq->pid==-1) - setstatus(concstatus(runq->status, getstatus())); - else{ - strncpy(status, getstatus(), NSTATUS); - status[NSTATUS]='\0'; - Waitfor(runq->pid, 1); + char *old = Getstatus(); + if(runq->pid==-1){ + Setstatus(concstatus(runq->status, old)); + runq->status=0; + }else{ + while(Waitfor(runq->pid) < 0) + ; runq->pid=-1; - setstatus(concstatus(getstatus(), status)); + Setstatus(concstatus(Getstatus(), old)); } } @@ -995,7 +1032,6 @@ Xrdcmds(void) p->lex = 0; } else --p->pc; /* re-execute Xrdcmds after codebuf runs */ - ntrap = 0; /* avoid double-interrupts during blocked writes */ start(codebuf, 2, p->local, p->redir); } lex = 0; @@ -1027,31 +1063,54 @@ srcfile(thread *p) } void -Xerror(char *s) +Xerror1(char *s) { + setstatus("error"); pfln(err, srcfile(runq), runq->line); - pfmt(err, ": %s: %r\n", s); + pfmt(err, ": %s\n", s); flushio(err); - setstatus("error"); while(!runq->iflag) Xreturn(); } - void -Xerror1(char *s) +Xerror2(char *s, char *e) { + setstatus(e); pfln(err, srcfile(runq), runq->line); - pfmt(err, ": %s\n", s); + pfmt(err, ": %s: %s\n", s, e); + flushio(err); + while(!runq->iflag) Xreturn(); +} +void +Xerror3(char *s, char *m, char *e) +{ + setstatus(e); + pfln(err, srcfile(runq), runq->line); + pfmt(err, ": %s: %s: %s\n", s, m, e); flushio(err); - setstatus("error"); while(!runq->iflag) Xreturn(); } void +Setstatus(char *s) +{ + setvar("status", Newword(s?s:estrdup(""), (word *)0)); +} +void setstatus(char *s) { - setvar("status", newword(s, (word *)0)); + Setstatus(estrdup(s)); +} +char* +Getstatus(void) +{ + var *status = vlook("status"); + word *val = status->val; + if(val==0) return 0; + status->val=0; + status->changed=1; + freewords(val->next); + return Freeword(val); } - char* getstatus(void) { diff --git a/sys/src/cmd/rc/exec.h b/sys/src/cmd/rc/exec.h index a696ece1e..308802679 100644 --- a/sys/src/cmd/rc/exec.h +++ b/sys/src/cmd/rc/exec.h @@ -11,8 +11,9 @@ extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void); extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void), Xpush(void); extern void Xrdcmds(void), Xwastrue(void), Xif(void), Xifnot(void), Xpipewait(void); extern void Xpopredir(void), Xsub(void), Xeflag(void), Xsettrue(void); -extern void Xerror(char*); extern void Xerror1(char*); +extern void Xerror2(char*,char*); +extern void Xerror3(char*,char*,char*); /* * word lists are in correct order, @@ -33,7 +34,6 @@ struct redir{ int from, to; /* what to do it to */ redir *next; /* what else to do (reverse order) */ }; -#define NSTATUS 128 /* length of status */ /* * redir types @@ -54,7 +54,7 @@ struct thread{ lexer *lex; /* lexer for Xrdcmds */ int iflag; /* interactive? */ int pid; /* process for Xpipewait to wait for */ - char status[NSTATUS]; /* status for Xpipewait */ + char *status; /* status for Xpipewait */ thread *ret; /* who continues when this finishes */ }; @@ -82,3 +82,5 @@ void startfunc(var*, word*, var*, redir*); char *srcfile(thread*); char *getstatus(void); + +extern char *argv0; diff --git a/sys/src/cmd/rc/fns.h b/sys/src/cmd/rc/fns.h index 1d60b988a..a4c33ed7f 100644 --- a/sys/src/cmd/rc/fns.h +++ b/sys/src/cmd/rc/fns.h @@ -8,10 +8,11 @@ int Dup1(int); int Eintr(void); int Executable(char*); void Exec(char**); -void Exit(char*); +void Exit(void); char* Errstr(void); char* Freeword(word*); int Fork(void); +char* Getstatus(void); int Isatty(int); word* Newword(char*,word*); void Noerror(void); @@ -23,10 +24,11 @@ word* Pushword(char*); long Read(int, void*, long); char* Readdir(void*, int); long Seek(int, long, long); +void Setstatus(char*); void Trapinit(void); void Updenv(void); void Vinit(void); -int Waitfor(int, int); +int Waitfor(int); long Write(int, void*, long); void addwaitpid(int); void clearwaitpids(void); @@ -52,7 +54,7 @@ void poplist(void); void popword(void); void pprompt(void); void Prompt(char*); -void psubst(io *f, uchar *s); +void psubst(io*, unsigned char*); void pushlist(void); void pushredir(int, int, int); word* pushword(char*); diff --git a/sys/src/cmd/rc/getflags.c b/sys/src/cmd/rc/getflags.c index 3c2f9adeb..7a46c435c 100644 --- a/sys/src/cmd/rc/getflags.c +++ b/sys/src/cmd/rc/getflags.c @@ -205,7 +205,8 @@ usage(char *tail) errs(tail); } errs("\n"); - Exit("bad flags"); + setstatus("bad flags"); + Exit(); } static void diff --git a/sys/src/cmd/rc/glob.c b/sys/src/cmd/rc/glob.c index a82d59280..e455a59e2 100644 --- a/sys/src/cmd/rc/glob.c +++ b/sys/src/cmd/rc/glob.c @@ -21,7 +21,7 @@ deglob(char *s) } static int -globcmp(void *s, void *t) +globcmp(const void *s, const void *t) { return strcmp(*(char**)s, *(char**)t); } @@ -70,11 +70,13 @@ globdir(word *list, char *pattern, char *name) char *slash, *glob, *entry; void *dir; +#ifdef Plan9 /* append slashes, Readdir() already filtered directories */ while(*pattern=='/'){ pappend(&name, "/"); pattern++; } +#endif if(*pattern=='\0') return Newword(name, list); @@ -140,32 +142,51 @@ globword(word *w) * Return a pointer to the next utf code in the string, * not jumping past nuls in broken utf codes! */ - static char* nextutf(char *p) { - Rune dummy; + int i, n, c = *p; - return p + chartorune(&dummy, p); + if(onebyte(c)) + return p+1; + if(twobyte(c)) + n = 2; + else if(threebyte(c)) + n = 3; + else + n = 4; + for(i = 1; i < n; i++) + if(!xbyte(p[i])) + break; + return p+i; } /* * Convert the utf code at *p to a unicode value */ - static int unicode(char *p) { - Rune r; + int c = *p; - chartorune(&r, p); - return r; + if(onebyte(c)) + return c&0xFF; + if(twobyte(c)){ + if(xbyte(p[1])) + return ((c&0x1F)<<6) | (p[1]&0x3F); + } else if(threebyte(c)){ + if(xbyte(p[1]) && xbyte(p[2])) + return ((c&0x0F)<<12) | ((p[1]&0x3F)<<6) | (p[2]&0x3F); + } else if(fourbyte(c)){ + if(xbyte(p[1]) && xbyte(p[2]) && xbyte(p[3])) + return ((c&0x07)<<18) | ((p[1]&0x3F)<<12) | ((p[2]&0x3F)<<6) | (p[3]&0x3F); + } + return -1; } /* * Do p and q point at equal utf codes */ - static int equtf(char *p, char *q) { diff --git a/sys/src/cmd/rc/havefork.c b/sys/src/cmd/rc/havefork.c index 669540e54..e50197b81 100644 --- a/sys/src/cmd/rc/havefork.c +++ b/sys/src/cmd/rc/havefork.c @@ -50,7 +50,7 @@ Xasync(void) switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); @@ -76,12 +76,12 @@ Xpipe(void) int pfd[2]; if(pipe(pfd)<0){ - Xerror("can't get pipe"); + Xerror2("can't get pipe", Errstr()); return; } switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); @@ -114,12 +114,12 @@ Xbackq(void) io *f; if(pipe(pfd)<0){ - Xerror("can't make pipe"); + Xerror2("can't make pipe", Errstr()); return; } switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); Close(pfd[PRD]); Close(pfd[PWR]); return; @@ -146,7 +146,7 @@ Xbackq(void) closeio(f); free(split); - Waitfor(pid, 0); + Waitfor(pid); runq->pc = runq->code[runq->pc].i; return; @@ -163,7 +163,7 @@ Xpipefd(void) int sidefd, mainfd; if(pipe(pfd)<0){ - Xerror("can't get pipe"); + Xerror2("can't get pipe", Errstr()); return; } if(p->code[pc].i==READ){ @@ -176,7 +176,7 @@ Xpipefd(void) } switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); @@ -205,7 +205,7 @@ Xsubshell(void) switch(pid = Fork()){ case -1: - Xerror("try again"); + Xerror2("try again", Errstr()); break; case 0: clearwaitpids(); @@ -214,7 +214,8 @@ Xsubshell(void) break; default: addwaitpid(pid); - Waitfor(pid, 1); + while(Waitfor(pid) < 0) + ; runq->pc = runq->code[runq->pc].i; break; } diff --git a/sys/src/cmd/rc/here.c b/sys/src/cmd/rc/here.c index 0f9258fe6..c148430ff 100644 --- a/sys/src/cmd/rc/here.c +++ b/sys/src/cmd/rc/here.c @@ -3,7 +3,7 @@ #include "io.h" #include "fns.h" -void psubst(io*, uchar*); +void psubst(io*, unsigned char*); void pstrs(io*, word*); char* @@ -48,11 +48,12 @@ readhere(tree *tag, io *in) } void -psubst(io *f, uchar *s) +psubst(io *f, unsigned char *s) { - int savec, n; - uchar *t, *u; + unsigned char *t, *u; word *star; + int savec, n; + while(*s){ if(*s!='$'){ if(0xa0 <= *s && *s <= 0xf5){ diff --git a/sys/src/cmd/rc/io.c b/sys/src/cmd/rc/io.c index e4b3258e4..6ec226641 100644 --- a/sys/src/cmd/rc/io.c +++ b/sys/src/cmd/rc/io.c @@ -36,9 +36,6 @@ vpfmt(io *f, char *fmt, va_list ap) case 'q': pwrd(f, va_arg(ap, char *)); break; - case 'r': - pstr(f, Errstr()); - break; case 's': pstr(f, va_arg(ap, char *)); break; @@ -141,23 +138,23 @@ void pwrd(io *f, char *s) { char *t; - for(t = s;*t;t++) if(*t >= 0 && needsrcquote(*t)) break; + for(t = s;*t;t++) if(*t >= 0 && strchr("`^#*[]=|\\?${}()'<>&;", *t)) break; if(t==s || *t) pquo(f, s); else pstr(f, s); } void -pptr(io *f, void *v) +pptr(io *f, void *p) { + static char hex[] = "0123456789ABCDEF"; + unsigned long long v; int n; - uintptr p; - - p = (uintptr)v; - if(sizeof(uintptr) == sizeof(uvlong) && p>>32) - for(n = 60;n>=32;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); - for(n = 28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]); + v = (unsigned long long)p; + if(sizeof(v) == sizeof(p) && v>>32) + for(n = 60;n>=32;n-=4) pchr(f, hex[(v>>n)&0xF]); + for(n = 28;n>=0;n-=4) pchr(f, hex[(v>>n)&0xF]); } void @@ -212,7 +209,7 @@ pval(io *f, word *a) } io* -newio(uchar *buf, int len, int fd) +newio(unsigned char *buf, int len, int fd) { io *f = new(io); f->buf = buf; @@ -228,7 +225,7 @@ newio(uchar *buf, int len, int fd) io* openiostr(void) { - uchar *buf = emalloc(100+1); + unsigned char *buf = emalloc(100+1); memset(buf, '\0', 100+1); return newio(buf, 100, -1); } @@ -258,7 +255,7 @@ openiofd(int fd) * characters from buf. */ io* -openiocore(uchar *buf, int len) +openiocore(void *buf, int len) { return newio(buf, len, -1); } diff --git a/sys/src/cmd/rc/io.h b/sys/src/cmd/rc/io.h index 7a1600397..e9537ecb3 100644 --- a/sys/src/cmd/rc/io.h +++ b/sys/src/cmd/rc/io.h @@ -2,12 +2,12 @@ struct io{ int fd; - uchar *buf, *bufp, *ebuf; + unsigned char *buf, *bufp, *ebuf; io *next; }; io *err; -io *openiofd(int), *openiostr(void), *openiocore(uchar*, int); +io *openiofd(int), *openiostr(void), *openiocore(void*, int); void pchr(io*, int); int rchr(io*); char *rstr(io*, char*); diff --git a/sys/src/cmd/rc/lex.c b/sys/src/cmd/rc/lex.c index 5e061b989..5afb5f584 100644 --- a/sys/src/cmd/rc/lex.c +++ b/sys/src/cmd/rc/lex.c @@ -190,21 +190,22 @@ addtok(char *p, int val) static char* addutf(char *p, int c) { - uchar b, m; - int i; + int i, n; p = addtok(p, c); /* 1-byte UTF runes are special */ if(onebyte(c)) return p; - - m = 0xc0; - b = 0x80; - for(i=1; i < UTFmax; i++){ - if((c&m) == b) + if(twobyte(c)) + n = 2; + else if(threebyte(c)) + n = 3; + else + n = 4; + for(i = 1; i < n; i++) { + c = nextc(); + if(c == EOF || !xbyte(c)) break; p = addtok(p, advance()); - b = m; - m = (m >> 1)|0x80; } return p; } diff --git a/sys/src/cmd/rc/mkfile b/sys/src/cmd/rc/mkfile index de6e8c2e7..67c307fe9 100644 --- a/sys/src/cmd/rc/mkfile +++ b/sys/src/cmd/rc/mkfile @@ -21,7 +21,7 @@ OFILES=\ y.tab.$O\ HFILES=rc.h\ - x.tab.h\ + y.tab.h\ io.h\ exec.h\ fns.h\ @@ -38,10 +38,9 @@ UPDATE=\ $YFILES\ ${TARG:%=/386/bin/%}\ -</sys/src/cmd/mkone +CFLAGS=$CFLAGS -DPlan9 -x.tab.h: y.tab.h - cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h +</sys/src/cmd/mkone clean:V: - rm -f [$OS].out *.[$OS] [xy].tab.? y.debug $TARG + rm -f [$OS].out *.[$OS] y.tab.? y.debug $TARG diff --git a/sys/src/cmd/rc/plan9.c b/sys/src/cmd/rc/plan9.c index 215ac318a..ada169123 100644 --- a/sys/src/cmd/rc/plan9.c +++ b/sys/src/cmd/rc/plan9.c @@ -47,13 +47,17 @@ static char *syssigname[] = { 0 }; +/* + * finit could be removed but is kept for + * backwards compatibility, see: rcmain.plan9 + */ static void execfinit(void) { char *cmds = estrdup("for(i in '/env/fn#'*){. -bq $i}\n"); int line = runq->line; poplist(); - execcmds(openiocore((uchar*)cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir); + execcmds(openiocore(cmds, strlen(cmds)), estrdup(srcfile(runq)), runq->local, runq->redir); runq->lex->line = line; runq->lex->qflag = 1; } @@ -131,7 +135,7 @@ Vinit(void) dir = Open(Env("", 0), 0); if(dir<0){ - pfmt(err, "%s: can't open: %r\n", argv0); + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); return; } for(;;){ @@ -169,7 +173,7 @@ Errstr(void) } int -Waitfor(int pid, int) +Waitfor(int pid) { thread *p; Waitmsg *w; @@ -187,7 +191,8 @@ Waitfor(int pid, int) for(p = runq->ret;p;p = p->ret) if(p->pid==w->pid){ p->pid=-1; - strcpy(p->status, w->msg); + p->status = estrdup(w->msg); + break; } free(w); } @@ -206,7 +211,7 @@ addenv(var *v) if(v->changed){ v->changed = 0; if((fd = Creat(Env(v->name, 0)))<0) - pfmt(err, "%s: can't open: %r\n", argv0); + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); else{ f = openiofd(fd); for(w = v->val;w;w = w->next){ @@ -220,7 +225,7 @@ addenv(var *v) if(v->fnchanged){ v->fnchanged = 0; if((fd = Creat(Env(v->name, 1)))<0) - pfmt(err, "%s: can't open: %r\n", argv0); + pfmt(err, "%s: can't open: %s\n", argv0, Errstr()); else{ f = openiofd(fd); if(v->fn) @@ -420,16 +425,15 @@ Dup(int a, int b) } int -Dup1(int) +Dup1(int a) { - return -1; + return dup(a, -1); } void -Exit(char *stat) +Exit(void) { Updenv(); - setstatus(stat); exits(truestatus()?"":getstatus()); } @@ -459,8 +463,7 @@ Isatty(int fd) void Abort(void) { - pfmt(err, "aborting\n"); - Exit("aborting"); + abort(); } static int newwdir; diff --git a/sys/src/cmd/rc/rc.h b/sys/src/cmd/rc/rc.h index 7e0b0611c..d02c1312f 100644 --- a/sys/src/cmd/rc/rc.h +++ b/sys/src/cmd/rc/rc.h @@ -1,28 +1,29 @@ /* * Plan9 is defined for plan 9 - * V9 is defined for 9th edition - * Sun is defined for sun-os + * otherwise its UNIX. * Please don't litter the code with ifdefs. The three below (and one in * getflags) should be enough. */ -#define Plan9 -#ifdef Plan9 +#ifdef Plan9 #include <u.h> #include <libc.h> -#define NSIG 32 +#define NSIG 32 #define SIGINT 2 #define SIGQUIT 3 -#endif -#ifdef V9 +#else +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <string.h> #include <signal.h> -#include <libc.h> +#ifndef NSIG +#define NSIG 32 #endif -#ifdef Sun -#include <signal.h> #endif + #define YYMAXDEPTH 500 #ifndef PAREN -#include "x.tab.h" +#include "y.tab.h" #endif typedef struct tree tree; typedef struct word word; @@ -143,10 +144,13 @@ int mypid; */ #define GLOB ((char)0x01) /* - * onebyte(c) - * Is c the first character of a one-byte utf sequence? + * Is c the first character of a utf sequence? */ -#define onebyte(c) ((c&0x80)==0x00) +#define onebyte(c) (((c)&0x80)==0x00) +#define twobyte(c) (((c)&0xe0)==0xc0) +#define threebyte(c) (((c)&0xf0)==0xe0) +#define fourbyte(c) (((c)&0xf8)==0xf0) +#define xbyte(c) (((c)&0xc0)==0x80) extern char **argp; extern char **args; diff --git a/sys/src/cmd/rc/rcmain.plan9 b/sys/src/cmd/rc/rcmain.plan9 new file mode 100644 index 000000000..f511e96b7 --- /dev/null +++ b/sys/src/cmd/rc/rcmain.plan9 @@ -0,0 +1,41 @@ +# rcmain: Plan 9 version +if(~ $#home 0) home=/ +if(~ $#ifs 0) ifs=' +' +switch($#prompt){ +case 0 + prompt=('% ' ' ') +case 1 + prompt=($prompt ' ') +} +if(~ $rcname ?.out) prompt=('broken! ' ' ') +if(flag p) path=/bin +if not{ + for(i in '/env/fn#'*){ + . -bq $i + } + if(~ $#path 0) path=(/bin .) +} +fn sigexit +if(! ~ $#cflag 0){ + if(flag l){ + . -q /rc/lib/rcmain.local + . -q $home/lib/profile + } + status='' + eval $cflag +} +if not if(flag i){ + if(flag l){ + . -q /rc/lib/rcmain.local + . -q $home/lib/profile + } + status='' + if(! ~ $#* 0) . $* + . -i '#d/0' +} +if not if(~ $#* 0) . '#d/0' +if not{ + status='' + . $* +} diff --git a/sys/src/cmd/rc/rcmain.unix b/sys/src/cmd/rc/rcmain.unix new file mode 100644 index 000000000..7ccbe1b90 --- /dev/null +++ b/sys/src/cmd/rc/rcmain.unix @@ -0,0 +1,38 @@ +# rcmain: unix version +if(~ $#home 0) home=$HOME +if(~ $#ifs 0) ifs=' +' +profile=$home/.rcrc +switch($#prompt){ +case 0 + prompt=('% ' ' ') +case 1 + prompt=($prompt ' ') +} +if(~ $rcname ?.out) prompt=('broken! ' ' ') +if(flag p) path=/bin +if not { + finit + if(~ $#path 0) path=(. /bin /usr/bin /usr/local/bin) +} +fn sigexit +if(! ~ $#cflag 0){ + if(flag l) { + . -q $profile + } + status='' + eval $cflag +} +if not if(flag i){ + if(flag l) { + . -q $profile + } + status='' + if(! ~ $#* 0) . $* + . -i /dev/fd/0 +} +if not if(~ $#* 0) . /dev/fd/0 +if not{ + status='' + . $* +} diff --git a/sys/src/cmd/rc/simple.c b/sys/src/cmd/rc/simple.c index 812914573..1f2162c39 100644 --- a/sys/src/cmd/rc/simple.c +++ b/sys/src/cmd/rc/simple.c @@ -94,13 +94,13 @@ Xsimple(void) } else{ if((pid = execforkexec()) < 0){ - Xerror("try again"); + Xerror2("try again", Errstr()); return; } + poplist(); /* interrupts don't get us out */ - poplist(); - while(Waitfor(pid, 1) < 0) + while(Waitfor(pid) < 0) ; } } @@ -177,7 +177,7 @@ execexec(void) popword(); /* "exec" */ if(runq->argv->words==0){ - Xerror1("empty argument list"); + Xerror1("exec: empty argument list"); return; } argv = mkargv(runq->argv->words); @@ -189,7 +189,7 @@ execexec(void) } setstatus(Errstr()); pfln(err, srcfile(runq), runq->line); - pfmt(err, ": %s: %r\n", argv[1]); + pfmt(err, ": %s: %s\n", argv[1], getstatus()); Xexit(); } @@ -226,7 +226,7 @@ execcd(void) free(dir); } if(cdpath==0) - pfmt(err, "Can't cd %s: %r\n", a->word); + pfmt(err, "Can't cd %s: %s\n", a->word, Errstr()); break; case 1: a = vlook("home")->val; @@ -234,7 +234,7 @@ execcd(void) if(Chdir(a->word)>=0) setstatus(""); else - pfmt(err, "Can't cd %s: %r\n", a->word); + pfmt(err, "Can't cd %s: %s\n", a->word, Errstr()); } else pfmt(err, "Can't cd -- $home empty\n"); @@ -347,7 +347,7 @@ execeval(void) pfln(f, srcfile(runq), runq->line); pstr(f, " *eval*"); - execcmds(openiocore((uchar*)cmds, len), closeiostr(f), runq->local, runq->redir); + execcmds(openiocore(cmds, len), closeiostr(f), runq->local, runq->redir); } void @@ -406,7 +406,8 @@ Usage: free(file); } if(fd<0){ - if(!qflag) Xerror(".: can't open"); + if(!qflag) + Xerror3(". can't open", argv->word, Errstr()); freewords(argv); return; } @@ -436,18 +437,18 @@ execflag(void) char *letter, *val; switch(count(runq->argv->words)){ case 2: - setstatus(flag[(uchar)runq->argv->words->next->word[0]]?"":"flag not set"); + setstatus(flag[(unsigned char)runq->argv->words->next->word[0]]?"":"flag not set"); break; case 3: letter = runq->argv->words->next->word; val = runq->argv->words->next->next->word; if(strlen(letter)==1){ if(strcmp(val, "+")==0){ - flag[(uchar)letter[0]] = flagset; + flag[(unsigned char)letter[0]] = flagset; break; } if(strcmp(val, "-")==0){ - flag[(uchar)letter[0]] = 0; + flag[(unsigned char)letter[0]] = 0; break; } } @@ -526,10 +527,10 @@ execwait(void) Xerror1("Usage: wait [pid]"); return; case 2: - Waitfor(atoi(runq->argv->words->next->word), 0); + Waitfor(atoi(runq->argv->words->next->word)); break; case 1: - Waitfor(-1, 0); + Waitfor(-1); break; } poplist(); diff --git a/sys/src/cmd/rc/subr.c b/sys/src/cmd/rc/subr.c index 723fa429d..4c3ada4fc 100644 --- a/sys/src/cmd/rc/subr.c +++ b/sys/src/cmd/rc/subr.c @@ -41,7 +41,7 @@ pfln(io *fd, char *file, int line) pstr(fd, argv0); } -char *bp; +static char *bp; static void iacvt(int n) @@ -69,5 +69,7 @@ panic(char *s, int n) pfmt(err, "%s: ", argv0); pfmt(err, s, n); pchr(err, '\n'); + flushio(err); + Abort(); } diff --git a/sys/src/cmd/rc/trap.c b/sys/src/cmd/rc/trap.c index 59f06d25b..8ee8b2441 100644 --- a/sys/src/cmd/rc/trap.c +++ b/sys/src/cmd/rc/trap.c @@ -11,10 +11,10 @@ dotrap(void) var *trapreq; word *starval; starval = vlook("*")->val; - while(ntrap) for(i = 0;i!=NSIG;i++) while(trap[i]){ + while(ntrap) for(i = 0;i<NSIG;i++) while(trap[i]){ --trap[i]; --ntrap; - if(getpid()!=mypid) Exit(getstatus()); + if(getpid()!=mypid) Exit(); trapreq = vlook(Signame[i]); if(trapreq->fn) startfunc(trapreq, copywords(starval, (word*)0), (var*)0, (redir*)0); @@ -27,6 +27,6 @@ dotrap(void) */ while(!runq->iflag) Xreturn(); } - else Exit(getstatus()); + else Exit(); } } diff --git a/sys/src/cmd/rc/unix.c b/sys/src/cmd/rc/unix.c new file mode 100644 index 000000000..05d883c36 --- /dev/null +++ b/sys/src/cmd/rc/unix.c @@ -0,0 +1,420 @@ +/* + * 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 "io.h" +#include "fns.h" +#include "getflags.h" + +#include <errno.h> +#include <fcntl.h> +#include <dirent.h> +#include <sys/wait.h> + +static void execfinit(void); + +builtin Builtin[] = { + "cd", execcd, + "whatis", execwhatis, + "eval", execeval, + "exec", execexec, /* but with popword first */ + "exit", execexit, + "shift", execshift, + "wait", execwait, + ".", execdot, + "flag", execflag, + "finit", execfinit, + 0 +}; + +char Rcmain[] = PREFIX "/lib/rcmain"; +char Fdprefix[] = "/dev/fd/"; + +char *Signame[NSIG]; + +#define SEP '\1' +extern char **environ; +static char **envp; + +static void +Xrdfn(void) +{ + char *s; + int len; + + for(;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '(': /* Bourne again */ + if(strncmp(s, "()fn ", 5)!=0) + continue; + s=estrdup(s+2); + len=strlen(s); + s[len++]='\n'; + envp++; + runq->pc--; /* re-execute */ + execcmds(openiocore(s, len), estrdup("*environ*"), runq->local, runq->redir); + runq->lex->qflag = 1; + return; + default: + continue; + } + } +} + +static void +execfinit(void) +{ + static union code rdfns[5]; + if(rdfns[0].i==0){ + rdfns[0].i = 1; + rdfns[1].s = "*rdfns*"; + rdfns[2].f = Xrdfn; + rdfns[3].f = Xreturn; + rdfns[4].f = 0; + } + poplist(); + envp=environ; + start(rdfns, 2, runq->local, runq->redir); +} + +static int +cmpenv(const void *aa, const void *ab) +{ + return strcmp(*(char**)aa, *(char**)ab); +} + +static char** +mkenv(void) +{ + 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. + * locals no longer exist - geoff + */ + for(h = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *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 = gvar-1; h != &gvar[NVAR]; h++) + for(v = h >= gvar? *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((void *)env, nvar, sizeof ep[0], cmpenv); + return env; +} + +static word* +envval(char *s) +{ + char *t, c; + word *v; + for(t=s;*t&&*t!=SEP;t++); + c=*t; + *t='\0'; + v=newword(s, c=='\0'?(word*)0:envval(t+1)); + *t=c; + return v; +} + +void +Vinit(void) +{ + char *s; + + for(envp=environ;*envp;envp++){ + for(s=*envp;*s && *s!='(' && *s!='=';s++); + switch(*s){ + case '=': + *s='\0'; + setvar(*envp, envval(s+1)); + *s='='; + break; + default: continue; + } + } +} + +static void +sighandler(int sig) +{ + trap[sig]++; + ntrap++; +} + +void +Trapinit(void) +{ + int i; + + Signame[0] = "sigexit"; + +#ifdef SIGINT + Signame[SIGINT] = "sigint"; +#endif +#ifdef SIGTERM + Signame[SIGTERM] = "sigterm"; +#endif +#ifdef SIGHUP + Signame[SIGHUP] = "sighup"; +#endif +#ifdef SIGQUIT + Signame[SIGQUIT] = "sigquit"; +#endif +#ifdef SIGPIPE + Signame[SIGPIPE] = "sigpipe"; +#endif +#ifdef SIGUSR1 + Signame[SIGUSR1] = "sigusr1"; +#endif +#ifdef SIGUSR2 + Signame[SIGUSR2] = "sigusr2"; +#endif +#ifdef SIGBUS + Signame[SIGBUS] = "sigbus"; +#endif +#ifdef SIGWINCH + Signame[SIGWINCH] = "sigwinch"; +#endif + + for(i=1; i<NSIG; i++) if(Signame[i]){ +#ifdef SA_RESTART + struct sigaction a; + + sigaction(i, NULL, &a); + a.sa_flags &= ~SA_RESTART; + a.sa_handler = sighandler; + sigaction(i, &a, NULL); +#else + signal(i, sighandler); +#endif + } +} + +char* +Errstr(void) +{ + return strerror(errno); +} + +int +Waitfor(int pid) +{ + thread *p; + char num[12]; + int wpid, status; + + if(pid >= 0 && !havewaitpid(pid)) + return 0; + while((wpid = wait(&status))!=-1){ + delwaitpid(wpid); + inttoascii(num, WIFSIGNALED(status)?WTERMSIG(status)+1000:WEXITSTATUS(status)); + if(wpid==pid){ + setstatus(num); + return 0; + } + for(p = runq->ret;p;p = p->ret) + if(p->pid==wpid){ + p->pid=-1; + p->status = estrdup(num); + break; + } + } + if(Eintr()) return -1; + return 0; +} + +static char **nextenv; + +void +Updenv(void) +{ + if(nextenv){ + free(nextenv); + nextenv = NULL; + } + if(err) + flushio(err); +} + +void +Exec(char **argv) +{ + if(nextenv==NULL) nextenv=mkenv(); + execve(argv[0], argv+1, nextenv); +} + +int +Fork(void) +{ + Updenv(); + return fork(); +} + +void* +Opendir(char *name) +{ + return opendir(name); +} + +char* +Readdir(void *arg, int onlydirs) +{ + DIR *rd = arg; + struct dirent *ent = readdir(rd); + if(ent == NULL) + return 0; + return ent->d_name; +} + +void +Closedir(void *arg) +{ + DIR *rd = arg; + closedir(rd); +} + +long +Write(int fd, void *buf, long cnt) +{ + return write(fd, buf, cnt); +} + +long +Read(int fd, void *buf, long cnt) +{ + return read(fd, buf, cnt); +} + +long +Seek(int fd, long cnt, long whence) +{ + return lseek(fd, cnt, whence); +} + +int +Executable(char *file) +{ + return access(file, 01)==0; +} + +int +Open(char *file, int mode) +{ + static int tab[] = {O_RDONLY,O_WRONLY,O_RDWR,O_RDONLY}; + int fd = open(file, tab[mode&3]); + if(fd >= 0 && mode == 3) + unlink(file); + return fd; +} + +void +Close(int fd) +{ + close(fd); +} + +int +Creat(char *file) +{ + return creat(file, 0666L); +} + +int +Dup(int a, int b) +{ + return dup2(a, b); +} + +int +Dup1(int a) +{ + return dup(a); +} + +void +Exit(void) +{ + Updenv(); + exit(truestatus()?0:1); +} + +int +Eintr(void) +{ + return errno==EINTR; +} + +void +Noerror(void) +{ + errno=0; +} + +int +Isatty(int fd) +{ + return isatty(fd); +} + +void +Abort(void) +{ + abort(); +} + +int +Chdir(char *dir) +{ + return chdir(dir); +} + +void +Prompt(char *s) +{ + pstr(err, s); + flushio(err); +} |