137da2899SCharles.Forsythimplement Rcmd; 237da2899SCharles.Forsyth 337da2899SCharles.Forsythinclude "sys.m"; 437da2899SCharles.Forsythinclude "draw.m"; 537da2899SCharles.Forsythinclude "arg.m"; 637da2899SCharles.Forsythinclude "keyring.m"; 7*fbc1184cSCharles Forsythinclude "dial.m"; 837da2899SCharles.Forsythinclude "security.m"; 937da2899SCharles.Forsyth 1037da2899SCharles.ForsythRcmd: module 1137da2899SCharles.Forsyth{ 1237da2899SCharles.Forsyth init: fn(ctxt: ref Draw->Context, argv: list of string); 1337da2899SCharles.Forsyth}; 1437da2899SCharles.Forsyth 1537da2899SCharles.ForsythDEFAULTALG := "none"; 1637da2899SCharles.Forsythsys: Sys; 1737da2899SCharles.Forsythauth: Auth; 18*fbc1184cSCharles Forsythdial: Dial; 1937da2899SCharles.Forsyth 2037da2899SCharles.Forsythinit(nil: ref Draw->Context, argv: list of string) 2137da2899SCharles.Forsyth{ 2237da2899SCharles.Forsyth sys = load Sys Sys->PATH; 23*fbc1184cSCharles Forsyth dial = load Dial Dial->PATH; 24*fbc1184cSCharles Forsyth if(dial == nil) 25*fbc1184cSCharles Forsyth badmodule(Dial->PATH); 2637da2899SCharles.Forsyth arg := load Arg Arg->PATH; 2737da2899SCharles.Forsyth if(arg == nil) 2837da2899SCharles.Forsyth badmodule(Arg->PATH); 2937da2899SCharles.Forsyth arg->init(argv); 3037da2899SCharles.Forsyth alg: string; 3137da2899SCharles.Forsyth doauth := 1; 3237da2899SCharles.Forsyth exportpath := "/"; 3337da2899SCharles.Forsyth keyfile: string; 34e2311792SCharles Forsyth arg->setusage("rcmd [-A] [-f keyfile] [-e alg] [-x exportpath] tcp!mach cmd"); 3537da2899SCharles.Forsyth while((o := arg->opt()) != 0) 3637da2899SCharles.Forsyth case o { 37e2311792SCharles Forsyth 'e' or 'a' => 3837da2899SCharles.Forsyth alg = arg->earg(); 3937da2899SCharles.Forsyth 'A' => 4037da2899SCharles.Forsyth doauth = 0; 41e2311792SCharles Forsyth 'x' => 4237da2899SCharles.Forsyth exportpath = arg->earg(); 4337da2899SCharles.Forsyth (n, nil) := sys->stat(exportpath); 4437da2899SCharles.Forsyth if (n == -1 || exportpath == nil) 4537da2899SCharles.Forsyth arg->usage(); 4637da2899SCharles.Forsyth 'f' => 4737da2899SCharles.Forsyth keyfile = arg->earg(); 4837da2899SCharles.Forsyth if (! (keyfile[0] == '/' || (len keyfile > 2 && keyfile[0:2] == "./"))) 4937da2899SCharles.Forsyth keyfile = "/usr/" + user() + "/keyring/" + keyfile; 5037da2899SCharles.Forsyth * => 5137da2899SCharles.Forsyth arg->usage(); 5237da2899SCharles.Forsyth } 5337da2899SCharles.Forsyth 5437da2899SCharles.Forsyth argv = arg->argv(); 5537da2899SCharles.Forsyth if(argv == nil) 5637da2899SCharles.Forsyth arg->usage(); 5737da2899SCharles.Forsyth arg = nil; 5837da2899SCharles.Forsyth 5937da2899SCharles.Forsyth if (doauth && alg == nil) 6037da2899SCharles.Forsyth alg = DEFAULTALG; 6137da2899SCharles.Forsyth 6237da2899SCharles.Forsyth addr := hd argv; 6337da2899SCharles.Forsyth argv = tl argv; 6437da2899SCharles.Forsyth 6537da2899SCharles.Forsyth args := ""; 6637da2899SCharles.Forsyth while(argv != nil){ 6737da2899SCharles.Forsyth args += " " + hd argv; 6837da2899SCharles.Forsyth argv = tl argv; 6937da2899SCharles.Forsyth } 7037da2899SCharles.Forsyth if(args == "") 7137da2899SCharles.Forsyth args = "sh"; 7237da2899SCharles.Forsyth 7337da2899SCharles.Forsyth kr: Keyring; 7437da2899SCharles.Forsyth au: Auth; 7537da2899SCharles.Forsyth if (doauth) { 7637da2899SCharles.Forsyth kr = load Keyring Keyring->PATH; 7737da2899SCharles.Forsyth if(kr == nil) 7837da2899SCharles.Forsyth badmodule(Keyring->PATH); 7937da2899SCharles.Forsyth au = load Auth Auth->PATH; 8037da2899SCharles.Forsyth if(au == nil) 8137da2899SCharles.Forsyth badmodule(Auth->PATH); 8237da2899SCharles.Forsyth if (keyfile == nil) 8337da2899SCharles.Forsyth keyfile = "/usr/" + user() + "/keyring/default"; 8437da2899SCharles.Forsyth } 8537da2899SCharles.Forsyth 86*fbc1184cSCharles Forsyth c := dial->dial(dial->netmkaddr(addr, "tcp", "rstyx"), nil); 87*fbc1184cSCharles Forsyth if(c == nil) 88*fbc1184cSCharles Forsyth error(sys->sprint("dial %s failed: %r", addr)); 8937da2899SCharles.Forsyth 9037da2899SCharles.Forsyth fd := c.dfd; 9137da2899SCharles.Forsyth if (doauth) { 9237da2899SCharles.Forsyth ai := kr->readauthinfo(keyfile); 9337da2899SCharles.Forsyth # 9437da2899SCharles.Forsyth # let auth->client handle nil ai 9537da2899SCharles.Forsyth # if(ai == nil){ 9637da2899SCharles.Forsyth # sys->fprint(stderr(), "rcmd: certificate for %s not found\n", addr); 9737da2899SCharles.Forsyth # raise "fail:no certificate"; 9837da2899SCharles.Forsyth # } 9937da2899SCharles.Forsyth # 10037da2899SCharles.Forsyth 10137da2899SCharles.Forsyth err := au->init(); 10237da2899SCharles.Forsyth if(err != nil) 10337da2899SCharles.Forsyth error(err); 10437da2899SCharles.Forsyth 10537da2899SCharles.Forsyth (fd, err) = au->client(alg, ai, c.dfd); 10637da2899SCharles.Forsyth if(fd == nil){ 10737da2899SCharles.Forsyth sys->fprint(stderr(), "rcmd: authentication failed: %s\n", err); 10837da2899SCharles.Forsyth raise "fail:auth failed"; 10937da2899SCharles.Forsyth } 11037da2899SCharles.Forsyth } 11137da2899SCharles.Forsyth t := array of byte sys->sprint("%d\n%s\n", len (array of byte args)+1, args); 11237da2899SCharles.Forsyth if(sys->write(fd, t, len t) != len t){ 11337da2899SCharles.Forsyth sys->fprint(stderr(), "rcmd: cannot write arguments: %r\n"); 11437da2899SCharles.Forsyth raise "fail:bad arg write"; 11537da2899SCharles.Forsyth } 11637da2899SCharles.Forsyth 11737da2899SCharles.Forsyth if(sys->export(fd, exportpath, sys->EXPWAIT) < 0) { 11837da2899SCharles.Forsyth sys->fprint(stderr(), "rcmd: export: %r\n"); 11937da2899SCharles.Forsyth raise "fail:export failed"; 12037da2899SCharles.Forsyth } 12137da2899SCharles.Forsyth} 12237da2899SCharles.Forsyth 12337da2899SCharles.Forsythexists(f: string): int 12437da2899SCharles.Forsyth{ 12537da2899SCharles.Forsyth (ok, nil) := sys->stat(f); 12637da2899SCharles.Forsyth return ok >= 0; 12737da2899SCharles.Forsyth} 12837da2899SCharles.Forsyth 12937da2899SCharles.Forsythuser(): string 13037da2899SCharles.Forsyth{ 13137da2899SCharles.Forsyth sys = load Sys Sys->PATH; 13237da2899SCharles.Forsyth 13337da2899SCharles.Forsyth fd := sys->open("/dev/user", sys->OREAD); 13437da2899SCharles.Forsyth if(fd == nil) 13537da2899SCharles.Forsyth return ""; 13637da2899SCharles.Forsyth 13737da2899SCharles.Forsyth buf := array[128] of byte; 13837da2899SCharles.Forsyth n := sys->read(fd, buf, len buf); 13937da2899SCharles.Forsyth if(n < 0) 14037da2899SCharles.Forsyth return ""; 14137da2899SCharles.Forsyth 14237da2899SCharles.Forsyth return string buf[0:n]; 14337da2899SCharles.Forsyth} 14437da2899SCharles.Forsyth 14537da2899SCharles.Forsythstderr(): ref Sys->FD 14637da2899SCharles.Forsyth{ 14737da2899SCharles.Forsyth return sys->fildes(2); 14837da2899SCharles.Forsyth} 14937da2899SCharles.Forsyth 15037da2899SCharles.Forsythbadmodule(p: string) 15137da2899SCharles.Forsyth{ 15237da2899SCharles.Forsyth sys->fprint(stderr(), "rcmd: cannot load %s: %r\n", p); 15337da2899SCharles.Forsyth raise "fail:bad module"; 15437da2899SCharles.Forsyth} 15537da2899SCharles.Forsyth 15637da2899SCharles.Forsytherror(e: string) 15737da2899SCharles.Forsyth{ 15837da2899SCharles.Forsyth sys->fprint(stderr(), "rcmd: %s\n", e); 15937da2899SCharles.Forsyth raise "fail:errors"; 16037da2899SCharles.Forsyth} 161