/*
 * Lib9 is miscellany from the Plan 9 C library that doesn't
 * fit into libutf or into libfmt, but is still missing from traditional
 * Unix C libraries.
 */
#ifndef _LIBC_H_
#define _LIBC_H_ 1
#if defined(__cplusplus)
extern "C" {
#endif                                                                

#include <utf.h>
#include <fmt.h>

/*
 * Begin usual libc.h 
 */

#ifndef nil
#define	nil	((void*)0)
#endif
#define	nelem(x)	(sizeof(x)/sizeof((x)[0]))

#ifndef offsetof
#define offsetof(s, m)	(ulong)(&(((s*)0)->m))
#endif

/*
 * mem routines (provided by system <string.h>)
 *
extern	void*	memccpy(void*, void*, int, ulong);
extern	void*	memset(void*, int, ulong);
extern	int	memcmp(void*, void*, ulong);
extern	void*	memcpy(void*, void*, ulong);
extern	void*	memmove(void*, void*, ulong);
extern	void*	memchr(void*, int, ulong);
 */

/*
 * string routines (provided by system <string.h>)
 *
extern	char*	strcat(char*, char*);
extern	char*	strchr(char*, int);
extern	int	strcmp(char*, char*);
extern	char*	strcpy(char*, char*);
 */
extern	char*	strecpy(char*, char*, char*);
extern	char*	p9strdup(char*);
/*
extern	char*	strncat(char*, char*, long);
extern	char*	strncpy(char*, char*, long);
extern	int	strncmp(char*, char*, long);
extern	char*	strpbrk(char*, char*);
extern	char*	strrchr(char*, int);
extern	char*	strtok(char*, char*);
extern	long	strlen(char*);
extern	long	strspn(char*, char*);
extern	long	strcspn(char*, char*);
extern	char*	strstr(char*, char*);
 */
extern	int	cistrncmp(char*, char*, int);
extern	int	cistrcmp(char*, char*);
extern	char*	cistrstr(char*, char*);
extern	int	tokenize(char*, char**, int);

/*
enum
{
	UTFmax		= 4,
	Runesync	= 0x80,
	Runeself	= 0x80,
	Runeerror	= 0xFFFD,
	Runemax	= 0x10FFFF,
};
*/

/*
 * rune routines (provided by <utf.h>
 *
extern	int	runetochar(char*, Rune*);
extern	int	chartorune(Rune*, char*);
extern	int	runelen(long);
extern	int	runenlen(Rune*, int);
extern	int	fullrune(char*, int);
extern	int	utflen(char*);
extern	int	utfnlen(char*, long);
extern	char*	utfrune(char*, long);
extern	char*	utfrrune(char*, long);
extern	char*	utfutf(char*, char*);
extern	char*	utfecpy(char*, char*, char*);

extern	Rune*	runestrcat(Rune*, Rune*);
extern	Rune*	runestrchr(Rune*, Rune);
extern	int	runestrcmp(Rune*, Rune*);
extern	Rune*	runestrcpy(Rune*, Rune*);
extern	Rune*	runestrncpy(Rune*, Rune*, long);
extern	Rune*	runestrecpy(Rune*, Rune*, Rune*);
extern	Rune*	runestrdup(Rune*);
extern	Rune*	runestrncat(Rune*, Rune*, long);
extern	int	runestrncmp(Rune*, Rune*, long);
extern	Rune*	runestrrchr(Rune*, Rune);
extern	long	runestrlen(Rune*);
extern	Rune*	runestrstr(Rune*, Rune*);

extern	Rune	tolowerrune(Rune);
extern	Rune	totitlerune(Rune);
extern	Rune	toupperrune(Rune);
extern	int	isalpharune(Rune);
extern	int	islowerrune(Rune);
extern	int	isspacerune(Rune);
extern	int	istitlerune(Rune);
extern	int	isupperrune(Rune);
 */

/*
 * malloc (provied by system <stdlib.h>)
 *
extern	void*	malloc(ulong);
 */
extern	void*	p9malloc(ulong);
extern	void*	mallocz(ulong, int);
extern	void	p9free(void*);
extern	void*	p9calloc(ulong, ulong);
extern	void*	p9realloc(void*, ulong);
extern	void		setmalloctag(void*, ulong);
extern	void		setrealloctag(void*, ulong);
extern	ulong	getmalloctag(void*);
extern	ulong	getrealloctag(void*);
/*
extern	void*	malloctopoolblock(void*);
*/
#ifndef NOPLAN9DEFINES
#define	malloc	p9malloc
#define	realloc	p9realloc
#define	calloc	p9calloc
#define	free	p9free
#undef strdup
#define	strdup	p9strdup
#endif

/*
 * print routines (provided by <fmt.h>)
 *
typedef struct Fmt	Fmt;
struct Fmt{
	uchar	runes;
	void	*start;
	void	*to;
	void	*stop;
	int	(*flush)(Fmt *);
	void	*farg;
	int	nfmt;
	va_list	args;
	int	r;
	int	width;
	int	prec;
	ulong	flags;
};

enum{
	FmtWidth	= 1,
	FmtLeft		= FmtWidth << 1,
	FmtPrec		= FmtLeft << 1,
	FmtSharp	= FmtPrec << 1,
	FmtSpace	= FmtSharp << 1,
	FmtSign		= FmtSpace << 1,
	FmtZero		= FmtSign << 1,
	FmtUnsigned	= FmtZero << 1,
	FmtShort	= FmtUnsigned << 1,
	FmtLong		= FmtShort << 1,
	FmtVLong	= FmtLong << 1,
	FmtComma	= FmtVLong << 1,
	FmtByte	= FmtComma << 1,

	FmtFlag		= FmtByte << 1
};

extern	int	print(char*, ...);
extern	char*	seprint(char*, char*, char*, ...);
extern	char*	vseprint(char*, char*, char*, va_list);
extern	int	snprint(char*, int, char*, ...);
extern	int	vsnprint(char*, int, char*, va_list);
extern	char*	smprint(char*, ...);
extern	char*	vsmprint(char*, va_list);
extern	int	sprint(char*, char*, ...);
extern	int	fprint(int, char*, ...);
extern	int	vfprint(int, char*, va_list);

extern	int	runesprint(Rune*, char*, ...);
extern	int	runesnprint(Rune*, int, char*, ...);
extern	int	runevsnprint(Rune*, int, char*, va_list);
extern	Rune*	runeseprint(Rune*, Rune*, char*, ...);
extern	Rune*	runevseprint(Rune*, Rune*, char*, va_list);
extern	Rune*	runesmprint(char*, ...);
extern	Rune*	runevsmprint(char*, va_list);

extern	int	fmtfdinit(Fmt*, int, char*, int);
extern	int	fmtfdflush(Fmt*);
extern	int	fmtstrinit(Fmt*);
extern	char*	fmtstrflush(Fmt*);
extern	int	runefmtstrinit(Fmt*);
extern	Rune*	runefmtstrflush(Fmt*);

extern	int	fmtinstall(int, int (*)(Fmt*));
extern	int	dofmt(Fmt*, char*);
extern	int	dorfmt(Fmt*, Rune*);
extern	int	fmtprint(Fmt*, char*, ...);
extern	int	fmtvprint(Fmt*, char*, va_list);
extern	int	fmtrune(Fmt*, int);
extern	int	fmtstrcpy(Fmt*, char*);
extern	int	fmtrunestrcpy(Fmt*, Rune*);
 */

/*
 * error string for %r
 * supplied on per os basis, not part of fmt library
 *
 * (provided by lib9, but declared in fmt.h)
 *
extern	int	errfmt(Fmt *f);
 */

/*
 * quoted strings
 */
extern	char	*unquotestrdup(char*);
extern	Rune	*unquoterunestrdup(Rune*);
extern	char	*quotestrdup(char*);
extern	Rune	*quoterunestrdup(Rune*);
/*
 * in fmt.h
 *
extern	void	quotefmtinstall(void);
extern	int	quotestrfmt(Fmt*);
extern	int	quoterunestrfmt(Fmt*);
 */
#ifndef NOPLAN9DEFINES
#define doquote fmtdoquote
#endif
extern	int	needsrcquote(int);

/*
 * random number
 */
extern	void	p9srand(long);
extern	int	p9rand(void);

extern	int	p9nrand(int);
extern	long	p9lrand(void);
extern	long	p9lnrand(long);
extern	double	p9frand(void);
extern	ulong	truerand(void);			/* uses /dev/random */
extern	ulong	ntruerand(ulong);		/* uses /dev/random */

#ifndef NOPLAN9DEFINES
#define	srand	p9srand
#define	rand	p9rand
#define	nrand	p9nrand
#define	lrand	p9lrand
#define	lnrand	p9lnrand
#define	frand	p9frand
#endif

/*
 * math
 */
extern	ulong	getfcr(void);
extern	void	setfsr(ulong);
extern	ulong	getfsr(void);
extern	void	setfcr(ulong);
extern	double	NaN(void);
extern	double	Inf(int);
extern	int	isNaN(double);
extern	int	isInf(double, int);
extern	ulong	umuldiv(ulong, ulong, ulong);
extern	long	muldiv(long, long, long);

/*
 * provided by math.h
 *
extern	double	pow(double, double);
extern	double	atan2(double, double);
extern	double	fabs(double);
extern	double	atan(double);
extern	double	log(double);
extern	double	log10(double);
extern	double	exp(double);
extern	double	floor(double);
extern	double	ceil(double);
extern	double	hypot(double, double);
extern	double	sin(double);
extern	double	cos(double);
extern	double	tan(double);
extern	double	asin(double);
extern	double	acos(double);
extern	double	sinh(double);
extern	double	cosh(double);
extern	double	tanh(double);
extern	double	sqrt(double);
extern	double	fmod(double, double);
#define	HUGE	3.4028234e38
#define	PIO2	1.570796326794896619231e0
#define	PI	(PIO2+PIO2)
 */
#define PI	M_PI
#define	PIO2	M_PI_2

/*
 * Time-of-day
 */

typedef
struct Tm
{
	int	sec;
	int	min;
	int	hour;
	int	mday;
	int	mon;
	int	year;
	int	wday;
	int	yday;
	char	zone[4];
	int	tzoff;
} Tm;

extern	Tm*	p9gmtime(long);
extern	Tm*	p9localtime(long);
extern	char*	p9asctime(Tm*);
extern	char*	p9ctime(long);
extern	double	p9cputime(void);
extern	long	p9times(long*);
extern	long	p9tm2sec(Tm*);
extern	vlong	p9nsec(void);

#ifndef NOPLAN9DEFINES
/* Clear some declarations to avoid conflicts in edge situation.
 * uClibc based systems have this issue.
 */
#undef gmtime
#undef localtime
#undef asctime
#undef ctime
#define	gmtime		p9gmtime
#define	localtime	p9localtime
#define	asctime		p9asctime
#define	ctime		p9ctime
#define	cputime		p9cputime
#define	times		p9times
#define	tm2sec		p9tm2sec
#define	nsec		p9nsec
#endif

/*
 * one-of-a-kind
 */
enum
{
	PNPROC		= 1,
	PNGROUP		= 2
};

/* extern	int	abs(int); <stdlib.h> */
extern	int	p9atexit(void(*)(void));
extern	void	p9atexitdont(void(*)(void));
extern	int	atnotify(int(*)(void*, char*), int);
/* 
 * <stdlib.h>
extern	double	atof(char*); <stdlib.h>
 */
extern	int	p9atoi(char*);
extern	long	p9atol(char*);
extern	vlong	p9atoll(char*);
extern	double	fmtcharstod(int(*)(void*), void*);
extern	char*	cleanname(char*);
extern	int	p9decrypt(void*, void*, int);
extern	int	p9encrypt(void*, void*, int);
extern	int	netcrypt(void*, void*);
extern	int	dec64(uchar*, int, char*, int);
extern	int	enc64(char*, int, uchar*, int);
extern	int	dec32(uchar*, int, char*, int);
extern	int	enc32(char*, int, uchar*, int);
extern	int	dec16(uchar*, int, char*, int);
extern	int	enc16(char*, int, uchar*, int);
extern	int	encodefmt(Fmt*);
extern	int	dirmodefmt(Fmt*);
extern	int	exitcode(char*);
extern	void	exits(char*);
extern	double	frexp(double, int*);
extern	ulong	getcallerpc(void*);
extern	char*	p9getenv(char*);
extern	int	p9putenv(char*, char*);
extern	int	getfields(char*, char**, int, int, char*);
extern	int	gettokens(char *, char **, int, char *);
extern	char*	getuser(void);
extern	char*	p9getwd(char*, int);
extern	int	iounit(int);
/* extern	long	labs(long); <math.h> */
/* extern	double	ldexp(double, int); <math.h> */
extern	void	p9longjmp(p9jmp_buf, int);
extern	char*	mktemp(char*);
extern	int		opentemp(char*, int);
/* extern	double	modf(double, double*); <math.h> */
extern	void	p9notejmp(void*, p9jmp_buf, int);
extern	void	perror(const char*);
extern	int	postnote(int, int, char *);
extern	double	p9pow10(int);
/* extern	int	putenv(char*, char*); <stdlib.h. */
/* extern	void	qsort(void*, long, long, int (*)(void*, void*)); <stdlib.h> */
extern	char*	searchpath(char*);
/* extern	int	p9setjmp(p9jmp_buf); */
#define p9setjmp(b)	sigsetjmp((void*)(b), 1)
/*
 * <stdlib.h>
extern	long	strtol(char*, char**, int);
extern	ulong	strtoul(char*, char**, int);
extern	vlong	strtoll(char*, char**, int);
extern	uvlong	strtoull(char*, char**, int);
 */
extern	void	sysfatal(char*, ...);
extern	void	p9syslog(int, char*, char*, ...);
extern	long	p9time(long*);
/* extern	int	tolower(int); <ctype.h> */
/* extern	int	toupper(int); <ctype.h> */
extern	void	needstack(int);
extern	char*	readcons(char*, char*, int);

extern	void	(*_pin)(void);
extern	void	(*_unpin)(void);

#ifndef NOPLAN9DEFINES
#define atexit		p9atexit
#define atexitdont	p9atexitdont
#define atoi		p9atoi
#define atol		p9atol
#define atoll		p9atoll
#define encrypt		p9encrypt
#define decrypt		p9decrypt
#define getenv		p9getenv
#define	getwd		p9getwd
#undef longjmp
#define	longjmp		p9longjmp
#undef  setjmp
#define setjmp		p9setjmp
#define putenv		p9putenv
#define notejmp		p9notejmp
#define jmp_buf		p9jmp_buf
#define time		p9time
#define pow10		p9pow10
#define strtod		fmtstrtod
#define charstod	fmtcharstod
#define syslog		p9syslog
#endif

/*
 *  just enough information so that libc can be
 *  properly locked without dragging in all of libthread
 */
typedef struct _Thread _Thread;
typedef struct _Threadlist _Threadlist;
struct _Threadlist
{
	_Thread	*head;
	_Thread	*tail;
};

extern	_Thread	*(*threadnow)(void);

/*
 *  synchronization
 */
typedef struct Lock Lock;
struct Lock
{
#ifdef PLAN9PORT_USING_PTHREADS
	int init;
	pthread_mutex_t mutex;
#endif
	int held;
};

extern	void	lock(Lock*);
extern	void	unlock(Lock*);
extern	int	canlock(Lock*);
extern	int	(*_lock)(Lock*, int, ulong);
extern	void	(*_unlock)(Lock*, ulong);	

typedef struct QLock QLock;
struct QLock
{
	Lock		l;
	_Thread	*owner;
	_Threadlist	waiting;
};

extern	void	qlock(QLock*);
extern	void	qunlock(QLock*);
extern	int	canqlock(QLock*);
extern	int	(*_qlock)(QLock*, int, ulong);	/* do not use */
extern	void	(*_qunlock)(QLock*, ulong);

typedef struct Rendez Rendez;
struct Rendez
{
	QLock	*l;
	_Threadlist	waiting;
};

extern	void	rsleep(Rendez*);	/* unlocks r->l, sleeps, locks r->l again */
extern	int	rwakeup(Rendez*);
extern	int	rwakeupall(Rendez*);
extern	void	(*_rsleep)(Rendez*, ulong);	/* do not use */
extern	int	(*_rwakeup)(Rendez*, int, ulong);

typedef struct RWLock RWLock;
struct RWLock
{
	Lock		l;
	int	readers;
	_Thread	*writer;
	_Threadlist	rwaiting;
	_Threadlist	wwaiting;
};

extern	void	rlock(RWLock*);
extern	void	runlock(RWLock*);
extern	int		canrlock(RWLock*);
extern	void	wlock(RWLock*);
extern	void	wunlock(RWLock*);
extern	int		canwlock(RWLock*);
extern	int	(*_rlock)(RWLock*, int, ulong);	/* do not use */
extern	int	(*_wlock)(RWLock*, int, ulong);
extern	void	(*_runlock)(RWLock*, ulong);
extern	void	(*_wunlock)(RWLock*, ulong);

/*
 * per-process private data
 */
extern	void**	privalloc(void);
extern	void	privfree(void**);

/*
 *  network dialing
 */
#define NETPATHLEN 40
extern	int	p9accept(int, char*);
extern	int	p9announce(char*, char*);
extern	int	p9dial(char*, char*, char*, int*);
extern	int	p9dialparse(char *ds, char **net, char **unixa, u32int *ip, int *port);
extern	void	p9setnetmtpt(char*, int, char*);
extern	int	p9listen(char*, char*);
extern	char*	p9netmkaddr(char*, char*, char*);
extern	int	p9reject(int, char*, char*);

#ifndef NOPLAN9DEFINES
#define	accept		p9accept
#define	announce	p9announce
#define	dial		p9dial
#define	setnetmtpt	p9setnetmtpt
#define	listen		p9listen
#define	netmkaddr	p9netmkaddr
#define	reject		p9reject
#endif

/*
 *  encryption
 */
extern	int	pushssl(int, char*, char*, char*, int*);
extern	int	pushtls(int, char*, char*, int, char*, char*);

/*
 *  network services
 */
typedef struct NetConnInfo NetConnInfo;
struct NetConnInfo
{
	char	*dir;		/* connection directory */
	char	*root;		/* network root */
	char	*spec;		/* binding spec */
	char	*lsys;		/* local system */
	char	*lserv;		/* local service */
	char	*rsys;		/* remote system */
	char	*rserv;		/* remote service */
	char *laddr;
	char *raddr;
};
extern	NetConnInfo*	getnetconninfo(char*, int);
extern	void		freenetconninfo(NetConnInfo*);

/*
 * system calls
 *
 */
#define	STATMAX	65535U	/* max length of machine-independent stat structure */
#define	DIRMAX	(sizeof(Dir)+STATMAX)	/* max length of Dir structure */
#define	ERRMAX	128	/* max length of error string */

#define	MORDER	0x0003	/* mask for bits defining order of mounting */
#define	MREPL	0x0000	/* mount replaces object */
#define	MBEFORE	0x0001	/* mount goes before others in union directory */
#define	MAFTER	0x0002	/* mount goes after others in union directory */
#define	MCREATE	0x0004	/* permit creation in mounted directory */
#define	MCACHE	0x0010	/* cache some data */
#define	MMASK	0x0017	/* all bits on */

#define	OREAD	0	/* open for read */
#define	OWRITE	1	/* write */
#define	ORDWR	2	/* read and write */
#define	OEXEC	3	/* execute, == read but check execute permission */
#define	OTRUNC	16	/* or'ed in (except for exec), truncate file first */
#define	OCEXEC	32	/* or'ed in, close on exec */
#define	ORCLOSE	64	/* or'ed in, remove on close */
#define	ODIRECT	128	/* or'ed in, direct access */
#define	ONONBLOCK 256	/* or'ed in, non-blocking call */
#define	OEXCL	0x1000	/* or'ed in, exclusive use (create only) */
#define	OLOCK	0x2000	/* or'ed in, lock after opening */
#define	OAPPEND	0x4000	/* or'ed in, append only */

#define	AEXIST	0	/* accessible: exists */
#define	AEXEC	1	/* execute access */
#define	AWRITE	2	/* write access */
#define	AREAD	4	/* read access */

/* Segattch */
#define	SG_RONLY	0040	/* read only */
#define	SG_CEXEC	0100	/* detach on exec */

#define	NCONT	0	/* continue after note */
#define	NDFLT	1	/* terminate after note */
#define	NSAVE	2	/* clear note but hold state */
#define	NRSTR	3	/* restore saved state */

/* bits in Qid.type */
#define QTDIR		0x80		/* type bit for directories */
#define QTAPPEND	0x40		/* type bit for append only files */
#define QTEXCL		0x20		/* type bit for exclusive use files */
#define QTMOUNT		0x10		/* type bit for mounted channel */
#define QTAUTH		0x08		/* type bit for authentication file */
#define QTTMP		0x04		/* type bit for non-backed-up file */
#define QTSYMLINK	0x02		/* type bit for symbolic link */
#define QTFILE		0x00		/* type bits for plain file */

/* bits in Dir.mode */
#define DMDIR		0x80000000	/* mode bit for directories */
#define DMAPPEND	0x40000000	/* mode bit for append only files */
#define DMEXCL		0x20000000	/* mode bit for exclusive use files */
#define DMMOUNT		0x10000000	/* mode bit for mounted channel */
#define DMAUTH		0x08000000	/* mode bit for authentication file */
#define DMTMP		0x04000000	/* mode bit for non-backed-up file */
#define DMSYMLINK	0x02000000	/* mode bit for symbolic link (Unix, 9P2000.u) */
#define DMDEVICE	0x00800000	/* mode bit for device file (Unix, 9P2000.u) */
#define DMNAMEDPIPE	0x00200000	/* mode bit for named pipe (Unix, 9P2000.u) */
#define DMSOCKET	0x00100000	/* mode bit for socket (Unix, 9P2000.u) */
#define DMSETUID	0x00080000	/* mode bit for setuid (Unix, 9P2000.u) */
#define DMSETGID	0x00040000	/* mode bit for setgid (Unix, 9P2000.u) */

#define DMREAD		0x4		/* mode bit for read permission */
#define DMWRITE		0x2		/* mode bit for write permission */
#define DMEXEC		0x1		/* mode bit for execute permission */

#ifdef RFMEM	/* FreeBSD, OpenBSD */
#undef RFFDG
#undef RFNOTEG
#undef RFPROC
#undef RFMEM
#undef RFNOWAIT
#undef RFCFDG
#undef RFNAMEG
#undef RFENVG
#undef RFCENVG
#undef RFCFDG
#undef RFCNAMEG
#endif

enum
{
	RFNAMEG		= (1<<0), 
	RFENVG		= (1<<1), 
	RFFDG		= (1<<2),
	RFNOTEG		= (1<<3),
	RFPROC		= (1<<4),
	RFMEM		= (1<<5),
	RFNOWAIT	= (1<<6),
	RFCNAMEG	= (1<<10), 
	RFCENVG		= (1<<11), 
	RFCFDG		= (1<<12)
/*	RFREND		= (1<<13), */
/*	RFNOMNT		= (1<<14) */
};

typedef
struct Qid
{
	uvlong	path;
	ulong	vers;
	uchar	type;
} Qid;

typedef
struct Dir {
	/* system-modified data */
	ushort	type;	/* server type */
	uint	dev;	/* server subtype */
	/* file data */
	Qid	qid;	/* unique id from server */
	ulong	mode;	/* permissions */
	ulong	atime;	/* last read time */
	ulong	mtime;	/* last write time */
	vlong	length;	/* file length */
	char	*name;	/* last element of path */
	char	*uid;	/* owner name */
	char	*gid;	/* group name */
	char	*muid;	/* last modifier name */
	
	/* 9P2000.u extensions */
	uint	uidnum;		/* numeric uid */
	uint	gidnum;		/* numeric gid */
	uint	muidnum;	/* numeric muid */
	char	*ext;		/* extended info */
} Dir;

/* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
typedef
struct Waitmsg
{
	int pid;	/* of loved one */
	ulong time[3];	/* of loved one & descendants */
	char	*msg;
} Waitmsg;

