cmd	universe
hdr	dirent,filio,jioctl,locale,mman,ndir,utime,vfork,wchar
dat	_tzname,tzname
lib	_cleanup,BSDsetpgrp,atexit,bcopy,bzero,confstr,dirread,dup2,fchmod
lib	fcntl,fnmatch,fork,fsync,getconf,getdents,getdirentries,getdtablesize
lib	getgroups,getpagesize,getrlimit,getuniverse,index,killpg,link
lib	localeconv,lstat,mbtowc,memccpy
lib	memchr,memcmp,memcpy,memmove,memset,mkdir,mkfifo,mknod,mktemp
lib	mount,on_exit,onexit,opendir,pathconf,readlink,remove,rename,rindex
lib	rmdir,rewinddir,setlocale,setpgid,setpgrp,setpgrp2,setreuid,setsid
lib	setuid,sigaction,sigprocmask,sigsetmask,sigvec
lib	socketpair,spawnve,spawnveg,strchr,strcoll,strdup,strerror,strrchr
lib	strtod,strtol,strtoul,strxfrm,symlink,sysconf
lib	telldir,tmpnam,tzset,universe,unlink,utime,vfork
lib	wctype,iswblank,iswctype
lib	execve,pcreateve,NutForkExecve
mem	direct.d_reclen sys/types.h sys/dir.h
mem	dirent.d_fileno,dirent.d_ino,dirent.d_namlen,dirent.d_off,dirent.d_reclen sys/types.h dirent.h
mem	DIR.dd_fd sys/types.h - dirent.h - sys/dir.h
sys	dir,filio,jioctl,localedef,mman,ptem,resource,socket,stream,universe
sys	vfork

tst	tst_errno note{ errno can be assigned }end link{
	_BEGIN_EXTERNS_
	extern int errno;
	error() { }
	strerror() { }
	_END_EXTERNS_
	main() { errno = 0; error(); strerror(); }
}end

tst	lib_poll_fd_1 note{ fd is first arg to poll() }end execute{
	#include <poll.h>
	_BEGIN_EXTERNS_
	extern int	pipe _ARG_((int*));
	_END_EXTERNS_
	main()
	{	int		rw[2];
		struct pollfd	fd;
		if (pipe(rw) < 0) return 1;
		fd.fd = rw[0];
		fd.events = POLLIN;
		fd.revents = 0;
		return poll(&fd, 1, 0) < 0;
	}
}end

tst	lib_poll_fd_2 note{ fd is second arg to poll() }end execute{
	#include <poll.h>
	_BEGIN_EXTERNS_
	extern int	pipe _ARG_((int*));
	_END_EXTERNS_
	main()
	{	int		rw[2];
		struct pollfd	fd;
		if (pipe(rw) < 0) return 1;
		fd.fd = rw[0];
		fd.events = POLLIN;
		fd.revents = 0;
		return poll(1, &fd, 0) < 0;
	}
}end

cat{
	#if _lib_poll_fd_1 || _lib_poll_fd_2
	#define _lib_poll	1
	#endif
	#if _lib_NutForkExecve
	#define _map_spawnve	NutForkExecve
	#else
	#if _lib_pcreateve
	#define _map_spawnve	pcreateve
	#endif
	#endif
}end

tst	lib_poll_notimer note{ poll with no fds ignores timeout }end execute{
	#include <sys/types.h>
	#include <poll.h>
	_BEGIN_EXTERNS_
	extern time_t	time _ARG_((time_t*));
	_END_EXTERNS_
	#define TIMEOUT		4
	main()
	{
		unsigned long	start;
		unsigned long	finish;
		struct pollfd	fd;
		start = time((time_t*)0);
		if (poll(&fd, 0, TIMEOUT * 1000) < 0)
			return 0;
		finish = time((time_t*)0);
		return (finish - start) > (TIMEOUT / 2);
	}
}end

tst	lib_select note{ select() has standard 5 arg interface }end link{
	#include <sys/types.h>
	#include <sys/time.h>
	#include <sys/socket.h>
	main()
	{	struct timeval	tmb;
		fd_set		rd;
		FD_ZERO(&rd);
		FD_SET(0,&rd);
		tmb.tv_sec = 0;
		tmb.tv_usec = 0;
		select(1,&rd,(fd_set*)0,(fd_set*)0,&tmb);
		return 0;
	}
}end

tst	pipe_rw note{ full duplex pipes }end execute{
	_BEGIN_EXTERNS_
	extern int	pipe _ARG_((int*));
	extern int	read _ARG_((int, void*, int));
	extern int	strcmp _ARG_((const char*, const char*));
	extern int	write _ARG_((int, void*, int));
	_END_EXTERNS_
	main()
	{
		static char	test[] = "test\n";
		int		io[2];
		char		buf[sizeof(test)];
		if (pipe(io)) return 1;
		if (write(io[1], test, sizeof(test)) != sizeof(test)) return 1;
		if (read(io[0], buf, sizeof(test)) != sizeof(test)) return 1;
		if (strcmp(test, buf)) return 1;
		if (write(io[0], test, sizeof(test)) != sizeof(test)) return 1;
		if (read(io[1], buf, sizeof(test)) != sizeof(test)) return 1;
		if (strcmp(test, buf)) return 1;
		return 0;
	}
}end

tst	real_vfork note{ vfork child shares data with parent }end execute{
	_BEGIN_EXTERNS_
	extern int	vfork();
	extern int	_exit(int);
	_END_EXTERNS_
	int		code;
	main()
	{
		code = 1;
		if (!vfork()) code = 0;
		_exit(code);
	}
}end

