ref	-lsocket -lnsl
hdr,sys	poll,socket,netinet/in
lib	select,poll,socket
lib	htons,htonl sys/types.h sys/socket.h netinet/in.h
lib	getaddrinfo sys/types.h sys/socket.h netdb.h
typ	fd_set sys/socket.h sys/select.h
typ	socklen_t unistd.h sys/socket.h = unsigned int
tst	pipe_socketpair note{ use socketpair() for peekable pipe() }end execute{
	#include <ast.h>
	#include <sig.h>
	#include <sys/types.h>
	#include <sys/socket.h>
	#include <sys/wait.h>
	#ifndef SHUT_RD
	#define SHUT_RD		0
	#endif
	#ifndef SHUT_WR
	#define SHUT_WR		1
	#endif
	static void handler(int sig)
	{
		_exit(0);
	}
	int main(void)
	{
		int		n;
		int		pfd[2];
		int		sfd[2];
		char		buf[256];
		pid_t		pid;
		static char	msg[] = "hello world\n";
		close(0);
		if (pipe(pfd) < 0 ||
		    socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
		    shutdown(sfd[1], SHUT_RD) < 0 ||
		    shutdown(sfd[0], SHUT_WR) < 0)
			return 1;
		if ((pid = fork()) < 0)
			return 1;
		if (pid)
		{
			close(pfd[1]);
			close(sfd[1]);
			wait(&n);
			if (sfpkrd(pfd[0], buf, sizeof(buf), '\n', -1, 1) >= 0 ||
			    sfpkrd(sfd[0], buf, sizeof(buf), '\n', -1, 1) < 0)
				return 1;
		}
		else
		{
			close(pfd[0]);
			close(sfd[0]);
			write(pfd[1], msg, sizeof(msg) - 1);
			write(sfd[1], msg, sizeof(msg) - 1);
			return 0;
		}
		close(pfd[0]);
		close(sfd[0]);
		signal(SIGPIPE, handler);
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
		    shutdown(sfd[1], SHUT_RD) < 0 ||
		    shutdown(sfd[0], SHUT_WR) < 0)
			return 1;
		close(sfd[0]);
		write(sfd[1], msg, sizeof(msg) - 1);
		return 1;
	}
}end
tst	socketpair_devfd note{ /dev/fd/N handles socketpair() }end execute{
	#include <ast.h>
	#include <sys/types.h>
	#include <sys/socket.h>
	int main(void)
	{
		int		devfd;
		int		n;
		int		sfd[2];
		close(0);
		open("/dev/null", O_RDONLY);
		if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
			return 1;
		close(n);
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
		    shutdown(sfd[0], 1) < 0 ||
		    shutdown(sfd[1], 0) < 0)
			return 1;
		close(0);
		dup(sfd[0]);
		close(sfd[0]);
		if ((n = open("/dev/fd/0", O_RDONLY)) < 0)
			return 1;
		return 0;
	}
}end
tst	socketpair_shutdown_mode note{ fchmod() after socketpair() shutdown() }end execute{
	#include <ast.h>
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <sys/socket.h>
	int main(void)
	{
		int		sfd[2];
		struct stat	st0;
		struct stat	st1;
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, sfd) < 0 ||
		    shutdown(sfd[0], 1) < 0 ||
		    shutdown(sfd[1], 0) < 0)
			return 1;
		if (fstat(sfd[0], &st0) < 0 || fstat(sfd[1], &st1) < 0)
			return 1;
		if ((st0.st_mode & (S_IRUSR|S_IWUSR)) == S_IRUSR &&
		    (st1.st_mode & (S_IRUSR|S_IWUSR)) == S_IWUSR)
			return 1;
		if (fchmod(sfd[0], S_IRUSR) < 0 ||
		    fstat(sfd[0], &st0) < 0 ||
		    (st0.st_mode & (S_IRUSR|S_IWUSR)) != S_IRUSR)
			return 1;
		if (fchmod(sfd[1], S_IWUSR) < 0 ||
		    fstat(sfd[1], &st1) < 0 ||
		    (st1.st_mode & (S_IRUSR|S_IWUSR)) != S_IWUSR)
			return 1;
		return 0;
	}
}end
cat{
	#if _hdr_poll
	#    include    <poll.h>
	#else
	#   if _sys_poll
	#	include    <sys/poll.h>
	#   endif /* _sys_poll */
	#endif /* _hdr_poll */
	#if _lib_select
	#   ifndef FD_ZERO
	#	define FD_ZERO(x)	(*(x)=0)
	#   endif /* FD_ZERO */
	#   ifndef FD_SET
	#	define FD_SET(n,x)	(*(x)|=(1L<<(n)))
	#   endif /* FD_SET */
	#   if !_typ_fd_set
		typedef long fd_set;
	#   endif /* _typ_fd_set */
	#endif /* _lib_select */
}end
