~kris/9p

9hist

a58e250508740bf66041bd946455d286b4603dec — David du Colombier 34 years ago 9882d60
Plan 9 from Bell Labs 1992-03-17
A boot/aux.c => boot/aux.c +144 -0
@@ 0,0 1,144 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

int
plumb(char *dir, char *dest, int *efd, char *here)
{
	char buf[128];
	char name[128];
	int n;

	sprint(name, "%s/clone", dir);
	efd[0] = open(name, ORDWR);
	if(efd[0] < 0)
		return -1;
	n = read(efd[0], buf, sizeof(buf)-1);
	if(n < 0){
		close(efd[0]);
		return -1;
	}
	buf[n] = 0;
	sprint(name, "%s/%s/data", dir, buf);
	if(here){
		sprint(buf, "announce %s", here);
		if(sendmsg(efd[0], buf) < 0){
			close(efd[0]);
			return -1;
		}
	}
	sprint(buf, "connect %s", dest);
	if(sendmsg(efd[0], buf) < 0){
		close(efd[0]);
		return -1;
	}
	efd[1] = open(name, ORDWR);
	if(efd[1] < 0){
		close(efd[0]);
		return -1;
	}
	return efd[1];
}

int
sendmsg(int fd, char *msg)
{
	int n;

	n = strlen(msg);
	if(write(fd, msg, n) != n)
		return -1;
	return 0;
}

void
warning(char *s)
{
	char buf[ERRLEN];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
}

void
fatal(char *s)
{
	char buf[ERRLEN];

	errstr(buf);
	fprint(2, "boot: %s: %s\n", s, buf);
	exits(0);
}

int
readenv(char *name, char *buf, int len)
{
	int f, n;
	char ename[2*NAMELEN];

	sprint(ename, "#e/%s", name);
	buf[0] = 0;
	f = open(ename, OREAD);
	if(f < 0)
		return -1;
	n = read(f, buf, len-1);
	if(n >= 0)
		buf[n] = 0;
	close(f);
	return 0;
}

void
setenv(char *name, char *val)
{
	int f;
	char ename[2*NAMELEN];

	sprint(ename, "#e/%s", name);
	f = create(ename, 1, 0666);
	if(f < 0)
		return;
	write(f, val, strlen(val));
	close(f);
}

void
srvcreate(char *name, int fd)
{
	char *srvname;
	int f;

	srvname = strrchr(name, '/');
	if(srvname)
		srvname++;
	else
		srvname = name;

	sprint(buf, "#s/%s", srvname);
	f = create(buf, 1, 0666);
	if(f < 0)
		fatal(buf);
	sprint(buf, "%d", fd);
	if(write(f, buf, strlen(buf)) != strlen(buf))
		fatal("write");
	close(f);
}

int
outin(char *prompt, char *def, int len)
{
	int n;
	char buf[256];

	do{
		print("%s[%s]: ", prompt, *def ? def : "no default");
		n = read(0, buf, len);
	}while(n==0);
	if(n < 0)
		fatal("can't read #c/cons; please reboot");
	if(n != 1){
		buf[n-1] = 0;
		strcpy(def, buf);
	}
	return n;
}

A boot/boot.c => boot/boot.c +327 -0
@@ 0,0 1,327 @@
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "../port/bootp.h"
#include "../port/arp.h"

#define DEFSYS "bootes"
typedef struct Net	Net;
typedef struct Flavor	Flavor;

enum
{
	Nterm	= 4,
	CtrlD	= 4,
	Cr	= 13,
	View	= 0x80,
};

Fcall	hdr;
int	printcol;

char	cputype[NAMELEN];
char	terminal[NAMELEN];
char	sys[2*NAMELEN];
char	username[NAMELEN];

int mflag;
int fflag;
int kflag;

void	nop(int);
void	session(int);
int	cache(int);
void	swapproc(void);
void	settime(int);
Method	*rootserver(char*);

