diff options
Diffstat (limited to 'appl/cmd/sh/sh.y')
| -rw-r--r-- | appl/cmd/sh/sh.y | 48 |
1 files changed, 37 insertions, 11 deletions
diff --git a/appl/cmd/sh/sh.y b/appl/cmd/sh/sh.y index 083357c1..44984a1b 100644 --- a/appl/cmd/sh/sh.y +++ b/appl/cmd/sh/sh.y @@ -319,7 +319,7 @@ runscript(ctxt: ref Context, path: string, args: list of ref Listnode, reporterr runfile(ctxt, fd, path, args); else if (reporterr) ctxt.fail("bad script path", sys->sprint("sh: cannot open %s: %r", path)); - } exception e { + } exception { "fail:*" => if(!reporterr) return; @@ -375,7 +375,7 @@ runfile(ctxt: ref Context, fd: ref Sys->FD, path: string, args: list of ref List raise "fail:" + laststatus; ctxt.pop(); } - exception e { + exception { "fail:*" => ctxt.pop(); raise; @@ -569,6 +569,28 @@ listjoin(left, right: list of ref Listnode): list of ref Listnode return right; } +pipecmd(ctxt: ref Context, cmd: list of ref Listnode, redir: ref Redir): ref Sys->FD +{ + if(redir.fd2 != -1 || (redir.rtype & OAPPEND)) + ctxt.fail("bad redir", "sh: bad redirection"); + r := *redir; + case redir.rtype { + Sys->OREAD => + r.rtype = Sys->OWRITE; + Sys->OWRITE => + r.rtype = Sys->OREAD; + } + + p := array[2] of ref Sys->FD; + if(sys->pipe(p) == -1) + ctxt.fail("no pipe", sys->sprint("sh: cannot make pipe: %r")); + startchan := chan of (int, ref Expropagate); + spawn runasync(ctxt, 1, cmd, ref Redirlist((p[1], nil, r) :: nil), startchan); + p[1] = nil; + <-startchan; + return p[0]; +} + glomoperation(ctxt: ref Context, n: ref Node, redirs: ref Redirlist): list of ref Listnode { if (n == nil) @@ -580,11 +602,15 @@ glomoperation(ctxt: ref Context, n: ref Node, redirs: ref Redirlist): list of re nlist = ref Listnode(nil, n.word) :: nil; n_REDIR => wlist := glob(glom(ctxt, n.left, ref Redirlist(nil), nil)); - if (len wlist != 1 || (hd wlist).word == nil) + if (len wlist != 1) ctxt.fail("bad redir", "sh: single redirection operand required"); - - # add to redir list - redirs.r = Redirword(nil, (hd wlist).word, *n.redir) :: redirs.r; + if((hd wlist).cmd != nil){ + fd := pipecmd(ctxt, wlist, n.redir); + redirs.r = Redirword(fd, nil, (n.redir.rtype, fd.fd, -1)) :: redirs.r; + nlist = ref Listnode(nil, "/fd/"+string fd.fd) :: nil; + }else{ + redirs.r = Redirword(nil, (hd wlist).word, *n.redir) :: redirs.r; + } n_DUP => redirs.r = Redirword(nil, "", *n.redir) :: redirs.r; n_LIST => @@ -938,7 +964,7 @@ runblock(ctxt: ref Context, args: list of ref Listnode, last: int): string status := walk(ctxt, cmd, last); ctxt.pop(); return status; - } exception e{ + } exception { "fail:*" => ctxt.pop(); raise; @@ -950,7 +976,7 @@ runblock(ctxt: ref Context, args: list of ref Listnode, last: int): string trybuiltin(ctxt: ref Context, args: list of ref Listnode, lseq: int) : (int, string) { - (n, bmods) := findbuiltin(ctxt.env.builtins, (hd args).word); + (nil, bmods) := findbuiltin(ctxt.env.builtins, (hd args).word); if (bmods == nil) return (0, nil); return (1, (hd bmods)->runbuiltin(ctxt, myself, args, lseq)); @@ -976,7 +1002,7 @@ externalexec(mod: Command, { mod->init(drawcontext, argv); } - exception e{ + exception { EPIPE => raise "fail:" + EPIPE; } @@ -1626,6 +1652,8 @@ patquote(word: string): string i++; if (i >= len word) return outword; + if(word[i] == '[' && i < len word - 1 && word[i+1] == '~') + word[i+1] = '^'; } outword[len outword] = word[i]; } @@ -1987,10 +2015,8 @@ builtin_load(ctxt: ref Context, args: list of ref Listnode, nil: int): string if (tl args == nil || (hd tl args).word == nil) builtinusage(ctxt, "load path..."); args = tl args; - path := (hd args).word; if (args == nil) builtinusage(ctxt, "load path..."); - status := ""; for (; args != nil; args = tl args) { s := loadmodule(ctxt, (hd args).word); if (s != nil) |
