ref: babf901b4a508c3ec5d1f89655f10377bbdf9637
dir: /os/init/pcdemo.b/
#
# 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);
}