void
main(int argc, char *argv)
{
	int fd;
	Method *mp;
	char cmd[64];
	char flags[5];
	int islocal;

	sleep(1000);

	open("#c/cons", OREAD);
	open("#c/cons", OWRITE);
	open("#c/cons", OWRITE);

	ARGBEGIN{
	case 'u':
		strcpy(username, ARGF());
		break;
	case 'k':
		kflag = 1;
		break;
	case 'm':
		mflag = 1;
		break;
	case 'f':
		fflag = 1;
		break;
	}ARGEND

	readenv("cputype", cputype, sizeof(cputype));
	readenv("terminal", terminal, sizeof(cputype));

	/*
	 *  pick a method and initialize it
	 */
	mp = rootserver(*argv);
	islocal = strcmp(mp->name, "local") == 0;
	(*mp->config)(mp);

	/*
	 *  get/set key or password
	 */
	(*pword)(mp);

	/*
	 *  connect to the root file system
	 */
	fd = (*mp->connect)();
	if(fd < 0)
		fatal("can't connect to file server");
	if(!islocal){
		nop(fd);
		session(fd);
		fd = cache(fd);
		srvcreate(sys, fd);
	}
	srvcreate("boot", fd);

	/*
	 *  create the name space, mount the root fs
	 */
	if(bind("/", "/", MREPL) < 0)
		fatal("bind");
	if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0)
		fatal("mount");
	close(fd);

	/*
	 *  start local fs if its not the root file server
	 */
	if(!islocal){
		for(mp = method; mp->name; mp++)
			if(strcmp(mp->name, "local")==0){
				local = (*mp->connect)(mp);
				if(local < 0)
					break;
				if(mount(local, "/n/kfs", MAFTER|MCREATE, "", "") < 0)
					fatal("mount");
				close(local);
				break;
			}
	}

	settime(islocal);
	swapproc();

	sleep(1000);
	sprint(cmd, "/%s/init", cputype);
	sprint(flags, "-%s%s", cpuflag ? "c" : "t", mflag ? "m", "");
	execl(cmd, "init", flags, 0);
	fatal(cmd);
}

/*
 *  ask user from whence comes the root file system
 */
Method*
rootserver(char *arg)
{
	char prompt[256];
	char reply[64];
	Method *mp;
	char *cp;
	int n;

	mp = method;
	n = 0;
	sprint(prompt, "root is from (", mp->name);
	for(mp++; mp->name; mp++)
		n += sprint(prompt+n, ", %s", mp->name);
	sprint(prompt+n, ")");

	for(;;){
		strcpy(reply, method->name);
		if(arg == 0)
			outin(prompt, reply, sizeof(reply));
		else
			strcpy(reply, arg);
		arg = 0;
		for(mp = method; mp->name; mp++)
			if(*reply == *mp->name){
				cp = strchr(reply, '!');
				if(cp)
					strcpy(sys, cp+1);
				return mp;
			}
		if(mp->name == 0)
			continue;
	}
}

void
nop(int fd)
{
	long n;

	print("nop...");
	hdr.type = Tnop;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write nop");
	n = read(fd, buf, sizeof buf);
	if(n==2 && buf[0]=='O' && buf[1]=='K')
		n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read nop");
	if(convM2S(buf, &hdr, n) == 0) {
		print("n = %d; buf = %#.2x %#.2x %#.2x %#.2x\n",
			n, buf[0], buf[1], buf[2], buf[3]);
		fatal("format nop");
	}
	if(hdr.type != Rnop)
		fatal("not Rnop");
}

void
session(int fd)
{
	long n;

	print("session...");
	hdr.type = Tsession;
	hdr.tag = NOTAG;
	n = convS2M(&hdr, buf);
	if(write(fd, buf, n) != n)
		fatal("write session");
	n = read(fd, buf, sizeof buf);
	if(n <= 0)
		fatal("read session");
	if(convM2S(buf, &hdr, n) == 0)
		fatal("format session");
	if(hdr.type == Rerror){
		print("error %s;", hdr.ename);
		fatal(hdr.ename);
	}
	if(hdr.type != Rsession)
		fatal("not Rsession");
}