typedef
struct IOchunk
{
	void	*addr;
	ulong	len;
} IOchunk;

extern	void	_exits(char*);

extern	void	abort(void);
/* extern	int	access(char*, int); */
extern	long	p9alarm(ulong);
extern	int	await(char*, int);
extern	int	awaitfor(int, char*, int);
extern	int	awaitnohang(char*, int);
/* extern	int	bind(char*, char*, int); give up */
/* extern	int	brk(void*); <unistd.h> */
extern	int	p9chdir(char*);
extern	int	close(int);
extern	int	p9create(char*, int, ulong);
extern	int	p9dup(int, int);
extern	int	errstr(char*, uint);
extern	int	p9exec(char*, char*[]);
extern	int	p9execl(char*, ...);
/* extern	int	p9fork(void); */
extern	int	p9rfork(int);
/* not implemented 
extern	int	fauth(int, char*);
extern	int	fstat(int, uchar*, int);
extern	int	fwstat(int, uchar*, int);
extern	int	fversion(int, int, char*, int);
extern	int	mount(int, int, char*, int, char*);
extern	int	unmount(char*, char*);
*/
extern	int	noted(int);
extern	int	notify(void(*)(void*, char*));
extern	int	noteenable(char*);
extern	int	notedisable(char*);
extern	int	notifyon(char*);
extern	int	notifyoff(char*);
extern	int	p9open(char*, int);
extern	int	fd2path(int, char*, int);
extern	int	p9pipe(int*);
/* 
 * use defs from <unistd.h>
extern	long	pread(int, void*, long, vlong);
extern	long	preadv(int, IOchunk*, int, vlong);
extern	long	pwrite(int, void*, long, vlong);
extern	long	pwritev(int, IOchunk*, int, vlong);
extern	long	read(int, void*, long);
 */
