From e923adef5df8077259ed9973a4bffb0e08999fbe Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Tue, 16 Nov 2021 14:46:55 -0800 Subject: chore: integrated redir code --- src/cmd/rc/code.c | 10 ++++- src/cmd/rc/exec.c | 112 ++++++++++++++++++++++++++++++++++++++++++---------- src/cmd/rc/exec.h | 1 + src/cmd/rc/job.c | 3 ++ src/cmd/rc/lex.c | 2 + src/cmd/rc/parse.c | 2 +- src/cmd/rc/rc.h | 1 + src/cmd/rc/syntax.y | 2 +- src/cmd/rc/sys.c | 9 +++-- src/cmd/rc/tree.c | 19 +++++++++ src/cmd/rc/var.c | 2 +- 11 files changed, 135 insertions(+), 28 deletions(-) (limited to 'src/cmd') diff --git a/src/cmd/rc/code.c b/src/cmd/rc/code.c index dd0e99c..748c964 100644 --- a/src/cmd/rc/code.c +++ b/src/cmd/rc/code.c @@ -164,7 +164,7 @@ walk(Tree *node) break; case '=': - for(n=node; node && node->type == '='; node = node->child[2]) + for(n=node; node && node->type == '='; node=node->child[2]) ; if(node){ for(node=n; node->type=='='; node = node->child[2]){ @@ -317,6 +317,14 @@ walk(Tree *node) storepc(addr1); break; + case '`': + emitf(Xsubcmd); + addr1 = emiti(0); + walk(node->child[0]); + emitf(Xexit); + storepc(addr1); + break; + case Tpipe: emitf(Xpipe); diff --git a/src/cmd/rc/exec.c b/src/cmd/rc/exec.c index 28b6135..28941a0 100644 --- a/src/cmd/rc/exec.c +++ b/src/cmd/rc/exec.c @@ -168,8 +168,7 @@ undoredirs(void) Xpopredir(); } -static inline -int +static inline int exitsnext(void) { Code *c = &runner->code.exe[runner->code.i]; @@ -191,8 +190,7 @@ defaultsignal(void) signal(SIGCHLD, SIG_DFL); } -static inline -void +static inline void setpid(Thread *job, int pid) { job->pid = pid; @@ -206,8 +204,7 @@ setpid(Thread *job, int pid) /* fork/execute helpers */ -static inline -void +static inline void initchild(Thread *job, int fg) { int pid = getpid(); @@ -224,8 +221,7 @@ initchild(Thread *job, int fg) clearwait(job); } -static inline -void +static inline void initparent(Thread *job, int pid, int fg) { setpid(job, pid); @@ -239,8 +235,7 @@ initparent(Thread *job, int pid, int fg) addwait(job, pid); } -static -void +static void xx(void) { popword(); // "exec" @@ -248,32 +243,29 @@ xx(void) Xerror("empty argument list"); return; } - + // set up file descriptors redirect(runner->redir.end); execute(runner->args->word, path(runner->args->word->str)); poplist(); } -static -int +static int xforkx(void) { int n, pid; switch(pid=fork()){ case -1: - Xerror("try again\n"); + Xerror("fork failed: try again\n"); return -1; case 0: // child initchild(runner, 1); - pushword("exec"); xx(); - - exit(2); // NOTE: unreachable: xx does not return + exit(2); // reach here on failed execs + break; default: // parent initparent(runner, pid, 0); - return pid; } } @@ -286,7 +278,7 @@ pushredir(int type, int from, int to) r->type = type; r->from = from; - r->to = to; + r->to = to; r->link = runner->redir.end, runner->redir.end = r; } @@ -1080,7 +1072,7 @@ Xjoin(void) } s = runner->args->word->str; - // deglob(s) + deglob(s); arg = var(s)->val; poplist(); @@ -1282,6 +1274,86 @@ Xsubshell(void) } } +void +Xsubcmd(void) +{ + Io *io; + rune r; + Var *ifs; + Word *w, *nw; + int n, c, pid, pfd[2]; + char *s, *end, *hit, *q, buf[8193]; + + ifs = var("ifs"); + end = arrend(buf)-1; + hit = ifs->val ? ifs->val->str : ""; + + if(pipe(pfd)<0){ + Xerror("pipe failed"); + return; + } + + switch(pid=fork()){ + case -1: + Xerror("fork failed: try again"); + close(pfd[0]), close(pfd[1]); + return; + + case 0: // child + initchild(runner, 1); + + close(pfd[0]); + run(runner->code.exe, runner->code.i+1, runner->local, 1); + pushredir(Ropen, pfd[1], 1); + break; + + default: // parent + initparent(runner, pid, 0); + close(pfd[1]); + io = openfd(pfd[0]); + + s = buf; + w = nil; + while((c=get(io))!=EOF){ + if(s != end){ + *s++ = c; + for(q=hit; *q; q+=n){ + n = utf8·decode(q, &r); + if(s-buf >= n && memcmp(s-n, q, n)==0){ + s -= n; + goto finish; + } + } + continue; + } + finish: + if(s != buf){ + *s = 0; + w = makeword(buf, w); + } + s = buf; + } + if(s != buf){ + *s = 0; + w = makeword(buf, w); + } + + waitfor(runner, pid); + terminate(io); + + /* reverse the list */ + while(w){ + nw = w->link; + w->link = runner->args->word; + runner->args->word = w; + w = nw; + } + assert(runner->wait.status == Pdone); + deljob(runner); + runner->code.i = runner->code.exe[runner->code.i].i; + } +} + void Xpipewait(void) { diff --git a/src/cmd/rc/exec.h b/src/cmd/rc/exec.h index 9db7e60..d7eee73 100644 --- a/src/cmd/rc/exec.h +++ b/src/cmd/rc/exec.h @@ -8,6 +8,7 @@ */ void Xnewpgid(void); +void Xsubcmd(void); void Xunmark(void); void Xwrite(void); void Xread(void); diff --git a/src/cmd/rc/job.c b/src/cmd/rc/job.c index 1587951..3a53365 100644 --- a/src/cmd/rc/job.c +++ b/src/cmd/rc/job.c @@ -88,4 +88,7 @@ deljob(Thread *job) ; *jp = job->link; + // XXX: I think this is mandatory hygeine + job->status = Pnil; + job->pgid = job->pid = -1; } diff --git a/src/cmd/rc/lex.c b/src/cmd/rc/lex.c index 0eb023c..a22dc7d 100644 --- a/src/cmd/rc/lex.c +++ b/src/cmd/rc/lex.c @@ -529,6 +529,8 @@ yylex(void) *w = 0; node = token(Tword, lexer.buf); node->quoted = 1; + + yylval.tree = node; return node->type; default: diff --git a/src/cmd/rc/parse.c b/src/cmd/rc/parse.c index 7ff860e..6a08f17 100644 --- a/src/cmd/rc/parse.c +++ b/src/cmd/rc/parse.c @@ -1651,7 +1651,7 @@ yyreduce: case 25: /* cmd: basic */ #line 87 "src/cmd/rc/syntax.y" - { (yyval.tree) = maketree1(Tbasic, (yyvsp[0].tree)); } + { (yyval.tree) = basictree((yyvsp[0].tree)); } #line 1656 "src/cmd/rc/parse.c" break; diff --git a/src/cmd/rc/rc.h b/src/cmd/rc/rc.h index 720c6f2..f5c8a6d 100644 --- a/src/cmd/rc/rc.h +++ b/src/cmd/rc/rc.h @@ -217,6 +217,7 @@ Tree *maketree(void); Tree *maketree1(int, Tree*); Tree *maketree2(int, Tree*, Tree*); Tree *maketree3(int, Tree*, Tree*, Tree*); +Tree *basictree(Tree*); Tree *token(int, char *); Tree *hangchild1(Tree *, Tree *, int); diff --git a/src/cmd/rc/syntax.y b/src/cmd/rc/syntax.y index 4acd92f..36e1dad 100644 --- a/src/cmd/rc/syntax.y +++ b/src/cmd/rc/syntax.y @@ -84,7 +84,7 @@ epilog: cmd: /* empty */ %prec Twhile { $$ = nil; } -| basic { $$ = maketree1(Tbasic, $1); } +| basic { $$ = basictree($1); } | block epilog { $$ = hangepilog($1, $2); } | cmd Tpipe nl cmd { $$ = hangchild2($2, $1, 0, $4, 1); } | cmd Tandand nl cmd { $$ = maketree2(Tandand, $1, $4); } diff --git a/src/cmd/rc/sys.c b/src/cmd/rc/sys.c index a845122..9b6124b 100644 --- a/src/cmd/rc/sys.c +++ b/src/cmd/rc/sys.c @@ -3,14 +3,13 @@ // ----------------------------------------------------------------------- // internal -static -char** +static char** mkargv(Word *args) { char **argv=emalloc((count(args)+2)*sizeof(char *)); - char **argp=argv+1; /* leave one at front for runcoms */ + char **argp=argv+1; /* leave one at front for executable */ - for(;args;args=args->link) + for(; args; args=args->link) *argp++=args->str; *argp=nil; @@ -107,9 +106,11 @@ redirect(Redir *r) case Rdup: dup2(r->from, r->to); // TODO: error checking break; + case Rclose: close(r->from); break; + default: fatal("unrecognized redirection type %d\n", r->type); } diff --git a/src/cmd/rc/tree.c b/src/cmd/rc/tree.c index 3703a25..3b7aeb8 100644 --- a/src/cmd/rc/tree.c +++ b/src/cmd/rc/tree.c @@ -78,6 +78,25 @@ hangchild3(Tree *node, Tree *c0, Tree *c1, Tree *c2) return node; } +/* + * add a Tbasic node. + * percolate all the redirections up to the root + */ +Tree* +basictree(Tree *cmd) +{ + Tree *c; + cmd = maketree1(Tbasic, cmd); + for(c=cmd->child[0]; c->type==Targs; c = c->child[0]){ + if(c->child[1]->type == Tdup || c->child[1]->type == Tredir){ + c->child[1]->child[1] = cmd; + cmd = c->child[1]; + c->child[1] = nil; + } + } + return cmd; +} + Tree* hangepilog(Tree *cmd, Tree *epi) { diff --git a/src/cmd/rc/var.c b/src/cmd/rc/var.c index 6004bb9..e2d3e08 100644 --- a/src/cmd/rc/var.c +++ b/src/cmd/rc/var.c @@ -6,7 +6,7 @@ // ----------------------------------------------------------------------- // globals -struct Keyword +struct Keyword { char *name; int type; -- cgit v1.2.1