forsyth20121205-174063a80cc13 years agoHistory
115 lines · 2.7 KB · Brainfuck
RawDownload
implement Join;include "sys.m";	sys: Sys;include "draw.m";include "sh.m";include "arg.m";include "join.m"; usage(){	sys->fprint(stderr(), "usage: joinsession [-d mntdir] [-j joinrequest] name\n");	raise "fail:usage";} CLIENTDIR: con "/dis/spree/clients"; init(ctxt: ref Draw->Context, argv: list of string){	sys = load Sys Sys->PATH;	arg := load Arg Arg->PATH;	arg->init(argv);	mnt := "/n/remote";	joinmsg := "join";	while ((opt := arg->opt()) != 0) {		case opt {		'd' =>			if ((mnt = arg->arg()) == nil)				usage();		'j' =>			joinmsg = arg->arg();		* =>			usage();		}	}	argv = arg->argv();	if (len argv != 1)		usage();	arg = nil;	e := join(ctxt, mnt, hd argv, joinmsg);	if (e != nil) {		sys->fprint(stderr(), "startclient: %s\n", e);		raise "fail:error";	}} join(ctxt: ref Draw->Context, mnt: string, dir: string, joinmsg: string): string{	if (sys == nil)		sys = load Sys Sys->PATH; 	fd := sys->open(mnt + "/" + dir + "/ctl", Sys->ORDWR);	if (fd == nil)		return sys->sprint("cannot open %s: %r", mnt + "/" + dir + "/ctl");	if (joinmsg != nil)		if (sys->fprint(fd, "%s", joinmsg) == -1)			return sys->sprint("cannot join: %r"); 	buf := array[Sys->ATOMICIO] of byte;	while ((n := sys->read(fd, buf, len buf)) > 0) {		(nil, lines) := sys->tokenize(string buf[0:n], "\n");		for (; lines != nil; lines = tl lines) {			(nil, toks) := sys->tokenize(hd lines, " ");			if (len toks > 1 && hd toks == "clienttype") {				sync := chan of string;				spawn startclient(ctxt, hd tl toks :: mnt :: dir :: tl tl toks, fd, sync);				fd = nil;				return <-sync;			}			sys->fprint(stderr(), "startclient: unknown lobby message %s\n", hd lines);		}	}	return "premature EOF";} startclient(ctxt: ref Draw->Context, argv: list of string, fd: ref Sys->FD, sync: chan of string){	sys->pctl(Sys->FORKNS|Sys->FORKFD|Sys->NEWPGRP, nil);	sys->dup(fd.fd, 0);	fd = nil;	sys->pctl(Sys->NEWFD, 0 :: 1 :: 2 :: nil); 	# XXX security: weed out slashes	path := CLIENTDIR + "/" + hd argv + ".dis";	mod := load Command path;	if (mod == nil) {		sync <-= sys->sprint("cannot load %s: %r\n", path);		return;	}	spawn clientmod(mod, ctxt, argv);	sync <-= nil;} clientmod(mod: Command, ctxt: ref Draw->Context, argv: list of string){	wfd := sys->open("/prog/" + string sys->pctl(0, nil) + "/wait", Sys->OREAD);	spawn mod->init(ctxt, argv);	buf := array[Sys->ATOMICIO] of byte;	n := sys->read(wfd, buf, len buf);	sys->print("client process (%s) exited: %s\n", concat(argv), string buf[0:n]);} concat(l: list of string): string{	if (l == nil)		return nil;	s := hd l;	for (l = tl l; l != nil; l = tl l)		s += " " + hd l;	return s;} stderr(): ref Sys->FD{	return sys->fildes(2);}