code: purgatorio

ref: 09d11c64e5014a64dbc7b807899b3dd2581fe26f
dir: /os/init/pcdemo.b/

View raw version
#
#	Init shell ``with the kitchen sink'', for development purposes.
#
implement InitShell;

include "sys.m";
include "draw.m";

sys: Sys;
FD, Connection, sprint, Dir: import sys;
print, fprint, open, bind, mount, dial, sleep, read: import sys;

stderr:	ref sys->FD;						# standard error FD

InitShell: module
{
	init:	fn(nil: ref Draw->Context, nil: list of string);
};

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

init(nil: ref Draw->Context, nil: list of string)
{
	sys = load Sys Sys->PATH;
	stderr = sys->fildes(2);

	sys->print("Welcome to Inferno...\n");

	sys->pctl(Sys->NEWNS, nil);
	if (imount("/n/remote")) {
		bind("/n/remote", "/", sys->MAFTER);
		bind("/n/remote/dis", "/dis", sys->MBEFORE);
		mountkfs("#W/flash0fs", "fs", "/n/local", sys->MREPL);
	}
	else {
		# bind("#U/pcdemo", "/", sys->MREPL);
		# mountkfs("#U/pcdemo.kfs", "fs", "/", sys->MBEFORE);
		# bind("#U/pcdemo/usr", "/usr", sys->MAFTER);
		mountkfs("#R/ramdisk", "fs", "/", sys->MBEFORE);
		bind("/services", "/data", sys->MREPL|sys->MCREATE);
	}

	namespace();
	srv();

	if (1) {
		bind("/icons/oldlogon.bit", "/icons/logon.bit", sys->MREPL);
		bind("/icons/tk/oldinferno.bit", "/icons/tk/inferno.bit", sys->MREPL);
	}

	sys->print("starting shell (type wm/logon or wm/wmcp)\n");
	shell := sysenv("shell");
	if (shell == nil)
		shell = "/dis/sh.dis";
	sh := load Sh shell;
	spawn sh->init(nil, nil);
}

namespace()
{
	# Bind anything useful we can get our hands on.  Ignore errors.
	sys->print("namespace...\n");
	sys->bind("#I", "/net", sys->MAFTER);	# IP
	sys->bind("#I1", "/net.alt", sys->MREPL);	# second IP for PPP tests
	sys->bind("#p", "/prog", sys->MREPL);	# prog device
	sys->bind("#d", "/fd", Sys->MREPL);
	sys->bind("#i", "/dev", sys->MREPL); 	# draw device
	sys->bind("#t", "/dev", sys->MAFTER);	# serial line
	sys->bind("#c", "/dev", sys->MAFTER); 	# console device
	sys->bind("#W", "/dev", sys->MAFTER);	# Flash
	sys->bind("#O", "/dev", sys->MAFTER);	# Modem
	sys->bind("#T", "/dev", sys->MAFTER);	# Touchscreen
	sys->bind("#H", "/dev", sys->MAFTER);	# Ata disk device
	sys->bind("#b", "/dev", sys->MAFTER);	# debug device
	sys->bind("#c", "/chan", sys->MREPL);
	sys->bind("/data", "/usr/inferno", sys->MREPL|sys->MCREATE);
	sys->bind("/data", "/usr/charon", sys->MREPL|sys->MCREATE);
	sys->bind("/data", "/usr/shaggy", sys->MREPL|sys->MCREATE);
}

mountkfs(devname: string, fsname: string, where: string, flags: int): int
{
	sys->print("mount kfs...\n");
	fd := sys->open("#Kcons/kfsctl", sys->OWRITE);
	if (fd == nil) {
		sys->fprint(stderr, "could not open #Kcons/kfsctl: %r\n");
		return 0;
	}
	kfsopt := "";
	kfsrw := sysenv("kfsrw");
#	if (kfsrw != "1")
#		kfsopt = " ronly";
	b := array of byte ("filsys " + fsname + " " + devname + kfsopt);
	if (sys->write(fd, b, len b) < 0) {
		sys->fprint(stderr, "could not write #Kcons/kfsctl: %r\n");
		return 0;
	}
	if (sys->bind("#K" + fsname, where, flags) < 0) {
		sys->fprint(stderr, "could not bind %s to %s: %r\n", "#K" + fsname, where);
		return 0;
	}
	return 1;
}

