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/exec.c | 112 ++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 20 deletions(-) (limited to 'src/cmd/rc/exec.c') 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) { -- cgit v1.2.1