shithub: purgatorio

ref: a411870ee4640241e3c494367d922847da84f972
dir: purgatorio/appl/lib/dbsrv.b

View raw version
implement DBserver;

include "sys.m";
	sys: Sys;

include "draw.m";

include "keyring.m";

include "security.m";

include "db.m";              # For now.

stderr: ref Sys->FD;

DBserver : module
{
	init:   fn(ctxt: ref Draw->Context, argv: list of string);
};

# argv is a list of Inferno supported algorithms from Security->Auth

init(nil: ref Draw->Context, argv: list of string)
{
	sys = load Sys Sys->PATH;
	stdin := sys->fildes(0);
	stderr = sys->fildes(2);
	if(argv != nil)
		argv = tl argv;
	if(argv == nil)
		err("no algorithm list");

	kr := load Keyring Keyring->PATH;
	if(nil == kr)
		err(sys->sprint("can't load Keyring: %r"));

	auth := load Auth Auth->PATH;
	if(auth == nil)
		err(sys->sprint("can't load Auth: %r"));

	error := auth->init();
	if(error != nil)
		err(sys->sprint("Auth init failed: %s", error));

	ai := kr->readauthinfo("/usr/"+user()+"/keyring/default");

	(client_fd, info_or_err) := auth->server(argv, ai, stdin, 1);
	if(client_fd == nil)
		err(sys->sprint("can't authenticate client: %s", info_or_err));

	auth = nil;
	kr = nil;

	sys->pctl(Sys->FORKNS|Sys->NEWPGRP, nil);

	# run the infdb database program in the host system using /cmd

	cmdfd := sys->open("/cmd/clone", sys->ORDWR);
	if (cmdfd == nil)
		err(sys->sprint("can't open /cmd/clone: %r"));

	buf := array [20] of byte;
	n := sys->read(cmdfd, buf, len buf);
	if(n <= 0)
		err(sys->sprint("can't read /cmd/clone: %r"));
	cmddir := string buf[0:n];

	if (sys->fprint(cmdfd, "exec infdb") <= 0)
		err(sys->sprint("can't start infdb via /cmd/clone: %r"));

	datafile := "/cmd/" + cmddir + "/data";
	infdb_fd := sys->open(datafile, Sys->ORDWR);
	if (infdb_fd == nil)
		err(sys->sprint("can't open %s: %r", datafile));

	spawn dbxfer(infdb_fd, client_fd, "client");

	dbxfer(client_fd, infdb_fd, "infdb");
	sys->fprint(infdb_fd, "X1          0   0 \n");
}

dbxfer(source, sink: ref Sys->FD, tag: string)
{
	buf := array [Sys->ATOMICIO] of byte;
	while((nr := sys->read(source, buf, len buf)) > 0)
		if(sys->write(sink, buf, nr) != nr){
			sys->fprint(stderr, "dbsrv: write to %s failed: %r\n", tag);
			shutdown();
		}
	if(nr < 0){
		sys->fprint(stderr, "dbsrv: reading data for %s: %r\n", tag);
		shutdown();
	}
}

shutdown()
{
	pid := sys->pctl(0, nil);
	fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE);
	if(fd == nil || sys->fprint(fd, "killgrp") < 0)
		err(sys->sprint("can't kill group %d: %r", pid));
}

err(s: string)
{
	sys->fprint(stderr, "dbsrv: %s\n", s);
	raise "fail:error";
}

user(): string
{
	sys = load Sys Sys->PATH;

	fd := sys->open("/dev/user", sys->OREAD);
	if(fd == nil)
		return "";

	buf := array[Sys->NAMEMAX] of byte;
	n := sys->read(fd, buf, len buf);
	if(n < 0)
		return "";

	return string buf[0:n]; 
}