diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/cmd/dial.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/cmd/dial.b')
| -rw-r--r-- | appl/cmd/dial.b | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/appl/cmd/dial.b b/appl/cmd/dial.b new file mode 100644 index 00000000..c562a570 --- /dev/null +++ b/appl/cmd/dial.b @@ -0,0 +1,148 @@ +implement Dial; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "arg.m"; +include "keyring.m"; + keyring: Keyring; +include "security.m"; + auth: Auth; +include "sh.m"; + sh: Sh; + Context: import sh; + +Dial: module { + init: fn(nil: ref Draw->Context, argv: list of string); +}; + +badmodule(p: string) +{ + sys->fprint(stderr(), "dial: cannot load %s: %r\n", p); + raise "fail:bad module"; +} + +DEFAULTALG := "none"; + +verbose := 0; + +init(drawctxt: ref Draw->Context, argv: list of string) +{ + sys = load Sys Sys->PATH; + keyring = load Keyring Keyring->PATH; + auth = load Auth Auth->PATH; + if (auth == nil) + badmodule(Auth->PATH); + arg := load Arg Arg->PATH; + if (arg == nil) + badmodule(Arg->PATH); + sh = load Sh Sh->PATH; + if (sh == nil) + badmodule(Sh->PATH); + + auth->init(); + alg: string; + keyfile: string; + doauth := 1; + arg->init(argv); + arg->setusage("dial [-A] [-k keyfile] [-a alg] addr command [arg...]"); + while ((opt := arg->opt()) != 0) { + case opt { + 'A' => + doauth = 0; + 'a' => + alg = arg->earg(); + 'f' or + 'k' => + keyfile = arg->earg(); + if (! (keyfile[0] == '/' || (len keyfile > 2 && keyfile[0:2] == "./"))) + keyfile = "/usr/" + user() + "/keyring/" + keyfile; + 'v' => + verbose = 1; + * => + arg->usage(); + } + } + argv = arg->argv(); + if (len argv < 2) + arg->usage(); + arg = nil; + (addr, shcmd) := (hd argv, tl argv); + + if (doauth && alg == nil) + alg = DEFAULTALG; + + if (alg != nil && keyfile == nil) { + kd := "/usr/" + user() + "/keyring/"; + if (exists(kd + addr)) + keyfile = kd + addr; + else + keyfile = kd + "default"; + } + cert: ref Keyring->Authinfo; + if (alg != nil) { + cert = keyring->readauthinfo(keyfile); + if (cert == nil) { + sys->fprint(stderr(), "dial: cannot read %s: %r\n", keyfile); + raise "fail:bad keyfile"; + } + } + + (ok, c) := sys->dial(addr, nil); + if (ok == -1) { + sys->fprint(stderr(), "dial: cannot dial %s:: %r\n", addr); + raise "fail:errors"; + } + user: string; + if (alg != nil) { + err: string; + (c.dfd, err) = auth->client(alg, cert, c.dfd); + if (c.dfd == nil) { + sys->fprint(stderr(), "dial: authentication failed: %s\n", err); + raise "fail:errors"; + } + user = err; + } + sys->dup(c.dfd.fd, 0); + sys->dup(c.dfd.fd, 1); + c.dfd = c.cfd = nil; + ctxt := Context.new(drawctxt); + if (user != nil) + ctxt.set("user", sh->stringlist2list(user :: nil)); + else + ctxt.set("user", nil); + ctxt.set("net", ref Sh->Listnode(nil, c.dir) :: nil); + ctxt.run(sh->stringlist2list(shcmd), 1); +} + +exists(f: string): int +{ + (ok, nil) := sys->stat(f); + return ok != -1; +} + +stderr(): ref Sys->FD +{ + return sys->fildes(2); +} + +user(): string +{ + u := readfile("/dev/user"); + if (u == nil) + return "nobody"; + return u; +} + +readfile(f: string): string +{ + fd := sys->open(f, sys->OREAD); + if(fd == nil) + return nil; + + buf := array[128] of byte; + n := sys->read(fd, buf, len buf); + if(n < 0) + return nil; + + return string buf[0:n]; +} |