extern	long	readn(int, void*, long);
/* extern	long	readv(int, IOchunk*, int); <unistd.h> */
extern	int	remove(const char*);
/* extern	long	oseek(int, long, int); */
extern	vlong	p9seek(int, vlong, int);
/* give up
extern	long	segattach(int, char*, void*, ulong);
extern	int	segbrk(void*, void*);
extern	int	segdetach(void*);
extern	int	segflush(void*, ulong);
extern	int	segfree(void*, ulong);
*/
extern	int	p9sleep(long);
/* extern	int	stat(char*, uchar*, int); give up */
extern	Waitmsg*	p9wait(void);
extern	Waitmsg*	p9waitfor(int);
extern	Waitmsg*	waitnohang(void);
extern	int	p9waitpid(void);
/* <unistd.h>
extern	long	write(int, void*, long);
extern	long	writev(int, IOchunk*, int);
*/
extern	long	p9write(int, void*, long);
/* extern	int	wstat(char*, uchar*, int); give up */
extern	ulong	rendezvous(ulong, ulong);

#ifndef NOPLAN9DEFINES
#define alarm		p9alarm
#define	dup		p9dup
#define	exec		p9exec
#define	execl	p9execl
#define	seek		p9seek
#define sleep		p9sleep
#define wait		p9wait
#define waitpid		p9waitpid
/* #define fork		p9fork */
#define rfork		p9rfork
/* #define access		p9access */
#define create		p9create
#undef open
#define open		p9open
#define pipe		p9pipe
#define	waitfor		p9waitfor
#define write		p9write
#endif