tst	stream_peek note{ ioctl(I_PEEK) works }end link{
	#include <sys/types.h>
	#include <stropts.h>
	main()
	{	struct strpeek	pbuf;
		pbuf.flags = 0;
		pbuf.ctlbuf.maxlen = pbuf.databuf.maxlen =
		pbuf.ctlbuf.len = pbuf.databuf.len = 0;
		pbuf.ctlbuf.buf = pbuf.databuf.buf = 0;
		ioctl(0,I_PEEK,&pbuf);
		return 0;
	}
}end

tst	socket_peek note{ recv(MSG_PEEK) works }end link{
	#include <sys/types.h>
	#include <sys/socket.h>
	main()
	{	char	buf[128];
		recv(0,buf,sizeof(buf),MSG_PEEK);
		return 0;
	}
}end

tst	lib_mmap sys/types.h sys/stat.h unistd.h fcntl.h mman.h sys/mman.h sys/times.h note{ standard mmap interface that works }end execute{
	#define BUFSIZE	(16*1024)
	#define MAPSIZE	(16*1024)
	#define WRITE	(64)
	#if _STD_
	main(int argc, char** argv)
	#else
	main(argc,argv)
	int	argc;
	char**	argv;
	#endif
	{
		caddr_t		mm;
		char*		t;
		char*		f;
		int		i;
		int		fd;
		char		file[1024];
		char		buf[BUFSIZE];
		struct tms	brdtm, erdtm, bmmtm, emmtm;
	
		f = argv[0];
		t = file;
		while (*t = *f++) t++;
		*t++ = '.';
		*t++ = 'D';
		*t = 0;
		/* create data file */
		if ((fd = creat(file,0666)) < 0)
			return(1);
		for (i = 0; i < sizeof(buf); ++i)
			buf[i] = '0' + (i%10);
		for (i = 0; i < WRITE; ++i)
			if (write(fd,buf,sizeof(buf)) != sizeof(buf))
				return(1);
		close(fd);
		/* read time */
		if ((fd = open(file, 0)) < 0)
			return(1);
		times(&brdtm);
		for (i = 0; i < WRITE; ++i)
			if (read(fd,buf,sizeof(buf)) != sizeof(buf))
				return(1);
		times(&erdtm);
		close(fd);
		/* memory map time */
		if ((fd = open(file,0)) < 0)
			return(1);
		times(&bmmtm);
		mm = 0;
		for (i = 0; i < (WRITE/(MAPSIZE/BUFSIZE)); ++i)
		{	mm = (caddr_t)mmap(mm, MAPSIZE, (PROT_READ|PROT_WRITE),
				  (MAP_PRIVATE | (mm ? MAP_FIXED : 0)),
				  fd, i*MAPSIZE );
			if(mm == (caddr_t)(-1) || mm == (caddr_t)0)
				return(1);
		}
		times(&emmtm);
		close(fd);
		unlink(file);
		if(((erdtm.tms_utime-brdtm.tms_utime)+(erdtm.tms_stime-brdtm.tms_stime)) <=
		   ((emmtm.tms_utime-bmmtm.tms_utime)+(emmtm.tms_stime-bmmtm.tms_stime)) )
			return(1);
	
		return(0);
	}
}end

tst	ptr_dd_buf sys/types.h - dirent.h - ndir.h - sys/dir.h note{ DIR.dd_buf is a pointer }end compile{
	main()
	{
		DIR*	dirp;
		dirp->dd_buf = 0;
		return 0;
	}
}end

tst	lib_utime_now note{ utime works with 0 time vector }end execute{
	#include <sys/types.h>
	_BEGIN_EXTERNS_
	extern int	utime _ARG_((const char*, void*));
	_END_EXTERNS_
	main()
	{
		return utime(".", (void*)0) == -1;
	}
}end

tst	run{
	u=att
	case `/bin/cat -s /dev/null/foo 2>&1` in
	'')	;;
	*)	case `/bin/echo '\\\\t'` in
		'\\t')	u=ucb ;;
		esac
		;;
	esac
	echo "#define _UNIV_DEFAULT	\\"$u\\"	/* default universe name */"
}end

std	cleanup note{ stuck with standard _cleanup }end noexecute{
	#include <stdio.h>
	_BEGIN_EXTERNS_
	extern void exit _ARG_((int));
	extern void _exit _ARG_((int));
	extern void _cleanup();
	void _cleanup() { _exit(0); }
	_END_EXTERNS_
	main() { printf("cleanup\n"); exit(1); }
}end

std	malloc note{ stuck with standard malloc }end noexecute{
	_BEGIN_EXTERNS_
	extern char* strdup _ARG_((const char*));
	#if _STD_
	char* malloc(unsigned n) { return 0; }
	#else
	char* malloc(n) unsigned n; { return 0; }
	#endif
	_END_EXTERNS_
	main() { return strdup("yo") != 0; }
}end

std	signal note{ stuck with standard signal }end nolink{
	_BEGIN_EXTERNS_
	extern int abort();
	int signal() { return 0; }
	_END_EXTERNS_
	main() { signal(); abort(); return 0; }
}end

std	strcoll note{ standard strcoll works }end execute{
	#include <string.h>
	#define S	"hello world"
	main()
	{
		char	s[] = S;
		char	t[] = S;
		return strcoll(s, t) || strcmp(s, t);
	}
}end
