tsync with plan 9 - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
commit c8f538425f4e92e1e438b9bd25cb08e250a93d5b | |
parent 79049567a0fac8707ea3f2927403445bdb2394fa | |
Author: rsc <devnull@localhost> | |
Date: Mon, 26 Mar 2007 12:02:41 +0000 | |
sync with plan 9 | |
Diffstat: | |
M src/cmd/rc/code.c | 223 +++++++++++++++++++----------… | |
M src/cmd/rc/exec.c | 989 ++++++++++++++++-------------… | |
M src/cmd/rc/exec.h | 10 +++++++--- | |
M src/cmd/rc/fns.h | 10 ++++++---- | |
M src/cmd/rc/getflags.c | 171 ++++++++++++++++++-----------… | |
M src/cmd/rc/glob.c | 165 +++++++++++++++++++----------… | |
M src/cmd/rc/havefork.c | 10 ---------- | |
A src/cmd/rc/havep9p.c | 246 +++++++++++++++++++++++++++++… | |
M src/cmd/rc/here.c | 97 ++++++++++++++++++-----------… | |
M src/cmd/rc/io.c | 231 +++++++++++++++++++++--------… | |
M src/cmd/rc/io.h | 6 +++--- | |
M src/cmd/rc/lex.c | 278 ++++++++++++++++++-----------… | |
M src/cmd/rc/mkfile | 1 + | |
M src/cmd/rc/pcmd.c | 107 +++++++++++++++++++++--------… | |
M src/cmd/rc/pfnc.c | 16 ++++++++++------ | |
M src/cmd/rc/plan9ish.c | 4 +++- | |
M src/cmd/rc/rc.h | 1 + | |
M src/cmd/rc/simple.c | 329 ++++++++++++++++++-----------… | |
M src/cmd/rc/subr.c | 47 +++++++++++++++++++++--------… | |
M src/cmd/rc/syn.y | 3 --- | |
M src/cmd/rc/trap.c | 25 ++++++++++++++----------- | |
M src/cmd/rc/tree.c | 132 +++++++++++++++++++----------… | |
M src/cmd/rc/var.c | 98 ++++++++++++++++++++++-------… | |
23 files changed, 1967 insertions(+), 1232 deletions(-) | |
--- | |
diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c | |
t@@ -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=… | |
-#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i=… | |
-#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s=… | |
+#define emitf(x) ((void)(codep!=ncode || morecode()), codebuf[codep].f … | |
+#define emiti(x) ((void)(codep!=ncode || morecode()), codebuf[codep].i … | |
+#define emits(x) ((void)(codep!=ncode || morecode()), codebuf[codep].s … | |
void stuffdot(int); | |
char *fnstr(tree*); | |
void outcode(tree*, int); | |
t@@ -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){ | |
t@@ -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); | |
t@@ -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); | |
t@@ -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; | |
t@@ -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 $* */ | |
t@@ -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; | |
t@@ -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); | |
t@@ -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 == whi… | |
+ if(q==codep) | |
+ emitf(Xsettrue); /* empty condition == while(tr… | |
emitf(Xtrue); | |
- p=emiti(0); | |
+ p = emiti(0); | |
outcode(c1, eflag); | |
emitf(Xjump); | |
emiti(q); | |
t@@ -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); | |
t@@ -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); | |
t@@ -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); | |
t@@ -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); | |
t@@ -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: | |
t@@ -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 */ | |
t@@ -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, efla… | |
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); | |
t@@ -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 | |
t@@ -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" | |
t@@ -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; | |
} | |
/* | |
t@@ -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(); | |
} | |
} | |
/* | |
t@@ -197,6 +223,7 @@ main(int argc, char *argv[]) | |
* Xpipefd[type]{... Xreturn} connect {} to pipe (input or outp… | |
* 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 | |
t@@ -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; | |
t@@ -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; | |
t@@ -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; | |
t@@ -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; | |
t@@ -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; | |
} | |
} | |
t@@ -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->ne… | |
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"); | |
t@@ -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; | |
t@@ -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; | |
t@@ -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); | |
} | |
t@@ -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; | |
t@@ -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]='|'; | |
t@@ -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())); | |
t@@ -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 */ | |
} | |
t@@ -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); | |
t@@ -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); | |
t@@ -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 | |
t@@ -5,6 +5,7 @@ extern void Xappend(void), Xasync(void), Xbackq(void), Xbang(v… | |
extern void Xconc(void), Xcount(void), Xdelfn(void), Xdol(void), Xqdol(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… | |
extern void Xtrue(void), Xword(void), Xwrite(void), Xpipefd(void), Xcase(void); | |
extern void Xlocal(void), Xunlocal(void), Xassign(void), Xsimple(void), Xpopm(… | |
t@@ -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 th… | |
char status[NSTATUS]; /* status for Xpipewait */ | |
tree *treenodes; /* tree nodes created by this process … | |
thread *ret; /* who continues when this finishes */ | |
t@@ -61,12 +61,16 @@ code *codecopy(code*); | |
code *codebuf; /* compiler output */ | |
int ntrap; /* number of outstanding traps */ | |
int trap[NSIG]; /* number of outstanding traps … | |
-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 … | |
+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 | |
t@@ -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*); | |
t@@ -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); | |
t@@ -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); | |
t@@ -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 | |
t@@ -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; | |
t@@ -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… | |
+ count = 0; | |
+ while('0'<=*f && *f<='9') count = count*10+*f+… | |
+ } | |
+ else | |
+ count = 0; | |
+ if(*f=='['){ | |
+ do{ | |
+ f++; | |
+ if(*f=='\0'){ reason = FLAGSYN; return… | |
+ }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 -"); | |
t@@ -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"); | |
t@@ -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){ | |
t@@ -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 | |
t@@ -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 astac… | |
* 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); | |
} | |
} | |
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); | |
t@@ -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 strin… | |
+ 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; | |
t@@ -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; | |
t@@ -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); | |
t@@ -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; /* synta… | |
- lo=unicode(p); | |
- p=nextutf(p); | |
- if(*p!='-') hi=lo; | |
+ if(*p=='\0') | |
+ return 0; /* syntax err… | |
+ lo = unicode(p); | |
+ p = nextutf(p); | |
+ if(*p!='-') | |
+ hi = lo; | |
else{ | |
p++; | |
- if(*p=='\0') return 0; /* synta… | |
- hi=unicode(p); | |
- p=nextutf(p); | |
- if(hi<lo){ t=lo; lo=hi; hi=t; } | |
+ if(*p=='\0') | |
+ return 0; /* syntax err… | |
+ 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 | |
t@@ -1,5 +1,3 @@ | |
-#include <u.h> | |
-#include <signal.h> | |
#include "rc.h" | |
#include "getflags.h" | |
#include "exec.h" | |
t@@ -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; | |
t@@ -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 | |
t@@ -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 | |
t@@ -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); | |
} | |
/* | |
t@@ -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); | |
t@@ -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; | |
t@@ -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+*… | |
+ n = 0; | |
+ for(u = s;*u && '0'<=*u && *u<='9';u++) n = n*… | |
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 | |
t@@ -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; /*unportab… | |
- 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; | |
t@@ -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 | |
t@@ -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 | |
t@@ -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: | |
t@@ -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 com… | |
+ 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 = 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 termin… | |
-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 unq… | |
* WORD then we alter the meaning of what follows. If the next charac… | |
t@@ -146,7 +193,7 @@ int yylex(void){ | |
* we insert a `^' before it. | |
*/ | |
if(lastword){ | |
- lastword=0; | |
+ lastword = 0; | |
if(d=='('){ | |
advance(); | |
strcpy(tok, "( [SUB]"); | |
t@@ -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; | |
t@@ -177,7 +224,7 @@ int yylex(void){ | |
strcpy(tok, "$"); | |
return '$'; | |
case '&': | |
- lastdol=0; | |
+ lastdol = 0; | |
if(nextis('&')){ | |
skipnl(); | |
strcpy(tok, "&&"); | |
t@@ -186,7 +233,7 @@ int yylex(void){ | |
strcpy(tok, "&"); | |
return '&'; | |
case '|': | |
- lastdol=0; | |
+ lastdol = 0; | |
if(nextis(c)){ | |
skipnl(); | |
strcpy(tok, "||"); | |
t@@ -194,7 +241,7 @@ int yylex(void){ | |
} | |
case '<': | |
case '>': | |
- lastdol=0; | |
+ lastdol = 0; | |
/* | |
* funny redirection tokens: | |
* redir: arrow | arrow '[' fd ']' | |
t@@ -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 … | |
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 | |
t@@ -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 | |
t@@ -5,39 +5,66 @@ char nl='\n'; /* change to semicolon for bour… | |
#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); | |
t@@ -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: | |
t@@ -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 | |
t@@ -5,7 +5,7 @@ | |
struct{ | |
void (*f)(void); | |
char *name; | |
-}fname[]={ | |
+}fname[] = { | |
Xappend, "Xappend", | |
Xasync, "Xasync", | |
Xbang, "Xbang", | |
t@@ -18,6 +18,7 @@ struct{ | |
Xjump, "Xjump", | |
Xmark, "Xmark", | |
Xpopm, "Xpopm", | |
+ Xrdwr, "Xrdwr", | |
Xread, "Xread", | |
Xreturn, "Xreturn", | |
Xtrue, "Xtrue", | |
t@@ -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 | |
t@@ -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 | |
t@@ -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 | |
t@@ -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{ | |
t@@ -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; | |
t@@ -58,30 +60,22 @@ void Xsimple(void){ | |
else{ | |
flush(err); | |
Updenv(); /* necessary so changes don't go out … | |
- 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); | |
t@@ -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"); | |
t@@ -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; | |
t@@ -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) | |
t@@ -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(""); | |
t@@ -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; | |
t@@ -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'; | |
t@@ -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 */ | |
t@@ -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); | |
t@@ -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]]?"":"fl… | |
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; | |
} | |
} | |
t@@ -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->n… | |
+ for(path = searchpath(a->word);path;path = pat… | |
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); | |
t@@ -435,11 +485,20 @@ void execwhatis(void){ /* mildly wrong -- should … | |
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 | |
t@@ -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) | |
t@@ -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 */ | |
t@@ -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 | |
t@@ -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 | |
t@@ -10,7 +9,6 @@ | |
%left '^' | |
%right '$' COUNT '"' | |
%left SUB | |
-%left '=' | |
%{ | |
#include "rc.h" | |
#include "fns.h" | |
t@@ -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, … | |
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 | |
t@@ -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 | |
t@@ -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 | |
t@@ -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; | |
t@@ -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"); | |
t@@ -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; | |
t@@ -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 pr… | |
} | |
-void pathinit(void) | |
+ | |
+void | |
+pathinit(void) | |
{ | |
var *v; | |