dialfs(server: string, where: string): int
{
	ok, n: int;
	c: Connection;

	(ok, c) = dial("tcp!" + server + "!6666", nil);
	if(ok < 0)
		return 0;

	sys->print("mount...");

	c.cfd = nil;
	n = mount(c.dfd, where, sys->MREPL, "");
	if(n > 0)
		return 1;
	sys->print("mount failed: %r\n");
	return 0;
}

Bootpreadlen: con 128;

imount(where: string): int
{
	sys->print("bootp...");
	if (sys->bind("#I", "/net", sys->MREPL) < 0) {
		sys->fprint(stderr, "could not bind ip device: %r\n");
		return 0;
	}
	if (sys->bind("#l", "/net", sys->MAFTER) < 0) {
		sys->fprint(stderr, "could not bind ether device: %r\n");
		return 0;
	}

	fd := sys->open("/net/ipifc/clone", sys->OWRITE);
	if(fd == nil) {
		sys->print("init: open /net/ipifc: %r");
		return 0;
	}

	cfg := array of byte "bind ether ether0";
	if(sys->write(fd, cfg, len cfg) != len cfg) {
		sys->fprint(stderr, "could not bind interface: %r\n");
		return 0;
	}
	cfg = array of byte "bootp";
	if(sys->write(fd, cfg, len cfg) != len cfg) {
		sys->fprint(stderr, "could not bootp: %r\n");
		return 0;
	}

	bfd := sys->open("/net/bootp", sys->OREAD);
	if(bfd == nil) {
		sys->print("init: can't open /net/bootp: %r");
		return 0;
	}

	buf := array[Bootpreadlen] of byte;
	nr := sys->read(bfd, buf, len buf);
	bfd = nil;
	if(nr <= 0) {
		sys->print("init: read /net/bootp: %r");
		return 0;
	}

	(ntok, ls) := sys->tokenize(string buf, " \t\n");
	while(ls != nil) {
		if(hd ls == "fsip"){
			ls = tl ls;
			break;
		}
		ls = tl ls;
	}
	if(ls == nil) {
		sys->print("init: server address not in bootp read");
		return 0;
	}

	server := hd ls;
	sys->print("imount: server %s\n", server);

	return dialfs(server, where);
}

srv()
{
	remotedebug := sysenv("remotedebug");
	if(remotedebug != "1")
		return;
	remotespeed := sysenv("remotespeed");
	if (remotespeed == nil)
		remotespeed = "38400";

	sys->print("srv...");
	if(echoto("#t/eia0ctl", "b" + remotespeed) < 0)
		return;

	fd := sys->open("/dev/eia0", Sys->ORDWR);
	if (fd == nil) {
		sys->print("eia data open: %r\n");
		return;
	}
	if (sys->export(fd, Sys->EXPASYNC) < 0) {
		sys->print("export: %r\n");
		return;
	}
	sys->print("ok\n");
}

sysenv(param: string): string
{
	fd := sys->open("#c/sysenv", sys->OREAD);
	if (fd == nil)
		return(nil);
	buf := array[4096] of byte;
	nb := sys->read(fd, buf, len buf);
	(nfl,fl) := sys->tokenize(string buf, "\n");
	while (fl != nil) {
		pair := hd fl;
		(npl, pl) := sys->tokenize(pair, "=");
		if (npl > 1) {
			if ((hd pl) == param)
				return hd tl pl;
		}
		fl = tl fl;
	}
	return nil;
}

echoto(fname, str: string): int
{
	fd := sys->open(fname, Sys->OWRITE);
	if(fd == nil) {
		sys->print("%s: %r\n", fname);
		return -1;
	}
	x := array of byte str;
	if(sys->write(fd, x, len x) == -1) {
		sys->print("write: %r\n");
		return -1;
	}
	return 0;
}

hang()
{
	c := chan of int;
	<- c;
}

#
# Set system name from nvram
#
setsysname()
{
	fd := open("/nvfs/ID", sys->OREAD);
	if(fd == nil)
		return;
	fds := open("/dev/sysname", sys->OWRITE);
	if(fds == nil)
		return;
	buf := array[128] of byte;
	nr := sys->read(fd, buf, len buf);
	if(nr <= 0)
		return;
	sys->write(fds, buf, nr);
}