Small tweaks
Lots of new code imported.
diff --git a/include/9p.h b/include/9p.h
new file mode 100644
index 0000000..6703d60
--- /dev/null
+++ b/include/9p.h
@@ -0,0 +1,244 @@
+#ifndef __9P_H__
+#define __9P_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+#pragma src "/sys/src/lib9p"
+#pragma lib "lib9p.a"
+*/
+
+/*
+ * Maps from ulongs to void*s.
+ */
+typedef struct Intmap	Intmap;
+
+Intmap*	allocmap(void (*inc)(void*));
+void		freemap(Intmap*, void (*destroy)(void*));
+void*	lookupkey(Intmap*, ulong);
+void*	insertkey(Intmap*, ulong, void*);
+int		caninsertkey(Intmap*, ulong, void*);
+void*	deletekey(Intmap*, ulong);
+
+/*
+ * Fid and Request structures.
+ */
+typedef struct Fid		Fid;
+typedef struct Req		Req;
+typedef struct Fidpool	Fidpool;
+typedef struct Reqpool	Reqpool;
+typedef struct File		File;
+typedef struct Filelist	Filelist;
+typedef struct Tree		Tree;
+typedef struct Readdir	Readdir;
+typedef struct Srv Srv;
+
+struct Fid
+{
+	ulong	fid;
+	char		omode;	/* -1 = not open */
+	File*		file;
+	char*	uid;
+	Qid		qid;
+	void*	aux;
+
+/* below is implementation-specific; don't use */
+	Readdir*	rdir;
+	Ref		ref;
+	Fidpool*	pool;
+	vlong	diroffset;
+	long		dirindex;
+};
+
+struct Req
+{
+	ulong	tag;
+	void*	aux;
+	Fcall		ifcall;
+	Fcall		ofcall;
+	Dir		d;
+	Req*		oldreq;
+	Fid*		fid;
+	Fid*		afid;
+	Fid*		newfid;
+	Srv*		srv;
+
+/* below is implementation-specific; don't use */
+	QLock	lk;
+	Ref		ref;
+	Reqpool*	pool;
+	uchar*	buf;
+	uchar	type;
+	uchar	responded;
+	char*	error;
+	void*	rbuf;
+	Req**	flush;
+	int		nflush;
+};
+
+/*
+ * Pools to maintain Fid <-> fid and Req <-> tag maps.
+ */
+
+struct Fidpool {
+	Intmap	*map;
+	void		(*destroy)(Fid*);
+	Srv		*srv;
+};
+
+struct Reqpool {
+	Intmap	*map;
+	void		(*destroy)(Req*);
+	Srv		*srv;
+};
+
+Fidpool*	allocfidpool(void (*destroy)(Fid*));
+void		freefidpool(Fidpool*);
+Fid*		allocfid(Fidpool*, ulong);
+Fid*		lookupfid(Fidpool*, ulong);
+void		closefid(Fid*);
+Fid*		removefid(Fidpool*, ulong);
+
+Reqpool*	allocreqpool(void (*destroy)(Req*));
+void		freereqpool(Reqpool*);
+Req*		allocreq(Reqpool*, ulong);
+Req*		lookupreq(Reqpool*, ulong);
+void		closereq(Req*);
+Req*		removereq(Reqpool*, ulong);
+
+typedef	int	Dirgen(int, Dir*, void*);
+void		dirread9p(Req*, Dirgen*, void*);
+
+/*
+ * File trees.
+ */
+struct File {
+	Ref ref;
+	Dir dir;
+	File *parent;
+	void *aux;
+
+/* below is implementation-specific; don't use */
+	RWLock rwlock;
+	Filelist *filelist;
+	Tree *tree;
+	int nchild;
+	int allocd;
+};
+
+struct Tree {
+	File *root;
+	void	(*destroy)(File *file);
+
+/* below is implementation-specific; don't use */
+	Lock genlock;
+	ulong qidgen;
+	ulong dirqidgen;
+};
+
+Tree*	alloctree(char*, char*, ulong, void(*destroy)(File*));
+void		freetree(Tree*);
+File*		createfile(File*, char*, char*, ulong, void*);
+int		removefile(File*);
+void		closefile(File*);
+File*		walkfile(File*, char*);
+Readdir*	opendirfile(File*);
+long		readdirfile(Readdir*, uchar*, long);
+void		closedirfile(Readdir*);
+
+/*
+ * Kernel-style command parser
+ */
+typedef struct Cmdbuf Cmdbuf;
+typedef struct Cmdtab Cmdtab;
+Cmdbuf*		parsecmd(char *a, int n);
+void		respondcmderror(Req*, Cmdbuf*, char*, ...);
+Cmdtab*	lookupcmd(Cmdbuf*, Cmdtab*, int);
+/*
+#pragma varargck argpos respondcmderr 3
+*/
+struct Cmdbuf
+{
+	char	*buf;
+	char	**f;
+	int	nf;
+};
+
+struct Cmdtab
+{
+	int	index;	/* used by client to switch on result */
+	char	*cmd;	/* command name */
+	int	narg;	/* expected #args; 0 ==> variadic */
+};
+
+/*
+ * File service loop.
+ */
+struct Srv {
+	Tree*	tree;
+	void		(*destroyfid)(Fid*);
+	void		(*destroyreq)(Req*);
+	void		(*end)(Srv*);
+	void*	aux;
+
+	void		(*attach)(Req*);
+	void		(*auth)(Req*);
+	void		(*open)(Req*);
+	void		(*create)(Req*);
+	void		(*read)(Req*);
+	void		(*write)(Req*);
+	void		(*remove)(Req*);
+	void		(*flush)(Req*);
+	void		(*stat)(Req*);
+	void		(*wstat)(Req*);
+	void		(*walk)(Req*);
+	char*	(*clone)(Fid*, Fid*);
+	char*	(*walk1)(Fid*, char*, Qid*);
+
+	int		infd;
+	int		outfd;
+	int		nopipe;
+	int		srvfd;
+	int		leavefdsopen;	/* magic for acme win */
+
+/* below is implementation-specific; don't use */
+	Fidpool*	fpool;
+	Reqpool*	rpool;
+	uint		msize;
+
+	uchar*	rbuf;
+	QLock	rlock;
+	uchar*	wbuf;
+	QLock	wlock;
+};
+
+void		srv(Srv*);
+void		postmountsrv(Srv*, char*, char*, int);
+int 		postfd(char*, int);
+int		chatty9p;
+void		respond(Req*, char*);
+void		threadpostmountsrv(Srv*, char*, char*, int);
+
+/*
+ * Helper.  Assumes user is same as group.
+ */
+int		hasperm(File*, char*, int);
+
+void*	emalloc9p(ulong);
+void*	erealloc9p(void*, ulong);
+char*	estrdup9p(char*);
+
+enum {
+	OMASK = 3
+};
+
+void readstr(Req*, char*);
+void readbuf(Req*, void*, long);
+void	walkandclone(Req*, char*(*walk1)(Fid*,char*,void*), char*(*clone)(Fid*,Fid*,void*), void*);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/auth.h b/include/auth.h
new file mode 100644
index 0000000..f0ecdea
--- /dev/null
+++ b/include/auth.h
@@ -0,0 +1,159 @@
+#ifndef __AUTH_H__
+#define __AUTH_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+#pragma	src	"/sys/src/libauth"
+#pragma	lib	"libauth.a"
+*/
+
+/*
+ * Interface for typical callers.
+ */
+
+typedef struct	AuthInfo	AuthInfo;
+typedef struct	Chalstate	Chalstate;
+typedef struct	Chapreply	Chapreply;
+typedef struct	MSchapreply	MSchapreply;
+typedef struct	UserPasswd	UserPasswd;
+typedef struct	AuthRpc		AuthRpc;
+
+enum
+{
+	MAXCHLEN=	256,		/* max challenge length	*/
+	MAXNAMELEN=	256,		/* maximum name length */
+	MD5LEN=		16,
+
+	ARok = 0,			/* rpc return values */
+	ARdone,
+	ARerror,
+	ARneedkey,
+	ARbadkey,
+	ARwritenext,
+	ARtoosmall,
+	ARtoobig,
+	ARrpcfailure,
+	ARphase,
+
+	AuthRpcMax = 4096,
+};
+
+struct AuthRpc
+{
+	int afd;
+	char ibuf[AuthRpcMax];
+	char obuf[AuthRpcMax];
+	char *arg;
+	uint narg;
+};
+
+struct AuthInfo
+{
+	char	*cuid;		/* caller id */
+	char	*suid;		/* server id */
+	char	*cap;		/* capability (only valid on server side) */
+	int	nsecret;	/* length of secret */
+	uchar	*secret;	/* secret */
+};
+
+struct Chalstate
+{
+	char	*user;
+	char	chal[MAXCHLEN];
+	int	nchal;
+	void	*resp;
+	int	nresp;
+
+/* for implementation only */
+	int	afd;			/* to factotum */
+	AuthRpc	*rpc;			/* to factotum */
+	char	userbuf[MAXNAMELEN];	/* temp space if needed */
+	int	userinchal;		/* user was sent to obtain challenge */
+};
+
+struct	Chapreply		/* for protocol "chap" */
+{
+	uchar	id;
+	char	resp[MD5LEN];
+};
+
+struct	MSchapreply	/* for protocol "mschap" */
+{
+	char	LMresp[24];		/* Lan Manager response */
+	char	NTresp[24];		/* NT response */
+};
+
+struct	UserPasswd
+{
+	char	*user;
+	char	*passwd;
+};
+
+extern	int	newns(char*, char*);
+extern	int	addns(char*, char*);
+
+extern	int	noworld(char*);
+extern	int	amount(int, char*, int, char*);
+
+/* these two may get generalized away -rsc */
+extern	int	login(char*, char*, char*);
+extern	int	httpauth(char*, char*);
+
+typedef struct Attr Attr;
+enum {
+	AttrNameval,		/* name=val -- when matching, must have name=val */
+	AttrQuery,		/* name? -- when matching, must be present */
+	AttrDefault,		/* name:=val -- when matching, if present must match INTERNAL */
+};
+struct Attr
+{
+	int type;
+	Attr *next;
+	char *name;
+	char *val;
+};
+
+typedef int AuthGetkey(char*);
+
+int	_attrfmt(Fmt*);
+Attr	*_copyattr(Attr*);
+Attr	*_delattr(Attr*, char*);
+Attr	*_findattr(Attr*, char*);
+void	_freeattr(Attr*);
+Attr	*_mkattr(int, char*, char*, Attr*);
+Attr	*_parseattr(char*);
+char	*_strfindattr(Attr*, char*);
+/*
+#pragma varargck type "A" Attr*
+*/
+
+extern AuthInfo*	fauth_proxy(int, AuthRpc *rpc, AuthGetkey *getkey, char *params);
+extern AuthInfo*	auth_proxy(int fd, AuthGetkey *getkey, char *fmt, ...);
+extern int		auth_getkey(char*);
+extern int		(*amount_getkey)(char*);
+extern void		auth_freeAI(AuthInfo *ai);
+extern int		auth_chuid(AuthInfo *ai, char *ns);
+extern Chalstate	*auth_challenge(char*, ...);
+extern AuthInfo*	auth_response(Chalstate*);
+extern int		auth_respond(void*, uint, char*, uint, void*, uint, AuthGetkey *getkey, char*, ...);
+extern void		auth_freechal(Chalstate*);
+extern AuthInfo*	auth_userpasswd(char *user, char *passwd);
+extern UserPasswd*	auth_getuserpasswd(AuthGetkey *getkey, char*, ...);
+extern AuthInfo*	auth_getinfo(AuthRpc *rpc);
+extern AuthRpc*		auth_allocrpc(int afd);
+extern Attr*		auth_attr(AuthRpc *rpc);
+extern void		auth_freerpc(AuthRpc *rpc);
+extern uint		auth_rpc(AuthRpc *rpc, char *verb, void *a, int n);
+extern int		auth_wep(char*, char*, ...);
+/*
+#pragma varargck argpos auth_proxy 3
+#pragma varargck argpos auth_challenge 1
+#pragma varargck argpos auth_respond 3
+#pragma varargck argpos auth_getuserpasswd 2
+*/
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/authsrv.h b/include/authsrv.h
new file mode 100644
index 0000000..1149a21
--- /dev/null
+++ b/include/authsrv.h
@@ -0,0 +1,177 @@
+#ifndef __AUTHSRV_H__
+#define __AUTHSRV_H__ 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+#pragma	src	"/sys/src/libauthsrv"
+#pragma	lib	"libauthsrv.a"
+*/
+
+/*
+ * Interface for talking to authentication server.
+ */
+typedef struct	Ticket		Ticket;
+typedef struct	Ticketreq	Ticketreq;
+typedef struct	Authenticator	Authenticator;
+typedef struct	Nvrsafe		Nvrsafe;
+typedef struct	Passwordreq	Passwordreq;
+typedef struct	OChapreply	OChapreply;
+typedef struct	OMSchapreply	OMSchapreply;
+
+enum
+{
+	ANAMELEN=	28,		/* maximum size of name in previous proto */
+	AERRLEN=	64,		/* maximum size of errstr in previous proto */
+	DOMLEN=		48,		/* length of an authentication domain name */
+	DESKEYLEN=	7,		/* length of a des key for encrypt/decrypt */
+	CHALLEN=	8,		/* length of a plan9 sk1 challenge */
+	NETCHLEN=	16,		/* max network challenge length (used in AS protocol) */
+	CONFIGLEN=	14,
+	SECRETLEN=	32,		/* max length of a secret */
+
+	KEYDBOFF=	8,		/* length of random data at the start of key file */
+	OKEYDBLEN=	ANAMELEN+DESKEYLEN+4+2,	/* length of an entry in old key file */
+	KEYDBLEN=	OKEYDBLEN+SECRETLEN,	/* length of an entry in key file */
+	OMD5LEN=	16,
+};
+
+/* encryption numberings (anti-replay) */
+enum
+{
+	AuthTreq=1,	/* ticket request */
+	AuthChal=2,	/* challenge box request */
+	AuthPass=3,	/* change password */
+	AuthOK=4,	/* fixed length reply follows */
+	AuthErr=5,	/* error follows */
+	AuthMod=6,	/* modify user */
+	AuthApop=7,	/* apop authentication for pop3 */
+	AuthOKvar=9,	/* variable length reply follows */
+	AuthChap=10,	/* chap authentication for ppp */
+	AuthMSchap=11,	/* MS chap authentication for ppp */
+	AuthCram=12,	/* CRAM verification for IMAP (RFC2195 & rfc2104) */
+	AuthHttp=13,	/* http domain login */
+	AuthVNC=14,	/* VNC server login (deprecated) */
+
+
+	AuthTs=64,	/* ticket encrypted with server's key */
+	AuthTc,		/* ticket encrypted with client's key */
+	AuthAs,		/* server generated authenticator */
+	AuthAc,		/* client generated authenticator */
+	AuthTp,		/* ticket encrypted with client's key for password change */
+	AuthHr,		/* http reply */
+};
+
+struct Ticketreq
+{
+	char	type;
+	char	authid[ANAMELEN];	/* server's encryption id */
+	char	authdom[DOMLEN];	/* server's authentication domain */
+	char	chal[CHALLEN];		/* challenge from server */
+	char	hostid[ANAMELEN];	/* host's encryption id */
+	char	uid[ANAMELEN];		/* uid of requesting user on host */
+};
+#define	TICKREQLEN	(3*ANAMELEN+CHALLEN+DOMLEN+1)
+
+struct Ticket
+{
+	char	num;			/* replay protection */
+	char	chal[CHALLEN];		/* server challenge */
+	char	cuid[ANAMELEN];		/* uid on client */
+	char	suid[ANAMELEN];		/* uid on server */
+	char	key[DESKEYLEN];		/* nonce DES key */
+};
+#define	TICKETLEN	(CHALLEN+2*ANAMELEN+DESKEYLEN+1)
+
+struct Authenticator
+{
+	char	num;			/* replay protection */
+	char	chal[CHALLEN];
+	ulong	id;			/* authenticator id, ++'d with each auth */
+};
+#define	AUTHENTLEN	(CHALLEN+4+1)
+
+struct Passwordreq
+{
+	char	num;
+	char	old[ANAMELEN];
+	char	new[ANAMELEN];
+	char	changesecret;
+	char	secret[SECRETLEN];	/* new secret */
+};
+#define	PASSREQLEN	(2*ANAMELEN+1+1+SECRETLEN)
+
+struct	OChapreply
+{
+	uchar	id;
+	char	uid[ANAMELEN];
+	char	resp[OMD5LEN];
+};
+
+struct	OMSchapreply
+{
+	char	uid[ANAMELEN];
+	char	LMresp[24];		/* Lan Manager response */
+	char	NTresp[24];		/* NT response */
+};
+
+/*
+ *  convert to/from wire format
+ */
+extern	int	convT2M(Ticket*, char*, char*);
+extern	void	convM2T(char*, Ticket*, char*);
+extern	void	convM2Tnoenc(char*, Ticket*);
+extern	int	convA2M(Authenticator*, char*, char*);
+extern	void	convM2A(char*, Authenticator*, char*);
+extern	int	convTR2M(Ticketreq*, char*);
+extern	void	convM2TR(char*, Ticketreq*);
+extern	int	convPR2M(Passwordreq*, char*, char*);
+extern	void	convM2PR(char*, Passwordreq*, char*);
+
+/*
+ *  convert ascii password to DES key
+ */
+extern	int	opasstokey(char*, char*);
+extern	int	passtokey(char*, char*);
+
+/*
+ *  Nvram interface
+ */
+enum {
+	NVwrite = 1<<0,		/* always prompt and rewrite nvram */
+	NVwriteonerr = 1<<1,	/* prompt and rewrite nvram when corrupt */
+};
+
+struct Nvrsafe
+{
+	char	machkey[DESKEYLEN];
+	uchar	machsum;
+	char	authkey[DESKEYLEN];
+	uchar	authsum;
+	char	config[CONFIGLEN];
+	uchar	configsum;
+	char	authid[ANAMELEN];
+	uchar	authidsum;
+	char	authdom[DOMLEN];
+	uchar	authdomsum;
+};
+
+extern	uchar	nvcsum(void*, int);
+extern int	readnvram(Nvrsafe*, int);
+
+/*
+ *  call up auth server
+ */
+extern	int	authdial(char *netroot, char *authdom);
+
+/*
+ *  exchange messages with auth server
+ */
+extern	int	_asgetticket(int, char*, char*);
+extern	int	_asrdresp(int, char*, int);
+extern	int	sslnegotiate(int, Ticket*, char**, char**);
+extern	int	srvsslnegotiate(int, Ticket*, char**, char**);
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/mp.h b/include/mp.h
new file mode 100644
index 0000000..876c0c7
--- /dev/null
+++ b/include/mp.h
@@ -0,0 +1,153 @@
+#ifndef __MP_H__
+#define __MP_H__ 1
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+#pragma	src	"/sys/src/libmp"
+#pragma	lib	"libmp.a"
+*/
+
+#define _MPINT 1
+
+typedef long mpdigit;
+
+// the code assumes mpdigit to be at least an int
+// mpdigit must be an atomic type.  mpdigit is defined
+// in the architecture specific u.h
+
+typedef struct mpint mpint;
+
+struct mpint
+{
+	int	sign;	// +1 or -1
+	int	size;	// allocated digits
+	int	top;	// significant digits
+	mpdigit	*p;
+	char	flags;
+};
+
+enum
+{
+	MPstatic=	0x01,
+	Dbytes=		sizeof(mpdigit),	// bytes per digit
+	Dbits=		Dbytes*8		// bits per digit
+};
+
+// allocation
+void	mpsetminbits(int n);	// newly created mpint's get at least n bits
+mpint*	mpnew(int n);		// create a new mpint with at least n bits
+void	mpfree(mpint *b);
+void	mpbits(mpint *b, int n);	// ensure that b has at least n bits
+void	mpnorm(mpint *b);		// dump leading zeros
+mpint*	mpcopy(mpint *b);
+void	mpassign(mpint *old, mpint *new);
+
+// random bits
+mpint*	mprand(int bits, void (*gen)(uchar*, int), mpint *b);
+
+// conversion
+mpint*	strtomp(char*, char**, int, mpint*);	// ascii
+int	mpfmt(Fmt*);
+char*	mptoa(mpint*, int, char*, int);
+mpint*	letomp(uchar*, uint, mpint*);	// byte array, little-endian
+int	mptole(mpint*, uchar*, uint, uchar**);
+mpint*	betomp(uchar*, uint, mpint*);	// byte array, little-endian
+int	mptobe(mpint*, uchar*, uint, uchar**);
+uint	mptoui(mpint*);			// unsigned int
+mpint*	uitomp(uint, mpint*);
+int	mptoi(mpint*);			// int
+mpint*	itomp(int, mpint*);
+uvlong	mptouv(mpint*);			// unsigned vlong
+mpint*	uvtomp(uvlong, mpint*);
+vlong	mptov(mpint*);			// vlong
+mpint*	vtomp(vlong, mpint*);
+
+// divide 2 digits by one
+void	mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
+
+// in the following, the result mpint may be
+// the same as one of the inputs.
+void	mpadd(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
+void	mpsub(mpint *b1, mpint *b2, mpint *diff);	// diff = b1-b2
+void	mpleft(mpint *b, int shift, mpint *res);	// res = b<<shift
+void	mpright(mpint *b, int shift, mpint *res);	// res = b>>shift
+void	mpmul(mpint *b1, mpint *b2, mpint *prod);	// prod = b1*b2
+void	mpexp(mpint *b, mpint *e, mpint *m, mpint *res);	// res = b**e mod m
+void	mpmod(mpint *b, mpint *m, mpint *remainder);	// remainder = b mod m
+
+// quotient = dividend/divisor, remainder = dividend % divisor
+void	mpdiv(mpint *dividend, mpint *divisor,  mpint *quotient, mpint *remainder);
+
+// return neg, 0, pos as b1-b2 is neg, 0, pos
+int	mpcmp(mpint *b1, mpint *b2);
+
+// extended gcd return d, x, and y, s.t. d = gcd(a,b) and ax+by = d
+void	mpextendedgcd(mpint *a, mpint *b, mpint *d, mpint *x, mpint *y);
+
+// res = b**-1 mod m
+void	mpinvert(mpint *b, mpint *m, mpint *res);
+
+// bit counting
+int	mpsignif(mpint*);	// number of sigificant bits in mantissa
+int	mplowbits0(mpint*);	// k, where n = 2**k * q for odd q
+
+// well known constants
+extern mpint	*mpzero, *mpone, *mptwo;
+
+// sum[0:alen] = a[0:alen-1] + b[0:blen-1]
+// prereq: alen >= blen, sum has room for alen+1 digits
+void	mpvecadd(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *sum);
+
+// diff[0:alen-1] = a[0:alen-1] - b[0:blen-1]
+// prereq: alen >= blen, diff has room for alen digits
+void	mpvecsub(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *diff);
+
+// p[0:n] += m * b[0:n-1]
+// prereq: p has room for n+1 digits
+void	mpvecdigmuladd(mpdigit *b, int n, mpdigit m, mpdigit *p);
+
+// p[0:n] -= m * b[0:n-1]
+// prereq: p has room for n+1 digits
+int	mpvecdigmulsub(mpdigit *b, int n, mpdigit m, mpdigit *p);
+
+// p[0:alen*blen-1] = a[0:alen-1] * b[0:blen-1]
+// prereq: alen >= blen, p has room for m*n digits
+void	mpvecmul(mpdigit *a, int alen, mpdigit *b, int blen, mpdigit *p);
+
+// sign of a - b or zero if the same
+int	mpveccmp(mpdigit *a, int alen, mpdigit *b, int blen);
+
+// divide the 2 digit dividend by the one digit divisor and stick in quotient
+// we assume that the result is one digit - overflow is all 1's
+void	mpdigdiv(mpdigit *dividend, mpdigit divisor, mpdigit *quotient);
+
+// playing with magnitudes
+int	mpmagcmp(mpint *b1, mpint *b2);
+void	mpmagadd(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
+void	mpmagsub(mpint *b1, mpint *b2, mpint *sum);	// sum = b1+b2
+
+// chinese remainder theorem
+typedef struct CRTpre	CRTpre;		// precomputed values for converting
+					//  twixt residues and mpint
+typedef struct CRTres	CRTres;		// residue form of an mpint
+
+struct CRTres
+{
+	int	n;		// number of residues
+	mpint	*r[1];		// residues
+};
+
+CRTpre*	crtpre(int, mpint**);			// precompute conversion values
+CRTres*	crtin(CRTpre*, mpint*);			// convert mpint to residues
+void	crtout(CRTpre*, CRTres*, mpint*);	// convert residues to mpint
+void	crtprefree(CRTpre*);
+void	crtresfree(CRTres*);
+
+
+/* #pragma	varargck	type	"B"	mpint* */
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/include/nfs3.h b/include/nfs3.h
new file mode 100644
index 0000000..0da51b5
--- /dev/null
+++ b/include/nfs3.h
@@ -0,0 +1,801 @@
+/* 
+ * NFS mounter V3;  see RFC 1813
+ */
+/*
+#pragma lib "libsunrpc.a"
+#pragma src "/sys/src/libsunrpc"
+*/
+#define _NFS3H_ /* sorry */
+
+enum {
+	NfsMount1HandleSize = 32,
+	NfsMount3MaxPathSize = 1024,
+	NfsMount3MaxNameSize = 255,
+	NfsMount3MaxHandleSize = 64,
+	NfsMount3Program = 100005,
+	NfsMount3Version = 3,
+	NfsMount1Program = 100005,
+	NfsMount1Version = 1
+};
+typedef struct NfsMount3TNull NfsMount3TNull;
+typedef struct NfsMount3RNull NfsMount3RNull;
+typedef struct NfsMount3TMnt NfsMount3TMnt;
+typedef struct NfsMount3RMnt NfsMount3RMnt;
+typedef struct NfsMount3TDump NfsMount3TDump;
+typedef struct NfsMount3Entry NfsMount3Entry;
+typedef struct NfsMount3RDump NfsMount3RDump;
+typedef struct NfsMount3TUmnt NfsMount3TUmnt;
+typedef struct NfsMount3RUmnt NfsMount3RUmnt;
+typedef struct NfsMount3Export NfsMount3Export;
+typedef struct NfsMount3TUmntall NfsMount3TUmntall;
+typedef struct NfsMount3RUmntall NfsMount3RUmntall;
+typedef struct NfsMount3TExport NfsMount3TExport;
+typedef struct NfsMount3RExport NfsMount3RExport;
+
+typedef enum
+{
+	NfsMount3CallTNull,
+	NfsMount3CallRNull,
+	NfsMount3CallTMnt,
+	NfsMount3CallRMnt,
+	NfsMount3CallTDump,
+	NfsMount3CallRDump,
+	NfsMount3CallTUmnt,
+	NfsMount3CallRUmnt,
+	NfsMount3CallTUmntall,
+	NfsMount3CallRUmntall,
+	NfsMount3CallTExport,
+	NfsMount3CallRExport
+} NfsMount3CallType;
+
+struct NfsMount3TNull {
+	SunCall call;
+};
+
+struct NfsMount3RNull {
+	SunCall call;
+};
+
+struct NfsMount3TMnt {
+	SunCall call;
+	char *path;
+};
+
+struct NfsMount3RMnt {
+	SunCall call;
+	uint status;
+	uchar *handle;
+	uint len;
+	u32int *auth;
+	u32int nauth;
+};
+
+struct NfsMount3TDump {
+	SunCall call;
+};
+
+struct NfsMount3Entry {
+	char *host;
+	char *path;
+};
+
+struct NfsMount3RDump {
+	SunCall call;
+	uchar *data;
+	u32int count;
+};
+
+struct NfsMount3TUmnt {
+	SunCall call;
+	char *path;
+};
+
+struct NfsMount3RUmnt {
+	SunCall call;
+};
+
+struct NfsMount3Export {
+	char *path;
+	char **g;
+	u32int ng;
+};
+
+struct NfsMount3TUmntall {
+	SunCall call;
+};
+
+struct NfsMount3RUmntall {
+	SunCall call;
+};
+
+struct NfsMount3TExport {
+	SunCall call;
+};
+
+struct NfsMount3RExport {
+	SunCall call;
+	uchar *data;
+	u32int count;
+};
+
+uint nfsmount3exportgroupsize(uchar*);
+uint nfsmount3exportsize(NfsMount3Export*);
+int nfsmount3exportpack(uchar*, uchar*, uchar**, NfsMount3Export*);
+int nfsmount3exportunpack(uchar*, uchar*, uchar**, char**, char***, NfsMount3Export*);
+int nfsmount3entrypack(uchar*, uchar*, uchar**, NfsMount3Entry*);
+int nfsmount3entryunpack(uchar*, uchar*, uchar**, NfsMount3Entry*);
+uint nfsmount3entrysize(NfsMount3Entry*);
+
+extern SunProg nfsmount3prog;
+
+/*
+ * NFS V3; see RFC 1813
+ */
+enum {
+	Nfs3MaxHandleSize = 64,
+	Nfs3CookieVerfSize = 8,
+	Nfs3CreateVerfSize = 8,
+	Nfs3WriteVerfSize = 8,
+	Nfs3AccessRead = 1,
+	Nfs3AccessLookup = 2,
+	Nfs3AccessModify = 4,
+	Nfs3AccessExtend = 8,
+	Nfs3AccessDelete = 16,
+	Nfs3AccessExecute = 32,
+	Nfs3FsHasLinks = 1,
+	Nfs3FsHasSymlinks = 2,
+	Nfs3FsHomogeneous = 8,
+	Nfs3FsCanSetTime = 16,
+
+	Nfs3Version = 3,	
+	Nfs3Program = 100003,
+};
+typedef enum
+{
+	Nfs3Ok = 0,
+	Nfs3ErrNotOwner = 1,
+	Nfs3ErrNoEnt = 2,
+	Nfs3ErrIo = 5,
+	Nfs3ErrNxio = 6,
+	Nfs3ErrNoMem = 12,
+	Nfs3ErrAcces = 13,
+	Nfs3ErrExist = 17,
+	Nfs3ErrXDev = 18,
+	Nfs3ErrNoDev = 19,
+	Nfs3ErrNotDir = 20,
+	Nfs3ErrIsDir = 21,
+	Nfs3ErrInval = 22,
+	Nfs3ErrFbig = 27,
+	Nfs3ErrNoSpc = 28,
+	Nfs3ErrRoFs = 30,
+	Nfs3ErrMLink = 31,
+	Nfs3ErrNameTooLong = 63,
+	Nfs3ErrNotEmpty = 66,
+	Nfs3ErrDQuot = 69,
+	Nfs3ErrStale = 70,
+	Nfs3ErrRemote = 71,
+	Nfs3ErrBadHandle = 10001,
+	Nfs3ErrNotSync = 10002,
+	Nfs3ErrBadCookie = 10003,
+	Nfs3ErrNotSupp = 10004,
+	Nfs3ErrTooSmall = 10005,
+	Nfs3ErrServerFault = 10006,
+	Nfs3ErrBadType = 10007,
+	Nfs3ErrJukebox = 10008,
+	Nfs3ErrFprintNotFound = 10009,
+	Nfs3ErrAborted = 10010,
+} Nfs3Status;
+
+void nfs3Errstr(Nfs3Status);
+
+typedef enum
+{
+	Nfs3FileReg = 1,
+	Nfs3FileDir = 2,
+	Nfs3FileBlock = 3,
+	Nfs3FileChar = 4,
+	Nfs3FileSymlink = 5,
+	Nfs3FileSocket = 6,
+	Nfs3FileFifo = 7,
+} Nfs3FileType;
+
+enum
+{
+	Nfs3ModeSetUid = 0x800,
+	Nfs3ModeSetGid = 0x400,
+	Nfs3ModeSticky = 0x200,
+};
+
+typedef enum
+{
+	Nfs3CallTNull,
+	Nfs3CallRNull,
+	Nfs3CallTGetattr,
+	Nfs3CallRGetattr,
+	Nfs3CallTSetattr,
+	Nfs3CallRSetattr,
+	Nfs3CallTLookup,
+	Nfs3CallRLookup,
+	Nfs3CallTAccess,
+	Nfs3CallRAccess,
+	Nfs3CallTReadlink,
+	Nfs3CallRReadlink,
+	Nfs3CallTRead,
+	Nfs3CallRRead,
+	Nfs3CallTWrite,
+	Nfs3CallRWrite,
+	Nfs3CallTCreate,
+	Nfs3CallRCreate,
+	Nfs3CallTMkdir,
+	Nfs3CallRMkdir,
+	Nfs3CallTSymlink,
+	Nfs3CallRSymlink,
+	Nfs3CallTMknod,
+	Nfs3CallRMknod,
+	Nfs3CallTRemove,
+	Nfs3CallRRemove,
+	Nfs3CallTRmdir,
+	Nfs3CallRRmdir,
+	Nfs3CallTRename,
+	Nfs3CallRRename,
+	Nfs3CallTLink,
+	Nfs3CallRLink,
+	Nfs3CallTReadDir,
+	Nfs3CallRReadDir,
+	Nfs3CallTReadDirPlus,
+	Nfs3CallRReadDirPlus,
+	Nfs3CallTFsStat,
+	Nfs3CallRFsStat,
+	Nfs3CallTFsInfo,
+	Nfs3CallRFsInfo,
+	Nfs3CallTPathconf,
+	Nfs3CallRPathconf,
+	Nfs3CallTCommit,
+	Nfs3CallRCommit,
+} Nfs3CallType;
+
+typedef struct Nfs3Handle Nfs3Handle;
+typedef struct Nfs3Time Nfs3Time;
+typedef struct Nfs3Attr Nfs3Attr;
+typedef struct Nfs3WccAttr Nfs3WccAttr;
+typedef struct Nfs3Wcc Nfs3Wcc;
+typedef enum
+{
+	Nfs3SetTimeDont = 0,
+	Nfs3SetTimeServer = 1,
+	Nfs3SetTimeClient = 2,
+} Nfs3SetTime;
+
+typedef struct Nfs3SetAttr Nfs3SetAttr;
+typedef struct Nfs3TNull Nfs3TNull;
+typedef struct Nfs3RNull Nfs3RNull;
+typedef struct Nfs3TGetattr Nfs3TGetattr;
+typedef struct Nfs3RGetattr Nfs3RGetattr;
+typedef struct Nfs3TSetattr Nfs3TSetattr;
+typedef struct Nfs3RSetattr Nfs3RSetattr;
+typedef struct Nfs3TLookup Nfs3TLookup;
+typedef struct Nfs3RLookup Nfs3RLookup;
+typedef struct Nfs3TAccess Nfs3TAccess;
+typedef struct Nfs3RAccess Nfs3RAccess;
+typedef struct Nfs3TReadlink Nfs3TReadlink;
+typedef struct Nfs3RReadlink Nfs3RReadlink;
+typedef struct Nfs3TRead Nfs3TRead;
+typedef struct Nfs3RRead Nfs3RRead;
+typedef enum
+{
+	Nfs3SyncNone = 0,
+	Nfs3SyncData = 1,
+	Nfs3SyncFile = 2,
+} Nfs3Sync;
+
+typedef struct Nfs3TWrite Nfs3TWrite;
+typedef struct Nfs3RWrite Nfs3RWrite;
+typedef enum
+{
+	Nfs3CreateUnchecked = 0,
+	Nfs3CreateGuarded = 1,
+	Nfs3CreateExclusive = 2,
+} Nfs3Create;
+
+typedef struct Nfs3TCreate Nfs3TCreate;
+typedef struct Nfs3RCreate Nfs3RCreate;
+typedef struct Nfs3TMkdir Nfs3TMkdir;
+typedef struct Nfs3RMkdir Nfs3RMkdir;
+typedef struct Nfs3TSymlink Nfs3TSymlink;
+typedef struct Nfs3RSymlink Nfs3RSymlink;
+typedef struct Nfs3TMknod Nfs3TMknod;
+typedef struct Nfs3RMknod Nfs3RMknod;
+typedef struct Nfs3TRemove Nfs3TRemove;
+typedef struct Nfs3RRemove Nfs3RRemove;
+typedef struct Nfs3TRmdir Nfs3TRmdir;
+typedef struct Nfs3RRmdir Nfs3RRmdir;
+typedef struct Nfs3TRename Nfs3TRename;
+typedef struct Nfs3RRename Nfs3RRename;
+typedef struct Nfs3TLink Nfs3TLink;
+typedef struct Nfs3RLink Nfs3RLink;
+typedef struct Nfs3TReadDir Nfs3TReadDir;
+typedef struct Nfs3Entry Nfs3Entry;
+typedef struct Nfs3RReadDir Nfs3RReadDir;
+typedef struct Nfs3TReadDirPlus Nfs3TReadDirPlus;
+typedef struct Nfs3EntryPlus Nfs3EntryPlus;
+typedef struct Nfs3RReadDirPlus Nfs3RReadDirPlus;
+typedef struct Nfs3TFsStat Nfs3TFsStat;
+typedef struct Nfs3RFsStat Nfs3RFsStat;
+typedef struct Nfs3TFsInfo Nfs3TFsInfo;
+typedef struct Nfs3RFsInfo Nfs3RFsInfo;
+typedef struct Nfs3TPathconf Nfs3TPathconf;
+typedef struct Nfs3RPathconf Nfs3RPathconf;
+typedef struct Nfs3TCommit Nfs3TCommit;
+typedef struct Nfs3RCommit Nfs3RCommit;
+
+struct Nfs3Handle {
+	uchar h[Nfs3MaxHandleSize];
+	u32int len;
+};
+
+struct Nfs3Time {
+	u32int sec;
+	u32int nsec;
+};
+
+struct Nfs3Attr {
+	Nfs3FileType type;
+	u32int mode;
+	u32int nlink;
+	u32int uid;
+	u32int gid;
+	u64int size;
+	u64int used;
+	u32int major;
+	u32int minor;
+	u64int fsid;
+	u64int fileid;
+	Nfs3Time atime;
+	Nfs3Time mtime;
+	Nfs3Time ctime;
+};
+
+struct Nfs3WccAttr {
+	u64int size;
+	Nfs3Time mtime;
+	Nfs3Time ctime;
+};
+
+struct Nfs3Wcc {
+	u1int haveWccAttr;
+	Nfs3WccAttr wccAttr;
+	u1int haveAttr;
+	Nfs3Attr attr;
+};
+
+struct Nfs3SetAttr {
+	u1int setMode;
+	u32int mode;
+	u1int setUid;
+	u32int uid;
+	u1int setGid;
+	u32int gid;
+	u1int setSize;
+	u64int size;
+	Nfs3SetTime setAtime;
+	Nfs3Time atime;
+	Nfs3SetTime setMtime;
+	Nfs3Time mtime;
+};
+
+struct Nfs3TNull {
+	SunCall call;
+};
+
+struct Nfs3RNull {
+	SunCall call;
+};
+
+struct Nfs3TGetattr {
+	SunCall call;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RGetattr {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Attr attr;
+};
+
+struct Nfs3TSetattr {
+	SunCall call;
+	Nfs3Handle handle;
+	Nfs3SetAttr attr;
+	u1int checkCtime;
+	Nfs3Time ctime;
+};
+
+struct Nfs3RSetattr {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc wcc;
+};
+
+struct Nfs3TLookup {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+};
+
+struct Nfs3RLookup {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Handle handle;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u1int haveDirAttr;
+	Nfs3Attr dirAttr;
+};
+
+struct Nfs3TAccess {
+	SunCall call;
+	Nfs3Handle handle;
+	u32int access;
+};
+
+struct Nfs3RAccess {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u32int access;
+};
+
+struct Nfs3TReadlink {
+	SunCall call;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RReadlink {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	char *data;
+};
+
+struct Nfs3TRead {
+	SunCall call;
+	Nfs3Handle handle;
+	u64int offset;
+	u32int count;
+};
+
+struct Nfs3RRead {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u32int count;
+	u1int eof;
+	uchar *data;
+	u32int ndata;
+};
+
+struct Nfs3TWrite {
+	SunCall call;
+	Nfs3Handle handle;
+	u64int offset;
+	u32int count;
+	Nfs3Sync stable;
+	uchar *data;
+	u32int ndata;
+};
+
+struct Nfs3RWrite {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc wcc;
+	u32int count;
+	Nfs3Sync committed;
+	uchar verf[Nfs3WriteVerfSize];
+};
+
+struct Nfs3TCreate {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+	Nfs3Create mode;
+	Nfs3SetAttr attr;
+	uchar verf[Nfs3CreateVerfSize];
+};
+
+struct Nfs3RCreate {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveHandle;
+	Nfs3Handle handle;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	Nfs3Wcc dirWcc;
+};
+
+struct Nfs3TMkdir {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+	Nfs3SetAttr attr;
+};
+
+struct Nfs3RMkdir {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveHandle;
+	Nfs3Handle handle;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	Nfs3Wcc dirWcc;
+};
+
+struct Nfs3TSymlink {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+	Nfs3SetAttr attr;
+	char *data;
+};
+
+struct Nfs3RSymlink {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveHandle;
+	Nfs3Handle handle;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	Nfs3Wcc dirWcc;
+};
+
+struct Nfs3TMknod {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+	Nfs3FileType type;
+	Nfs3SetAttr attr;
+	u32int major;
+	u32int minor;
+};
+
+struct Nfs3RMknod {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveHandle;
+	Nfs3Handle handle;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	Nfs3Wcc dirWcc;
+};
+
+struct Nfs3TRemove {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+};
+
+struct Nfs3RRemove {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc wcc;
+};
+
+struct Nfs3TRmdir {
+	SunCall call;
+	Nfs3Handle handle;
+	char *name;
+};
+
+struct Nfs3RRmdir {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc wcc;
+};
+
+struct Nfs3TRename {
+	SunCall call;
+	struct {
+		Nfs3Handle handle;
+		char *name;
+	} from;
+	struct {
+		Nfs3Handle handle;
+		char *name;
+	} to;
+};
+
+struct Nfs3RRename {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc fromWcc;
+	Nfs3Wcc toWcc;
+};
+
+struct Nfs3TLink {
+	SunCall call;
+	Nfs3Handle handle;
+	struct {
+		Nfs3Handle handle;
+		char *name;
+	} link;
+};
+
+struct Nfs3RLink {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	Nfs3Wcc dirWcc;
+};
+
+struct Nfs3TReadDir {
+	SunCall call;
+	Nfs3Handle handle;
+	u64int cookie;
+	uchar verf[Nfs3CookieVerfSize];
+	u32int count;
+};
+
+struct Nfs3RReadDir {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	uchar verf[Nfs3CookieVerfSize];
+	uchar *data;
+	u32int count;
+	u1int eof;
+};
+
+struct Nfs3TReadDirPlus {
+	SunCall call;
+	Nfs3Handle handle;
+	u64int cookie;
+	uchar verf[Nfs3CookieVerfSize];
+	u32int dirCount;
+	u32int maxCount;
+};
+
+struct Nfs3Entry {
+	u64int fileid;
+	char *name;
+	u64int cookie;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u1int haveHandle;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RReadDirPlus {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	uchar verf[Nfs3CookieVerfSize];
+	uchar *data;
+	u32int count;
+	u1int eof;
+};
+
+struct Nfs3TFsStat {
+	SunCall call;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RFsStat {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u64int totalBytes;
+	u64int freeBytes;
+	u64int availBytes;
+	u64int totalFiles;
+	u64int freeFiles;
+	u64int availFiles;
+	u32int invarSec;
+};
+
+struct Nfs3TFsInfo {
+	SunCall call;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RFsInfo {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u32int readMax;
+	u32int readPref;
+	u32int readMult;
+	u32int writeMax;
+	u32int writePref;
+	u32int writeMult;
+	u32int readDirPref;
+	u64int maxFileSize;
+	Nfs3Time timePrec;
+	u32int flags;
+};
+
+struct Nfs3TPathconf {
+	SunCall call;
+	Nfs3Handle handle;
+};
+
+struct Nfs3RPathconf {
+	SunCall call;
+	Nfs3Status status;
+	u1int haveAttr;
+	Nfs3Attr attr;
+	u32int maxLink;
+	u32int maxName;
+	u1int noTrunc;
+	u1int chownRestricted;
+	u1int caseInsensitive;
+	u1int casePreserving;
+};
+
+struct Nfs3TCommit {
+	SunCall call;
+	Nfs3Handle handle;
+	u64int offset;
+	u32int count;
+};
+
+struct Nfs3RCommit {
+	SunCall call;
+	Nfs3Status status;
+	Nfs3Wcc wcc;
+	uchar verf[Nfs3WriteVerfSize];
+};
+
+char *nfs3statusstr(Nfs3Status);
+char *nfs3typestr(SunCallType);
+char *nfs3settimestr(Nfs3SetTime);
+char *nfs3syncstr(Nfs3Sync);
+
+void nfs3handleprint(Fmt*, Nfs3Handle*);
+u32int nfs3handlesize(Nfs3Handle*);
+int nfs3handlepack(uchar*, uchar*, uchar**, Nfs3Handle*);
+int nfs3handleunpack(uchar*, uchar*, uchar**, Nfs3Handle*);
+
+void nfs3timeprint(Fmt*, Nfs3Time*);
+u32int nfs3timesize(Nfs3Time*);
+int nfs3timepack(uchar*, uchar*, uchar**, Nfs3Time*);
+int nfs3timeunpack(uchar*, uchar*, uchar**, Nfs3Time*);
+
+void nfs3attrprint(Fmt*, Nfs3Attr*);
+u32int nfs3attrsize(Nfs3Attr*);
+int nfs3attrpack(uchar*, uchar*, uchar**, Nfs3Attr*);
+int nfs3attrunpack(uchar*, uchar*, uchar**, Nfs3Attr*);
+
+void nfs3wccattrprint(Fmt*, Nfs3WccAttr*);
+u32int nfs3wccattrsize(Nfs3WccAttr*);
+int nfs3wccattrpack(uchar*, uchar*, uchar**, Nfs3WccAttr*);
+int nfs3wccattrunpack(uchar*, uchar*, uchar**, Nfs3WccAttr*);
+
+void nfs3wccprint(Fmt*, Nfs3Wcc*);
+u32int nfs3wccsize(Nfs3Wcc*);
+int nfs3wccpack(uchar*, uchar*, uchar**, Nfs3Wcc*);
+int nfs3wccunpack(uchar*, uchar*, uchar**, Nfs3Wcc*);
+
+void nfs3setattrprint(Fmt*, Nfs3SetAttr*);
+u32int nfs3setattrsize(Nfs3SetAttr*);
+int nfs3setattrpack(uchar*, uchar*, uchar**, Nfs3SetAttr*);
+int nfs3setattrunpack(uchar*, uchar*, uchar**, Nfs3SetAttr*);
+
+extern SunProg nfs3prog;
+
+void nfs3entryprint(Fmt*, Nfs3Entry*);
+u32int nfs3entrysize(Nfs3Entry*);
+int nfs3entrypack(uchar*, uchar*, uchar**, Nfs3Entry*);
+int nfs3entryunpack(uchar*, uchar*, uchar**, Nfs3Entry*);
+
+void nfs3entryplusprint(Fmt*, Nfs3Entry*);
+u32int nfs3entryplussize(Nfs3Entry*);
+int nfs3entrypluspack(uchar*, uchar*, uchar**, Nfs3Entry*);
+int nfs3entryplusunpack(uchar*, uchar*, uchar**, Nfs3Entry*);
+
diff --git a/include/sunrpc.h b/include/sunrpc.h
new file mode 100644
index 0000000..4f108aa
--- /dev/null
+++ b/include/sunrpc.h
@@ -0,0 +1,400 @@
+/*
+ * Sun RPC; see RFC 1057
+ */
+
+/*
+#pragma lib "libsunrpc.a"
+#pragma src "/sys/src/libsunrpc"
+*/
+
+typedef uchar u1int;
+
+typedef struct SunAuthInfo SunAuthInfo;
+typedef struct SunAuthUnix SunAuthUnix;
+typedef struct SunRpc SunRpc;
+typedef struct SunCall SunCall;
+
+enum
+{
+	/* Authinfo.flavor */
+	SunAuthNone = 0,
+	SunAuthSys,
+	SunAuthShort,
+	SunAuthDes,
+};
+
+typedef enum {
+	SunAcceptError = 0x10000,
+	SunRejectError = 0x20000,
+	SunAuthError = 0x40000,
+
+	/* Reply.status */
+	SunSuccess = 0,
+
+	SunProgUnavail = SunAcceptError | 1,
+	SunProgMismatch,
+	SunProcUnavail,
+	SunGarbageArgs,
+	SunSystemErr,
+
+	SunRpcMismatch = SunRejectError | 0,
+
+	SunAuthBadCred = SunAuthError | 1,
+	SunAuthRejectedCred,
+	SunAuthBadVerf,
+	SunAuthRejectedVerf,
+	SunAuthTooWeak,
+	SunAuthInvalidResp,
+	SunAuthFailed,
+} SunStatus;
+
+struct SunAuthInfo
+{
+	uint flavor;
+	uchar *data;
+	uint ndata;
+};
+
+struct SunAuthUnix
+{
+	u32int stamp;
+	char *sysname;
+	u32int uid;
+	u32int gid;
+	u32int g[16];
+	u32int ng;
+};
+
+struct SunRpc
+{
+	u32int xid;
+	uint iscall;
+
+	/*
+	 * only sent on wire in call
+	 * caller fills in for the reply unpackers.
+	 */
+	u32int proc;
+
+	/* call */
+	// uint proc;
+	u32int prog, vers;
+	SunAuthInfo cred;
+	SunAuthInfo verf;
+	uchar *data;
+	uint ndata;
+
+	/* reply */
+	u32int status;
+	// SunAuthInfo verf;
+	u32int low, high;
+	// uchar *data;
+	// uint ndata;
+};
+
+typedef enum
+{
+	SunCallTypeTNull,
+	SunCallTypeRNull,
+} SunCallType;
+
+struct SunCall
+{
+	SunRpc rpc;
+	SunCallType type;
+};
+
+void sunerrstr(SunStatus);
+
+void sunrpcprint(Fmt*, SunRpc*);
+uint sunrpcsize(SunRpc*);
+SunStatus sunrpcpack(uchar*, uchar*, uchar**, SunRpc*);
+SunStatus sunrpcunpack(uchar*, uchar*, uchar**, SunRpc*);
+
+void sunauthinfoprint(Fmt*, SunAuthInfo*);
+uint sunauthinfosize(SunAuthInfo*);
+int sunauthinfopack(uchar*, uchar*, uchar**, SunAuthInfo*);
+int sunauthinfounpack(uchar*, uchar*, uchar**, SunAuthInfo*);
+
+void sunauthunixprint(Fmt*, SunAuthUnix*);
+uint sunauthunixsize(SunAuthUnix*);
+int sunauthunixpack(uchar*, uchar*, uchar**, SunAuthUnix*);
+int sunauthunixunpack(uchar*, uchar*, uchar**, SunAuthUnix*);
+
+int sunenumpack(uchar*, uchar*, uchar**, int*);
+int sunenumunpack(uchar*, uchar*, uchar**, int*);
+int sunuint1pack(uchar*, uchar*, uchar**, u1int*);
+int sunuint1unpack(uchar*, uchar*, uchar**, u1int*);
+
+int sunstringpack(uchar*, uchar*, uchar**, char**, u32int);
+int sunstringunpack(uchar*, uchar*, uchar**, char**, u32int);
+uint sunstringsize(char*);
+
+int sunuint32pack(uchar*, uchar*, uchar**, u32int*);
+int sunuint32unpack(uchar*, uchar*, uchar**, u32int*);
+int sunuint64pack(uchar*, uchar*, uchar**, u64int*);
+int sunuint64unpack(uchar*, uchar*, uchar**, u64int*);
+
+int sunvaropaquepack(uchar*, uchar*, uchar**, uchar**, u32int*, u32int);
+int sunvaropaqueunpack(uchar*, uchar*, uchar**, uchar**, u32int*, u32int);
+uint sunvaropaquesize(u32int);
+
+int sunfixedopaquepack(uchar*, uchar*, uchar**, uchar*, u32int);
+int sunfixedopaqueunpack(uchar*, uchar*, uchar**, uchar*, u32int);
+uint sunfixedopaquesize(u32int);
+
+/*
+ * Sun RPC Program
+ */
+typedef struct SunProc SunProc;
+typedef struct SunProg SunProg;
+struct SunProg
+{
+	uint prog;
+	uint vers;
+	SunProc *proc;
+	int nproc;
+};
+
+struct SunProc
+{
+	int (*pack)(uchar*, uchar*, uchar**, SunCall*);
+	int (*unpack)(uchar*, uchar*, uchar**, SunCall*);
+	uint (*size)(SunCall*);
+	void (*fmt)(Fmt*, SunCall*);
+	uint sizeoftype;
+};
+
+SunStatus suncallpack(SunProg*, uchar*, uchar*, uchar**, SunCall*);
+SunStatus suncallunpack(SunProg*, uchar*, uchar*, uchar**, SunCall*);
+SunStatus suncallunpackalloc(SunProg*, SunCallType, uchar*, uchar*, uchar**, SunCall**);
+void suncallsetup(SunCall*, SunProg*, uint);
+uint suncallsize(SunProg*, SunCall*);
+
+/*
+ * Formatting
+#pragma varargck type "B" SunRpc*
+#pragma varargck type "C" SunCall*
+ */
+
+int	sunrpcfmt(Fmt*);
+int	suncallfmt(Fmt*);
+void	sunfmtinstall(SunProg*);
+
+
+/*
+ * Sun RPC Server
+ */
+typedef struct SunMsg SunMsg;
+typedef struct SunSrv SunSrv;
+
+enum
+{
+	SunStackSize = 32768,
+};
+
+struct SunMsg
+{
+	uchar *data;
+	int count;
+	SunSrv *srv;
+	SunRpc rpc;
+	SunProg *pg;
+	SunCall *call;
+	Channel *creply;	/* chan(SunMsg*) */
+};
+
+struct SunSrv
+{
+	int chatty;
+	int cachereplies;
+	int alwaysreject;
+	int localonly;
+	int localparanoia;
+	SunProg **map;
+	Channel *crequest;
+
+/* implementation use only */
+	Channel **cdispatch;
+	SunProg **prog;
+	int nprog;
+	void *cache;
+	Channel *creply;
+	Channel *cthread;
+};
+
+SunSrv *sunsrv(void);
+
+void	sunsrvprog(SunSrv *srv, SunProg *prog, Channel *c);
+int	sunsrvannounce(SunSrv *srv, char *address);
+int	sunsrvudp(SunSrv *srv, char *address);
+int	sunsrvnet(SunSrv *srv, char *address);
+int	sunsrvfd(SunSrv *srv, int fd);
+void	sunsrvthreadcreate(SunSrv *srv, void (*fn)(void*), void*);
+void	sunsrvclose(SunSrv*);
+
+int	sunmsgreply(SunMsg*, SunCall*);
+int	sunmsgdrop(SunMsg*);
+int	sunmsgreplyerror(SunMsg*, SunStatus);
+
+/*
+ * Sun RPC Client
+ */
+typedef struct SunClient SunClient;
+
+struct SunClient
+{
+	int		fd;
+	int		chatty;
+	int		needcount;
+	ulong	maxwait;
+	ulong	xidgen;
+	int		nsend;
+	int		nresend;
+	struct {
+		ulong min;
+		ulong max;
+		ulong avg;
+	} rtt;
+	Channel	*dying;
+	Channel	*rpcchan;
+	Channel	*timerchan;
+	Channel	*flushchan;
+	Channel	*readchan;
+	SunProg	**prog;
+	int		nprog;
+	int 		timertid;
+	int 		nettid;
+};
+
+SunClient	*sundial(char*);
+
+int	sunclientrpc(SunClient*, ulong, SunCall*, SunCall*, uchar**);
+void	sunclientclose(SunClient*);
+void	sunclientflushrpc(SunClient*, ulong);
+void	sunclientprog(SunClient*, SunProg*);
+
+
+/*
+ * Provided by callers.
+ * Should remove dependence on this, but hard.
+ */
+void	*emalloc(ulong);
+void *erealloc(void*, ulong);
+
+
+/*
+ * Sun RPC port mapper; see RFC 1057 Appendix A
+ */
+
+typedef struct PortMap PortMap;
+typedef struct PortTNull PortTNull;
+typedef struct PortRNull PortRNull;
+typedef struct PortTSet PortTSet;
+typedef struct PortRSet PortRSet;
+typedef struct PortTUnset PortTUnset;
+typedef struct PortRUnset PortRUnset;
+typedef struct PortTGetport PortTGetport;
+typedef struct PortRGetport PortRGetport;
+typedef struct PortTDump PortTDump;
+typedef struct PortRDump PortRDump;
+typedef struct PortTCallit PortTCallit;
+typedef struct PortRCallit PortRCallit;
+
+typedef enum
+{
+	PortCallTNull,
+	PortCallRNull,
+	PortCallTSet,
+	PortCallRSet,
+	PortCallTUnset,
+	PortCallRUnset,
+	PortCallTGetport,
+	PortCallRGetport,
+	PortCallTDump,
+	PortCallRDump,
+	PortCallTCallit,
+	PortCallRCallit,
+} PortCallType;
+
+enum
+{
+	PortProgram	= 100000,
+	PortVersion	= 2,
+
+	PortProtoTcp	= 6,	/* protocol number for TCP/IP */
+	PortProtoUdp	= 17	/* protocol number for UDP/IP */
+};
+
+struct PortMap {
+	u32int prog;
+	u32int vers;
+	u32int prot;
+	u32int port;
+};
+
+struct PortTNull {
+	SunCall call;
+};
+
+struct PortRNull {
+	SunCall call;
+};
+
+struct PortTSet {
+	SunCall call;
+	PortMap map;
+};
+
+struct PortRSet {
+	SunCall call;
+	u1int b;
+};
+
+struct PortTUnset {
+	SunCall call;
+	PortMap map;
+};
+
+struct PortRUnset {
+	SunCall call;
+	u1int b;
+};
+
+struct PortTGetport {
+	SunCall call;
+	PortMap map;
+};
+
+struct PortRGetport {
+	SunCall call;
+	u32int port;
+};
+
+struct PortTDump {
+	SunCall call;
+};
+
+struct PortRDump {
+	SunCall call;
+	PortMap *map;
+	int nmap;
+};
+
+struct PortTCallit {
+	SunCall call;
+	u32int prog;
+	u32int vers;
+	u32int proc;
+	uchar *data;
+	u32int count;
+};
+
+struct PortRCallit {
+	SunCall call;
+	u32int port;
+	uchar *data;
+	u32int count;
+};
+
+extern SunProg portprog;