xref: /inferno-os/appl/cmd/dial.b (revision 1ac9729e9325d84db36c04b5cda3b5b1bc0d041f)
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