extern	Dir*	dirstat(char*);
extern	Dir*	dirfstat(int);
extern	int	dirwstat(char*, Dir*);
extern	int	dirfwstat(int, Dir*);
extern	long	dirread(int, Dir**);
extern	void	nulldir(Dir*);
extern	long	dirreadall(int, Dir**);
/* extern	int	getpid(void); <unistd.h> */
/* extern	int	getppid(void); */
extern	void	rerrstr(char*, uint);
extern	char*	sysname(void);
extern	void	werrstr(char*, ...);
extern	char*	getns(void);
extern	char*	get9root(void);
extern	char*	unsharp(char*);
extern	int	sendfd(int, int);
extern	int	recvfd(int);
extern	int	post9pservice(int, char*, char*);
extern	int	chattyfuse;

/* external names that we don't want to step on */
#ifndef NOPLAN9DEFINES
#define main	p9main
#endif

#ifdef VARARGCK
#pragma	varargck	type	"lld"	vlong
#pragma	varargck	type	"llx"	vlong
#pragma	varargck	type	"lld"	uvlong
#pragma	varargck	type	"llx"	uvlong
#pragma	varargck	type	"ld"	long
#pragma	varargck	type	"lx"	long
#pragma	varargck	type	"ld"	ulong
#pragma	varargck	type	"lx"	ulong
#pragma	varargck	type	"d"	int
#pragma	varargck	type	"x"	int
#pragma	varargck	type	"c"	int
#pragma	varargck	type	"C"	int
#pragma	varargck	type	"d"	uint
#pragma	varargck	type	"x"	uint
#pragma	varargck	type	"c"	uint
#pragma	varargck	type	"C"	uint
#pragma	varargck	type	"f"	double
#pragma	varargck	type	"e"	double
#pragma	varargck	type	"g"	double
#pragma	varargck	type	"lf"	long double
#pragma	varargck	type	"le"	long double
#pragma	varargck	type	"lg"	long double
#pragma	varargck	type	"s"	char*
#pragma	varargck	type	"q"	char*
#pragma	varargck	type	"S"	Rune*
#pragma	varargck	type	"Q"	Rune*
#pragma	varargck	type	"r"	void
#pragma	varargck	type	"%"	void
#pragma	varargck	type	"n"	int*
#pragma	varargck	type	"p"	void*
#pragma	varargck	type	"<"	void*
#pragma	varargck	type	"["	void*
#pragma	varargck	type	"H"	void*
#pragma	varargck	type	"lH"	void*

