1implement Dialc; 2include "sys.m"; 3 sys: Sys; 4include "draw.m"; 5include "arg.m"; 6include "keyring.m"; 7 keyring: Keyring; 8include "security.m"; 9 auth: Auth; 10include "dial.m"; 11 dial: Dial; 12include "sh.m"; 13 sh: Sh; 14 Context: import sh; 15 16Dialc: module { 17 init: fn(nil: ref Draw->Context, argv: list of string); 18}; 19 20badmodule(p: string) 21{ 22 sys->fprint(stderr(), "dial: cannot load %s: %r\n", p); 23 raise "fail:bad module"; 24} 25 26DEFAULTALG := "none"; 27 28verbose := 0; 29 30init(drawctxt: ref Draw->Context, argv: list of string) 31{ 32 sys = load Sys Sys->PATH; 33 keyring = load Keyring Keyring->PATH; 34 auth = load Auth Auth->PATH; 35 if (auth == nil) 36 badmodule(Auth->PATH); 37 arg := load Arg Arg->PATH; 38 if (arg == nil) 39 badmodule(Arg->PATH); 40 sh = load Sh Sh->PATH; 41 if (sh == nil) 42 badmodule(Sh->PATH); 43 dial = load Dial Dial->PATH; 44 if (dial == nil) 45 badmodule(Dial->PATH); 46 47 auth->init(); 48 alg: string; 49 keyfile: string; 50 doauth := 1; 51 arg->init(argv); 52 arg->setusage("dial [-A] [-k keyfile] [-a alg] addr command [arg...]"); 53 while ((opt := arg->opt()) != 0) { 54 case opt { 55 'A' => 56 doauth = 0; 57 'a' => 58 alg = arg->earg(); 59 'f' or 60 'k' => 61 keyfile = arg->earg(); 62 if (! (keyfile[0] == '/' || (len keyfile > 2 && keyfile[0:2] == "./"))) 63 keyfile = "/usr/" + user() + "/keyring/" + keyfile; 64 'v' => 65 verbose = 1; 66 * => 67 arg->usage(); 68 } 69 } 70 argv = arg->argv(); 71 if (len argv < 2) 72 arg->usage(); 73 arg = nil; 74 (addr, shcmd) := (hd argv, tl argv); 75 76 if (doauth && alg == nil) 77 alg = DEFAULTALG; 78 79 if (alg != nil && keyfile == nil) { 80 kd := "/usr/" + user() + "/keyring/"; 81 if (exists(kd + addr)) 82 keyfile = kd + addr; 83 else 84 keyfile = kd + "default"; 85 } 86 cert: ref Keyring->Authinfo; 87 if (alg != nil) { 88 cert = keyring->readauthinfo(keyfile); 89 if (cert == nil) { 90 sys->fprint(stderr(), "dial: cannot read %s: %r\n", keyfile); 91 raise "fail:bad keyfile"; 92 } 93 } 94 95 c := dial->dial(addr, nil); 96 if (c == nil) { 97 sys->fprint(stderr(), "dial: cannot dial %s: %r\n", addr); 98 raise "fail:errors"; 99 } 100 user: string; 101 if (alg != nil) { 102 err: string; 103 (c.dfd, err) = auth->client(alg, cert, c.dfd); 104 if (c.dfd == nil) { 105 sys->fprint(stderr(), "dial: authentication failed: %s\n", err); 106 raise "fail:errors"; 107 } 108 user = err; 109 } 110 sys->dup(c.dfd.fd, 0); 111 sys->dup(c.dfd.fd, 1); 112 c.dfd = c.cfd = nil; 113 ctxt := Context.new(drawctxt); 114 if (user != nil) 115 ctxt.set("user", sh->stringlist2list(user :: nil)); 116 else 117 ctxt.set("user", nil); 118 ctxt.set("net", ref Sh->Listnode(nil, c.dir) :: nil); 119 ctxt.run(sh->stringlist2list(shcmd), 1); 120} 121 122exists(f: string): int 123{ 124 (ok, nil) := sys->stat(f); 125 return ok != -1; 126} 127 128stderr(): ref Sys->FD 129{ 130 return sys->fildes(2); 131} 132 133user(): string 134{ 135 u := readfile("/dev/user"); 136 if (u == nil) 137 return "nobody"; 138 return u; 139} 140 141readfile(f: string): string 142{ 143 fd := sys->open(f, sys->OREAD); 144 if(fd == nil) 145 return nil; 146 147 buf := array[128] of byte; 148 n := sys->read(fd, buf, len buf); 149 if(n < 0) 150 return nil; 151 152 return string buf[0:n]; 153} 154