int
cache(int fd)
{
	ulong i;
	int p[2];
	char d[DIRLEN];
	char partition[2*NAMELEN];

	if(stat("/cfs", d) < 0)
		return fd;
	sprint(partition, "%scache", bootdisk);
	if(stat(partition, d) < 0)
		return fd;
	print("cfs...");
	if(pipe(p)<0)
		fatal("pipe");
	switch(fork()){
	case -1:
		fatal("fork");
	case 0:
		close(p[1]);
		dup(fd, 0);
		close(fd);
		dup(p[0], 1);
		close(p[0]);
		if(format)
			execl("/cfs", "bootcfs", "-fs", "-p", partition, 0);
		else
			execl("/cfs", "bootcfs", "-s", "-p", partition, 0);
		break;
	default:
		close(p[0]);
		close(fd);
		fd = p[1];
		break;
	}
	return fd;
}

void
swapproc(void)
{
	int fd;

	fd = open("#c/swap", OWRITE);
	if(fd < 0){
		warning("opening #c/swap");
		return;
	}
	if(write(fd, "start", 5) <= 0)
		warning("starting swap kproc");
}

void
settime(int islocal)
{
	int n, f;
	int timeset;
	Dir dir;
	char dirbuf[DIRLEN];
	char *srvname;

	print("time...");
	timeset = 0;
	if(islocal){
		/*
		 *  set the time from the real time clock
		 */
		f = open("#r/rtc", ORDWR);
		if(f >= 0){
			if((n = read(f, dirbuf, sizeof(dirbuf)-1)) > 0){
				dirbuf[n] = 0;
				timeset = 1;
			}
			close(f);
		}
	}
	if(timeset == 0){
		/*
		 *  set the time from the access time of the root
		 */
		f = open("#s/boot", ORDWR);
		if(f < 0)
			return;
		if(mount(f, "/n/boot", MREPL, "", "") < 0){
			close(f);
			return;
		}
		close(f);
		if(stat("/n/boot", dirbuf) < 0)
			fatal("stat");
		convM2D(dirbuf, &dir);
		sprint(dirbuf, "%ld", dir.atime);
		unmount(0, "/n/boot");
		/*
		 *  set real time clock if there is one
		 */
		f = open("#r/rtc", ORDWR);
		if(f > 0){
			write(f, dirbuf, strlen(dirbuf));
			close(f);
		}
		close(f);
	}

	f = open("#c/time", OWRITE);
	write(f, dirbuf, strlen(dirbuf));
	close(f);
}

A boot/boot.h => boot/boot.h +59 -0
@@ 0,0 1,59 @@
typedef struct Method	Method;
struct Method
{
	char	*name;
	void	(*config)(Method*);
	void	(*auth)(Method*);
	void	(*connect)(Method*);
	char	*arg;
};

extern char	terminal[NAMELEN];
extern char	sys[2*NAMELEN];
extern char	password[NAMELEN];
extern char	username[NAMELEN];
extern char	cputype[NAMELEN];
extern char	*bootdisk;
extern char	*initflag;
extern void	(*pword)(Method*);
extern int	kflag;

/* libc equivalent */
extern int	plumb(char*, char*, int*, char*);
extern int	outin(char*, char*, int);
extern int	sendmsg(int, char*);
extern void	warning(char*);
extern void	fatal(char*);
extern int	readenv(char*, char*, int);
extern void	setenv(char*, char*);
extern void	srvcreate(char*, int);
extern int	dkauth(void);
extern int	dkconnect(void);
extern void	userpasswd(int);
extern void	getpasswd(char*, int);

/* methods */
extern void	config9600(Method*);
extern int	auth9600(Method*);
extern int	connect9600(Method*);
extern void	config192000(Method*);
extern int	auth192000(Method*);
extern int	connect192000(Method*);
extern void	confighs(Method*);
extern int	authhs(Method*);
extern int	connecths(Method*);
extern void	configincon(Method*);
extern int	authincon(Method*);
extern int	connectincon(Method*);
extern void	configil(Method*);
extern int	authil(Method*);
extern int	connectil(Method*);
extern void	configtcp(Method*);
extern int	authtcp(Method*);
extern int	connecttcp(Method*);
extern void	configcyc(Method*);
extern int	authcyc(Method*);
extern int	connectcyc(Method*);
extern void	configlocal(Method*);
extern int	authlocal(Method*);
extern int	connectlocal(Method*);