#pragma	varargck	flag	' '
#pragma	varargck	flag	'#'
#pragma	varargck	flag	'+'
#pragma	varargck	flag	','
#pragma	varargck	flag	'-'
#pragma	varargck	flag	'u'

#pragma	varargck	argpos	fmtprint	2
#pragma	varargck	argpos	fprint	2
#pragma	varargck	argpos	print	1
#pragma	varargck	argpos	runeseprint	3
#pragma	varargck	argpos	runesmprint	1
#pragma	varargck	argpos	runesnprint	3
#pragma	varargck	argpos	runesprint	2
#pragma	varargck	argpos	seprint	3
#pragma	varargck	argpos	smprint	1
#pragma	varargck	argpos	snprint	3
#pragma	varargck	argpos	sprint	2
#pragma	varargck	argpos	sysfatal	1
#pragma	varargck	argpos	p9syslog	3
#pragma	varargck	argpos	werrstr	1
#endif

/* compiler directives on plan 9 */
#define	SET(x)	((x)=0)
#define	USED(x)	if(x){}else{}
#ifdef __GNUC__
#	if __GNUC__ >= 3
#		undef USED
#		define USED(x) ((void)(x))
#	endif
#endif

/* command line */
extern char	*argv0;
extern void __fixargv0(void);
#define	ARGBEGIN	for((argv0?0:(argv0=(__fixargv0(),*argv))),argv++,argc--;\
			    argv[0] && argv[0][0]=='-' && argv[0][1];\
			    argc--, argv++) {\
				char *_args, *_argt;\
				Rune _argc;\
				_args = &argv[0][1];\
				if(_args[0]=='-' && _args[1]==0){\
					argc--; argv++; break;\
				}\
				_argc = 0;\
				while(*_args && (_args += chartorune(&_argc, _args)))\
				switch(_argc)
#define	ARGEND		SET(_argt);USED(_argt);USED(_argc);USED(_args);}USED(argv);USED(argc);
#define	ARGF()		(_argt=_args, _args="",\
				(*_argt? _argt: argv[1]? (argc--, *++argv): 0))
#define	EARGF(x)	(_argt=_args, _args="",\
				(*_argt? _argt: argv[1]? (argc--, *++argv): ((x), abort(), (char*)0)))

#define	ARGC()		_argc

#if defined(__cplusplus)
}
#endif
#endif	/* _LIB9_H_ */
