ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /appl/cmd/rcmd.b/
implement Rcmd;
include "sys.m";
include "draw.m";
include "arg.m";
include "keyring.m";
include "dial.m";
include "security.m";
Rcmd: module
{
init: fn(ctxt: ref Draw->Context, argv: list of string);
};
DEFAULTALG := "none";
sys: Sys;
auth: Auth;
dial: Dial;
init(nil: ref Draw->Context, argv: list of string)
{
sys = load Sys Sys->PATH;
dial = load Dial Dial->PATH;
if(dial == nil)
badmodule(Dial->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] [-e alg] [-x exportpath] tcp!mach cmd");
while((o := arg->opt()) != 0)
case o {
'e' or 'a' =>
alg = arg->earg();
'A' =>
doauth = 0;
'x' =>
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";
}
c := dial->dial(dial->netmkaddr(addr, "tcp", "rstyx"), nil);
if(c == nil)
error(sys->sprint("dial %s failed: %r", addr));
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];
}
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";
}