aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/rc
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2007-03-26 12:02:41 +0000
committerrsc <devnull@localhost>2007-03-26 12:02:41 +0000
commitc8f538425f4e92e1e438b9bd25cb08e250a93d5b (patch)
treed701abbcd4973d5b6909d104eefe521de70a4e1c /src/cmd/rc
parent79049567a0fac8707ea3f2927403445bdb2394fa (diff)
downloadplan9port-c8f538425f4e92e1e438b9bd25cb08e250a93d5b.tar.gz
plan9port-c8f538425f4e92e1e438b9bd25cb08e250a93d5b.tar.bz2
plan9port-c8f538425f4e92e1e438b9bd25cb08e250a93d5b.zip
sync with plan 9
Diffstat (limited to 'src/cmd/rc')
-rw-r--r--src/cmd/rc/code.c223
-rw-r--r--src/cmd/rc/exec.c989
-rw-r--r--src/cmd/rc/exec.h10
-rw-r--r--src/cmd/rc/fns.h10
-rw-r--r--src/cmd/rc/getflags.c171
-rw-r--r--src/cmd/rc/glob.c165
-rw-r--r--src/cmd/rc/havefork.c10
-rw-r--r--src/cmd/rc/havep9p.c246
-rw-r--r--src/cmd/rc/here.c97
-rw-r--r--src/cmd/rc/io.c231
-rw-r--r--src/cmd/rc/io.h6
-rw-r--r--src/cmd/rc/lex.c278
-rw-r--r--src/cmd/rc/mkfile1
-rw-r--r--src/cmd/rc/pcmd.c107
-rw-r--r--src/cmd/rc/pfnc.c16
-rw-r--r--src/cmd/rc/plan9ish.c4
-rw-r--r--src/cmd/rc/rc.h1
-rw-r--r--src/cmd/rc/simple.c329
-rw-r--r--src/cmd/rc/subr.c47
-rw-r--r--src/cmd/rc/syn.y3
-rw-r--r--src/cmd/rc/trap.c25
-rw-r--r--src/cmd/rc/tree.c132
-rw-r--r--src/cmd/rc/var.c98
23 files changed, 1967 insertions, 1232 deletions
diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c
index 748b9f82..0ae90eeb 100644
--- a/src/cmd/rc/code.c
+++ b/src/cmd/rc/code.c
@@ -7,9 +7,9 @@
#define c1 t->child[1]
#define c2 t->child[2]
int codep, ncode;
-#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f=(x), codep++)
-#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i=(x), codep++)
-#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s=(x), codep++)
+#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f = (x), codep++)
+#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i = (x), codep++)
+#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s = (x), codep++)
void stuffdot(int);
char *fnstr(tree*);
void outcode(tree*, int);
@@ -17,22 +17,32 @@ void codeswitch(tree*, int);
int iscase(tree*);
code *codecopy(code*);
void codefree(code*);
-int morecode(void){
+
+int
+morecode(void)
+{
ncode+=100;
- codebuf=(code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
- if(codebuf==0) panic("Can't realloc %d bytes in morecode!",
+ codebuf = (code *)realloc((char *)codebuf, ncode*sizeof codebuf[0]);
+ if(codebuf==0)
+ panic("Can't realloc %d bytes in morecode!",
ncode*sizeof codebuf[0]);
return 0;
}
-void stuffdot(int a){
- if(a<0 || codep<=a) panic("Bad address %d in stuffdot", a);
- codebuf[a].i=codep;
+
+void
+stuffdot(int a)
+{
+ if(a<0 || codep<=a)
+ panic("Bad address %d in stuffdot", a);
+ codebuf[a].i = codep;
}
-int compile(tree *t)
+
+int
+compile(tree *t)
{
- ncode=100;
- codebuf=(code *)emalloc(ncode*sizeof codebuf[0]);
- codep=0;
+ ncode = 100;
+ codebuf = (code *)emalloc(ncode*sizeof codebuf[0]);
+ codep = 0;
emiti(0); /* reference count */
outcode(t, flag['e']?1:0);
if(nerror){
@@ -44,31 +54,39 @@ int compile(tree *t)
emitf(0);
return 1;
}
-void cleanhere(char *f)
+
+void
+cleanhere(char *f)
{
emitf(Xdelhere);
emits(strdup(f));
}
-char *fnstr(tree *t)
+
+char*
+fnstr(tree *t)
{
- io *f=openstr();
+ io *f = openstr();
char *v;
extern char nl;
- char svnl=nl;
+ char svnl = nl;
nl=';';
pfmt(f, "%t", t);
- nl=svnl;
- v=f->strp;
- f->strp=0;
+ nl = svnl;
+ v = f->strp;
+ f->strp = 0;
closeio(f);
return v;
}
-void outcode(tree *t, int eflag)
+
+void
+outcode(tree *t, int eflag)
{
int p, q;
tree *tt;
- if(t==0) return;
- if(t->type!=NOT && t->type!=';') runq->iflast=0;
+ if(t==0)
+ return;
+ if(t->type!=NOT && t->type!=';')
+ runq->iflast = 0;
switch(t->type){
default:
pfmt(err, "bad type %d in outcode\n", t->type);
@@ -92,10 +110,13 @@ void outcode(tree *t, int eflag)
break;
case '&':
emitf(Xasync);
- p=emiti(0);
- outcode(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
+ if(havefork){
+ p = emiti(0);
+ outcode(c0, eflag);
+ emitf(Xexit);
+ stuffdot(p);
+ } else
+ emits(fnstr(c0));
break;
case ';':
outcode(c0, eflag);
@@ -110,15 +131,18 @@ void outcode(tree *t, int eflag)
break;
case '`':
emitf(Xbackq);
- p=emiti(0);
- outcode(c0, 0);
- emitf(Xexit);
- stuffdot(p);
+ if(havefork){
+ p = emiti(0);
+ outcode(c0, 0);
+ emitf(Xexit);
+ stuffdot(p);
+ } else
+ emits(fnstr(c0));
break;
case ANDAND:
outcode(c0, 0);
emitf(Xtrue);
- p=emiti(0);
+ p = emiti(0);
outcode(c1, eflag);
stuffdot(p);
break;
@@ -144,7 +168,7 @@ void outcode(tree *t, int eflag)
outcode(c0, eflag);
if(c1){
emitf(Xfn);
- p=emiti(0);
+ p = emiti(0);
emits(fnstr(c1));
outcode(c1, eflag);
emitf(Xunlocal); /* get rid of $* */
@@ -157,22 +181,23 @@ void outcode(tree *t, int eflag)
case IF:
outcode(c0, 0);
emitf(Xif);
- p=emiti(0);
+ p = emiti(0);
outcode(c1, eflag);
emitf(Xwastrue);
stuffdot(p);
break;
case NOT:
- if(!runq->iflast) yyerror("`if not' does not follow `if(...)'");
+ if(!runq->iflast)
+ yyerror("`if not' does not follow `if(...)'");
emitf(Xifnot);
- p=emiti(0);
+ p = emiti(0);
outcode(c0, eflag);
stuffdot(p);
break;
case OROR:
outcode(c0, 0);
emitf(Xfalse);
- p=emiti(0);
+ p = emiti(0);
outcode(c1, eflag);
stuffdot(p);
break;
@@ -183,15 +208,20 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xsimple);
- if(eflag) emitf(Xeflag);
+ if(eflag)
+ emitf(Xeflag);
break;
case SUBSHELL:
emitf(Xsubshell);
- p=emiti(0);
- outcode(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
- if(eflag) emitf(Xeflag);
+ if(havefork){
+ p = emiti(0);
+ outcode(c0, eflag);
+ emitf(Xexit);
+ stuffdot(p);
+ } else
+ emits(fnstr(c0));
+ if(eflag)
+ emitf(Xeflag);
break;
case SWITCH:
codeswitch(t, eflag);
@@ -202,14 +232,16 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xmatch);
- if(eflag) emitf(Xeflag);
+ if(eflag)
+ emitf(Xeflag);
break;
case WHILE:
- q=codep;
+ q = codep;
outcode(c0, 0);
- if(q==codep) emitf(Xsettrue); /* empty condition == while(true) */
+ if(q==codep)
+ emitf(Xsettrue); /* empty condition == while(true) */
emitf(Xtrue);
- p=emiti(0);
+ p = emiti(0);
outcode(c1, eflag);
emitf(Xjump);
emiti(q);
@@ -235,8 +267,8 @@ void outcode(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xlocal);
- p=emitf(Xfor);
- q=emiti(0);
+ p = emitf(Xfor);
+ q = emiti(0);
outcode(c2, eflag);
emitf(Xjump);
emiti(p);
@@ -263,10 +295,14 @@ void outcode(tree *t, int eflag)
case PIPEFD:
emitf(Xpipefd);
emiti(t->rtype);
- p=emiti(0);
- outcode(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
+ if(havefork){
+ p = emiti(0);
+ outcode(c0, eflag);
+ emitf(Xexit);
+ stuffdot(p);
+ } else {
+ emits(fnstr(c0));
+ }
break;
case REDIR:
emitf(Xmark);
@@ -283,28 +319,31 @@ void outcode(tree *t, int eflag)
case HERE:
emitf(Xread);
break;
+ case RDWR:
+ emitf(Xrdwr);
+ break;
}
emiti(t->fd0);
outcode(c1, eflag);
emitf(Xpopredir);
break;
case '=':
- tt=t;
- for(;t && t->type=='=';t=c2);
+ tt = t;
+ for(;t && t->type=='=';t = c2);
if(t){
- for(t=tt;t->type=='=';t=c2){
+ for(t = tt;t->type=='=';t = c2){
emitf(Xmark);
outcode(c1, eflag);
emitf(Xmark);
outcode(c0, eflag);
emitf(Xlocal);
}
- t=tt;
+ t = tt;
outcode(c2, eflag);
- for(;t->type=='=';t=c2) emitf(Xunlocal);
+ for(;t->type=='=';t = c2) emitf(Xunlocal);
}
else{
- for(t=tt;t;t=c2){
+ for(t = tt;t;t = c2){
emitf(Xmark);
outcode(c1, eflag);
emitf(Xmark);
@@ -312,17 +351,22 @@ void outcode(tree *t, int eflag)
emitf(Xassign);
}
}
- t=tt; /* so tests below will work */
+ t = tt; /* so tests below will work */
break;
case PIPE:
emitf(Xpipe);
emiti(t->fd0);
emiti(t->fd1);
- p=emiti(0);
- q=emiti(0);
- outcode(c0, eflag);
- emitf(Xexit);
- stuffdot(p);
+ if(havefork){
+ p = emiti(0);
+ q = emiti(0);
+ outcode(c0, eflag);
+ emitf(Xexit);
+ stuffdot(p);
+ } else {
+ emits(fnstr(c0));
+ q = emiti(0);
+ }
outcode(c1, eflag);
emitf(Xreturn);
stuffdot(q);
@@ -330,8 +374,8 @@ void outcode(tree *t, int eflag)
break;
}
if(t->type!=NOT && t->type!=';')
- runq->iflast=t->type==IF;
- else if(c0) runq->iflast=c0->type==IF;
+ runq->iflast = t->type==IF;
+ else if(c0) runq->iflast = c0->type==IF;
}
/*
* switch code looks like this:
@@ -353,7 +397,9 @@ void outcode(tree *t, int eflag)
* leave:
* Xpopm
*/
-void codeswitch(tree *t, int eflag)
+
+void
+codeswitch(tree *t, int eflag)
{
int leave; /* patch jump address to leave switch */
int out; /* jump here to leave switch */
@@ -368,23 +414,23 @@ void codeswitch(tree *t, int eflag)
emitf(Xmark);
outcode(c0, eflag);
emitf(Xjump);
- nextcase=emiti(0);
- out=emitf(Xjump);
- leave=emiti(0);
+ nextcase = emiti(0);
+ out = emitf(Xjump);
+ leave = emiti(0);
stuffdot(nextcase);
- t=c1->child[0];
+ t = c1->child[0];
while(t->type==';'){
- tt=c1;
+ tt = c1;
emitf(Xmark);
- for(t=c0->child[0];t->type==ARGLIST;t=c0) outcode(c1, eflag);
+ for(t = c0->child[0];t->type==ARGLIST;t = c0) outcode(c1, eflag);
emitf(Xcase);
- nextcase=emiti(0);
- t=tt;
+ nextcase = emiti(0);
+ t = tt;
for(;;){
if(t->type==';'){
if(iscase(c0)) break;
outcode(c0, eflag);
- t=c1;
+ t = c1;
}
else{
if(!iscase(t)) outcode(t, eflag);
@@ -398,23 +444,32 @@ void codeswitch(tree *t, int eflag)
stuffdot(leave);
emitf(Xpopm);
}
-int iscase(tree *t)
+
+int
+iscase(tree *t)
{
- if(t->type!=SIMPLE) return 0;
- do t=c0; while(t->type==ARGLIST);
+ if(t->type!=SIMPLE)
+ return 0;
+ do t = c0; while(t->type==ARGLIST);
return t->type==WORD && !t->quoted && strcmp(t->str, "case")==0;
}
-code *codecopy(code *cp)
+
+code*
+codecopy(code *cp)
{
cp[0].i++;
return cp;
}
-void codefree(code *cp)
+
+void
+codefree(code *cp)
{
code *p;
- if(--cp[0].i!=0) return;
- for(p=cp+1;p->f;p++){
+ if(--cp[0].i!=0)
+ return;
+ for(p = cp+1;p->f;p++){
if(p->f==Xappend || p->f==Xclose || p->f==Xread || p->f==Xwrite
+ || p->f==Xrdwr
|| p->f==Xasync || p->f==Xbackq || p->f==Xcase || p->f==Xfalse
|| p->f==Xfor || p->f==Xjump
|| p->f==Xsubshell || p->f==Xtrue) p++;
diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c
index 72e57845..86d97cd2 100644
--- a/src/cmd/rc/exec.c
+++ b/src/cmd/rc/exec.c
@@ -1,9 +1,3 @@
-#include <u.h>
-#include <signal.h>
-#if defined(PLAN9PORT) && defined(__sun__)
-# define BSD_COMP /* sigh. for TIOCNOTTY */
-#endif
-#include <sys/ioctl.h>
#include "rc.h"
#include "getflags.h"
#include "exec.h"
@@ -13,91 +7,118 @@
* Start executing the given code at the given pc with the given redirection
*/
char *argv0="rc";
-void start(code *c, int pc, var *local)
-{
- struct thread *p=new(struct thread);
- p->code=codecopy(c);
- p->pc=pc;
- p->argv=0;
- p->redir=p->startredir=runq?runq->redir:0;
- p->local=local;
- p->cmdfile=0;
- p->cmdfd=0;
- p->eof=0;
- p->iflag=0;
- p->lineno=1;
- p->pid=-1;
- p->ret=runq;
- runq=p;
-}
-word *newword(char *wd, word *next)
-{
- word *p=new(word);
- p->word=strdup(wd);
- p->next=next;
+
+void
+start(code *c, int pc, var *local)
+{
+ struct thread *p = new(struct thread);
+
+ p->code = codecopy(c);
+ p->pc = pc;
+ p->argv = 0;
+ p->redir = p->startredir = runq?runq->redir:0;
+ p->local = local;
+ p->cmdfile = 0;
+ p->cmdfd = 0;
+ p->eof = 0;
+ p->iflag = 0;
+ p->lineno = 1;
+ p->ret = runq;
+ runq = p;
+}
+
+word*
+newword(char *wd, word *next)
+{
+ word *p = new(word);
+ p->word = strdup(wd);
+ p->next = next;
return p;
}
-void pushword(char *wd)
+
+void
+pushword(char *wd)
{
- if(runq->argv==0) panic("pushword but no argv!", 0);
- runq->argv->words=newword(wd, runq->argv->words);
+ if(runq->argv==0)
+ panic("pushword but no argv!", 0);
+ runq->argv->words = newword(wd, runq->argv->words);
}
-void popword(void){
+
+void
+popword(void)
+{
word *p;
- if(runq->argv==0) panic("popword but no argv!", 0);
- p=runq->argv->words;
- if(p==0) panic("popword but no word!", 0);
- runq->argv->words=p->next;
+ if(runq->argv==0)
+ panic("popword but no argv!", 0);
+ p = runq->argv->words;
+ if(p==0)
+ panic("popword but no word!", 0);
+ runq->argv->words = p->next;
efree(p->word);
efree((char *)p);
}
-void freelist(word *w)
+
+void
+freelist(word *w)
{
word *nw;
while(w){
- nw=w->next;
+ nw = w->next;
efree(w->word);
efree((char *)w);
- w=nw;
+ w = nw;
}
}
-void pushlist(void){
- list *p=new(list);
- p->next=runq->argv;
- p->words=0;
- runq->argv=p;
+
+void
+pushlist(void)
+{
+ list *p = new(list);
+ p->next = runq->argv;
+ p->words = 0;
+ runq->argv = p;
}
-void poplist(void){
- list *p=runq->argv;
- if(p==0) panic("poplist but no argv", 0);
+
+void
+poplist(void)
+{
+ list *p = runq->argv;
+ if(p==0)
+ panic("poplist but no argv", 0);
freelist(p->words);
- runq->argv=p->next;
+ runq->argv = p->next;
efree((char *)p);
}
-int count(word *w)
+
+int
+count(word *w)
{
int n;
- for(n=0;w;n++) w=w->next;
+ for(n = 0;w;n++) w = w->next;
return n;
}
-void pushredir(int type, int from, int to){
- redir * rp=new(redir);
- rp->type=type;
- rp->from=from;
- rp->to=to;
- rp->next=runq->redir;
- runq->redir=rp;
-}
-var *newvar(char *name, var *next)
-{
- var *v=new(var);
- v->name=name;
- v->val=0;
- v->fn=0;
- v->changed=0;
- v->fnchanged=0;
- v->next=next;
- v->changefn = 0;
+
+void
+pushredir(int type, int from, int to)
+{
+ redir * rp = new(redir);
+ rp->type = type;
+ rp->from = from;
+ rp->to = to;
+ rp->next = runq->redir;
+ runq->redir = rp;
+}
+
+var*
+newvar(char *name, var *next)
+{
+ var *v = new(var);
+ v->name = name;
+ v->val = 0;
+ v->fn = 0;
+ v->changed = 0;
+ v->fnchanged = 0;
+ v->next = next;
return v;
}
/*
@@ -117,50 +138,55 @@ main(int argc, char *argv[])
/* needed for rcmain later */
putenv("PLAN9", unsharp("#9"));
- argc=getflags(argc, argv, "srdiIlxepvVc:1m:1[command]", 1);
- if(argc==-1) usage("[file [arg ...]]");
- if(argv[0][0]=='-') flag['l']=flagset;
- if(flag['I']) flag['i'] = 0;
+ argc = getflags(argc, argv, "SsrdiIlxepvVc:1m:1[command]", 1);
+ if(argc==-1)
+ usage("[file [arg ...]]");
+ if(argv[0][0]=='-')
+ flag['l'] = flagset;
+ if(flag['I'])
+ flag['i'] = 0;
else if(flag['i']==0 && argc==1 && Isatty(0)) flag['i'] = flagset;
- rcmain=flag['m']?flag['m'][0]:Rcmain();
- err=openfd(2);
+ rcmain = flag['m'] ? flag['m'][0] : Rcmain();
+ err = openfd(2);
kinit();
Trapinit();
Vinit();
- itoa(num, mypid=getpid());
+ inttoascii(num, mypid = getpid());
pathinit();
setvar("pid", newword(num, (word *)0));
setvar("cflag", flag['c']?newword(flag['c'][0], (word *)0)
:(word *)0);
setvar("rcname", newword(argv[0], (word *)0));
- i=0;
- bootstrap[i++].i=1;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xword;
+ i = 0;
+ bootstrap[i++].i = 1;
+ bootstrap[i++].f = Xmark;
+ bootstrap[i++].f = Xword;
bootstrap[i++].s="*";
- bootstrap[i++].f=Xassign;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xmark;
- bootstrap[i++].f=Xword;
+ bootstrap[i++].f = Xassign;
+ bootstrap[i++].f = Xmark;
+ bootstrap[i++].f = Xmark;
+ bootstrap[i++].f = Xword;
bootstrap[i++].s="*";
- bootstrap[i++].f=Xdol;
- bootstrap[i++].f=Xword;
- bootstrap[i++].s=rcmain;
- bootstrap[i++].f=Xword;
+ bootstrap[i++].f = Xdol;
+ bootstrap[i++].f = Xword;
+ bootstrap[i++].s = rcmain;
+ bootstrap[i++].f = Xword;
bootstrap[i++].s=".";
- bootstrap[i++].f=Xsimple;
- bootstrap[i++].f=Xexit;
- bootstrap[i].i=0;
+ bootstrap[i++].f = Xsimple;
+ bootstrap[i++].f = Xexit;
+ bootstrap[i].i = 0;
start(bootstrap, 1, (var *)0);
/* prime bootstrap argv */
pushlist();
argv0 = strdup(argv[0]);
- for(i=argc-1;i!=0;--i) pushword(argv[i]);
+ for(i = argc-1;i!=0;--i) pushword(argv[i]);
for(;;){
- if(flag['r']) pfnc(err, runq);
+ if(flag['r'])
+ pfnc(err, runq);
runq->pc++;
(*runq->code[runq->pc-1].f)();
- if(ntrap) dotrap();
+ if(ntrap)
+ dotrap();
}
}
/*
@@ -197,6 +223,7 @@ main(int argc, char *argv[])
* Xpipefd[type]{... Xreturn} connect {} to pipe (input or output,
* depending on type), push /dev/fd/??
* Xpopm(value) pop value from stack
+ * Xrdwr(file)[fd] open file for reading and writing
* Xread(file)[fd] open file to read
* Xsettraps(names){... Xreturn} define trap functions
* Xshowtraps print trap list
@@ -208,16 +235,24 @@ main(int argc, char *argv[])
* Xword[string] push string
* Xwrite(file)[fd] open file to write
*/
-void Xappend(void){
+
+void
+Xappend(void)
+{
char *file;
int f;
switch(count(runq->argv->words)){
- default: Xerror1(">> requires singleton"); return;
- case 0: Xerror1(">> requires file"); return;
- case 1: break;
+ default:
+ Xerror1(">> requires singleton");
+ return;
+ case 0:
+ Xerror1(">> requires file");
+ return;
+ case 1:
+ break;
}
- file=runq->argv->words->word;
- if((f=open(file, 1))<0 && (f=Creat(file))<0){
+ file = runq->argv->words->word;
+ if((f = open(file, 1))<0 && (f = Creat(file))<0){
pfmt(err, "%s: ", file);
Xerror("can't open");
return;
@@ -227,126 +262,114 @@ void Xappend(void){
runq->pc++;
poplist();
}
-void Xasync(void){
- int null=open("/dev/null", 0);
- int tty;
- int pid;
- char npid[10];
- if(null<0){
- Xerror("Can't open /dev/null\n");
- return;
- }
- switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
- case -1:
- close(null);
- Xerror("try again");
- break;
- case 0:
- /*
- * I don't know what the right thing to do here is,
- * so this is all experimentally determined.
- * If we just dup /dev/null onto 0, then running
- * ssh foo & will reopen /dev/tty, try to read a password,
- * get a signal, and repeat, in a tight loop, forever.
- * Arguably this is a bug in ssh (it behaves the same
- * way under bash as under rc) but I'm fixing it here
- * anyway. If we dissociate the process from the tty,
- * then it won't be able to open /dev/tty ever again.
- * The SIG_IGN on SIGTTOU makes writing the tty
- * (via fd 1 or 2, for example) succeed even though
- * our pgrp is not the terminal's controlling pgrp.
- */
- if((tty=open("/dev/tty", OREAD)) >= 0){
- /*
- * Should make reads of tty fail, writes succeed.
- */
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- ioctl(tty, TIOCNOTTY);
- close(tty);
- }
- if(isatty(0))
- pushredir(ROPEN, null, 0);
- else
- close(null);
- start(runq->code, runq->pc+1, runq->local);
- runq->ret=0;
- break;
- default:
- close(null);
- runq->pc=runq->code[runq->pc].i;
- itoa(npid, pid);
- setvar("apid", newword(npid, (word *)0));
- break;
- }
-}
-void Xsettrue(void){
+
+void
+Xsettrue(void)
+{
setstatus("");
}
-void Xbang(void){
+
+void
+Xbang(void)
+{
setstatus(truestatus()?"false":"");
}
-void Xclose(void){
+
+void
+Xclose(void)
+{
pushredir(RCLOSE, runq->code[runq->pc].i, 0);
runq->pc++;
}
-void Xdup(void){
+
+void
+Xdup(void)
+{
pushredir(RDUP, runq->code[runq->pc].i, runq->code[runq->pc+1].i);
runq->pc+=2;
}
-void Xeflag(void){
+
+void
+Xeflag(void)
+{
if(eflagok && !truestatus()) Xexit();
}
-void Xexit(void){
+
+void
+Xexit(void)
+{
struct var *trapreq;
struct word *starval;
- static int beenhere=0;
+ static int beenhere = 0;
if(getpid()==mypid && !beenhere){
- trapreq=vlook("sigexit");
+ trapreq = vlook("sigexit");
if(trapreq->fn){
- beenhere=1;
+ beenhere = 1;
--runq->pc;
- starval=vlook("*")->val;
+ starval = vlook("*")->val;
start(trapreq->fn, trapreq->pc, (struct var *)0);
- runq->local=newvar(strdup("*"), runq->local);
- runq->local->val=copywords(starval, (struct word *)0);
- runq->local->changed=1;
- runq->redir=runq->startredir=0;
+ runq->local = newvar(strdup("*"), runq->local);
+ runq->local->val = copywords(starval, (struct word *)0);
+ runq->local->changed = 1;
+ runq->redir = runq->startredir = 0;
return;
}
}
Exit(getstatus());
}
-void Xfalse(void){
- if(truestatus()) runq->pc=runq->code[runq->pc].i;
+
+void
+Xfalse(void)
+{
+ if(truestatus()) runq->pc = runq->code[runq->pc].i;
else runq->pc++;
}
int ifnot; /* dynamic if not flag */
-void Xifnot(void){
+
+void
+Xifnot(void)
+{
if(ifnot)
runq->pc++;
else
- runq->pc=runq->code[runq->pc].i;
+ runq->pc = runq->code[runq->pc].i;
}
-void Xjump(void){
- runq->pc=runq->code[runq->pc].i;
+
+void
+Xjump(void)
+{
+ runq->pc = runq->code[runq->pc].i;
}
-void Xmark(void){
+
+void
+Xmark(void)
+{
pushlist();
}
-void Xpopm(void){
+
+void
+Xpopm(void)
+{
poplist();
}
-void Xread(void){
+
+void
+Xread(void)
+{
char *file;
int f;
switch(count(runq->argv->words)){
- default: Xerror1("< requires singleton\n"); return;
- case 0: Xerror1("< requires file\n"); return;
- case 1: break;
+ default:
+ Xerror1("< requires singleton\n");
+ return;
+ case 0:
+ Xerror1("< requires file\n");
+ return;
+ case 1:
+ break;
}
- file=runq->argv->words->word;
- if((f=open(file, 0))<0){
+ file = runq->argv->words->word;
+ if((f = open(file, 0))<0){
pfmt(err, "%s: ", file);
Xerror("can't open");
return;
@@ -355,51 +378,110 @@ void Xread(void){
runq->pc++;
poplist();
}
-void turfredir(void){
+
+void
+Xrdwr(void)
+{
+ char *file;
+ int f;
+
+ switch(count(runq->argv->words)){
+ default:
+ Xerror1("<> requires singleton\n");
+ return;
+ case 0:
+ Xerror1("<> requires file\n");
+ return;
+ case 1:
+ break;
+ }
+ file = runq->argv->words->word;
+ if((f = open(file, ORDWR))<0){
+ pfmt(err, "%s: ", file);
+ Xerror("can't open");
+ return;
+ }
+ pushredir(ROPEN, f, runq->code[runq->pc].i);
+ runq->pc++;
+ poplist();
+}
+
+void
+turfredir(void)
+{
while(runq->redir!=runq->startredir)
Xpopredir();
}
-void Xpopredir(void){
- struct redir *rp=runq->redir;
- if(rp==0) panic("turfredir null!", 0);
- runq->redir=rp->next;
- if(rp->type==ROPEN) close(rp->from);
+
+void
+Xpopredir(void)
+{
+ struct redir *rp = runq->redir;
+ if(rp==0)
+ panic("turfredir null!", 0);
+ runq->redir = rp->next;
+ if(rp->type==ROPEN)
+ close(rp->from);
efree((char *)rp);
}
-void Xreturn(void){
- struct thread *p=runq;
+
+void
+Xreturn(void)
+{
+ struct thread *p = runq;
turfredir();
while(p->argv) poplist();
codefree(p->code);
- runq=p->ret;
+ runq = p->ret;
efree((char *)p);
- if(runq==0) Exit(getstatus());
+ if(runq==0)
+ Exit(getstatus());
}
-void Xtrue(void){
+
+void
+Xtrue(void)
+{
if(truestatus()) runq->pc++;
- else runq->pc=runq->code[runq->pc].i;
+ else runq->pc = runq->code[runq->pc].i;
}
-void Xif(void){
- ifnot=1;
+
+void
+Xif(void)
+{
+ ifnot = 1;
if(truestatus()) runq->pc++;
- else runq->pc=runq->code[runq->pc].i;
+ else runq->pc = runq->code[runq->pc].i;
}
-void Xwastrue(void){
- ifnot=0;
+
+void
+Xwastrue(void)
+{
+ ifnot = 0;
}
-void Xword(void){
+
+void
+Xword(void)
+{
pushword(runq->code[runq->pc++].s);
}
-void Xwrite(void){
+
+void
+Xwrite(void)
+{
char *file;
int f;
switch(count(runq->argv->words)){
- default: Xerror1("> requires singleton\n"); return;
- case 0: Xerror1("> requires file\n"); return;
- case 1: break;
+ default:
+ Xerror1("> requires singleton\n");
+ return;
+ case 0:
+ Xerror1("> requires file\n");
+ return;
+ case 1:
+ break;
}
- file=runq->argv->words->word;
- if((f=Creat(file))<0){
+ file = runq->argv->words->word;
+ if((f = Creat(file))<0){
pfmt(err, "%s: ", file);
Xerror("can't open");
return;
@@ -408,31 +490,35 @@ void Xwrite(void){
runq->pc++;
poplist();
}
-char *_list2str(word *words, int c){
+
+char*
+list2str(word *words)
+{
char *value, *s, *t;
- int len=0;
+ int len = 0;
word *ap;
- for(ap=words;ap;ap=ap->next)
+ for(ap = words;ap;ap = ap->next)
len+=1+strlen(ap->word);
- value=emalloc(len+1);
- s=value;
- for(ap=words;ap;ap=ap->next){
- for(t=ap->word;*t;) *s++=*t++;
- *s++=c;
- }
- if(s==value) *s='\0';
+ value = emalloc(len+1);
+ s = value;
+ for(ap = words;ap;ap = ap->next){
+ for(t = ap->word;*t;) *s++=*t++;
+ *s++=' ';
+ }
+ if(s==value)
+ *s='\0';
else s[-1]='\0';
return value;
}
-char *list2str(word *words){
- return _list2str(words, ' ');
-}
-void Xmatch(void){
+
+void
+Xmatch(void)
+{
word *p;
char *subject;
- subject=list2str(runq->argv->words);
+ subject = list2str(runq->argv->words);
setstatus("no match");
- for(p=runq->argv->next->words;p;p=p->next)
+ for(p = runq->argv->next->words;p;p = p->next)
if(match(subject, p->word, '\0')){
setstatus("");
break;
@@ -441,14 +527,17 @@ void Xmatch(void){
poplist();
poplist();
}
-void Xcase(void){
+
+void
+Xcase(void)
+{
word *p;
char *s;
- int ok=0;
- s=list2str(runq->argv->next->words);
- for(p=runq->argv->words;p;p=p->next){
+ int ok = 0;
+ s = list2str(runq->argv->next->words);
+ for(p = runq->argv->words;p;p = p->next){
if(match(s, p->word, '\0')){
- ok=1;
+ ok = 1;
break;
}
}
@@ -456,28 +545,33 @@ void Xcase(void){
if(ok)
runq->pc++;
else
- runq->pc=runq->code[runq->pc].i;
+ runq->pc = runq->code[runq->pc].i;
poplist();
}
-word *conclist(word *lp, word *rp, word *tail)
+
+word*
+conclist(word *lp, word *rp, word *tail)
{
char *buf;
word *v;
if(lp->next || rp->next)
- tail=conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
+ tail = conclist(lp->next==0?lp:lp->next, rp->next==0?rp:rp->next,
tail);
- buf=emalloc(strlen(lp->word)+strlen(rp->word)+1);
+ buf = emalloc(strlen(lp->word)+strlen(rp->word)+1);
strcpy(buf, lp->word);
strcat(buf, rp->word);
- v=newword(buf, tail);
+ v = newword(buf, tail);
efree(buf);
return v;
}
-void Xconc(void){
- word *lp=runq->argv->words;
- word *rp=runq->argv->next->words;
- word *vp=runq->argv->next->next->words;
- int lc=count(lp), rc=count(rp);
+
+void
+Xconc(void)
+{
+ word *lp = runq->argv->words;
+ word *rp = runq->argv->next->words;
+ word *vp = runq->argv->next->next->words;
+ int lc = count(lp), rc = count(rp);
if(lc!=0 || rc!=0){
if(lc==0 || rc==0){
Xerror1("null list in concatenation");
@@ -487,42 +581,48 @@ void Xconc(void){
Xerror1("mismatched list lengths in concatenation");
return;
}
- vp=conclist(lp, rp, vp);
+ vp = conclist(lp, rp, vp);
}
poplist();
poplist();
- runq->argv->words=vp;
+ runq->argv->words = vp;
}
-void Xassign(void){
+
+void
+Xassign(void)
+{
var *v;
if(count(runq->argv->words)!=1){
Xerror1("variable name not singleton!");
return;
}
deglob(runq->argv->words->word);
- v=vlook(runq->argv->words->word);
+ v = vlook(runq->argv->words->word);
poplist();
globlist();
freewords(v->val);
- v->val=runq->argv->words;
- v->changed=1;
- if(v->changefn)
- v->changefn(v);
- runq->argv->words=0;
+ v->val = runq->argv->words;
+ v->changed = 1;
+ runq->argv->words = 0;
poplist();
}
/*
* copy arglist a, adding the copy to the front of tail
*/
-word *copywords(word *a, word *tail)
+
+word*
+copywords(word *a, word *tail)
{
- word *v=0, **end;
- for(end=&v;a;a=a->next,end=&(*end)->next)
- *end=newword(a->word, 0);
- *end=tail;
+ word *v = 0, **end;
+ for(end=&v;a;a = a->next,end=&(*end)->next)
+ *end = newword(a->word, 0);
+ *end = tail;
return v;
}
-void Xdol(void){
+
+void
+Xdol(void)
+{
word *a, *star;
char *s, *t;
int n;
@@ -530,24 +630,27 @@ void Xdol(void){
Xerror1("variable name not singleton!");
return;
}
- s=runq->argv->words->word;
+ s = runq->argv->words->word;
deglob(s);
- n=0;
- for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
- a=runq->argv->next->words;
+ n = 0;
+ for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
+ a = runq->argv->next->words;
if(n==0 || *t)
- a=copywords(vlook(s)->val, a);
+ a = copywords(vlook(s)->val, a);
else{
- star=vlook("*")->val;
+ star = vlook("*")->val;
if(star && 1<=n && n<=count(star)){
- while(--n) star=star->next;
- a=newword(star->word, a);
+ while(--n) star = star->next;
+ a = newword(star->word, a);
}
}
poplist();
- runq->argv->words=a;
+ runq->argv->words = a;
}
-void Xqdol(void){
+
+void
+Xqdol(void)
+{
word *a, *p;
char *s;
int n;
@@ -555,20 +658,20 @@ void Xqdol(void){
Xerror1("variable name not singleton!");
return;
}
- s=runq->argv->words->word;
+ s = runq->argv->words->word;
deglob(s);
- a=vlook(s)->val;
+ a = vlook(s)->val;
poplist();
- n=count(a);
+ n = count(a);
if(n==0){
pushword("");
return;
}
- for(p=a;p;p=p->next) n+=strlen(p->word);
- s=emalloc(n);
+ for(p = a;p;p = p->next) n+=strlen(p->word);
+ s = emalloc(n);
if(a){
strcpy(s, a->word);
- for(p=a->next;p;p=p->next){
+ for(p = a->next;p;p = p->next){
strcat(s, " ");
strcat(s, p->word);
}
@@ -578,37 +681,47 @@ void Xqdol(void){
pushword(s);
efree(s);
}
-word *subwords(word *val, int len, word *sub, word *a)
+
+word*
+subwords(word *val, int len, word *sub, word *a)
{
int n;
char *s;
- if(!sub) return a;
- a=subwords(val, len, sub->next, a);
- s=sub->word;
+ if(!sub)
+ return a;
+ a = subwords(val, len, sub->next, a);
+ s = sub->word;
deglob(s);
- n=0;
- while('0'<=*s && *s<='9') n=n*10+ *s++ -'0';
- if(n<1 || len<n) return a;
- for(;n!=1;--n) val=val->next;
+ n = 0;
+ while('0'<=*s && *s<='9') n = n*10+ *s++ -'0';
+ if(n<1 || len<n)
+ return a;
+ for(;n!=1;--n) val = val->next;
return newword(val->word, a);
}
-void Xsub(void){
+
+void
+Xsub(void)
+{
word *a, *v;
char *s;
if(count(runq->argv->next->words)!=1){
Xerror1("variable name not singleton!");
return;
}
- s=runq->argv->next->words->word;
+ s = runq->argv->next->words->word;
deglob(s);
- a=runq->argv->next->next->words;
- v=vlook(s)->val;
- a=subwords(v, count(v), runq->argv->words, a);
+ a = runq->argv->next->next->words;
+ v = vlook(s)->val;
+ a = subwords(v, count(v), runq->argv->words, a);
poplist();
poplist();
- runq->argv->words=a;
+ runq->argv->words = a;
}
-void Xcount(void){
+
+void
+Xcount(void)
+{
word *a;
char *s, *t;
int n;
@@ -617,112 +730,102 @@ void Xcount(void){
Xerror1("variable name not singleton!");
return;
}
- s=runq->argv->words->word;
+ s = runq->argv->words->word;
deglob(s);
- n=0;
- for(t=s;'0'<=*t && *t<='9';t++) n=n*10+*t-'0';
+ n = 0;
+ for(t = s;'0'<=*t && *t<='9';t++) n = n*10+*t-'0';
if(n==0 || *t){
- a=vlook(s)->val;
- itoa(num, count(a));
+ a = vlook(s)->val;
+ inttoascii(num, count(a));
}
else{
- a=vlook("*")->val;
- itoa(num, a && 1<=n && n<=count(a)?1:0);
+ a = vlook("*")->val;
+ inttoascii(num, a && 1<=n && n<=count(a)?1:0);
}
poplist();
pushword(num);
}
-void Xlocal(void){
+
+void
+Xlocal(void)
+{
if(count(runq->argv->words)!=1){
Xerror1("variable name must be singleton\n");
return;
}
deglob(runq->argv->words->word);
- runq->local=newvar(strdup(runq->argv->words->word), runq->local);
- runq->local->val=copywords(runq->argv->next->words, (word *)0);
- runq->local->changed=1;
+ runq->local = newvar(strdup(runq->argv->words->word), runq->local);
+ runq->local->val = copywords(runq->argv->next->words, (word *)0);
+ runq->local->changed = 1;
poplist();
poplist();
}
-void Xunlocal(void){
- var *v=runq->local, *hid;
- if(v==0) panic("Xunlocal: no locals!", 0);
- runq->local=v->next;
- hid=vlook(v->name);
- hid->changed=1;
+
+void
+Xunlocal(void)
+{
+ var *v = runq->local, *hid;
+ if(v==0)
+ panic("Xunlocal: no locals!", 0);
+ runq->local = v->next;
+ hid = vlook(v->name);
+ hid->changed = 1;
efree(v->name);
freewords(v->val);
efree((char *)v);
}
-void freewords(word *w)
+
+void
+freewords(word *w)
{
word *nw;
while(w){
efree(w->word);
- nw=w->next;
+ nw = w->next;
efree((char *)w);
- w=nw;
+ w = nw;
}
}
-void Xfn(void){
+
+void
+Xfn(void)
+{
var *v;
word *a;
int end;
- end=runq->code[runq->pc].i;
- for(a=runq->argv->words;a;a=a->next){
- v=gvlook(a->word);
- if(v->fn) codefree(v->fn);
- v->fn=codecopy(runq->code);
- v->pc=runq->pc+2;
- v->fnchanged=1;
- }
- runq->pc=end;
+ end = runq->code[runq->pc].i;
+ for(a = runq->argv->words;a;a = a->next){
+ v = gvlook(a->word);
+ if(v->fn)
+ codefree(v->fn);
+ v->fn = codecopy(runq->code);
+ v->pc = runq->pc+2;
+ v->fnchanged = 1;
+ }
+ runq->pc = end;
poplist();
}
-void Xdelfn(void){
+
+void
+Xdelfn(void)
+{
var *v;
word *a;
- for(a=runq->argv->words;a;a=a->next){
- v=gvlook(a->word);
- if(v->fn) codefree(v->fn);
- v->fn=0;
- v->fnchanged=1;
+ for(a = runq->argv->words;a;a = a->next){
+ v = gvlook(a->word);
+ if(v->fn)
+ codefree(v->fn);
+ v->fn = 0;
+ v->fnchanged = 1;
}
poplist();
}
-void Xpipe(void){
- struct thread *p=runq;
- int pc=p->pc, forkid;
- int lfd=p->code[pc++].i;
- int rfd=p->code[pc++].i;
- int pfd[2];
- if(pipe(pfd)<0){
- Xerror("can't get pipe");
- return;
- }
- switch(forkid=fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(p->code, pc+2, runq->local);
- runq->ret=0;
- close(pfd[PRD]);
- pushredir(ROPEN, pfd[PWR], lfd);
- break;
- default:
- start(p->code, p->code[pc].i, runq->local);
- close(pfd[PWR]);
- pushredir(ROPEN, pfd[PRD], rfd);
- p->pc=p->code[pc+1].i;
- p->pid=forkid;
- break;
- }
-}
-char *concstatus(char *s, char *t)
+
+char*
+concstatus(char *s, char *t)
{
static char v[NSTATUS+1];
- int n=strlen(s);
+ int n = strlen(s);
strncpy(v, s, NSTATUS);
if(n<NSTATUS){
v[n]='|';
@@ -731,7 +834,10 @@ char *concstatus(char *s, char *t)
v[NSTATUS]='\0';
return v;
}
-void Xpipewait(void){
+
+void
+Xpipewait(void)
+{
char status[NSTATUS+1];
if(runq->pid==-1)
setstatus(concstatus(runq->status, getstatus()));
@@ -743,31 +849,35 @@ void Xpipewait(void){
setstatus(concstatus(getstatus(), status));
}
}
-void Xrdcmds(void){
- struct thread *p=runq;
+
+void
+Xrdcmds(void)
+{
+ struct thread *p = runq;
word *prompt;
flush(err);
- nerror=0;
+ nerror = 0;
if(flag['s'] && !truestatus())
pfmt(err, "status=%v\n", vlook("status")->val);
if(runq->iflag){
- prompt=vlook("prompt")->val;
+ prompt = vlook("prompt")->val;
if(prompt)
- promptstr=prompt->word;
+ promptstr = prompt->word;
else
promptstr="% ";
}
Noerror();
if(yyparse()){
if(!p->iflag || p->eof && !Eintr()){
- if(p->cmdfile) efree(p->cmdfile);
+ if(p->cmdfile)
+ efree(p->cmdfile);
closeio(p->cmdfd);
Xreturn(); /* should this be omitted? */
}
else{
if(Eintr()){
pchr(err, '\n');
- p->eof=0;
+ p->eof = 0;
}
--p->pc; /* go back for next command */
}
@@ -779,7 +889,9 @@ void Xrdcmds(void){
}
freenodes();
}
-void Xerror(char *s)
+
+void
+Xerror(char *s)
{
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
pfmt(err, "rc: %s: %r\n", s);
@@ -789,7 +901,9 @@ void Xerror(char *s)
setstatus("error");
while(!runq->iflag) Xreturn();
}
-void Xerror1(char *s)
+
+void
+Xerror1(char *s)
{
if(strcmp(argv0, "rc")==0 || strcmp(argv0, "/bin/rc")==0)
pfmt(err, "rc: %s\n", s);
@@ -799,150 +913,55 @@ void Xerror1(char *s)
setstatus("error");
while(!runq->iflag) Xreturn();
}
-void Xbackq(void){
- char wd[8193];
- int c;
- char *s, *ewd=&wd[8192], *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;
- }
- switch(pid=fork()){
- case -1: Xerror("try again");
- close(pfd[PRD]);
- close(pfd[PWR]);
- return;
- case 0:
- close(pfd[PRD]);
- start(runq->code, runq->pc+1, runq->local);
- pushredir(ROPEN, pfd[PWR], 1);
- return;
- default:
- close(pfd[PWR]);
- f=openfd(pfd[PRD]);
- s=wd;
- v=0;
- while((c=rchr(f))!=EOF){
- if(strchr(stop, c) || s==ewd){
- if(s!=wd){
- *s='\0';
- v=newword(wd, v);
- s=wd;
- }
- }
- else *s++=c;
- }
- if(s!=wd){
- *s='\0';
- v=newword(wd, v);
- }
- closeio(f);
- Waitfor(pid, 0);
- /* 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=runq->code[runq->pc].i;
- return;
- }
-}
-/*
- * Who should wait for the exit from the fork?
- */
-void Xpipefd(void){
- struct thread *p=runq;
- int pc=p->pc;
- char name[40];
- int pfd[2];
- int sidefd, mainfd;
- if(pipe(pfd)<0){
- Xerror("can't get pipe");
- return;
- }
- if(p->code[pc].i==READ){
- sidefd=pfd[PWR];
- mainfd=pfd[PRD];
- }
- else{
- sidefd=pfd[PRD];
- mainfd=pfd[PWR];
- }
- switch(fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(p->code, pc+2, runq->local);
- close(mainfd);
- pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
- runq->ret=0;
- break;
- default:
- close(sidefd);
- pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
- strcpy(name, Fdprefix);
- itoa(name+strlen(name), mainfd);
- pushword(name);
- p->pc=p->code[pc+1].i;
- break;
- }
-}
-void Xsubshell(void){
- int pid;
- switch(pid=fork()){
- case -1:
- Xerror("try again");
- break;
- case 0:
- start(runq->code, runq->pc+1, runq->local);
- runq->ret=0;
- break;
- default:
- Waitfor(pid, 1);
- runq->pc=runq->code[runq->pc].i;
- break;
- }
-}
-void setstatus(char *s)
+
+void
+setstatus(char *s)
{
setvar("status", newword(s, (word *)0));
}
-char *getstatus(void){
- var *status=vlook("status");
+
+char*
+getstatus(void)
+{
+ var *status = vlook("status");
return status->val?status->val->word:"";
}
-int truestatus(void){
+
+int
+truestatus(void)
+{
char *s;
- for(s=getstatus();*s;s++)
- if(*s!='|' && *s!='0') return 0;
+ for(s = getstatus();*s;s++)
+ if(*s!='|' && *s!='0')
+ return 0;
return 1;
}
-void Xdelhere(void){
+
+void
+Xdelhere(void)
+{
Unlink(runq->code[runq->pc++].s);
}
-void Xfor(void){
+
+void
+Xfor(void)
+{
if(runq->argv->words==0){
poplist();
- runq->pc=runq->code[runq->pc].i;
+ runq->pc = runq->code[runq->pc].i;
}
else{
freelist(runq->local->val);
- runq->local->val=runq->argv->words;
- runq->local->changed=1;
- runq->argv->words=runq->argv->words->next;
- runq->local->val->next=0;
+ runq->local->val = runq->argv->words;
+ runq->local->changed = 1;
+ runq->argv->words = runq->argv->words->next;
+ runq->local->val->next = 0;
runq->pc++;
}
}
-void Xglob(void){
+
+void
+Xglob(void)
+{
globlist();
}
diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h
index 1704b6f3..06d2991f 100644
--- a/src/cmd/rc/exec.h
+++ b/src/cmd/rc/exec.h
@@ -5,6 +5,7 @@ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(void), Xclose(void)
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqdol(void), Xdup(void);
extern void Xexit(void), Xfalse(void), Xfn(void), Xfor(void), Xglob(void);
extern void Xjump(void), Xmark(void), Xmatch(void), Xpipe(void), Xread(void);
+extern void Xrdwr(void);
extern void Xrdfn(void), Xunredir(void), Xstar(void), Xreturn(void), Xsubshell(void);
extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void);
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(void);
@@ -51,7 +52,6 @@ struct thread{
int iflag; /* interactive? */
int lineno; /* linenumber */
int pid; /* process for Xpipewait to wait for */
- int done; /* have we seen a wait message for this process? */
char status[NSTATUS]; /* status for Xpipewait */
tree *treenodes; /* tree nodes created by this process */
thread *ret; /* who continues when this finishes */
@@ -61,12 +61,16 @@ code *codecopy(code*);
code *codebuf; /* compiler output */
int ntrap; /* number of outstanding traps */
int trap[NSIG]; /* number of outstanding traps per type */
-extern struct builtin{
+struct builtin{
char *name;
void (*fnc)(void);
-}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);
void execexit(void), execshift(void);
void execwait(void), execumask(void), execdot(void), execflag(void);
void execfunc(var*), execcmds(io *);
diff --git a/src/cmd/rc/fns.h b/src/cmd/rc/fns.h
index b9e5cb73..f6454787 100644
--- a/src/cmd/rc/fns.h
+++ b/src/cmd/rc/fns.h
@@ -7,13 +7,14 @@ int Eintr(void);
int Executable(char*);
void Execute(word*, word*);
void Exit(char*);
+int ForkExecute(char*, char**, int, int, int);
int Globsize(char*);
int Isatty(int);
void Memcpy(char*, char*, long);
void Noerror(void);
int Opendir(char*);
long Read(int, char*, long);
-int Readdir(int, char*);
+int Readdir(int, char*, int);
long Seek(int, long, long);
void Trapinit(void);
void Unlink(char*);
@@ -27,7 +28,6 @@ void cleanhere(char*);
void codefree(code*);
int compile(tree*);
char * list2str(word*);
-char * _list2str(word*, int);
int count(word*);
void deglob(char*);
void dotrap(void);
@@ -35,10 +35,12 @@ void freenodes(void);
void freewords(word*);
void globlist(void);
int idchr(int);
-void itoa(char*, long);
+void inttoascii(char*, long);
void kinit(void);
+int mapfd(int);
int match(char*, char*, int);
int matchfn(char*, char*);
+char** mkargv(word*);
void panic(char*, int);
void pathinit(void);
void poplist(void);
@@ -48,9 +50,9 @@ void pushlist(void);
void pushredir(int, int, int);
void pushword(char*);
void readhere(void);
+word* searchpath(char*);
void setstatus(char*);
void setvar(char*, word*);
-void _setvar(char*, word*, int);
void skipnl(void);
void start(code*, int, var*);
int truestatus(void);
diff --git a/src/cmd/rc/getflags.c b/src/cmd/rc/getflags.c
index c452067f..09f6e3a7 100644
--- a/src/cmd/rc/getflags.c
+++ b/src/cmd/rc/getflags.c
@@ -3,7 +3,7 @@
#include "rc.h"
#include "getflags.h"
#include "fns.h"
-char *flagset[]={"<flag>"};
+char *flagset[] = {"<flag>"};
char **flag[NFLAG];
char cmdline[NCMDLINE+1];
char *cmdname;
@@ -19,105 +19,118 @@ static int reason;
#define FLAGSYN 3
#define BADFLAG 4
static int badflag;
-int getflags(int argc, char *argv[], char *flags, int stop)
+
+int
+getflags(int argc, char *argv[], char *flags, int stop)
{
char *s, *t;
int i, j, c, count;
- flagarg=flags;
- if(cmdname==0) cmdname=argv[0];
- s=cmdline;
- for(i=0;i!=argc;i++){
- for(t=argv[i];*t;t++)
+ flagarg = flags;
+ if(cmdname==0)
+ cmdname = argv[0];
+ s = cmdline;
+ for(i = 0;i!=argc;i++){
+ for(t = argv[i];*t;t++)
if(s!=&cmdline[NCMDLINE])
*s++=*t;
if(i!=argc-1 && s!=&cmdline[NCMDLINE])
*s++=' ';
}
*s='\0';
- i=1;
+ i = 1;
while(i!=argc){
if(argv[i][0]!='-' || argv[i][1]=='\0'){
- if(stop) return argc;
+ if(stop)
+ return argc;
i++;
continue;
}
- s=argv[i]+1;
+ s = argv[i]+1;
while(*s){
c=*s++;
- count=scanflag(c, flags);
- if(count==-1) return -1;
- if(flag[c]){ reason=RESET; badflag=c; return -1; }
+ count = scanflag(c, flags);
+ if(count==-1)
+ return -1;
+ if(flag[c]){ reason = RESET; badflag = c; return -1; }
if(count==0){
- flag[c]=flagset;
+ flag[c] = flagset;
if(*s=='\0'){
- for(j=i+1;j<=argc;j++)
- argv[j-1]=argv[j];
+ for(j = i+1;j<=argc;j++)
+ argv[j-1] = argv[j];
--argc;
}
}
else{
if(*s=='\0'){
- for(j=i+1;j<=argc;j++)
- argv[j-1]=argv[j];
+ for(j = i+1;j<=argc;j++)
+ argv[j-1] = argv[j];
--argc;
- s=argv[i];
+ s = argv[i];
}
if(argc-i<count){
- reason=FEWARGS;
- badflag=c;
+ reason = FEWARGS;
+ badflag = c;
return -1;
}
reverse(argv+i, argv+argc);
reverse(argv+i, argv+argc-count);
reverse(argv+argc-count+1, argv+argc);
argc-=count;
- flag[c]=argv+argc+1;
- flag[c][0]=s;
+ flag[c] = argv+argc+1;
+ flag[c][0] = s;
s="";
}
}
}
return argc;
}
-static void reverse(char **p, char **q)
+
+static void
+reverse(char **p, char **q)
{
char *t;
- for(;p<q;p++,--q){ t=*p; *p=*q; *q=t; }
+ for(;p<q;p++,--q){ t=*p; *p=*q; *q = t; }
}
-static int scanflag(int c, char *f)
+
+static int
+scanflag(int c, char *f)
{
int fc, count;
- if(0<=c && c<NFLAG) while(*f){
- if(*f==' '){
- f++;
- continue;
- }
- fc=*f++;
- if(*f==':'){
- f++;
- if(*f<'0' || '9'<*f){ reason=FLAGSYN; return -1; }
- count=0;
- while('0'<=*f && *f<='9') count=count*10+*f++-'0';
- }
- else
- count=0;
- if(*f=='['){
- do{
+ if(0<=c && c<NFLAG)
+ while(*f){
+ if(*f==' '){
+ f++;
+ continue;
+ }
+ fc=*f++;
+ if(*f==':'){
+ f++;
+ if(*f<'0' || '9'<*f){ reason = FLAGSYN; return -1; }
+ count = 0;
+ while('0'<=*f && *f<='9') count = count*10+*f++-'0';
+ }
+ else
+ count = 0;
+ if(*f=='['){
+ do{
+ f++;
+ if(*f=='\0'){ reason = FLAGSYN; return -1; }
+ }while(*f!=']');
f++;
- if(*f=='\0'){ reason=FLAGSYN; return -1; }
- }while(*f!=']');
- f++;
+ }
+ if(c==fc)
+ return count;
}
- if(c==fc) return count;
- }
- reason=BADFLAG;
- badflag=c;
+ reason = BADFLAG;
+ badflag = c;
return -1;
}
-void usage(char *tail)
+
+void
+usage(char *tail)
{
char *s, *t, c;
- int count, nflag=0;
+ int count, nflag = 0;
switch(reason){
case RESET:
errs("Flag -");
@@ -140,46 +153,52 @@ void usage(char *tail)
}
errs("Usage: ");
errs(cmdname);
- for(s=flagarg;*s;){
+ for(s = flagarg;*s;){
c=*s;
- if(*s++==' ') continue;
+ if(*s++==' ')
+ continue;
if(*s==':'){
s++;
- count=0;
- while('0'<=*s && *s<='9') count=count*10+*s++-'0';
+ count = 0;
+ while('0'<=*s && *s<='9') count = count*10+*s++-'0';
}
- else count=0;
+ else count = 0;
if(count==0){
- if(nflag==0) errs(" [-");
+ if(nflag==0)
+ errs(" [-");
nflag++;
errc(c);
}
if(*s=='['){
s++;
while(*s!=']' && *s!='\0') s++;
- if(*s==']') s++;
+ if(*s==']')
+ s++;
}
}
- if(nflag) errs("]");
- for(s=flagarg;*s;){
+ if(nflag)
+ errs("]");
+ for(s = flagarg;*s;){
c=*s;
- if(*s++==' ') continue;
+ if(*s++==' ')
+ continue;
if(*s==':'){
s++;
- count=0;
- while('0'<=*s && *s<='9') count=count*10+*s++-'0';
+ count = 0;
+ while('0'<=*s && *s<='9') count = count*10+*s++-'0';
}
- else count=0;
+ else count = 0;
if(count!=0){
errs(" [-");
errc(c);
if(*s=='['){
s++;
- t=s;
+ t = s;
while(*s!=']' && *s!='\0') s++;
errs(" ");
errn(t, s-t);
- if(*s==']') s++;
+ if(*s==']')
+ s++;
}
else
while(count--) errs(" arg");
@@ -188,7 +207,8 @@ void usage(char *tail)
else if(*s=='['){
s++;
while(*s!=']' && *s!='\0') s++;
- if(*s==']') s++;
+ if(*s==']')
+ s++;
}
}
if(tail){
@@ -198,20 +218,27 @@ void usage(char *tail)
errs("\n");
Exit("bad flags");
}
-static void errn(char *s, int count)
+
+static void
+errn(char *s, int count)
{
while(count){ errc(*s++); --count; }
}
-static void errs(char *s)
+
+static void
+errs(char *s)
{
while(*s) errc(*s++);
}
#define NBUF 80
-static char buf[NBUF], *bufp=buf;
-static void errc(int c){
+static char buf[NBUF], *bufp = buf;
+
+static void
+errc(int c)
+{
*bufp++=c;
if(bufp==&buf[NBUF] || c=='\n'){
Write(2, buf, bufp-buf);
- bufp=buf;
+ bufp = buf;
}
}
diff --git a/src/cmd/rc/glob.c b/src/cmd/rc/glob.c
index fcd09c0c..6eaa8316 100644
--- a/src/cmd/rc/glob.c
+++ b/src/cmd/rc/glob.c
@@ -6,68 +6,77 @@ struct word *globv;
/*
* delete all the GLOB marks from s, in place
*/
-void deglob(char *s)
+
+void
+deglob(char *s)
{
- char *t=s;
+ char *t = s;
do{
- if(*t==GLOB) t++;
+ if(*t==GLOB)
+ t++;
*s++=*t;
}while(*t++);
}
-int globcmp(const void *s, const void *t)
+
+int
+globcmp(const void *s, const void *t)
{
return strcmp(*(char**)s, *(char**)t);
}
-void globsort(word *left, word *right)
+
+void
+globsort(word *left, word *right)
{
char **list;
word *a;
- int n=0;
- for(a=left;a!=right;a=a->next) n++;
- list=(char **)emalloc(n*sizeof(char *));
- for(a=left,n=0;a!=right;a=a->next,n++) list[n]=a->word;
- qsort((char *)list, n, sizeof(char *), globcmp);
- for(a=left,n=0;a!=right;a=a->next,n++) a->word=list[n];
+ int n = 0;
+ for(a = left;a!=right;a = a->next) n++;
+ list = (char **)emalloc(n*sizeof(char *));
+ for(a = left,n = 0;a!=right;a = a->next,n++) list[n] = a->word;
+ qsort((void *)list, n, sizeof(void *), globcmp);
+ for(a = left,n = 0;a!=right;a = a->next,n++) a->word = list[n];
efree((char *)list);
}
/*
* Push names prefixed by globname and suffixed by a match of p onto the astack.
* namep points to the end of the prefix in globname.
*/
-void globdir(char *p, char *namep)
+
+void
+globdir(char *p, char *namep)
{
char *t, *newp;
int f;
/* scan the pattern looking for a component with a metacharacter in it */
if(*p=='\0'){
- globv=newword(globname, globv);
+ globv = newword(globname, globv);
return;
}
- t=namep;
- newp=p;
+ t = namep;
+ newp = p;
while(*newp){
if(*newp==GLOB)
break;
*t=*newp++;
if(*t++=='/'){
- namep=t;
- p=newp;
+ namep = t;
+ p = newp;
}
}
/* If we ran out of pattern, append the name if accessible */
if(*newp=='\0'){
*t='\0';
if(access(globname, 0)==0)
- globv=newword(globname, globv);
+ globv = newword(globname, globv);
return;
}
/* read the directory and recur for any entry that matches */
*namep='\0';
- if((f=Opendir(globname[0]?globname:"."))<0) return;
+ if((f = Opendir(globname[0]?globname:"."))<0) return;
while(*newp!='/' && *newp!='\0') newp++;
- while(Readdir(f, namep)){
+ while(Readdir(f, namep, *newp=='/')){
if(matchfn(namep, p)){
- for(t=namep;*t;t++);
+ for(t = namep;*t;t++);
globdir(newp, t);
}
}
@@ -77,22 +86,24 @@ void globdir(char *p, char *namep)
* Push all file names matched by p on the current thread's stack.
* If there are no matches, the list consists of p.
*/
-void glob(char *p)
+
+void
+glob(char *p)
{
- word *svglobv=globv;
- int globlen=Globsize(p);
+ word *svglobv = globv;
+ int globlen = Globsize(p);
if(!globlen){
deglob(p);
- globv=newword(p, globv);
+ globv = newword(p, globv);
return;
}
- globname=emalloc(globlen);
+ globname = emalloc(globlen);
globname[0]='\0';
globdir(p, globname);
efree(globname);
if(svglobv==globv){
deglob(p);
- globv=newword(p, globv);
+ globv = newword(p, globv);
}
else
globsort(globv, svglobv);
@@ -100,12 +111,18 @@ void glob(char *p)
/*
* Do p and q point at equal utf codes
*/
-int equtf(char *p, char *q){
- if(*p!=*q) return 0;
+
+int
+equtf(char *p, char *q)
+{
+ if(*p!=*q)
+ return 0;
if(twobyte(*p)) return p[1]==q[1];
if(threebyte(*p)){
- if(p[1]!=q[1]) return 0;
- if(p[1]=='\0') return 1; /* broken code at end of string! */
+ if(p[1]!=q[1])
+ return 0;
+ if(p[1]=='\0')
+ return 1; /* broken code at end of string! */
return p[2]==q[2];
}
return 1;
@@ -114,7 +131,10 @@ int equtf(char *p, char *q){
* Return a pointer to the next utf code in the string,
* not jumping past nuls in broken utf codes!
*/
-char *nextutf(char *p){
+
+char*
+nextutf(char *p)
+{
if(twobyte(*p)) return p[1]=='\0'?p+1:p+2;
if(threebyte(*p)) return p[1]=='\0'?p+1:p[2]=='\0'?p+2:p+3;
return p+1;
@@ -122,7 +142,10 @@ char *nextutf(char *p){
/*
* Convert the utf code at *p to a unicode value
*/
-int unicode(char *p){
+
+int
+unicode(char *p)
+{
int u=*p&0xff;
if(twobyte(u)) return ((u&0x1f)<<6)|(p[1]&0x3f);
if(threebyte(u)) return (u<<12)|((p[1]&0x3f)<<6)|(p[2]&0x3f);
@@ -135,77 +158,97 @@ int unicode(char *p){
* ? matches any single character
* [...] matches the enclosed list of characters
*/
-int matchfn(char *s, char *p)
+
+int
+matchfn(char *s, char *p)
{
if(s[0]=='.' && (s[1]=='\0' || s[1]=='.' && s[2]=='\0') && p[0]!='.')
return 0;
return match(s, p, '/');
}
-int match(char *s, char *p, int stop)
+
+int
+match(char *s, char *p, int stop)
{
int compl, hit, lo, hi, t, c;
- for(;*p!=stop && *p!='\0';s=nextutf(s),p=nextutf(p)){
+ for(;*p!=stop && *p!='\0';s = nextutf(s),p = nextutf(p)){
if(*p!=GLOB){
if(!equtf(p, s)) return 0;
}
else switch(*++p){
case GLOB:
- if(*s!=GLOB) return 0;
+ if(*s!=GLOB)
+ return 0;
break;
case '*':
for(;;){
if(match(s, nextutf(p), stop)) return 1;
- if(!*s) break;
- s=nextutf(s);
+ if(!*s)
+ break;
+ s = nextutf(s);
}
return 0;
case '?':
- if(*s=='\0') return 0;
+ if(*s=='\0')
+ return 0;
break;
case '[':
- if(*s=='\0') return 0;
- c=unicode(s);
+ if(*s=='\0')
+ return 0;
+ c = unicode(s);
p++;
compl=*p=='~';
- if(compl) p++;
- hit=0;
+ if(compl)
+ p++;
+ hit = 0;
while(*p!=']'){
- if(*p=='\0') return 0; /* syntax error */
- lo=unicode(p);
- p=nextutf(p);
- if(*p!='-') hi=lo;
+ if(*p=='\0')
+ return 0; /* syntax error */
+ lo = unicode(p);
+ p = nextutf(p);
+ if(*p!='-')
+ hi = lo;
else{
p++;
- if(*p=='\0') return 0; /* syntax error */
- hi=unicode(p);
- p=nextutf(p);
- if(hi<lo){ t=lo; lo=hi; hi=t; }
+ if(*p=='\0')
+ return 0; /* syntax error */
+ hi = unicode(p);
+ p = nextutf(p);
+ if(hi<lo){ t = lo; lo = hi; hi = t; }
}
- if(lo<=c && c<=hi) hit=1;
+ if(lo<=c && c<=hi)
+ hit = 1;
}
- if(compl) hit=!hit;
- if(!hit) return 0;
+ if(compl)
+ hit=!hit;
+ if(!hit)
+ return 0;
break;
}
}
return *s=='\0';
}
-void globlist1(word *gl)
+
+void
+globlist1(word *gl)
{
if(gl){
globlist1(gl->next);
glob(gl->word);
}
}
-void globlist(void){
+
+void
+globlist(void)
+{
word *a;
- globv=0;
+ globv = 0;
globlist1(runq->argv->words);
poplist();
pushlist();
if(globv){
- for(a=globv;a->next;a=a->next);
- a->next=runq->argv->words;
- runq->argv->words=globv;
+ for(a = globv;a->next;a = a->next);
+ a->next = runq->argv->words;
+ runq->argv->words = globv;
}
}
diff --git a/src/cmd/rc/havefork.c b/src/cmd/rc/havefork.c
index 6e4aa924..e81046d6 100644
--- a/src/cmd/rc/havefork.c
+++ b/src/cmd/rc/havefork.c
@@ -1,5 +1,3 @@
-#include <u.h>
-#include <signal.h>
#include "rc.h"
#include "getflags.h"
#include "exec.h"
@@ -13,9 +11,7 @@ Xasync(void)
{
int null = open("/dev/null", 0);
int pid;
- int tcpgrp, pgrp;
char npid[10];
-
if(null<0){
Xerror("Can't open /dev/null\n");
return;
@@ -26,12 +22,6 @@ Xasync(void)
Xerror("try again");
break;
case 0:
- /*
- * Should make reads of tty fail, writes succeed.
- */
- signal(SIGTTIN, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
-
pushredir(ROPEN, null, 0);
start(runq->code, runq->pc+1, runq->local);
runq->ret = 0;
diff --git a/src/cmd/rc/havep9p.c b/src/cmd/rc/havep9p.c
new file mode 100644
index 00000000..29e2272b
--- /dev/null
+++ b/src/cmd/rc/havep9p.c
@@ -0,0 +1,246 @@
+#include <u.h>
+#include <signal.h>
+#if defined(PLAN9PORT) && defined(__sun__)
+# define BSD_COMP /* sigh. for TIOCNOTTY */
+#endif
+#include <sys/ioctl.h>
+#include "rc.h"
+#include "getflags.h"
+#include "exec.h"
+#include "io.h"
+#include "fns.h"
+
+int havefork = 1;
+
+void
+Xasync(void)
+{
+ int null=open("/dev/null", 0);
+ int tty;
+ int pid;
+ char npid[10];
+ if(null<0){
+ Xerror("Can't open /dev/null\n");
+ return;
+ }
+ switch(pid=rfork(RFFDG|RFPROC|RFNOTEG)){
+ case -1:
+ close(null);
+ Xerror("try again");
+ break;
+ case 0:
+ /*
+ * I don't know what the right thing to do here is,
+ * so this is all experimentally determined.
+ * If we just dup /dev/null onto 0, then running
+ * ssh foo & will reopen /dev/tty, try to read a password,
+ * get a signal, and repeat, in a tight loop, forever.
+ * Arguably this is a bug in ssh (it behaves the same
+ * way under bash as under rc) but I'm fixing it here
+ * anyway. If we dissociate the process from the tty,
+ * then it won't be able to open /dev/tty ever again.
+ * The SIG_IGN on SIGTTOU makes writing the tty
+ * (via fd 1 or 2, for example) succeed even though
+ * our pgrp is not the terminal's controlling pgrp.
+ */
+ if((tty=open("/dev/tty", OREAD)) >= 0){
+ /*
+ * Should make reads of tty fail, writes succeed.
+ */
+ signal(SIGTTIN, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ ioctl(tty, TIOCNOTTY);
+ close(tty);
+ }
+ if(isatty(0))
+ pushredir(ROPEN, null, 0);
+ else
+ close(null);
+ start(runq->code, runq->pc+1, runq->local);
+ runq->ret=0;
+ break;
+ default:
+ close(null);
+ runq->pc=runq->code[runq->pc].i;
+ inttoascii(npid, pid);
+ setvar("apid", newword(npid, (word *)0));
+ break;
+ }
+}
+
+void
+Xpipe(void)
+{
+ struct thread *p = runq;
+ int pc = p->pc, forkid;
+ int lfd = p->code[pc++].i;
+ int rfd = p->code[pc++].i;
+ int pfd[2];
+
+ if(pipe(pfd)<0){
+ Xerror("can't get pipe");
+ return;
+ }
+ switch(forkid=fork()){
+ case -1:
+ Xerror("try again");
+ break;
+ case 0:
+ start(p->code, pc+2, runq->local);
+ runq->ret=0;
+ close(pfd[PRD]);
+ pushredir(ROPEN, pfd[PWR], lfd);
+ break;
+ default:
+ start(p->code, p->code[pc].i, runq->local);
+ close(pfd[PWR]);
+ pushredir(ROPEN, pfd[PRD], rfd);
+ p->pc=p->code[pc+1].i;
+ p->pid=forkid;
+ break;
+ }
+}
+
+void
+Xbackq(void)
+{
+ char wd[8193];
+ int c;
+ char *s, *ewd = &wd[8192], *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;
+ }
+ switch(pid = fork()){
+ case -1: Xerror("try again");
+ close(pfd[PRD]);
+ close(pfd[PWR]);
+ return;
+ case 0:
+ close(pfd[PRD]);
+ start(runq->code, runq->pc+1, runq->local);
+ pushredir(ROPEN, pfd[PWR], 1);
+ return;
+ default:
+ close(pfd[PWR]);
+ f=openfd(pfd[PRD]);
+ s=wd;
+ v=0;
+ while((c=rchr(f))!=EOF){
+ if(strchr(stop, c) || s==ewd){
+ if(s!=wd){
+ *s='\0';
+ v=newword(wd, v);
+ s=wd;
+ }
+ }
+ else *s++=c;
+ }
+ if(s!=wd){
+ *s='\0';
+ v=newword(wd, v);
+ }
+ closeio(f);
+ Waitfor(pid, 0);
+ /* 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=runq->code[runq->pc].i;
+ return;
+ }
+}
+
+/*
+ * Who should wait for the exit from the fork?
+ */
+void
+Xpipefd(void)
+{
+ struct thread *p=runq;
+ int pc=p->pc;
+ char name[40];
+ int pfd[2];
+ int sidefd, mainfd;
+ if(pipe(pfd)<0){
+ Xerror("can't get pipe");
+ return;
+ }
+ if(p->code[pc].i==READ){
+ sidefd=pfd[PWR];
+ mainfd=pfd[PRD];
+ }
+ else{
+ sidefd=pfd[PRD];
+ mainfd=pfd[PWR];
+ }
+ switch(fork()){
+ case -1:
+ Xerror("try again");
+ break;
+ case 0:
+ start(p->code, pc+2, runq->local);
+ close(mainfd);
+ pushredir(ROPEN, sidefd, p->code[pc].i==READ?1:0);
+ runq->ret=0;
+ break;
+ default:
+ close(sidefd);
+ pushredir(ROPEN, mainfd, mainfd); /* isn't this a noop? */
+ strcpy(name, Fdprefix);
+ inttoascii(name+strlen(name), mainfd);
+ pushword(name);
+ p->pc=p->code[pc+1].i;
+ break;
+ }
+}
+
+void
+Xsubshell(void)
+{
+ int pid;
+ switch(pid=fork()){
+ case -1:
+ Xerror("try again");
+ break;
+ case 0:
+ start(runq->code, runq->pc+1, runq->local);
+ runq->ret=0;
+ break;
+ default:
+ Waitfor(pid, 1);
+ runq->pc=runq->code[runq->pc].i;
+ break;
+ }
+}
+
+int
+execforkexec(void)
+{
+ int pid;
+ int n;
+ char buf[ERRMAX];
+
+ switch(pid = fork()){
+ case -1:
+ return -1;
+ case 0:
+ pushword("exec");
+ execexec();
+ strcpy(buf, "can't exec: ");
+ n = strlen(buf);
+ errstr(buf+n, ERRMAX-n);
+ Exit(buf);
+ }
+ return pid;
+}
diff --git a/src/cmd/rc/here.c b/src/cmd/rc/here.c
index 2a0fe2f2..17c62458 100644
--- a/src/cmd/rc/here.c
+++ b/src/cmd/rc/here.c
@@ -3,32 +3,37 @@
#include "io.h"
#include "fns.h"
struct here *here, **ehere;
-int ser=0;
+int ser = 0;
char tmp[]="/tmp/here0000.0000";
char hex[]="0123456789abcdef";
void psubst(io*, char*);
void pstrs(io*, word*);
-void hexnum(char *p, int n)
+
+void
+hexnum(char *p, int n)
{
*p++=hex[(n>>12)&0xF];
*p++=hex[(n>>8)&0xF];
*p++=hex[(n>>4)&0xF];
- *p=hex[n&0xF];
+ *p = hex[n&0xF];
}
-tree *heredoc(tree *tag)
+
+tree*
+heredoc(tree *tag)
{
- struct here *h=new(struct here);
- if(tag->type!=WORD) yyerror("Bad here tag");
- h->next=0;
+ struct here *h = new(struct here);
+ if(tag->type!=WORD)
+ yyerror("Bad here tag");
+ h->next = 0;
if(here)
- *ehere=h;
+ *ehere = h;
else
- here=h;
+ here = h;
ehere=&h->next;
- h->tag=tag;
+ h->tag = tag;
hexnum(&tmp[9], getpid());
hexnum(&tmp[14], ser++);
- h->name=strdup(tmp);
+ h->name = strdup(tmp);
return token(tmp, WORD);
}
/*
@@ -36,27 +41,32 @@ tree *heredoc(tree *tag)
* missubstitution, or a misrecognized EOF marker.
*/
#define NLINE 4096
-void readhere(void){
+
+void
+readhere(void)
+{
struct here *h, *nexth;
io *f;
char *s, *tag;
int c, subst;
char line[NLINE+1];
- for(h=here;h;h=nexth){
+ for(h = here;h;h = nexth){
subst=!h->tag->quoted;
- tag=h->tag->str;
- c=Creat(h->name);
- if(c<0) yyerror("can't create here document");
- f=openfd(c);
- s=line;
+ tag = h->tag->str;
+ c = Creat(h->name);
+ if(c<0)
+ yyerror("can't create here document");
+ f = openfd(c);
+ s = line;
pprompt();
- while((c=rchr(runq->cmdfd))!=EOF){
+ while((c = rchr(runq->cmdfd))!=EOF){
if(c=='\n' || s==&line[NLINE]){
*s='\0';
- if(strcmp(line, tag)==0) break;
- if(subst) psubst(f, line);
+ if(tag && strcmp(line, tag)==0) break;
+ if(subst)
+ psubst(f, line);
else pstr(f, line);
- s=line;
+ s = line;
if(c=='\n'){
pprompt();
pchr(f, c);
@@ -68,13 +78,15 @@ void readhere(void){
flush(f);
closeio(f);
cleanhere(h->name);
- nexth=h->next;
+ nexth = h->next;
efree((char *)h);
}
- here=0;
- doprompt=1;
+ here = 0;
+ doprompt = 1;
}
-void psubst(io *f, char *s)
+
+void
+psubst(io *f, char *s)
{
char *t, *u;
int savec, n;
@@ -83,48 +95,55 @@ void psubst(io *f, char *s)
if(*s!='$'){
if(0xa0<=(*s&0xff) && (*s&0xff)<=0xf5){
pchr(f, *s++);
- if(*s=='\0') break;
+ if(*s=='\0')
+ break;
}
else if(0xf6<=(*s&0xff) && (*s&0xff)<=0xf7){
pchr(f, *s++);
- if(*s=='\0') break;
+ if(*s=='\0')
+ break;
pchr(f, *s++);
- if(*s=='\0') break;
+ if(*s=='\0')
+ break;
}
pchr(f, *s++);
}
else{
t=++s;
- if(*t=='$') pchr(f, *t++);
+ if(*t=='$')
+ pchr(f, *t++);
else{
while(*t && idchr(*t)) t++;
savec=*t;
*t='\0';
- n=0;
- for(u=s;*u && '0'<=*u && *u<='9';u++) n=n*10+*u-'0';
+ n = 0;
+ for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*10+*u-'0';
if(n && *u=='\0'){
- star=vlook("*")->val;
+ star = vlook("*")->val;
if(star && 1<=n && n<=count(star)){
- while(--n) star=star->next;
+ while(--n) star = star->next;
pstr(f, star->word);
}
}
else
pstrs(f, vlook(s)->val);
- *t=savec;
- if(savec=='^') t++;
+ *t = savec;
+ if(savec=='^')
+ t++;
}
- s=t;
+ s = t;
}
}
}
-void pstrs(io *f, word *a)
+
+void
+pstrs(io *f, word *a)
{
if(a){
while(a->next && a->next->word){
pstr(f, a->word);
pchr(f, ' ');
- a=a->next;
+ a = a->next;
}
pstr(f, a->word);
}
diff --git a/src/cmd/rc/io.c b/src/cmd/rc/io.c
index c360b4a0..3ad1e2db 100644
--- a/src/cmd/rc/io.c
+++ b/src/cmd/rc/io.c
@@ -2,68 +2,121 @@
#include "exec.h"
#include "io.h"
#include "fns.h"
-int pfmtnest=0;
-void pfmt(io *f, char *fmt, ...){
+int pfmtnest = 0;
+
+void
+pfmt(io *f, char *fmt, ...)
+{
va_list ap;
char err[ERRMAX];
va_start(ap, fmt);
pfmtnest++;
for(;*fmt;fmt++)
- if(*fmt!='%') pchr(f, *fmt);
+ if(*fmt!='%')
+ pchr(f, *fmt);
else switch(*++fmt){
- case '\0': va_end(ap); return;
- case 'c': pchr(f, va_arg(ap, int)); break;
- case 'd': pdec(f, va_arg(ap, int)); break;
- case 'o': poct(f, va_arg(ap, unsigned)); break;
- case 'p': phex(f, (long)va_arg(ap, char *)); break; /*unportable*/
- case 'Q': pquo(f, va_arg(ap, char *)); break;
- case 'q': pwrd(f, va_arg(ap, char *)); break;
- case 'r': errstr(err, sizeof err); pstr(f, err); break;
- case 's': pstr(f, va_arg(ap, char *)); break;
- case 't': pcmd(f, va_arg(ap, struct tree *)); break;
- case 'v': pval(f, va_arg(ap, struct word *)); break;
- default: pchr(f, *fmt); break;
+ case '\0':
+ va_end(ap);
+ return;
+ case 'c':
+ pchr(f, va_arg(ap, int));
+ break;
+ case 'd':
+ pdec(f, va_arg(ap, int));
+ break;
+ case 'o':
+ poct(f, va_arg(ap, unsigned));
+ break;
+ case 'p':
+ pptr(f, va_arg(ap, void*));
+ break;
+ case 'Q':
+ pquo(f, va_arg(ap, char *));
+ break;
+ case 'q':
+ pwrd(f, va_arg(ap, char *));
+ break;
+ case 'r':
+ errstr(err, sizeof err); pstr(f, err);
+ break;
+ case 's':
+ pstr(f, va_arg(ap, char *));
+ break;
+ case 't':
+ pcmd(f, va_arg(ap, struct tree *));
+ break;
+ case 'v':
+ pval(f, va_arg(ap, struct word *));
+ break;
+ default:
+ pchr(f, *fmt);
+ break;
}
va_end(ap);
- if(--pfmtnest==0) flush(f);
+ if(--pfmtnest==0)
+ flush(f);
}
-void pchr(io *b, int c)
+
+void
+pchr(io *b, int c)
{
- if(b->bufp==b->ebuf) fullbuf(b, c);
+ if(b->bufp==b->ebuf)
+ fullbuf(b, c);
else *b->bufp++=c;
}
-int rchr(io *b)
+
+int
+rchr(io *b)
{
- if(b->bufp==b->ebuf) return emptybuf(b);
+ if(b->bufp==b->ebuf)
+ return emptybuf(b);
return *b->bufp++ & 0xFF;
}
-void pquo(io *f, char *s)
+void
+pquo(io *f, char *s)
{
pchr(f, '\'');
for(;*s;s++)
- if(*s=='\'') pfmt(f, "''");
+ if(*s=='\'')
+ pfmt(f, "''");
else pchr(f, *s);
pchr(f, '\'');
}
-void pwrd(io *f, char *s)
+
+void
+pwrd(io *f, char *s)
{
char *t;
- for(t=s;*t;t++) if(!wordchr(*t)) break;
- if(t==s || *t) pquo(f, s);
+ for(t = s;*t;t++) if(!wordchr(*t)) break;
+ if(t==s || *t)
+ pquo(f, s);
else pstr(f, s);
}
-void phex(io *f, long p)
+
+void
+pptr(io *f, void *v)
{
int n;
- for(n=28;n>=0;n-=4) pchr(f, "0123456789ABCDEF"[(p>>n)&0xF]);
+ 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]);
}
-void pstr(io *f, char *s)
+
+void
+pstr(io *f, char *s)
{
- if(s==0) s="(null)";
+ if(s==0)
+ s="(null)";
while(*s) pchr(f, *s++);
}
-void pdec(io *f, long n)
+
+void
+pdec(io *f, int n)
{
if(n<0){
n=-n;
@@ -73,110 +126,136 @@ void pdec(io *f, long n)
return;
}
/* n is two's complement minimum integer */
- n=1-n;
+ n = 1-n;
pchr(f, '-');
pdec(f, n/10);
pchr(f, n%10+'1');
return;
}
- if(n>9) pdec(f, n/10);
+ if(n>9)
+ pdec(f, n/10);
pchr(f, n%10+'0');
}
-void poct(io *f, ulong n)
+
+void
+poct(io *f, unsigned n)
{
- if(n>7) poct(f, n>>3);
+ if(n>7)
+ poct(f, n>>3);
pchr(f, (n&7)+'0');
}
-void pval(io *f, word *a)
+
+void
+pval(io *f, word *a)
{
if(a){
while(a->next && a->next->word){
pwrd(f, a->word);
pchr(f, ' ');
- a=a->next;
+ a = a->next;
}
pwrd(f, a->word);
}
}
-int fullbuf(io *f, int c)
+
+int
+fullbuf(io *f, int c)
{
flush(f);
return *f->bufp++=c;
}
-void flush(io *f)
+
+void
+flush(io *f)
{
int n;
char *s;
if(f->strp){
- n=f->ebuf-f->strp;
- f->strp=realloc(f->strp, n+101);
- if(f->strp==0) panic("Can't realloc %d bytes in flush!", n+101);
- f->bufp=f->strp+n;
- f->ebuf=f->bufp+100;
- for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
+ n = f->ebuf-f->strp;
+ f->strp = realloc(f->strp, n+101);
+ if(f->strp==0)
+ panic("Can't realloc %d bytes in flush!", n+101);
+ f->bufp = f->strp+n;
+ f->ebuf = f->bufp+100;
+ for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
}
else{
- n=f->bufp-f->buf;
+ n = f->bufp-f->buf;
if(n && Write(f->fd, f->buf, n) < 0){
Write(3, "Write error\n", 12);
- if(ntrap) dotrap();
+ if(ntrap)
+ dotrap();
}
- f->bufp=f->buf;
- f->ebuf=f->buf+NBUF;
+ f->bufp = f->buf;
+ f->ebuf = f->buf+NBUF;
}
}
-io *openfd(int fd){
- io *f;
- f=new(struct io);
- f->fd=fd;
- f->bufp=f->ebuf=f->buf;
- f->strp=0;
+
+io*
+openfd(int fd)
+{
+ io *f = new(struct io);
+ f->fd = fd;
+ f->bufp = f->ebuf = f->buf;
+ f->strp = 0;
return f;
}
-io *openstr(void){
- io *f=new(struct io);
+
+io*
+openstr(void)
+{
+ io *f = new(struct io);
char *s;
f->fd=-1;
- f->bufp=f->strp=emalloc(101);
- f->ebuf=f->bufp+100;
- for(s=f->bufp;s<=f->ebuf;s++) *s='\0';
+ f->bufp = f->strp = emalloc(101);
+ f->ebuf = f->bufp+100;
+ for(s = f->bufp;s<=f->ebuf;s++) *s='\0';
return f;
}
/*
* Open a corebuffer to read. EOF occurs after reading len
* characters from buf.
*/
-io *opencore(char *s, int len)
+
+io*
+opencore(char *s, int len)
{
- io *f=new(struct io);
- char *buf=emalloc(len);
+ io *f = new(struct io);
+ char *buf = emalloc(len);
f->fd= -1 /*open("/dev/null", 0)*/;
- f->bufp=f->strp=buf;
- f->ebuf=buf+len;
+ f->bufp = f->strp = buf;
+ f->ebuf = buf+len;
Memcpy(buf, s, len);
return f;
}
-/*
-void rewind(io *io)
+
+void
+rewind(io *io)
{
- if(io->fd==-1) io->bufp=io->strp;
+ if(io->fd==-1)
+ io->bufp = io->strp;
else{
- io->bufp=io->ebuf=io->buf;
+ io->bufp = io->ebuf = io->buf;
Seek(io->fd, 0L, 0);
}
}
-*/
-void closeio(io *io)
+
+void
+closeio(io *io)
{
- if(io->fd>=0) close(io->fd);
- if(io->strp) efree(io->strp);
+ if(io->fd>=0)
+ close(io->fd);
+ if(io->strp)
+ efree(io->strp);
efree((char *)io);
}
-int emptybuf(io *f)
+
+int
+emptybuf(io *f)
{
int n;
- if(f->fd==-1 || (n=Read(f->fd, f->buf, NBUF))<=0) return EOF;
- f->bufp=f->buf;
- f->ebuf=f->buf+n;
+ if(f->fd==-1 || (n = Read(f->fd, f->buf, NBUF))<=0) return EOF;
+ f->bufp = f->buf;
+ f->ebuf = f->buf+n;
return *f->bufp++&0xff;
}
diff --git a/src/cmd/rc/io.h b/src/cmd/rc/io.h
index ec511871..21cc6b8e 100644
--- a/src/cmd/rc/io.h
+++ b/src/cmd/rc/io.h
@@ -18,9 +18,9 @@ int rchr(io*);
void closeio(io*);
void flush(io*);
int fullbuf(io*, int);
-void pdec(io*, long);
-void poct(io*, ulong);
-void phex(io*, long);
+void pdec(io*, int);
+void poct(io*, unsigned);
+void pptr(io*, void*);
void pquo(io*, char*);
void pwrd(io*, char*);
void pstr(io*, char*);
diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c
index b0e27eb3..36934832 100644
--- a/src/cmd/rc/lex.c
+++ b/src/cmd/rc/lex.c
@@ -4,11 +4,15 @@
#include "getflags.h"
#include "fns.h"
int getnext(void);
-int wordchr(int c)
+
+int
+wordchr(int c)
{
return !strchr("\n \t#;&|^$=`'{}()<>", c) && c!=EOF;
}
-int idchr(int c)
+
+int
+idchr(int c)
{
/*
* Formerly:
@@ -17,127 +21,170 @@ int idchr(int c)
*/
return c>' ' && !strchr("!\"#$%&'()+,-./:;<=>?@[\\]^`{|}~", c);
}
-int future=EOF;
-int doprompt=1;
+int future = EOF;
+int doprompt = 1;
int inquote;
+int incomm;
/*
* Look ahead in the input stream
*/
-int nextc(void){
- if(future==EOF) future=getnext();
+
+int
+nextc(void)
+{
+ if(future==EOF)
+ future = getnext();
return future;
}
/*
* Consume the lookahead character.
*/
-int advance(void){
- int c=nextc();
- lastc=future;
- future=EOF;
+
+int
+advance(void)
+{
+ int c = nextc();
+ lastc = future;
+ future = EOF;
return c;
}
/*
* read a character from the input stream
*/
-int getnext(void){
- register int c;
- static int peekc=EOF;
+
+int
+getnext(void)
+{
+ int c;
+ static int peekc = EOF;
if(peekc!=EOF){
- c=peekc;
- peekc=EOF;
+ c = peekc;
+ peekc = EOF;
return c;
}
- if(runq->eof) return EOF;
- if(doprompt) pprompt();
- c=rchr(runq->cmdfd);
+ if(runq->eof)
+ return EOF;
+ if(doprompt)
+ pprompt();
+ c = rchr(runq->cmdfd);
if(!inquote && c=='\\'){
- c=rchr(runq->cmdfd);
- if(c=='\n'){
- doprompt=1;
+ c = rchr(runq->cmdfd);
+ if(c=='\n' && !incomm){ /* don't continue a comment */
+ doprompt = 1;
c=' ';
}
else{
- peekc=c;
+ peekc = c;
c='\\';
}
}
- doprompt=doprompt || c=='\n' || c==EOF;
- if(c==EOF) runq->eof++;
+ doprompt = doprompt || c=='\n' || c==EOF;
+ if(c==EOF)
+ runq->eof++;
else if(flag['V'] || ndot>=2 && flag['v']) pchr(err, c);
return c;
}
-void pprompt(void){
+
+void
+pprompt(void)
+{
var *prompt;
if(runq->iflag){
pstr(err, promptstr);
flush(err);
- prompt=vlook("prompt");
+ prompt = vlook("prompt");
if(prompt->val && prompt->val->next)
- promptstr=prompt->val->next->word;
+ promptstr = prompt->val->next->word;
else
promptstr="\t";
}
runq->lineno++;
- doprompt=0;
+ doprompt = 0;
}
-void skipwhite(void){
+
+void
+skipwhite(void)
+{
int c;
for(;;){
- c=nextc();
- if(c=='#'){ /* Why did this used to be if(!inquote && c=='#') ?? */
+ c = nextc();
+ /* Why did this used to be if(!inquote && c=='#') ?? */
+ if(c=='#'){
+ incomm = 1;
for(;;){
- c=nextc();
- if(c=='\n' || c==EOF) break;
+ c = nextc();
+ if(c=='\n' || c==EOF) {
+ incomm = 0;
+ break;
+ }
advance();
}
}
- if(c==' ' || c=='\t') advance();
+ if(c==' ' || c=='\t')
+ advance();
else return;
}
}
-void skipnl(void){
- register int c;
+
+void
+skipnl(void)
+{
+ int c;
for(;;){
skipwhite();
- c=nextc();
- if(c!='\n') return;
+ c = nextc();
+ if(c!='\n')
+ return;
advance();
}
}
-int nextis(int c){
+
+int
+nextis(int c)
+{
if(nextc()==c){
advance();
return 1;
}
return 0;
}
-char *addtok(char *p, int val){
- if(p==0) return 0;
+
+char*
+addtok(char *p, int val)
+{
+ if(p==0)
+ return 0;
if(p==&tok[NTOK-1]){
- *p=0;
+ *p = 0;
yyerror("token buffer too short");
return 0;
}
*p++=val;
return p;
}
-char *addutf(char *p, int c){
- p=addtok(p, c);
+
+char*
+addutf(char *p, int c)
+{
+ p = addtok(p, c);
if(twobyte(c)) /* 2-byte escape */
return addtok(p, advance());
if(threebyte(c)){ /* 3-byte escape */
- p=addtok(p, advance());
+ p = addtok(p, advance());
return addtok(p, advance());
}
return p;
}
int lastdol; /* was the last token read '$' or '$#' or '"'? */
int lastword; /* was the last token read a word or compound word terminator? */
-int yylex(void){
- register int c, d=nextc();
- register char *w=tok;
- register struct tree *t;
- yylval.tree=0;
+
+int
+yylex(void)
+{
+ int c, d = nextc();
+ char *w = tok;
+ struct tree *t;
+ yylval.tree = 0;
/*
* Embarassing sneakiness: if the last token read was a quoted or unquoted
* WORD then we alter the meaning of what follows. If the next character
@@ -146,7 +193,7 @@ int yylex(void){
* we insert a `^' before it.
*/
if(lastword){
- lastword=0;
+ lastword = 0;
if(d=='('){
advance();
strcpy(tok, "( [SUB]");
@@ -157,15 +204,15 @@ int yylex(void){
return '^';
}
}
- inquote=0;
+ inquote = 0;
skipwhite();
- switch(c=advance()){
+ switch(c = advance()){
case EOF:
- lastdol=0;
+ lastdol = 0;
strcpy(tok, "EOF");
return EOF;
case '$':
- lastdol=1;
+ lastdol = 1;
if(nextis('#')){
strcpy(tok, "$#");
return COUNT;
@@ -177,7 +224,7 @@ int yylex(void){
strcpy(tok, "$");
return '$';
case '&':
- lastdol=0;
+ lastdol = 0;
if(nextis('&')){
skipnl();
strcpy(tok, "&&");
@@ -186,7 +233,7 @@ int yylex(void){
strcpy(tok, "&");
return '&';
case '|':
- lastdol=0;
+ lastdol = 0;
if(nextis(c)){
skipnl();
strcpy(tok, "||");
@@ -194,7 +241,7 @@ int yylex(void){
}
case '<':
case '>':
- lastdol=0;
+ lastdol = 0;
/*
* funny redirection tokens:
* redir: arrow | arrow '[' fd ']'
@@ -204,121 +251,128 @@ int yylex(void){
* some possibilities are nonsensical and get a message.
*/
*w++=c;
- t=newtree();
+ t = newtree();
switch(c){
case '|':
- t->type=PIPE;
- t->fd0=1;
- t->fd1=0;
+ t->type = PIPE;
+ t->fd0 = 1;
+ t->fd1 = 0;
break;
case '>':
- t->type=REDIR;
+ t->type = REDIR;
if(nextis(c)){
- t->rtype=APPEND;
+ t->rtype = APPEND;
*w++=c;
}
- else t->rtype=WRITE;
- t->fd0=1;
+ else t->rtype = WRITE;
+ t->fd0 = 1;
break;
case '<':
- t->type=REDIR;
+ t->type = REDIR;
if(nextis(c)){
- t->rtype=HERE;
+ t->rtype = HERE;
*w++=c;
- }
- else t->rtype=READ;
- t->fd0=0;
+ } else if (nextis('>')){
+ t->rtype = RDWR;
+ *w++=c;
+ } else t->rtype = READ;
+ t->fd0 = 0;
break;
}
if(nextis('[')){
*w++='[';
- c=advance();
+ c = advance();
+ *w++=c;
if(c<'0' || '9'<c){
RedirErr:
- *w++ = c;
- *w=0;
+ *w = 0;
yyerror(t->type==PIPE?"pipe syntax"
:"redirection syntax");
return EOF;
}
- t->fd0=0;
+ t->fd0 = 0;
do{
- t->fd0=t->fd0*10+c-'0';
+ t->fd0 = t->fd0*10+c-'0';
*w++=c;
- c=advance();
+ c = advance();
}while('0'<=c && c<='9');
if(c=='='){
*w++='=';
- if(t->type==REDIR) t->type=DUP;
- c=advance();
+ if(t->type==REDIR)
+ t->type = DUP;
+ c = advance();
if('0'<=c && c<='9'){
- t->rtype=DUPFD;
- t->fd1=t->fd0;
- t->fd0=0;
+ t->rtype = DUPFD;
+ t->fd1 = t->fd0;
+ t->fd0 = 0;
do{
- t->fd0=t->fd0*10+c-'0';
+ t->fd0 = t->fd0*10+c-'0';
*w++=c;
- c=advance();
+ c = advance();
}while('0'<=c && c<='9');
}
else{
- if(t->type==PIPE) goto RedirErr;
- t->rtype=CLOSE;
+ if(t->type==PIPE)
+ goto RedirErr;
+ t->rtype = CLOSE;
}
}
- *w=0;
if(c!=']'
|| t->type==DUP && (t->rtype==HERE || t->rtype==APPEND))
goto RedirErr;
*w++=']';
}
*w='\0';
- yylval.tree=t;
- if(t->type==PIPE) skipnl();
+ yylval.tree = t;
+ if(t->type==PIPE)
+ skipnl();
return t->type;
case '\'':
- lastdol=0;
- lastword=1;
- inquote=1;
+ lastdol = 0;
+ lastword = 1;
+ inquote = 1;
for(;;){
- c=advance();
- if(c==EOF) break;
+ c = advance();
+ if(c==EOF)
+ break;
if(c=='\''){
if(nextc()!='\'')
break;
advance();
}
- w=addutf(w, c);
+ w = addutf(w, c);
}
- if(w!=0) *w='\0';
- t=token(tok, WORD);
- t->quoted=1;
- yylval.tree=t;
+ if(w!=0)
+ *w='\0';
+ t = token(tok, WORD);
+ t->quoted = 1;
+ yylval.tree = t;
return t->type;
}
if(!wordchr(c)){
- lastdol=0;
- tok[0]=c;
+ lastdol = 0;
+ tok[0] = c;
tok[1]='\0';
return c;
}
for(;;){
/* next line should have (char)c==GLOB, but ken's compiler is broken */
if(c=='*' || c=='[' || c=='?' || c==(unsigned char)GLOB)
- w=addtok(w, GLOB);
- w=addutf(w, c);
- c=nextc();
+ w = addtok(w, GLOB);
+ w = addutf(w, c);
+ c = nextc();
if(lastdol?!idchr(c):!wordchr(c)) break;
advance();
}
- lastword=1;
- lastdol=0;
- if(w!=0) *w='\0';
- t=klook(tok);
- if(t->type!=WORD) lastword=0;
- t->quoted=0;
- yylval.tree=t;
+ lastword = 1;
+ lastdol = 0;
+ if(w!=0)
+ *w='\0';
+ t = klook(tok);
+ if(t->type!=WORD)
+ lastword = 0;
+ t->quoted = 0;
+ yylval.tree = t;
return t->type;
}
-
diff --git a/src/cmd/rc/mkfile b/src/cmd/rc/mkfile
index b3d8ffd0..d1144e85 100644
--- a/src/cmd/rc/mkfile
+++ b/src/cmd/rc/mkfile
@@ -20,6 +20,7 @@ OFILES=\
var.$O\
y.tab.$O\
plan9ish.$O\
+ havep9p.$O\
HFILES=\
rc.h\
diff --git a/src/cmd/rc/pcmd.c b/src/cmd/rc/pcmd.c
index 0f84298a..8caf60a2 100644
--- a/src/cmd/rc/pcmd.c
+++ b/src/cmd/rc/pcmd.c
@@ -5,39 +5,66 @@ char nl='\n'; /* change to semicolon for bourne-proofing */
#define c0 t->child[0]
#define c1 t->child[1]
#define c2 t->child[2]
-void pdeglob(io *f, char *s)
+
+void
+pdeglob(io *f, char *s)
{
while(*s){
- if(*s==GLOB) s++;
+ if(*s==GLOB)
+ s++;
pchr(f, *s++);
}
}
-void pcmd(io *f, tree *t)
+
+void
+pcmd(io *f, tree *t)
{
- if(t==0) return;
+ if(t==0)
+ return;
switch(t->type){
- default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2); break;
- case '$': pfmt(f, "$%t", c0); break;
- case '"': pfmt(f, "$\"%t", c0); break;
- case '&': pfmt(f, "%t&", c0); break;
- case '^': pfmt(f, "%t^%t", c0, c1); break;
- case '`': pfmt(f, "`%t", c0); break;
- case ANDAND: pfmt(f, "%t && %t", c0, c1); break;
- case BANG: pfmt(f, "! %t", c0); break;
- case BRACE: pfmt(f, "{%t}", c0); break;
- case COUNT: pfmt(f, "$#%t", c0); break;
- case FN: pfmt(f, "fn %t %t", c0, c1); break;
- case IF: pfmt(f, "if%t%t", c0, c1); break;
- case NOT: pfmt(f, "if not %t", c0); break;
- case OROR: pfmt(f, "%t || %t", c0, c1); break;
+ default: pfmt(f, "bad %d %p %p %p", t->type, c0, c1, c2);
+ break;
+ case '$': pfmt(f, "$%t", c0);
+ break;
+ case '"': pfmt(f, "$\"%t", c0);
+ break;
+ case '&': pfmt(f, "%t&", c0);
+ break;
+ case '^': pfmt(f, "%t^%t", c0, c1);
+ break;
+ case '`': pfmt(f, "`%t", c0);
+ break;
+ case ANDAND: pfmt(f, "%t && %t", c0, c1);
+ break;
+ case BANG: pfmt(f, "! %t", c0);
+ break;
+ case BRACE: pfmt(f, "{%t}", c0);
+ break;
+ case COUNT: pfmt(f, "$#%t", c0);
+ break;
+ case FN: pfmt(f, "fn %t %t", c0, c1);
+ break;
+ case IF: pfmt(f, "if%t%t", c0, c1);
+ break;
+ case NOT: pfmt(f, "if not %t", c0);
+ break;
+ case OROR: pfmt(f, "%t || %t", c0, c1);
+ break;
case PCMD:
- case PAREN: pfmt(f, "(%t)", c0); break;
- case SUB: pfmt(f, "$%t(%t)", c0, c1); break;
- case SIMPLE: pfmt(f, "%t", c0); break;
- case SUBSHELL: pfmt(f, "@ %t", c0); break;
- case SWITCH: pfmt(f, "switch %t %t", c0, c1); break;
- case TWIDDLE: pfmt(f, "~ %t %t", c0, c1); break;
- case WHILE: pfmt(f, "while %t%t", c0, c1); break;
+ case PAREN: pfmt(f, "(%t)", c0);
+ break;
+ case SUB: pfmt(f, "$%t(%t)", c0, c1);
+ break;
+ case SIMPLE: pfmt(f, "%t", c0);
+ break;
+ case SUBSHELL: pfmt(f, "@ %t", c0);
+ break;
+ case SWITCH: pfmt(f, "switch %t %t", c0, c1);
+ break;
+ case TWIDDLE: pfmt(f, "~ %t %t", c0, c1);
+ break;
+ case WHILE: pfmt(f, "while %t%t", c0, c1);
+ break;
case ARGLIST:
if(c0==0)
pfmt(f, "%t", c1);
@@ -48,22 +75,26 @@ void pcmd(io *f, tree *t)
break;
case ';':
if(c0){
- if(c1) pfmt(f, "%t%c%t", c0, nl, c1);
+ if(c1)
+ pfmt(f, "%t%c%t", c0, nl, c1);
else pfmt(f, "%t", c0);
}
else pfmt(f, "%t", c1);
break;
case WORDS:
- if(c0) pfmt(f, "%t ", c0);
+ if(c0)
+ pfmt(f, "%t ", c0);
pfmt(f, "%t", c1);
break;
case FOR:
pfmt(f, "for(%t", c0);
- if(c1) pfmt(f, " in %t", c1);
+ if(c1)
+ pfmt(f, " in %t", c1);
pfmt(f, ")%t", c2);
break;
case WORD:
- if(t->quoted) pfmt(f, "%Q", t->str);
+ if(t->quoted)
+ pfmt(f, "%Q", t->str);
else pdeglob(f, t->str);
break;
case DUP:
@@ -79,27 +110,35 @@ void pcmd(io *f, tree *t)
case HERE:
pchr(f, '<');
case READ:
+ case RDWR:
pchr(f, '<');
- if(t->fd0!=0) pfmt(f, "[%d]", t->fd0);
+ if(t->rtype==RDWR)
+ pchr(f, '>');
+ if(t->fd0!=0)
+ pfmt(f, "[%d]", t->fd0);
break;
case APPEND:
pchr(f, '>');
case WRITE:
pchr(f, '>');
- if(t->fd0!=1) pfmt(f, "[%d]", t->fd0);
+ if(t->fd0!=1)
+ pfmt(f, "[%d]", t->fd0);
break;
}
pfmt(f, "%t", c0);
- if(c1) pfmt(f, " %t", c1);
+ if(c1)
+ pfmt(f, " %t", c1);
break;
case '=':
pfmt(f, "%t=%t", c0, c1);
- if(c2) pfmt(f, " %t", c2);
+ if(c2)
+ pfmt(f, " %t", c2);
break;
case PIPE:
pfmt(f, "%t|", c0);
if(t->fd1==0){
- if(t->fd0!=1) pfmt(f, "[%d]", t->fd0);
+ if(t->fd0!=1)
+ pfmt(f, "[%d]", t->fd0);
}
else pfmt(f, "[%d=%d]", t->fd0, t->fd1);
pfmt(f, "%t", c1);
diff --git a/src/cmd/rc/pfnc.c b/src/cmd/rc/pfnc.c
index a4606e7c..3f2b4c98 100644
--- a/src/cmd/rc/pfnc.c
+++ b/src/cmd/rc/pfnc.c
@@ -5,7 +5,7 @@
struct{
void (*f)(void);
char *name;
-}fname[]={
+}fname[] = {
Xappend, "Xappend",
Xasync, "Xasync",
Xbang, "Xbang",
@@ -18,6 +18,7 @@ struct{
Xjump, "Xjump",
Xmark, "Xmark",
Xpopm, "Xpopm",
+ Xrdwr, "Xrdwr",
Xread, "Xread",
Xreturn, "Xreturn",
Xtrue, "Xtrue",
@@ -50,18 +51,21 @@ struct{
Xrdfn, "Xrdfn",
Xqdol, "Xqdol",
0};
-void pfnc(io *fd, thread *t)
+
+void
+pfnc(io *fd, thread *t)
{
int i;
- void (*fn)(void)=t->code[t->pc].f;
+ void (*fn)(void) = t->code[t->pc].f;
list *a;
pfmt(fd, "pid %d cycle %p %d ", getpid(), t->code, t->pc);
- for(i=0;fname[i].f;i++) if(fname[i].f==fn){
+ for(i = 0;fname[i].f;i++) if(fname[i].f==fn){
pstr(fd, fname[i].name);
break;
}
- if(!fname[i].f) pfmt(fd, "%p", fn);
- for(a=t->argv;a;a=a->next) pfmt(fd, " (%v)", a->words);
+ if(!fname[i].f)
+ pfmt(fd, "%p", fn);
+ for(a = t->argv;a;a = a->next) pfmt(fd, " (%v)", a->words);
pchr(fd, '\n');
flush(fd);
}
diff --git a/src/cmd/rc/plan9ish.c b/src/cmd/rc/plan9ish.c
index 4e1ab7c0..1e896536 100644
--- a/src/cmd/rc/plan9ish.c
+++ b/src/cmd/rc/plan9ish.c
@@ -411,9 +411,11 @@ int Opendir(char *name)
close(f);
return -1;
}
-int Readdir(int f, char *p)
+int Readdir(int f, char *p, int onlydirs)
{
int n;
+ USED(onlydirs); /* only advisory */
+
if(f<0 || f>=NFD)
return 0;
if(dir[f].i==dir[f].n){ /* read */
diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h
index 3e79617d..f95b5287 100644
--- a/src/cmd/rc/rc.h
+++ b/src/cmd/rc/rc.h
@@ -80,6 +80,7 @@ char tok[NTOK];
#define HERE 4
#define DUPFD 5
#define CLOSE 6
+#define RDWR 7
struct var{
char *name; /* ascii name */
word *val; /* value */
diff --git a/src/cmd/rc/simple.c b/src/cmd/rc/simple.c
index 154678f6..15814c5c 100644
--- a/src/cmd/rc/simple.c
+++ b/src/cmd/rc/simple.c
@@ -15,22 +15,24 @@ exitnext(void){
while(c->f==Xpopredir) c++;
return c->f==Xexit;
}
-void Xsimple(void){
+
+void
+Xsimple(void)
+{
word *a;
- thread *p=runq;
+ thread *p = runq;
var *v;
struct builtin *bp;
- int pid, n;
- char buf[ERRMAX];
+ int pid;
globlist();
- a=runq->argv->words;
+ a = runq->argv->words;
if(a==0){
Xerror1("empty argument list");
return;
}
if(flag['x'])
pfmt(err, "%v\n", p->argv->words); /* wrong, should do redirs */
- v=gvlook(a->word);
+ v = gvlook(a->word);
if(v->fn)
execfunc(v);
else{
@@ -41,10 +43,10 @@ void Xsimple(void){
poplist();
return;
}
- a=a->next;
+ a = a->next;
popword();
}
- for(bp=Builtin;bp->name;bp++)
+ for(bp = Builtin;bp->name;bp++)
if(strcmp(a->word, bp->name)==0){
(*bp->fnc)();
return;
@@ -58,30 +60,22 @@ void Xsimple(void){
else{
flush(err);
Updenv(); /* necessary so changes don't go out again */
- switch(pid=fork()){
- case -1:
+ if((pid = execforkexec()) < 0){
Xerror("try again");
return;
- case 0:
- pushword("exec");
- execexec();
- strcpy(buf, "can't exec: ");
- n = strlen(buf);
- errstr(buf+n, ERRMAX-n);
- Exit(buf);
- default:
- kidpid = pid;
- poplist();
- /* interrupts don't get us out */
- while(Waitfor(pid, 1) < 0)
- ;
- kidpid = 0;
}
+
+ /* interrupts don't get us out */
+ poplist();
+ while(Waitfor(pid, 1) < 0)
+ ;
}
}
}
-struct word nullpath={ "", 0};
-void doredir(redir *rp)
+struct word nullpath = { "", 0};
+
+void
+doredir(redir *rp)
{
if(rp){
doredir(rp->next);
@@ -92,22 +86,32 @@ void doredir(redir *rp)
close(rp->from);
}
break;
- case RDUP: Dup(rp->from, rp->to); break;
- case RCLOSE: close(rp->from); break;
+ case RDUP:
+ Dup(rp->from, rp->to);
+ break;
+ case RCLOSE:
+ close(rp->from);
+ break;
}
}
}
-word *searchpath(char *w){
+
+word*
+searchpath(char *w)
+{
word *path;
if(strncmp(w, "/", 1)==0
/* || strncmp(w, "#", 1)==0 */
|| strncmp(w, "./", 2)==0
|| strncmp(w, "../", 3)==0
- || (path=vlook("path")->val)==0)
+ || (path = vlook("path")->val)==0)
path=&nullpath;
return path;
}
-void execexec(void){
+
+void
+execexec(void)
+{
popword(); /* "exec" */
if(runq->argv->words==0){
Xerror1("empty argument list");
@@ -117,19 +121,24 @@ void execexec(void){
Execute(runq->argv->words, searchpath(runq->argv->words->word));
poplist();
}
-void execfunc(var *func)
+
+void
+execfunc(var *func)
{
word *starval;
popword();
- starval=runq->argv->words;
- runq->argv->words=0;
+ starval = runq->argv->words;
+ runq->argv->words = 0;
poplist();
start(func->fn, func->pc, (struct var *)0);
- runq->local=newvar(strdup("*"), runq->local);
- runq->local->val=starval;
- runq->local->changed=1;
+ runq->local = newvar(strdup("*"), runq->local);
+ runq->local->val = starval;
+ runq->local->changed = 1;
}
-int dochdir(char *word){
+
+int
+dochdir(char *word)
+{
/* report to /dev/wdir if it exists and we're interactive */
static int wdirfd = -2;
if(chdir(word)<0) return -1;
@@ -141,21 +150,26 @@ int dochdir(char *word){
}
return 1;
}
-void execcd(void){
- word *a=runq->argv->words;
+
+void
+execcd(void)
+{
+ word *a = runq->argv->words;
word *cdpath;
char dir[512];
setstatus("can't cd");
- cdpath=vlook("cdpath")->val;
+ cdpath = vlook("cdpath")->val;
switch(count(a)){
default:
pfmt(err, "Usage: cd [directory]\n");
break;
case 2:
- if(a->next->word[0]=='/' || cdpath==0) cdpath=&nullpath;
- for(;cdpath;cdpath=cdpath->next){
+ if(a->next->word[0]=='/' || cdpath==0)
+ cdpath=&nullpath;
+ for(;cdpath;cdpath = cdpath->next){
strcpy(dir, cdpath->word);
- if(dir[0]) strcat(dir, "/");
+ if(dir[0])
+ strcat(dir, "/");
strcat(dir, a->next->word);
if(dochdir(dir)>=0){
if(strlen(cdpath->word)
@@ -165,10 +179,11 @@ void execcd(void){
break;
}
}
- if(cdpath==0) pfmt(err, "Can't cd %s: %r\n", a->next->word);
+ if(cdpath==0)
+ pfmt(err, "Can't cd %s: %r\n", a->next->word);
break;
case 1:
- a=vlook("HOME")->val;
+ a = vlook("home")->val;
if(count(a)>=1){
if(dochdir(a->word)>=0)
setstatus("");
@@ -181,14 +196,22 @@ void execcd(void){
}
poplist();
}
-void execexit(void){
+
+void
+execexit(void)
+{
switch(count(runq->argv->words)){
- default: pfmt(err, "Usage: exit [status]\nExiting anyway\n");
- case 2: setstatus(runq->argv->words->next->word);
+ default:
+ pfmt(err, "Usage: exit [status]\nExiting anyway\n");
+ case 2:
+ setstatus(runq->argv->words->next->word);
case 1: Xexit();
}
}
-void execshift(void){
+
+void
+execshift(void)
+{
int n;
word *a;
var *star;
@@ -198,72 +221,87 @@ void execshift(void){
setstatus("shift usage");
poplist();
return;
- case 2: n=atoi(runq->argv->words->next->word); break;
- case 1: n=1; break;
+ case 2:
+ n = atoi(runq->argv->words->next->word);
+ break;
+ case 1:
+ n = 1;
+ break;
}
- star=vlook("*");
+ star = vlook("*");
for(;n && star->val;--n){
- a=star->val->next;
+ a = star->val->next;
efree(star->val->word);
efree((char *)star->val);
- star->val=a;
- star->changed=1;
+ star->val = a;
+ star->changed = 1;
}
setstatus("");
poplist();
}
-int octal(char *s)
+
+int
+octal(char *s)
{
- int n=0;
+ int n = 0;
while(*s==' ' || *s=='\t' || *s=='\n') s++;
- while('0'<=*s && *s<='7') n=n*8+*s++-'0';
+ while('0'<=*s && *s<='7') n = n*8+*s++-'0';
return n;
}
-int mapfd(int fd)
+
+int
+mapfd(int fd)
{
redir *rp;
- for(rp=runq->redir;rp;rp=rp->next){
+ for(rp = runq->redir;rp;rp = rp->next){
switch(rp->type){
case RCLOSE:
- if(rp->from==fd) fd=-1;
+ if(rp->from==fd)
+ fd=-1;
break;
case RDUP:
case ROPEN:
- if(rp->to==fd) fd=rp->from;
+ if(rp->to==fd)
+ fd = rp->from;
break;
}
}
return fd;
}
union code rdcmds[4];
-void execcmds(io *f)
+
+void
+execcmds(io *f)
{
- static int first=1;
+ static int first = 1;
if(first){
- rdcmds[0].i=1;
- rdcmds[1].f=Xrdcmds;
- rdcmds[2].f=Xreturn;
- first=0;
+ rdcmds[0].i = 1;
+ rdcmds[1].f = Xrdcmds;
+ rdcmds[2].f = Xreturn;
+ first = 0;
}
start(rdcmds, 1, runq->local);
- runq->cmdfd=f;
- runq->iflast=0;
+ runq->cmdfd = f;
+ runq->iflast = 0;
}
-void execeval(void){
+
+void
+execeval(void)
+{
char *cmdline, *s, *t;
- int len=0;
+ int len = 0;
word *ap;
if(count(runq->argv->words)<=1){
Xerror1("Usage: eval cmd ...");
return;
}
- eflagok=1;
- for(ap=runq->argv->words->next;ap;ap=ap->next)
+ eflagok = 1;
+ for(ap = runq->argv->words->next;ap;ap = ap->next)
len+=1+strlen(ap->word);
- cmdline=emalloc(len);
- s=cmdline;
- for(ap=runq->argv->words->next;ap;ap=ap->next){
- for(t=ap->word;*t;) *s++=*t++;
+ cmdline = emalloc(len);
+ s = cmdline;
+ for(ap = runq->argv->words->next;ap;ap = ap->next){
+ for(t = ap->word;*t;) *s++=*t++;
*s++=' ';
}
s[-1]='\n';
@@ -272,36 +310,39 @@ void execeval(void){
efree(cmdline);
}
union code dotcmds[14];
-void execdot(void){
- int iflag=0;
+
+void
+execdot(void)
+{
+ int iflag = 0;
int fd;
list *av;
- thread *p=runq;
+ thread *p = runq;
char *zero;
- static int first=1;
+ static int first = 1;
char file[512];
word *path;
if(first){
- dotcmds[0].i=1;
- dotcmds[1].f=Xmark;
- dotcmds[2].f=Xword;
+ dotcmds[0].i = 1;
+ dotcmds[1].f = Xmark;
+ dotcmds[2].f = Xword;
dotcmds[3].s="0";
- dotcmds[4].f=Xlocal;
- dotcmds[5].f=Xmark;
- dotcmds[6].f=Xword;
+ dotcmds[4].f = Xlocal;
+ dotcmds[5].f = Xmark;
+ dotcmds[6].f = Xword;
dotcmds[7].s="*";
- dotcmds[8].f=Xlocal;
- dotcmds[9].f=Xrdcmds;
- dotcmds[10].f=Xunlocal;
- dotcmds[11].f=Xunlocal;
- dotcmds[12].f=Xreturn;
- first=0;
+ dotcmds[8].f = Xlocal;
+ dotcmds[9].f = Xrdcmds;
+ dotcmds[10].f = Xunlocal;
+ dotcmds[11].f = Xunlocal;
+ dotcmds[12].f = Xreturn;
+ first = 0;
}
else
- eflagok=1;
+ eflagok = 1;
popword();
if(p->argv->words && strcmp(p->argv->words->word, "-i")==0){
- iflag=1;
+ iflag = 1;
popword();
}
/* get input file */
@@ -309,18 +350,20 @@ void execdot(void){
Xerror1("Usage: . [-i] file [arg ...]");
return;
}
- zero=strdup(p->argv->words->word);
+ zero = strdup(p->argv->words->word);
popword();
fd=-1;
- for(path=searchpath(zero);path;path=path->next){
+ for(path = searchpath(zero);path;path = path->next){
strcpy(file, path->word);
- if(file[0]) strcat(file, "/");
+ if(file[0])
+ strcat(file, "/");
strcat(file, zero);
+ if((fd = open(file, 0))>=0) break;
if(strcmp(file, "/dev/stdin")==0){ /* for sun & ucb */
- fd=Dup1(0);
- if(fd>=0) break;
+ fd = Dup1(0);
+ if(fd>=0)
+ break;
}
- if((fd=open(file, 0))>=0) break;
}
if(fd<0){
pfmt(err, "%s: ", zero);
@@ -331,38 +374,41 @@ void execdot(void){
/* set up for a new command loop */
start(dotcmds, 1, (struct var *)0);
pushredir(RCLOSE, fd, 0);
- runq->cmdfile=zero;
- runq->cmdfd=openfd(fd);
- runq->iflag=iflag;
- runq->iflast=0;
+ runq->cmdfile = zero;
+ runq->cmdfd = openfd(fd);
+ runq->iflag = iflag;
+ runq->iflast = 0;
/* push $* value */
pushlist();
- runq->argv->words=p->argv->words;
+ runq->argv->words = p->argv->words;
/* free caller's copy of $* */
- av=p->argv;
- p->argv=av->next;
+ av = p->argv;
+ p->argv = av->next;
efree((char *)av);
/* push $0 value */
pushlist();
pushword(zero);
ndot++;
}
-void execflag(void){
+
+void
+execflag(void)
+{
char *letter, *val;
switch(count(runq->argv->words)){
case 2:
setstatus(flag[(uchar)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;
+ 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[(uchar)letter[0]] = flagset;
break;
}
if(strcmp(val, "-")==0){
- flag[(uchar)letter[0]]=0;
+ flag[(uchar)letter[0]] = 0;
break;
}
}
@@ -372,53 +418,57 @@ void execflag(void){
}
poplist();
}
-void execwhatis(void){ /* mildly wrong -- should fork before writing */
+
+void
+execwhatis(void){ /* mildly wrong -- should fork before writing */
word *a, *b, *path;
var *v;
struct builtin *bp;
char file[512];
struct io out[1];
int found, sep;
- a=runq->argv->words->next;
+ a = runq->argv->words->next;
if(a==0){
Xerror1("Usage: whatis name ...");
return;
}
setstatus("");
- out->fd=mapfd(1);
- out->bufp=out->buf;
- out->ebuf=&out->buf[NBUF];
- out->strp=0;
- for(;a;a=a->next){
- v=vlook(a->word);
+ out->fd = mapfd(1);
+ out->bufp = out->buf;
+ out->ebuf = &out->buf[NBUF];
+ out->strp = 0;
+ for(;a;a = a->next){
+ v = vlook(a->word);
if(v->val){
pfmt(out, "%s=", a->word);
if(v->val->next==0)
pfmt(out, "%q\n", v->val->word);
else{
sep='(';
- for(b=v->val;b && b->word;b=b->next){
+ for(b = v->val;b && b->word;b = b->next){
pfmt(out, "%c%q", sep, b->word);
sep=' ';
}
pfmt(out, ")\n");
}
- found=1;
+ found = 1;
}
else
- found=0;
- v=gvlook(a->word);
- if(v->fn) pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
+ found = 0;
+ v = gvlook(a->word);
+ if(v->fn)
+ pfmt(out, "fn %s %s\n", v->name, v->fn[v->pc-1].s);
else{
- for(bp=Builtin;bp->name;bp++)
+ for(bp = Builtin;bp->name;bp++)
if(strcmp(a->word, bp->name)==0){
pfmt(out, "builtin %s\n", a->word);
break;
}
if(!bp->name){
- for(path=searchpath(a->word);path;path=path->next){
+ for(path = searchpath(a->word);path;path = path->next){
strcpy(file, path->word);
- if(file[0]) strcat(file, "/");
+ if(file[0])
+ strcat(file, "/");
strcat(file, a->word);
if(Executable(file)){
pfmt(out, "%s\n", file);
@@ -435,11 +485,20 @@ void execwhatis(void){ /* mildly wrong -- should fork before writing */
poplist();
flush(err);
}
-void execwait(void){
+
+void
+execwait(void)
+{
switch(count(runq->argv->words)){
- default: Xerror1("Usage: wait [pid]"); return;
- case 2: Waitfor(atoi(runq->argv->words->next->word), 0); break;
- case 1: Waitfor(-1, 0); break;
+ default:
+ Xerror1("Usage: wait [pid]");
+ return;
+ case 2:
+ Waitfor(atoi(runq->argv->words->next->word), 0);
+ break;
+ case 1:
+ Waitfor(-1, 0);
+ break;
}
poplist();
}
diff --git a/src/cmd/rc/subr.c b/src/cmd/rc/subr.c
index 06a22b26..a6b533b3 100644
--- a/src/cmd/rc/subr.c
+++ b/src/cmd/rc/subr.c
@@ -2,20 +2,29 @@
#include "exec.h"
#include "io.h"
#include "fns.h"
-char *emalloc(long n){
- char *p=(char *)Malloc(n);
- if(p==0) panic("Can't malloc %d bytes", n);
-/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } */
+
+char*
+emalloc(long n)
+{
+ char *p = (char *)Malloc(n);
+ if(p==0)
+ panic("Can't malloc %d bytes", n);
+/* if(err){ pfmt(err, "malloc %d->%p\n", n, p); flush(err); } /**/
return p;
}
-void efree(char *p)
+
+void
+efree(char *p)
{
-/* pfmt(err, "free %p\n", p); flush(err); */
- if(p) free(p);
+/* pfmt(err, "free %p\n", p); flush(err); /**/
+ if(p)
+ free(p);
else pfmt(err, "free 0\n");
}
extern int lastword, lastdol;
-void yyerror(char *m)
+
+void
+yyerror(char *m)
{
pfmt(err, "rc: ");
if(runq->cmdfile && !runq->iflag)
@@ -24,17 +33,21 @@ void yyerror(char *m)
pfmt(err, "%s: ", runq->cmdfile);
else if(!runq->iflag)
pfmt(err, "line %d: ", runq->lineno);
- if(tok[0] && tok[0]!='\n') pfmt(err, "token %q: ", tok);
+ if(tok[0] && tok[0]!='\n')
+ pfmt(err, "token %q: ", tok);
pfmt(err, "%s\n", m);
flush(err);
- lastword=0;
- lastdol=0;
+ lastword = 0;
+ lastdol = 0;
while(lastc!='\n' && lastc!=EOF) advance();
nerror++;
setvar("status", newword(m, (word *)0));
}
char *bp;
-void iacvt(int n){
+
+static void
+iacvt(int n)
+{
if(n<0){
*bp++='-';
n=-n; /* doesn't work for n==-inf */
@@ -43,13 +56,17 @@ void iacvt(int n){
iacvt(n/10);
*bp++=n%10+'0';
}
-void itoa(char *s, long n)
+
+void
+inttoascii(char *s, long n)
{
- bp=s;
+ bp = s;
iacvt(n);
*bp='\0';
}
-void panic(char *s, int n)
+
+void
+panic(char *s, int n)
{
pfmt(err, "rc: ");
pfmt(err, s, n);
diff --git a/src/cmd/rc/syn.y b/src/cmd/rc/syn.y
index 5123ce4a..c7de3531 100644
--- a/src/cmd/rc/syn.y
+++ b/src/cmd/rc/syn.y
@@ -2,7 +2,6 @@
%term WORD REDIR DUP PIPE SUB
%term SIMPLE ARGLIST WORDS BRACE PAREN PCMD PIPEFD /* not used in syntax */
/* operator priorities -- lowest first */
-%left LOW
%left IF WHILE FOR SWITCH ')' NOT
%left ANDAND OROR
%left BANG SUBSHELL
@@ -10,7 +9,6 @@
%left '^'
%right '$' COUNT '"'
%left SUB
-%left '='
%{
#include "rc.h"
#include "fns.h"
@@ -80,7 +78,6 @@ first: comword
word: keyword {lastword=1; $1->type=WORD;}
| comword
| word '^' word {$$=tree2('^', $1, $3);}
-| word '=' word %prec LOW {$$=tree2('^', tree2('^', $1, token("=", WORD)), $3);}
comword: '$' word {$$=tree1('$', $2);}
| '$' word SUB words ')' {$$=tree2(SUB, $2, $4);}
| '"' word {$$=tree1('"', $2);}
diff --git a/src/cmd/rc/trap.c b/src/cmd/rc/trap.c
index 96ef364a..a572cac3 100644
--- a/src/cmd/rc/trap.c
+++ b/src/cmd/rc/trap.c
@@ -3,22 +3,25 @@
#include "fns.h"
#include "io.h"
extern char *Signame[];
-void dotrap(void){
- register int i;
- register struct var *trapreq;
- register struct word *starval;
- starval=vlook("*")->val;
- while(ntrap) for(i=0;i!=NSIG;i++) while(trap[i]){
+
+void
+dotrap(void)
+{
+ int i;
+ struct var *trapreq;
+ struct word *starval;
+ starval = vlook("*")->val;
+ while(ntrap) for(i = 0;i!=NSIG;i++) while(trap[i]){
--trap[i];
--ntrap;
if(getpid()!=mypid) Exit(getstatus());
- trapreq=vlook(Signame[i]);
+ trapreq = vlook(Signame[i]);
if(trapreq->fn){
start(trapreq->fn, trapreq->pc, (struct var *)0);
- runq->local=newvar(strdup("*"), runq->local);
- runq->local->val=copywords(starval, (struct word *)0);
- runq->local->changed=1;
- runq->redir=runq->startredir=0;
+ runq->local = newvar(strdup("*"), runq->local);
+ runq->local->val = copywords(starval, (struct word *)0);
+ runq->local->changed = 1;
+ runq->redir = runq->startredir = 0;
}
else if(i==SIGINT || i==SIGQUIT){
/*
diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c
index 9bf76d8e..897597e2 100644
--- a/src/cmd/rc/tree.c
+++ b/src/cmd/rc/tree.c
@@ -7,108 +7,140 @@ tree *treenodes;
* create and clear a new tree node, and add it
* to the node list.
*/
-tree *newtree(void){
- tree *t=new(tree);
- t->iskw=0;
- t->str=0;
- t->child[0]=t->child[1]=t->child[2]=0;
- t->next=treenodes;
- treenodes=t;
+
+tree*
+newtree(void)
+{
+ tree *t = new(tree);
+ t->iskw = 0;
+ t->str = 0;
+ t->child[0] = t->child[1] = t->child[2] = 0;
+ t->next = treenodes;
+ treenodes = t;
return t;
}
-void freenodes(void){
+
+void
+freenodes(void)
+{
tree *t, *u;
- for(t=treenodes;t;t=u){
- u=t->next;
- if(t->str) efree(t->str);
+ for(t = treenodes;t;t = u){
+ u = t->next;
+ if(t->str)
+ efree(t->str);
efree((char *)t);
}
- treenodes=0;
+ treenodes = 0;
}
-tree *tree1(int type, tree *c0)
+
+tree*
+tree1(int type, tree *c0)
{
return tree3(type, c0, (tree *)0, (tree *)0);
}
-tree *tree2(int type, tree *c0, tree *c1)
+
+tree*
+tree2(int type, tree *c0, tree *c1)
{
return tree3(type, c0, c1, (tree *)0);
}
-tree *tree3(int type, tree *c0, tree *c1, tree *c2)
+
+tree*
+tree3(int type, tree *c0, tree *c1, tree *c2)
{
tree *t;
if(type==';'){
- if(c0==0) return c1;
- if(c1==0) return c0;
+ if(c0==0)
+ return c1;
+ if(c1==0)
+ return c0;
}
- t=newtree();
- t->type=type;
- t->child[0]=c0;
- t->child[1]=c1;
- t->child[2]=c2;
+ t = newtree();
+ t->type = type;
+ t->child[0] = c0;
+ t->child[1] = c1;
+ t->child[2] = c2;
return t;
}
-tree *mung1(tree *t, tree *c0)
+
+tree*
+mung1(tree *t, tree *c0)
{
- t->child[0]=c0;
+ t->child[0] = c0;
return t;
}
-tree *mung2(tree *t, tree *c0, tree *c1)
+
+tree*
+mung2(tree *t, tree *c0, tree *c1)
{
- t->child[0]=c0;
- t->child[1]=c1;
+ t->child[0] = c0;
+ t->child[1] = c1;
return t;
}
-tree *mung3(tree *t, tree *c0, tree *c1, tree *c2)
+
+tree*
+mung3(tree *t, tree *c0, tree *c1, tree *c2)
{
- t->child[0]=c0;
- t->child[1]=c1;
- t->child[2]=c2;
+ t->child[0] = c0;
+ t->child[1] = c1;
+ t->child[2] = c2;
return t;
}
-tree *epimung(tree *comp, tree *epi)
+
+tree*
+epimung(tree *comp, tree *epi)
{
tree *p;
- if(epi==0) return comp;
- for(p=epi;p->child[1];p=p->child[1]);
- p->child[1]=comp;
+ if(epi==0)
+ return comp;
+ for(p = epi;p->child[1];p = p->child[1]);
+ p->child[1] = comp;
return epi;
}
/*
* Add a SIMPLE node at the root of t and percolate all the redirections
* up to the root.
*/
-tree *simplemung(tree *t)
+
+tree*
+simplemung(tree *t)
{
tree *u;
struct io *s;
- t=tree1(SIMPLE, t);
- s=openstr();
+ t = tree1(SIMPLE, t);
+ s = openstr();
pfmt(s, "%t", t);
- t->str=strdup(s->strp);
+ t->str = strdup(s->strp);
closeio(s);
- for(u=t->child[0];u->type==ARGLIST;u=u->child[0]){
+ for(u = t->child[0];u->type==ARGLIST;u = u->child[0]){
if(u->child[1]->type==DUP
|| u->child[1]->type==REDIR){
- u->child[1]->child[1]=t;
- t=u->child[1];
- u->child[1]=0;
+ u->child[1]->child[1] = t;
+ t = u->child[1];
+ u->child[1] = 0;
}
}
return t;
}
-tree *token(char *str, int type)
+
+tree*
+token(char *str, int type)
{
- tree *t=newtree();
- t->type=type;
- t->str=strdup(str);
+ tree *t = newtree();
+ t->type = type;
+ t->str = strdup(str);
return t;
}
-void freetree(tree *p)
+
+void
+freetree(tree *p)
{
- if(p==0) return;
+ if(p==0)
+ return;
freetree(p->child[0]);
freetree(p->child[1]);
freetree(p->child[2]);
- if(p->str) efree(p->str);
+ if(p->str)
+ efree(p->str);
efree((char *)p);
}
diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c
index 8a200ffd..2564ba2f 100644
--- a/src/cmd/rc/var.c
+++ b/src/cmd/rc/var.c
@@ -1,9 +1,11 @@
#include "rc.h"
#include "exec.h"
#include "fns.h"
-int hash(char *s, int n)
+
+int
+hash(char *s, int n)
{
- register int h=0, i=1;
+ int h = 0, i = 1;
while(*s) h+=*s++*i++;
h%=n;
return h<0?h+n:h;
@@ -14,16 +16,21 @@ struct kw{
int type;
struct kw *next;
}*kw[NKW];
-void kenter(int type, char *name)
+
+void
+kenter(int type, char *name)
{
- register int h=hash(name, NKW);
- register struct kw *p=new(struct kw);
- p->type=type;
- p->name=name;
- p->next=kw[h];
- kw[h]=p;
+ int h = hash(name, NKW);
+ struct kw *p = new(struct kw);
+ p->type = type;
+ p->name = name;
+ p->next = kw[h];
+ kw[h] = p;
}
-void kinit(void){
+
+void
+kinit(void)
+{
kenter(FOR, "for");
kenter(IN, "in");
kenter(WHILE, "while");
@@ -35,47 +42,59 @@ void kinit(void){
kenter(SWITCH, "switch");
kenter(FN, "fn");
}
-tree *klook(char *name)
+
+tree*
+klook(char *name)
{
struct kw *p;
- tree *t=token(name, WORD);
- for(p=kw[hash(name, NKW)];p;p=p->next)
+ tree *t = token(name, WORD);
+ for(p = kw[hash(name, NKW)];p;p = p->next)
if(strcmp(p->name, name)==0){
- t->type=p->type;
- t->iskw=1;
+ t->type = p->type;
+ t->iskw = 1;
break;
}
return t;
}
-var *gvlook(char *name)
+
+var*
+gvlook(char *name)
{
- int h=hash(name, NVAR);
+ int h = hash(name, NVAR);
var *v;
- for(v=gvar[h];v;v=v->next) if(strcmp(v->name, name)==0) return v;
- return gvar[h]=newvar(strdup(name), gvar[h]);
+ for(v = gvar[h];v;v = v->next) if(strcmp(v->name, name)==0) return v;
+ return gvar[h] = newvar(strdup(name), gvar[h]);
}
-var *vlook(char *name)
+
+var*
+vlook(char *name)
{
var *v;
if(runq)
- for(v=runq->local;v;v=v->next)
+ for(v = runq->local;v;v = v->next)
if(strcmp(v->name, name)==0) return v;
return gvlook(name);
}
-void _setvar(char *name, word *val, int callfn)
+
+void
+_setvar(char *name, word *val, int callfn)
{
- register struct var *v=vlook(name);
+ struct var *v = vlook(name);
freewords(v->val);
v->val=val;
v->changed=1;
if(callfn && v->changefn)
v->changefn(v);
}
-void setvar(char *name, word *val)
+
+void
+setvar(char *name, word *val)
{
_setvar(name, val, 1);
}
-void bigpath(var *v)
+
+void
+bigpath(var *v)
{
/* convert $PATH to $path */
char *p, *q;
@@ -107,19 +126,42 @@ void bigpath(var *v)
}
_setvar("path", w, 0);
}
-void littlepath(var *v)
+
+char*
+list2strcolon(word *words)
+{
+ char *value, *s, *t;
+ int len = 0;
+ word *ap;
+ for(ap = words;ap;ap = ap->next)
+ len+=1+strlen(ap->word);
+ value = emalloc(len+1);
+ s = value;
+ for(ap = words;ap;ap = ap->next){
+ for(t = ap->word;*t;) *s++=*t++;
+ *s++=':';
+ }
+ if(s==value)
+ *s='\0';
+ else s[-1]='\0';
+ return value;
+}
+void
+littlepath(var *v)
{
/* convert $path to $PATH */
char *p;
word *w;
- p = _list2str(v->val, ':');
+ p = list2strcolon(v->val);
w = new(word);
w->word = p;
w->next = nil;
_setvar("PATH", w, 1); /* 1: recompute $path to expose colon problems */
}
-void pathinit(void)
+
+void
+pathinit(void)
{
var *v;