xref: /inferno-os/appl/collab/collabsrv.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Collabsrv;
2
3include "sys.m";
4	sys: Sys;
5
6include "draw.m";
7
8include "keyring.m";
9include "security.m";
10	auth: Auth;
11
12include "srvmgr.m";
13include "proxy.m";
14
15include "arg.m";
16
17Collabsrv: module
18{
19	init: fn (ctxt: ref Draw->Context, args: list of string);
20};
21
22authinfo: ref Keyring->Authinfo;
23
24stderr: ref Sys->FD;
25Srvreq, Srvreply: import Srvmgr;
26
27usage()
28{
29	sys->fprint(stderr, "usage: collabsrv [-k keyfile] [-n netaddress] [dir]\n");
30	raise "fail:usage";
31}
32
33init(nil: ref Draw->Context, args: list of string)
34{
35	sys = load Sys Sys->PATH;
36	sys->pctl(Sys->NEWPGRP, nil);
37	stderr = sys->fildes(2);
38
39	(err, user) := user();
40	if (err != nil)
41		error(err);
42
43	netaddr := "tcp!*!9999";
44	keyfile := "/usr/" + user + "/keyring/default";
45	root := "/services/collab";
46
47	arg := load Arg Arg->PATH;
48	arg->init(args);
49	while ((opt := arg->opt()) != 0)
50		case opt {
51		'k' =>
52			keyfile = arg->arg();
53			if (keyfile == nil)
54				usage();
55			if (keyfile[0] != '/' && (len keyfile < 2 || keyfile[0:2] != "./"))
56				keyfile = "/usr/" + user + "/keyring/" + keyfile;
57		'n' =>
58			netaddr = arg->arg();
59			if (netaddr == nil)
60				usage();
61		* =>
62			usage();
63		}
64	args = arg->argv();
65	arg = nil;
66	if(args != nil)
67		root = hd args;
68
69	auth = load Auth Auth->PATH;
70	if (auth == nil)
71		badmodule(Auth->PATH);
72
73	kr := load Keyring Keyring->PATH;
74	if (kr == nil)
75		badmodule(Keyring->PATH);
76
77	srvmgr := load Srvmgr Srvmgr->PATH;
78	if (srvmgr == nil)
79		badmodule(Srvmgr->PATH);
80
81	err = auth->init();
82	if (err != nil)
83		error(sys->sprint("failed to init Auth: %s", err));
84
85	authinfo = kr->readauthinfo(keyfile);
86	kr = nil;
87	if (authinfo == nil)
88		error(sys->sprint("cannot read %s: %r", keyfile));
89
90	netaddr = netmkaddr(netaddr, "tcp", "9999");
91	(ok, c) := sys->announce(netaddr);
92	if (ok < 0)
93		error(sys->sprint("cannot announce %s: %r", netaddr));
94
95	rc: chan of ref Srvreq;
96	(err, rc) = srvmgr->init(root);
97	if (err != nil)
98		error(err);
99
100	sys->print("Srvmgr started\n");
101
102	for (;;) {
103		(okl, nc) := sys->listen(c);
104		if (okl < 0) {
105			sys->print("listen failed: %r\n");
106			sys->sleep(1000);
107			return;
108		}
109		fd := sys->open(nc.dir+"/data", Sys->ORDWR);
110		if(nc.cfd != nil)
111			sys->fprint(nc.cfd, "keepalive");
112		nc.cfd = nil;
113		if (fd != nil)
114			spawn newclient(rc, fd, root);
115		fd = nil;
116	}
117}
118
119badmodule(path: string)
120{
121	error(sys->sprint("cannot load module %s: %r", path));
122}
123
124error(s: string)
125{
126	sys->fprint(stderr, "collabsrv: %s\n", s);
127	raise "fail:error";
128}
129
130user(): (string, string)
131{
132	sys = load Sys Sys->PATH;
133	fd := sys->open("/dev/user", sys->OREAD);
134	if(fd == nil)
135		return (sys->sprint("can't open /dev/user: %r"), nil);
136	buf := array[128] of byte;
137	n := sys->read(fd, buf, len buf);
138	if(n <= 0)
139		return (sys->sprint("failed to read /dev/user: %r"), nil);
140	return (nil, string buf[0:n]);
141}
142
143newclient(rc: chan of ref Srvreq, fd: ref Sys->FD, root: string)
144{
145	algs := "none" :: "clear" :: "md4" :: "md5" :: nil;
146	sys->print("new client\n");
147	proxy := load Proxy Proxy->PATH;
148	if (proxy == nil) {
149		sys->fprint(stderr, "collabsrv: cannot load %s: %r\n", Proxy->PATH);
150		return;
151	}
152	sys->pctl(Sys->NEWPGRP|Sys->FORKNS|Sys->FORKENV, nil);
153	s := "";
154	(fd, s) = auth->server(algs, authinfo, fd, 1);
155	if (fd == nil){
156		sys->fprint(stderr, "collabsrv: cannot authenticate: %s\n", s);
157		return;
158	}
159	sys->fprint(stderr, "uname: %s\n", s);
160	spawn proxy->init(root, fd, rc, s);
161}
162
163netmkaddr(addr, net, svc: string): string
164{
165	if(net == nil)
166		net = "net";
167	(n, l) := sys->tokenize(addr, "!");
168	if(n <= 1){
169		if(svc== nil)
170			return sys->sprint("%s!%s", net, addr);
171		return sys->sprint("%s!%s!%s", net, addr, svc);
172	}
173	if(svc == nil || n > 2)
174		return addr;
175	return sys->sprint("%s!%s", addr, svc);
176}
177