1196554Sjilles/* $FreeBSD$ */ 2196554Sjilles 3196554Sjilles#include <sys/poll.h> 4196554Sjilles#include <sys/socket.h> 5196554Sjilles#include <sys/stat.h> 6196554Sjilles 7196554Sjilles#include <err.h> 8196554Sjilles#include <fcntl.h> 9196554Sjilles#include <signal.h> 10196554Sjilles#include <stdio.h> 11196554Sjilles#include <stdlib.h> 12196554Sjilles#include <unistd.h> 13196554Sjilles 14196554Sjillesstatic const char * 15196554Sjillesdecode_events(int events) 16196554Sjilles{ 17196554Sjilles char *ncresult; 18196554Sjilles const char *result; 19196554Sjilles 20196554Sjilles switch (events) { 21196554Sjilles case POLLIN: 22196554Sjilles result = "POLLIN"; 23196554Sjilles break; 24196554Sjilles case POLLOUT: 25196554Sjilles result = "POLLOUT"; 26196554Sjilles break; 27196554Sjilles case POLLIN | POLLOUT: 28196554Sjilles result = "POLLIN | POLLOUT"; 29196554Sjilles break; 30196554Sjilles case POLLHUP: 31196554Sjilles result = "POLLHUP"; 32196554Sjilles break; 33196554Sjilles case POLLIN | POLLHUP: 34196554Sjilles result = "POLLIN | POLLHUP"; 35196554Sjilles break; 36196554Sjilles case POLLOUT | POLLHUP: 37196554Sjilles result = "POLLOUT | POLLHUP"; 38196554Sjilles break; 39196554Sjilles case POLLIN | POLLOUT | POLLHUP: 40196554Sjilles result = "POLLIN | POLLOUT | POLLHUP"; 41196554Sjilles break; 42196554Sjilles default: 43196554Sjilles asprintf(&ncresult, "%#x", events); 44196554Sjilles result = ncresult; 45196554Sjilles break; 46196554Sjilles } 47196554Sjilles return (result); 48196554Sjilles} 49196554Sjilles 50196554Sjillesstatic void 51196554Sjillesreport(int num, const char *state, int expected, int got) 52196554Sjilles{ 53196554Sjilles if (expected == got) 54196554Sjilles printf("ok %-2d ", num); 55196554Sjilles else 56196554Sjilles printf("not ok %-2d", num); 57196554Sjilles printf(" state %s: expected %s; got %s\n", 58196554Sjilles state, decode_events(expected), decode_events(got)); 59196554Sjilles fflush(stdout); 60196554Sjilles} 61196554Sjilles 62196554Sjillesstatic int 63196554Sjillesset_nonblocking(int sck) 64196554Sjilles{ 65196554Sjilles int flags; 66196554Sjilles 67196554Sjilles flags = fcntl(sck, F_GETFL, 0); 68196554Sjilles flags |= O_NONBLOCK; 69196554Sjilles 70196554Sjilles if (fcntl(sck, F_SETFL, flags)) 71196554Sjilles return -1; 72196554Sjilles 73196554Sjilles return 0; 74196554Sjilles} 75196554Sjilles 76196554Sjillesstatic char largeblock[1048576]; /* should be more than AF_UNIX sockbuf size */ 77196554Sjillesstatic int fd[2]; 78196554Sjillesstatic struct pollfd pfd0; 79196554Sjillesstatic struct pollfd pfd1; 80196554Sjilles 81196554Sjillesvoid 82196554Sjillessetup(void) 83196554Sjilles{ 84196554Sjilles if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0) 85196554Sjilles err(1, "socketpair"); 86196554Sjilles if (set_nonblocking(fd[0]) == -1) 87196554Sjilles err(1, "fcntl"); 88196554Sjilles if (set_nonblocking(fd[1]) == -1) 89196554Sjilles err(1, "fcntl"); 90196554Sjilles pfd0.fd = fd[0]; 91196554Sjilles pfd0.events = POLLIN | POLLOUT; 92196554Sjilles pfd1.fd = fd[1]; 93196554Sjilles pfd1.events = POLLIN | POLLOUT; 94196554Sjilles} 95196554Sjilles 96196554Sjillesint 97196554Sjillesmain(void) 98196554Sjilles{ 99196554Sjilles int num; 100196554Sjilles 101196554Sjilles num = 1; 102196554Sjilles printf("1..18\n"); 103196554Sjilles fflush(stdout); 104196554Sjilles 105196554Sjilles /* Large write with close */ 106196554Sjilles setup(); 107196554Sjilles if (poll(&pfd0, 1, 0) == -1) 108196554Sjilles err(1, "poll"); 109196554Sjilles report(num++, "initial 0", POLLOUT, pfd0.revents); 110196554Sjilles if (poll(&pfd1, 1, 0) == -1) 111196554Sjilles err(1, "poll"); 112196554Sjilles report(num++, "initial 1", POLLOUT, pfd1.revents); 113196554Sjilles if (write(fd[0], largeblock, sizeof(largeblock)) == -1) 114196554Sjilles err(1, "write"); 115196554Sjilles if (poll(&pfd0, 1, 0) == -1) 116196554Sjilles err(1, "poll"); 117196554Sjilles report(num++, "after large write", 0, pfd0.revents); 118196554Sjilles if (poll(&pfd1, 1, 0) == -1) 119196554Sjilles err(1, "poll"); 120196554Sjilles report(num++, "other side after large write", POLLIN | POLLOUT, pfd1.revents); 121196554Sjilles close(fd[0]); 122196554Sjilles if (poll(&pfd1, 1, 0) == -1) 123196554Sjilles err(1, "poll"); 124196554Sjilles report(num++, "other side after close", POLLIN | POLLHUP, pfd1.revents); 125196554Sjilles if (read(fd[1], largeblock, sizeof(largeblock)) == -1) 126196554Sjilles err(1, "read"); 127196554Sjilles if (poll(&pfd1, 1, 0) == -1) 128196554Sjilles err(1, "poll"); 129196554Sjilles report(num++, "other side after reading input", POLLHUP, pfd1.revents); 130196554Sjilles close(fd[1]); 131196554Sjilles 132196554Sjilles /* With shutdown(SHUT_WR) */ 133196554Sjilles setup(); 134196554Sjilles if (shutdown(fd[0], SHUT_WR) == -1) 135196554Sjilles err(1, "shutdown"); 136196554Sjilles if (poll(&pfd0, 1, 0) == -1) 137196554Sjilles err(1, "poll"); 138196554Sjilles report(num++, "after shutdown(SHUT_WR)", POLLOUT, pfd0.revents); 139196554Sjilles if (poll(&pfd1, 1, 0) == -1) 140196554Sjilles err(1, "poll"); 141196554Sjilles report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents); 142196554Sjilles switch (read(fd[1], largeblock, sizeof(largeblock))) { 143196554Sjilles case 0: 144196554Sjilles break; 145196554Sjilles case -1: 146196554Sjilles err(1, "read after other side shutdown"); 147196554Sjilles break; 148196554Sjilles default: 149196554Sjilles errx(1, "kernel made up data that was never written"); 150196554Sjilles } 151196554Sjilles if (poll(&pfd1, 1, 0) == -1) 152196554Sjilles err(1, "poll"); 153196554Sjilles report(num++, "other side after reading EOF", POLLIN | POLLOUT, pfd1.revents); 154196554Sjilles if (write(fd[1], largeblock, sizeof(largeblock)) == -1) 155196554Sjilles err(1, "write"); 156196554Sjilles if (poll(&pfd0, 1, 0) == -1) 157196554Sjilles err(1, "poll"); 158196554Sjilles report(num++, "after data from other side", POLLIN | POLLOUT, pfd0.revents); 159196554Sjilles if (poll(&pfd1, 1, 0) == -1) 160196554Sjilles err(1, "poll"); 161196554Sjilles report(num++, "after writing", POLLIN, pfd1.revents); 162196554Sjilles if (shutdown(fd[1], SHUT_WR) == -1) 163196554Sjilles err(1, "shutdown second"); 164196554Sjilles if (poll(&pfd0, 1, 0) == -1) 165196554Sjilles err(1, "poll"); 166196554Sjilles report(num++, "after second shutdown", POLLIN | POLLHUP, pfd0.revents); 167196554Sjilles if (poll(&pfd1, 1, 0) == -1) 168196554Sjilles err(1, "poll"); 169196554Sjilles report(num++, "after second shutdown", POLLHUP, pfd1.revents); 170196554Sjilles close(fd[0]); 171196554Sjilles if (poll(&pfd1, 1, 0) == -1) 172196554Sjilles err(1, "poll"); 173196554Sjilles report(num++, "after close", POLLHUP, pfd1.revents); 174196554Sjilles close(fd[1]); 175196554Sjilles 176196554Sjilles /* 177196554Sjilles * With shutdown(SHUT_RD) 178196554Sjilles * Note that shutdown(SHUT_WR) is passed to the peer, but 179196554Sjilles * shutdown(SHUT_RD) is not. 180196554Sjilles */ 181196554Sjilles setup(); 182196554Sjilles if (shutdown(fd[0], SHUT_RD) == -1) 183196554Sjilles err(1, "shutdown"); 184196554Sjilles if (poll(&pfd0, 1, 0) == -1) 185196554Sjilles err(1, "poll"); 186196554Sjilles report(num++, "after shutdown(SHUT_RD)", POLLIN | POLLOUT, pfd0.revents); 187196554Sjilles if (poll(&pfd1, 1, 0) == -1) 188196554Sjilles err(1, "poll"); 189196554Sjilles report(num++, "other side after shutdown(SHUT_RD)", POLLOUT, pfd1.revents); 190196554Sjilles if (shutdown(fd[0], SHUT_WR) == -1) 191196554Sjilles err(1, "shutdown"); 192196554Sjilles if (poll(&pfd0, 1, 0) == -1) 193196554Sjilles err(1, "poll"); 194196554Sjilles report(num++, "after shutdown(SHUT_WR)", POLLHUP, pfd0.revents); 195196554Sjilles if (poll(&pfd1, 1, 0) == -1) 196196554Sjilles err(1, "poll"); 197196554Sjilles report(num++, "other side after shutdown(SHUT_WR)", POLLIN | POLLOUT, pfd1.revents); 198196554Sjilles close(fd[0]); 199196554Sjilles close(fd[1]); 200196554Sjilles 201196554Sjilles return (0); 202196554Sjilles} 203