diff options
Diffstat (limited to 'appl/cmd')
| -rw-r--r-- | appl/cmd/sh/sh.b | 51 | ||||
| -rw-r--r-- | appl/cmd/sh/sh.y | 48 | ||||
| -rw-r--r-- | appl/cmd/sh/tk.b | 38 |
3 files changed, 99 insertions, 38 deletions
diff --git a/appl/cmd/sh/sh.b b/appl/cmd/sh/sh.b index 6040457f..05a8227a 100644 --- a/appl/cmd/sh/sh.b +++ b/appl/cmd/sh/sh.b @@ -81,7 +81,6 @@ YYMAXDEPTH: con 200; EPERM: con "permission denied"; EPIPE: con "write on closed pipe"; -SHELLRC: con "lib/profile"; LIBSHELLRC: con "/lib/sh/profile"; BUILTINPATH: con "/dis/sh"; @@ -191,8 +190,6 @@ loop: while (argv != nil && hd argv != nil && (hd argv)[0] == '-') { runscript(ctxt, LIBSHELLRC, nil, 0); if (argv == nil) { - if (opts.lflag) - runscript(ctxt, SHELLRC, nil, 0); if (isconsole(sys->fildes(0))) interactive |= ctxt.INTERACTIVE; ctxt.setoptions(interactive, 1); @@ -256,7 +253,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; @@ -310,7 +307,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; @@ -495,6 +492,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) @@ -506,11 +525,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 => @@ -849,7 +872,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; @@ -859,7 +882,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)); @@ -885,7 +908,7 @@ externalexec(mod: Command, { mod->init(drawcontext, argv); } - exception e{ + exception { EPIPE => raise "fail:" + EPIPE; } @@ -1512,6 +1535,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]; } @@ -1852,10 +1877,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) 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) diff --git a/appl/cmd/sh/tk.b b/appl/cmd/sh/tk.b index bc6fe753..31040c45 100644 --- a/appl/cmd/sh/tk.b +++ b/appl/cmd/sh/tk.b @@ -118,7 +118,6 @@ builtin_tk(ctxt: ref Context, argv: list of ref Listnode): string argv = tl argv; if (len argv < 1 || !isnum((hd argv).word)) ctxt.fail("usage", "usage: tk onscreen winid [how]"); - wid := (hd argv).word; how := ""; if(tl argv != nil) how = word(hd tl argv); @@ -232,22 +231,35 @@ sbuiltin_alt(ctxt: ref Context, argv: list of ref Listnode): list of ref Listnod argv = tl argv; if (argv == nil) ctxt.fail("usage", "usage: alt chan..."); - ca := array[len argv] of chan of string; - cname := array[len ca] of string; + nc := len argv; + kbd := array[nc] of chan of int; + ptr := array[nc] of chan of ref Draw->Pointer; + ca := array[nc * 3] of chan of string; + win := array[nc] of ref Tk->Toplevel; + + cname := array[nc] of string; i := 0; for (; argv != nil; argv = tl argv) { - ca[i] = egetchan(ctxt, hd argv); - cname[i] = (hd argv).word; + w := (hd argv).word; + ca[i*3] = egetchan(ctxt, hd argv); + cname[i] = w; + if(isnum(w)){ + win[i] = egetwin(ctxt, hd argv); + ca[i*3+1] = win[i].ctxt.ctl; + ca[i*3+2] = win[i].wreq; + ptr[i] = win[i].ctxt.ptr; + kbd[i] = win[i].ctxt.kbd; + } i++; } - n := 0; - v: string; - if (i == 1) - v = <-ca[0]; - else - (n, v) = <-ca; - - return ref Listnode(nil, cname[n]) :: ref Listnode(nil, v) :: nil; + for(;;) alt{ + (n, key) := <-kbd => + tk->keyboard(win[n], key); + (n, p) := <-ptr => + tk->pointer(win[n], *p); + (n, v) := <-ca => + return ref Listnode(nil, cname[n/3]) :: ref Listnode(nil, v) :: nil; + } } sbuiltin_recv(ctxt: ref Context, argv: list of ref Listnode): list of ref Listnode |