A boot/getpasswd.c => boot/getpasswd.c +43 -0
@@ 0,0 1,43 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

void
getpasswd(char *p, int len)
{
	char c;
	int i, n, fd;

	fd = open("#c/consctl", OWRITE);
	if(fd < 0)
		fatal("can't open consctl; please reboot");
	write(fd, "rawon", 5);
 Prompt:		
	print("password: ");
	n = 0;
	for(;;){
		do{
			i = read(0, &c, 1);
			if(i < 0)
				fatal("can't read cons; please reboot");
		}while(i == 0);
		switch(c){
		case '\n':
			p[n] = '\0';
			close(fd);
			print("\n");
			return;
		case '\b':
			if(n > 0)
				n--;
			break;
		case 'u' - 'a' + 1:		/* cntrl-u */
			print("\n");
			goto Prompt;
		default:
			if(n < len - 1)
				p[n++] = c;
			break;
		}
	}
}

A boot/key.c => boot/key.c +42 -0
@@ 0,0 1,42 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

void
key(Method *mp)
{
	char password[20], key[7];
	int prompt, fd;

	USED(mp);

	prompt = kflag;
	fd = open("#r/nvram", ORDWR);
	if(fd < 0){
		prompt = 1;
		warning("can't open nvram");
	}
	if(prompt){
		do
			if(getpasswd(password, sizeof password) < 0){
				warning("can't read cons");
				return;
			}
		while(!passtokey(key, password, strlen(password)));
	}else if(seek(fd, 1024+900, 0) < 0 || read(fd, key, 7) != 7){
		close(fd);
		warning("can't read key from nvram");
	}
	if(kflag && seek(fd, 1024+900, 0) < 0 || write(fd, key, 7) != 7){
		close(fd);
		warning("can't write key to nvram");
	}
	close(fd);
	fd = open("#c/key", OWRITE);
	if(fd < 0)
		warning("can't open key");
	else if(write(fd, key, 7) != 7)
		warning("can't write key");
	close(fd);
}


A boot/local.c => boot/local.c +57 -0
@@ 0,0 1,57 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

static char *disk;

void
configlocal(Method *mp)
{
	disk = mp->arg;
	USED(mp);
}

int
authlocal(void)
{
	return -1;
}

int
connectlocal(void)
{
	ulong i;
	int p[2];
	char d[DIRLEN];
	char sbuf[32];
	char rbuf[32];
	char *mtpt;
	char partition[2*NAMELEN];

	if(stat("/kfs", d) < 0)
		return -1;
	sprint(partition, "%sfs", mp->arg ? mp->arg : bootdisk);
	if(stat(partition, d) < 0)
		return -1;

	if(bind("#c", "/dev", MREPL) < 0)
		fatal("bind #c");
	if(bind("#p", "/proc", MREPL) < 0)
		fatal("bind #p");
	if(pipe(p)<0)
		fatal("pipe");
	switch(fork()){
	case -1:
		fatal("fork");
	case 0:
		sprint(sbuf, "%d", p[0]);
		sprint(rbuf, "%d", p[1]);
		execl("/kfs", "kfs", "-f", partition, "-s", sbuf, rbuf, 0);
		fatal("can't exec kfs");
	default:
		break;
	}

	close(p[1]);
	return p[0];
}

A boot/userpasswd.c => boot/userpasswd.c +92 -0
@@ 0,0 1,92 @@
#include <u.h>
#include <libc.h>
#include <../boot/boot.h>

char	password[NAMELEN];

static int
passtokey(char *key, char *p, int n)
{
	uchar t[10];
	int c;

	memset(t, ' ', sizeof t);
	if(n < 5)
		return 0;
	if(n > 10)
		n = 10;
	strncpy((char*)t, p, n);
	if(n >= 9){
		c = p[8] & 0xf;
		if(n == 10)
			c += p[9] << 4;
		for(n = 0; n < 8; n++)
			if(c & (1 << n))
				t[n] -= ' ';
	}
	for(n = 0; n < 7; n++)
		key[n] = (t[n] >> n) + (t[n+1] << (8 - (n+1)));
	return 1;
}

