#include <u.h>
#include <libc.h>
#include <../boot/boot.h>
static char diskname[64];
static char *disk;
static char **args;
void
configlocal(Method *mp)
{
char *p, *inibootdisk;
int n;
inibootdisk = getenv("bootdisk");
if(*sys == '/' || *sys == '#'){
/*
* if the user specifies the disk in the boot cmd or
* 'root is from' prompt, use it
*/
disk = sys;
} else if(strncmp(argv0, "dksc(0,", 7) == 0){
/*
* on many mips arg0 of the boot command specifies the
* scsi logical unit number
*/
p = strchr(argv0, ',');
n = strtoul(p+1, 0, 10);
sprint(diskname, "#w%d/sd%dfs", n, n);
disk = diskname;
} else if(mp->arg){
/*
* a default is optionally supplied when the kernel is made
*/
disk = mp->arg;
} else if(inibootdisk != nil && *inibootdisk)
/* plan9.ini overrides default from config file */
disk = inibootdisk;
else if(bootdisk != nil && *bootdisk){
/*
* an environment variable from a pc's plan9.ini or
* from the mips nvram or generated by the kernel
* is the last resort.
*/
disk = bootdisk;
}
/* if we've decided on one, pass it on to all programs */
if(disk) {
bootdisk = disk;
setenv("bootdisk", bootdisk);
}
}
int
connectlocalkfs(void)
{
int i, pid, fd, p[2];
char partition[64];
char *dev;
char **arg, **argp;
Dir *d;
if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
return -1;
dev = disk ? disk : bootdisk;
snprint(partition, sizeof partition, "%sfs", dev);
fd = open(partition, OREAD);
if(fd < 0){
strcpy(partition, dev);
fd = open(partition, OREAD);
if(fd < 0)
return -1;
}
/*
* can't do this check -- might be some other server posing as kfs.
*
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 0);
close(fd);
if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
if(strstr(partition, "/fs"))
print("no kfs file system found on %s\n", partition);
return -1;
}
*
*/
d = dirfstat(fd);
close(fd);
if(d == nil)
return -1;
if(d->mode&DMDIR){
free(d);
return -1;
}
free(d);
print("kfs...");
if(pipe(p)<0)
fatal("pipe");
switch(pid = fork()){
case -1:
fatal("fork");
case 0:
arg = malloc((bargc+5)*sizeof(char*));
argp = arg;
*argp++ = "kfs";
*argp++ = "-f";
*argp++ = partition;
*argp++ = "-s";
for(i=1; i<bargc; i++)
*argp++ = bargv[i];
*argp = 0;
dup(p[0], 0);
dup(p[1], 1);
close(p[0]);
close(p[1]);
exec("/boot/kfs", arg);
fatal("can't exec kfs");
default:
break;
}
for(;;){
if((i = waitpid()) == -1)
fatal("waitpid for kfs failed");
if(i == pid)
break;
}
close(p[1]);
return p[0];
}
void
runv(char **argv)
{
int i, pid;
switch(pid = fork()){
case -1:
fatal("fork");
case 0:
exec(argv[0], argv);
fatal(smprint("can't exec %s: %r", argv[0]));
default:
while ((i = waitpid()) != pid && i != -1)
;
if(i == -1)
fatal(smprint("wait failed running %s", argv[0]));
}
}
void
run(char *file, ...)
{
runv(&file);
}
static int
print1(int fd, char *s)
{
return write(fd, s, strlen(s));
}
void
configloopback(void)
{
int fd;
if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
bind("#I", "/net", MAFTER);
if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
fatal("open /net/ipifc/clone for loopback");
}
if(print1(fd, "bind loopback /dev/null") < 0
|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
fatal("write /net/ipifc/clone for loopback");
}
int
connectlocalfossil(void)
{
int fd;
char *venti, *f[32], *p;
int nf;
char partition[128], buf[512];
char *dev;
if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
return -1;
/* look for fossil partition */
dev = disk ? disk : bootdisk;
snprint(partition, sizeof partition, "%sfossil", dev);
fd = open(partition, OREAD);
if(fd < 0){
strcpy(partition, dev);
fd = open(partition, OREAD);
if(fd < 0)
return -1;
}
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 127*1024);
close(fd);
if(memcmp(buf, "fossil config\n", 14) != 0){
if(strstr(partition, "/fossil"))
print("no fossil config found on %s\n", partition);
return -1;
}
settime(1, -1, nil);
/* make venti available. give it 20% of free memory. */
if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
if((fd = open(f[0], OREAD)) >= 0){
print("venti...");
memset(buf, 0, sizeof buf);
pread(fd, buf, 512, 248*1024);
close(fd);
if(memcmp(buf, "venti config\n", 13) != 0){
print("no venti config found on %s\n", f[0]);
return -1;
}
if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
print("/boot/venti does not exist\n");
return -1;
}
switch(nf){
case 1:
f[1] = "tcp!127.1!17034";
case 2:
f[2] = "tcp!127.1!8000";
}
configloopback();
run("/boot/venti", "-m", "20", "-c", f[0],
"-a", f[1], "-h", f[2], nil);
/*
* If the announce address is tcp!*!foo, then set
* $venti to tcp!127.1!foo instead, which is actually dialable.
*/
if((p = strstr(f[1], "!*!")) != 0){
*p = 0;
snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
f[1] = buf;
}
setenv("venti", f[1]);
}else{
/* set up the network so we can talk to the venti server */
/* this is such a crock. */
configip(nf, f, 0);
setenv("venti", f[0]);
}
}
/* start fossil. give it 20% of free memory. */
print("fossil(%s)...", partition);
run("/boot/fossil", "-m", "20", "-f", partition,
"-c", "srv -A fboot", "-c", "srv -p fscons", nil);
fd = open("#s/fboot", ORDWR);
if(fd < 0){
warning("open #s/fboot");
return -1;
}
remove("#s/fboot"); /* we'll repost fd as #s/boot after fversion(fd) */
return fd;
}
int
connectlocal(void)
{
int fd;
if(bind("#c", "/dev", MREPL) < 0)
fatal("bind #c");
if(bind("#p", "/proc", MREPL) < 0)
fatal("bind #p");
bind("#S", "/dev", MAFTER);
bind("#k", "/dev", MAFTER);
bind("#u", "/dev", MAFTER);
bind("#æ", "/dev", MAFTER);
mountusbparts(); /* make partfs partitions visible again */
if((fd = connectlocalfossil()) < 0)
fd = connectlocalkfs();
return fd;
}
|