summaryrefslogtreecommitdiff
path: root/appl/cmd/rcmd.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/rcmd.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/cmd/rcmd.b')
-rw-r--r--appl/cmd/rcmd.b170
1 files changed, 170 insertions, 0 deletions
diff --git a/appl/cmd/rcmd.b b/appl/cmd/rcmd.b
new file mode 100644
index 00000000..43fe9078
--- /dev/null
+++ b/appl/cmd/rcmd.b
@@ -0,0 +1,170 @@
+implement Rcmd;
+
+include "sys.m";
+include "draw.m";
+include "arg.m";
+include "keyring.m";
+include "security.m";
+
+Rcmd: module
+{
+ init: fn(ctxt: ref Draw->Context, argv: list of string);
+};
+
+DEFAULTALG := "none";
+sys: Sys;
+auth: Auth;
+
+init(nil: ref Draw->Context, argv: list of string)
+{
+ sys = load Sys Sys->PATH;
+ arg := load Arg Arg->PATH;
+ if(arg == nil)
+ badmodule(Arg->PATH);
+ arg->init(argv);
+ alg: string;
+ doauth := 1;
+ exportpath := "/";
+ keyfile: string;
+ arg->setusage("rcmd [-A] [-f keyfile] [-a alg] [-e exportpath] tcp!mach cmd");
+ while((o := arg->opt()) != 0)
+ case o {
+ 'a' =>
+ alg = arg->earg();
+ 'A' =>
+ doauth = 0;
+ 'e' =>
+ exportpath = arg->earg();
+ (n, nil) := sys->stat(exportpath);
+ if (n == -1 || exportpath == nil)
+ arg->usage();
+ 'f' =>
+ keyfile = arg->earg();
+ if (! (keyfile[0] == '/' || (len keyfile > 2 && keyfile[0:2] == "./")))
+ keyfile = "/usr/" + user() + "/keyring/" + keyfile;
+ * =>
+ arg->usage();
+ }
+
+ argv = arg->argv();
+ if(argv == nil)
+ arg->usage();
+ arg = nil;
+
+ if (doauth && alg == nil)
+ alg = DEFAULTALG;
+
+ addr := hd argv;
+ argv = tl argv;
+
+ args := "";
+ while(argv != nil){
+ args += " " + hd argv;
+ argv = tl argv;
+ }
+ if(args == "")
+ args = "sh";
+
+ kr: Keyring;
+ au: Auth;
+ if (doauth) {
+ kr = load Keyring Keyring->PATH;
+ if(kr == nil)
+ badmodule(Keyring->PATH);
+ au = load Auth Auth->PATH;
+ if(au == nil)
+ badmodule(Auth->PATH);
+ if (keyfile == nil)
+ keyfile = "/usr/" + user() + "/keyring/default";
+ }
+
+ (ok, c) := sys->dial(netmkaddr(addr, "tcp", "rstyx"), nil);
+ if(ok < 0)
+ error(sys->sprint("dial server failed: %r"));
+
+ fd := c.dfd;
+ if (doauth) {
+ ai := kr->readauthinfo(keyfile);
+ #
+ # let auth->client handle nil ai
+ # if(ai == nil){
+ # sys->fprint(stderr(), "rcmd: certificate for %s not found\n", addr);
+ # raise "fail:no certificate";
+ # }
+ #
+
+ err := au->init();
+ if(err != nil)
+ error(err);
+
+ (fd, err) = au->client(alg, ai, c.dfd);
+ if(fd == nil){
+ sys->fprint(stderr(), "rcmd: authentication failed: %s\n", err);
+ raise "fail:auth failed";
+ }
+ }
+ t := array of byte sys->sprint("%d\n%s\n", len (array of byte args)+1, args);
+ if(sys->write(fd, t, len t) != len t){
+ sys->fprint(stderr(), "rcmd: cannot write arguments: %r\n");
+ raise "fail:bad arg write";
+ }
+
+ if(sys->export(fd, exportpath, sys->EXPWAIT) < 0) {
+ sys->fprint(stderr(), "rcmd: export: %r\n");
+ raise "fail:export failed";
+ }
+}
+
+exists(f: string): int
+{
+ (ok, nil) := sys->stat(f);
+ return ok >= 0;
+}
+
+user(): string
+{
+ sys = load Sys Sys->PATH;
+
+ fd := sys->open("/dev/user", sys->OREAD);
+ if(fd == nil)
+ return "";
+
+ buf := array[128] of byte;
+ n := sys->read(fd, buf, len buf);
+ if(n < 0)
+ return "";
+
+ return string buf[0:n];
+}
+
+netmkaddr(addr, net, svc: string): string
+{
+ if(net == nil)
+ net = "net";
+ (n, l) := sys->tokenize(addr, "!");
+ if(n <= 1){
+ if(svc== nil)
+ return sys->sprint("%s!%s", net, addr);
+ return sys->sprint("%s!%s!%s", net, addr, svc);
+ }
+ if(svc == nil || n > 2)
+ return addr;
+ return sys->sprint("%s!%s", addr, svc);
+}
+
+stderr(): ref Sys->FD
+{
+ return sys->fildes(2);
+}
+
+badmodule(p: string)
+{
+ sys->fprint(stderr(), "rcmd: cannot load %s: %r\n", p);
+ raise "fail:bad module";
+}
+
+error(e: string)
+{
+ sys->fprint(stderr(), "rcmd: %s\n", e);
+ raise "fail:errors";
+}