/*
 *  get/set user name and password.  verify password with auth server.
 */
void
userpasswd(Method *mp)
{
	char key[7];
	char buf[8 + NAMELEN];
	int fd, crfd;

	if(*username == 0 || strcmp(username, "none") == 0){
		strcpy(username, "none");
		outin("user", username, sizeof(username));
	}
	crfd = fd = -1;
	while(strcmp(username, "none") != 0 && strcmp(mp->name, "local") != 0){
		getpasswd(password, sizeof password);
		if(!passtokey(key, password, strlen(password))){
			print("bad password; try again\n");
			continue;
		}
		fd = open("#c/key", OWRITE);
		if(fd < 0)
			fatal("can't open #c/key; please reboot");
		if(write(fd, key, 7) != 7)
			fatal("can't write #c/key; please reboot");
		close(fd);
		crfd = open("#c/crypt", ORDWR);
		if(crfd < 0)
			fatal("can't open crypt file");
		write(crfd, "E", 1);
		fd = (*mp->auth)();
		if(fd < 0){
			warning("password not checked!");
			break;
		}
		strncpy(buf+8, username, NAMELEN);
		if(read(fd, buf, 8) != 8
		|| write(crfd, buf, 8) != 8
		|| read(crfd, buf, 8) != 8
		|| write(fd, buf, 8 + NAMELEN) != 8 + NAMELEN){
			warning("password not checked!");
			break;
		}
		if(read(fd, buf, 2) == 2 && buf[0]=='O' && buf[1]=='K')
			break;
		close(fd);
		outin("user", username, sizeof(username));
	}
	close(fd);
	close(crfd);

	/* set user now that we're sure */
	fd = open("#c/user", OWRITE|OTRUNC);
	if(fd >= 0){
		if(write(fd, username, strlen(username)) < 0)
			warning("write user name");
		close(fd);
	}else
		warning("open #c/user");
}

M port/devcons.c => port/devcons.c +1 -1
@@ 379,7 379,7 @@ int
readnum(ulong off, char *buf, ulong n, ulong val, int size)
{
	char tmp[64];
	Op op = (Op){ tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG };
	Op op = { tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG };

	numbconv(&op, 10);
	tmp[size-1] = ' ';

M port/devmnt.c => port/devmnt.c +3 -4
@@ 160,12 160,11 @@ mntattach(char *muxattach)
	m->blocksize = MAXFDATA;

	switch(devchar[m->c->type]) {
	case 'H':			/* Hotrod */
	case '3':			/* BIT3 */
		m->mux = 1;
		break;
	default:
		m->mux = 0;
	case 'H':			/* Cyclone */
		m->mux = 1;
		break;
	}
	incref(m->c);
	unlock(m);

M port/page.c => port/page.c +2 -1
@@ 97,7 97,7 @@ addsplit(Region *r, ulong start, ulong end)
 *  Called to allocate permanent data structures, before calling pageinit().
 *  We assume all of text+data+bss is in the first memory bank.
 *
 *  alignment is in number of bytes.  It pretains both to the start and
 *  alignment is in number of bytes.  It pertains both to the start and
 *  end of the allocated memory.
 *
 *  If crevasse is specified, no allocation can span an address that is


@@ 195,6 195,7 @@ pageinit(void)
	ulong i, vmem, pmem, hw, hr;
	Page *p;

print("addr0 %lux addr1 %lux\n", palloc.addr0, palloc.addr1);
	/*
	 *  calculate an upper bound to the number of pages structures
	 *  we'll need (np).

M power/devhotrod.c => power/devhotrod.c +1 -3
@@ 423,9 423,7 @@ hotrodintr(int vec)
		if(h->ri >= NRQ)
			h->ri = 0;
		hm->intr = 1;
		if(hm->abort)
			print("abort wakeup\n");
		else
		if(!hm->abort)
			wakeup(&hm->r);
	}
}