summaryrefslogtreecommitdiff
path: root/appl/alphabet/grid/rexec.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/alphabet/grid/rexec.b')
-rw-r--r--appl/alphabet/grid/rexec.b112
1 files changed, 112 insertions, 0 deletions
diff --git a/appl/alphabet/grid/rexec.b b/appl/alphabet/grid/rexec.b
new file mode 100644
index 00000000..02869659
--- /dev/null
+++ b/appl/alphabet/grid/rexec.b
@@ -0,0 +1,112 @@
+implement Rexec, Gridmodule;
+include "sys.m";
+ sys: Sys;
+include "draw.m";
+include "sh.m";
+ sh: Sh;
+include "string.m";
+ str: String;
+include "alphabet/reports.m";
+ reports: Reports;
+ report, Report, quit: import reports;
+include "alphabet/endpoints.m";
+ endpoints: Endpoints;
+ Endpoint: import endpoints;
+include "alphabet/grid.m";
+ grid: Grid;
+ Value: import grid;
+
+Rexec: module {};
+
+types(): string
+{
+ return "eesc-A";
+}
+
+init()
+{
+ sys = load Sys Sys->PATH;
+ reports = checkload(load Reports Reports->PATH, Reports->PATH);
+ endpoints = checkload(load Endpoints Endpoints->PATH, Endpoints->PATH);
+ endpoints->init();
+ grid = checkload(load Grid Grid->PATH, Grid->PATH);
+ grid->init();
+ sh = checkload(load Sh Sh->PATH, Sh->PATH);
+ sh->initialise();
+ str = checkload(load String String->PATH, String->PATH);
+}
+
+run(nil: chan of string, r: ref Reports->Report,
+ opts: list of (int, list of ref Grid->Value), args: list of ref Grid->Value): ref Grid->Value
+{
+ ec0 := (hd args).e().i;
+ addr := (hd tl args).s().i;
+ cmd := (hd tl tl args).c().i;
+
+ spawn rexecproc(sync := chan of int, addr, ec0, cmd, r.start("rexec"), opts != nil, ec1 := chan of Endpoint);
+ <-sync;
+ return ref Value.Ve(ec1);
+}
+
+rexecproc(sync: chan of int,
+ addr: string,
+ ec0: chan of Endpoint,
+ cmd: ref Sh->Cmd,
+ errorc: chan of string,
+ noauth: int,
+ ec1: chan of Endpoint
+ )
+{
+ sys->pctl(Sys->FORKNS, nil);
+ sync <-= 1;
+
+ ep0 := <-ec0;
+ if(ep0.addr == nil){
+ ec1 <-= ep0;
+ quit(errorc);
+ }
+
+ (ep1, err) := exec(addr, ep0, cmd, noauth);
+ if(err != nil){
+ endpoints->open(nil, ep0); # discard
+ report(errorc, err);
+ }
+ ec1 <-= ep1;
+ quit(errorc);
+}
+
+Nope: con Endpoint(nil, nil, nil);
+
+exec(addr: string, ep0: Endpoint, cmd: ref Sh->Cmd, noauth: int): (Endpoint, string)
+{
+ args := addr::"/n/remote"::nil;
+ if(noauth)
+ args = "-A"::args;
+ if((e := sh->run(nil, "mount"::args)) != nil)
+ return (Nope, sys->sprint("cannot mount rexec at %q: %s", addr, e));
+
+ fd := sys->open("/n/remote/exec", Sys->ORDWR);
+ if(fd == nil)
+ return (Nope, sys->sprint("cannot open exec at %q: %r", addr));
+ if(sys->fprint(fd, "%q %q", ep0.text(), sh->cmd2string(cmd)) == -1)
+ return (Nope, sys->sprint("exec write failed: %r"));
+ buf := array[1024] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ return (Nope, sys->sprint("error reading endpoint: %r"));
+ if(n == 0)
+ return (Nope, "eof reading endpoint");
+ s := string buf[0:n];
+ ep1 := Endpoint.mk(s);
+ if(ep1.addr == nil)
+ return (Nope, sys->sprint("bad endpoint %#q: %s", s, ep1.about));
+ ep1.about = sys->sprint("%s | rexec %q %s", ep0.about, addr, sh->cmd2string(cmd));
+ return (ep1, nil);
+}
+
+checkload[T](m: T, path: string): T
+{
+ if(m != nil)
+ return m;
+ raise sys->sprint("fail:cannot load %s: %r", path);
+}