ref: 189731aad01e09db1807c78af421c615ed3a3242
parent: c51a5cfa06dd982da839c4cfcba1610259d27e38
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jan 3 13:41:48 EST 2022
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.
--- /dev/null
+++ b/sys/src/cmd/rc/Makefile
@@ -1,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
--- a/sys/src/cmd/rc/code.c
+++ b/sys/src/cmd/rc/code.c
@@ -460,7 +460,7 @@
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");
--- a/sys/src/cmd/rc/exec.c
+++ b/sys/src/cmd/rc/exec.c
@@ -19,6 +19,8 @@
p->lex = 0;
p->local = local;
p->iflag = 0;
+ p->pid = 0;
+ p->status = 0;
p->ret = runq;
runq = p;
}
@@ -42,6 +44,7 @@
runq = p->ret;
if(p->lex) freelexer(p->lex);
codefree(p->code);
+ free(p->status);
free(p);
}
@@ -341,7 +344,7 @@
}
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 @@
return;
}
}
- Exit(getstatus());
+ Exit();
}
void
@@ -443,25 +446,51 @@
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 @@
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 @@
/* 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 @@
void
Xread(void)
{
+ char *file;
int fd;
switch(count(runq->argv->words)){
@@ -504,8 +534,9 @@
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 @@
void
Xrdwr(void)
{
+ char *file;
int fd;
switch(count(runq->argv->words)){
@@ -527,8 +559,9 @@
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 @@
Xpopredir();
popthread();
if(runq==0)
- Exit(getstatus());
+ Exit();
}
void
@@ -588,6 +621,7 @@
void
Xwrite(void)
{
+ char *file;
int fd;
switch(count(runq->argv->words)){
@@ -600,8 +634,9 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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);
- setstatus("error");
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);
+ 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)
{
--- a/sys/src/cmd/rc/exec.h
+++ b/sys/src/cmd/rc/exec.h
@@ -11,8 +11,9 @@
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 @@
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 @@
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 @@
char *srcfile(thread*);
char *getstatus(void);
+
+extern char *argv0;
--- a/sys/src/cmd/rc/fns.h
+++ b/sys/src/cmd/rc/fns.h
@@ -8,10 +8,11 @@
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 @@
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 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*);
--- a/sys/src/cmd/rc/getflags.c
+++ b/sys/src/cmd/rc/getflags.c
@@ -205,7 +205,8 @@
errs(tail);
}
errs("\n");
- Exit("bad flags");
+ setstatus("bad flags");
+ Exit();
}
static void
--- a/sys/src/cmd/rc/glob.c
+++ b/sys/src/cmd/rc/glob.c
@@ -21,7 +21,7 @@
}
static int
-globcmp(void *s, void *t)
+globcmp(const void *s, const void *t)
{
return strcmp(*(char**)s, *(char**)t);
}
@@ -70,11 +70,13 @@
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 @@
* 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)
{
--- a/sys/src/cmd/rc/havefork.c
+++ b/sys/src/cmd/rc/havefork.c
@@ -50,7 +50,7 @@
switch(pid = Fork()){
case -1:
- Xerror("try again");
+ Xerror2("try again", Errstr());
break;
case 0:
clearwaitpids();
@@ -76,12 +76,12 @@
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 @@
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 @@
closeio(f);
free(split);
- Waitfor(pid, 0);
+ Waitfor(pid);
runq->pc = runq->code[runq->pc].i;
return;
@@ -163,7 +163,7 @@
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 @@
}
switch(pid = Fork()){
case -1:
- Xerror("try again");
+ Xerror2("try again", Errstr());
break;
case 0:
clearwaitpids();
@@ -205,7 +205,7 @@
switch(pid = Fork()){
case -1:
- Xerror("try again");
+ Xerror2("try again", Errstr());
break;
case 0:
clearwaitpids();
@@ -214,7 +214,8 @@
break;
default:
addwaitpid(pid);
- Waitfor(pid, 1);
+ while(Waitfor(pid) < 0)
+ ;
runq->pc = runq->code[runq->pc].i;
break;
}
--- 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 @@
}
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){
--- a/sys/src/cmd/rc/io.c
+++ b/sys/src/cmd/rc/io.c
@@ -36,9 +36,6 @@
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,7 +138,7 @@
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);
@@ -148,16 +145,16 @@
}
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 @@
}
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 @@
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 @@
* characters from buf.
*/
io*
-openiocore(uchar *buf, int len)
+openiocore(void *buf, int len)
{
return newio(buf, len, -1);
}
--- 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*);
--- a/sys/src/cmd/rc/lex.c
+++ b/sys/src/cmd/rc/lex.c
@@ -190,21 +190,22 @@
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;
}
--- a/sys/src/cmd/rc/mkfile
+++ b/sys/src/cmd/rc/mkfile
@@ -21,7 +21,7 @@
y.tab.$O\
HFILES=rc.h\
- x.tab.h\
+ y.tab.h\
io.h\
exec.h\
fns.h\
@@ -38,10 +38,9 @@
$YFILES\
${TARG:%=/386/bin/%}\
+CFLAGS=$CFLAGS -DPlan9
+
</sys/src/cmd/mkone
-x.tab.h: y.tab.h
- cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h
-
clean:V:
- rm -f [$OS].out *.[$OS] [xy].tab.? y.debug $TARG
+ rm -f [$OS].out *.[$OS] y.tab.? y.debug $TARG
--- a/sys/src/cmd/rc/plan9.c
+++ b/sys/src/cmd/rc/plan9.c
@@ -47,6 +47,10 @@
0
};
+/*
+ * finit could be removed but is kept for
+ * backwards compatibility, see: rcmain.plan9
+ */
static void
execfinit(void)
{
@@ -53,7 +57,7 @@
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 @@
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 @@
}
int
-Waitfor(int pid, int)
+Waitfor(int pid)
{
thread *p;
Waitmsg *w;
@@ -187,7 +191,8 @@
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 @@
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 @@
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 @@
}
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 @@
void
Abort(void)
{
- pfmt(err, "aborting\n");
- Exit("aborting");
+ abort();
}
static int newwdir;
--- 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 @@
*/
#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;
--- /dev/null
+++ b/sys/src/cmd/rc/rcmain.plan9
@@ -1,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=''
+ . $*
+}
--- /dev/null
+++ b/sys/src/cmd/rc/rcmain.unix
@@ -1,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=''
+ . $*
+}
--- a/sys/src/cmd/rc/simple.c
+++ b/sys/src/cmd/rc/simple.c
@@ -94,13 +94,13 @@
}
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 @@
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 @@
}
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 @@
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 @@
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 @@
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 @@
free(file);
}
if(fd<0){
- if(!qflag) Xerror(".: can't open");
+ if(!qflag)
+ Xerror3(". can't open", argv->word, Errstr());
freewords(argv);
return;
}
@@ -436,7 +437,7 @@
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;
@@ -443,11 +444,11 @@
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 @@
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();
--- a/sys/src/cmd/rc/subr.c
+++ b/sys/src/cmd/rc/subr.c
@@ -41,7 +41,7 @@
pstr(fd, argv0);
}
-char *bp;
+static char *bp;
static void
iacvt(int n)
@@ -69,5 +69,7 @@
pfmt(err, "%s: ", argv0);
pfmt(err, s, n);
pchr(err, '\n');
+ flushio(err);
+
Abort();
}
--- a/sys/src/cmd/rc/trap.c
+++ b/sys/src/cmd/rc/trap.c
@@ -11,10 +11,10 @@
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 @@
*/
while(!runq->iflag) Xreturn();
}
- else Exit(getstatus());
+ else Exit();
}
}
--- /dev/null
+++ b/sys/src/cmd/rc/unix.c
@@ -1,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);
+}