1 /* 2 * Copyright (c) 2004 Todd C. Miller <Todd.Miller@courtesan.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include <sys/param.h> 18 #include <sys/stat.h> 19 #include <sys/poll.h> 20 #include <errno.h> 21 #include <fcntl.h> 22 #include <signal.h> 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 #include <unistd.h> 27 28 #ifndef INFTIM 29 #define INFTIM -1 30 #endif 31 32 void usage(void); 33 void sigalrm(int); 34 void dopoll(int, int, char *, int); 35 void doselect(int, int, int); 36 void runtest(char *, int, int); 37 38 #if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) || \ 39 defined(__linux__) 40 extern char *__progname; 41 #else 42 char *__progname; 43 #endif 44 45 /* 46 * Test FIFOs and poll(2) both with an emtpy and full FIFO. 47 */ 48 int 49 main(int argc, char **argv) 50 { 51 #if !defined(__OpenBSD__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && \ 52 !defined(__linux__) 53 __progname = argv[0]; 54 #endif 55 if (argc != 2) 56 usage(); 57 58 runtest(argv[1], 0, 0); 59 runtest(argv[1], 0, INFTIM); 60 runtest(argv[1], O_NONBLOCK, 0); 61 runtest(argv[1], O_NONBLOCK, INFTIM); 62 63 exit(0); 64 } 65 66 void 67 runtest(char *fifo, int flags, int timeout) 68 { 69 struct sigaction sa; 70 ssize_t nread; 71 int fd; 72 char buf[BUFSIZ]; 73 74 (void)unlink(fifo); 75 if (mkfifo(fifo, 0644) != 0) { 76 printf("mkfifo %s: %s\n", fifo, strerror(errno)); 77 exit(1); 78 } 79 80 sigemptyset(&sa.sa_mask); 81 sa.sa_flags = 0; 82 sa.sa_handler = sigalrm; 83 sigaction(SIGALRM, &sa, NULL); 84 85 alarm(2); 86 if ((fd = open(fifo, O_RDWR | flags, 0644)) == -1) { 87 printf("open %s: %s\n", fifo, strerror(errno)); 88 exit(1); 89 } 90 alarm(0); 91 (void)unlink(fifo); 92 printf("\nOpened fifo %s%s\n", fifo, 93 (flags & O_NONBLOCK) ? " (nonblocking)" : ""); 94 95 printf("\nTesting empty FIFO:\n"); 96 dopoll(fd, POLLIN|POLLOUT, "POLLIN|POLLOUT", timeout); 97 dopoll(fd, POLLIN, "POLLIN", timeout); 98 dopoll(fd, POLLOUT, "POLLOUT", timeout); 99 doselect(fd, fd, timeout); 100 doselect(fd, -1, timeout); 101 doselect(-1, fd, timeout); 102 103 if (write(fd, "test", 4) != 4) { 104 printf("write error: %s\n", strerror(errno)); 105 exit(1); 106 } 107 108 printf("\nTesting full FIFO:\n"); 109 dopoll(fd, POLLIN|POLLOUT, "POLLIN|POLLOUT", timeout); 110 dopoll(fd, POLLIN, "POLLIN", timeout); 111 dopoll(fd, POLLOUT, "POLLOUT", timeout); 112 doselect(fd, fd, timeout); 113 doselect(fd, -1, timeout); 114 doselect(-1, fd, timeout); 115 116 if ((nread = read(fd, buf, sizeof(buf))) <= 0) { 117 printf("read error: %s\n", (nread == 0) ? "EOF" : strerror(errno)); 118 exit(1); 119 } 120 buf[nread] = '\0'; 121 printf("\treceived '%s' from FIFO\n", buf); 122 } 123 124 void 125 dopoll(int fd, int events, char *str, int timeout) 126 { 127 struct pollfd pfd; 128 int nready; 129 130 pfd.fd = fd; 131 pfd.events = events; 132 133 printf("\tpoll %s, timeout=%d\n", str, timeout); 134 pfd.events = events; 135 alarm(2); 136 nready = poll(&pfd, 1, timeout); 137 alarm(0); 138 if (nready < 0) { 139 printf("poll: %s\n", strerror(errno)); 140 return; 141 } 142 printf("\t\t%d fd(s) ready%s", nready, nready ? ", revents ==" : ""); 143 if (pfd.revents & POLLIN) 144 printf(" POLLIN"); 145 if (pfd.revents & POLLOUT) 146 printf(" POLLOUT"); 147 if (pfd.revents & POLLERR) 148 printf(" POLLERR"); 149 if (pfd.revents & POLLHUP) 150 printf(" POLLHUP"); 151 if (pfd.revents & POLLNVAL) 152 printf(" POLLNVAL"); 153 printf("\n"); 154 } 155 156 void 157 doselect(int rfd, int wfd, int timeout) 158 { 159 struct timeval tv, *tvp; 160 fd_set *rfds = NULL, *wfds = NULL; 161 int nready, maxfd; 162 163 if (timeout == INFTIM) 164 tvp = NULL; 165 else { 166 tv.tv_sec = timeout / 1000; 167 tv.tv_usec = (timeout % 1000) * 1000; 168 tvp = &tv; 169 } 170 tv.tv_sec = tv.tv_usec = 0; 171 maxfd = rfd > wfd ? rfd : wfd; 172 if (rfd != -1) { 173 rfds = calloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask)); 174 if (rfds == NULL) { 175 printf("unable to allocate memory\n"); 176 exit(1); 177 } 178 FD_SET(rfd, rfds); 179 } 180 if (wfd != -1) { 181 wfds = calloc(howmany(maxfd + 1, NFDBITS), sizeof(fd_mask)); 182 if (wfds == NULL) { 183 printf("unable to allocate memory\n"); 184 exit(1); 185 } 186 FD_SET(wfd, wfds); 187 } 188 189 printf("\tselect%s%s\n", rfds ? " read" : "", 190 wfds ? " write" : ""); 191 192 alarm(2); 193 nready = select(maxfd + 1, rfds, wfds, NULL, &tv); 194 alarm(0); 195 if (nready < 0) { 196 printf("select: %s\n", strerror(errno)); 197 goto cleanup; 198 } 199 printf("\t\t%d fd(s) ready", nready); 200 if (rfds != NULL && FD_ISSET(rfd, rfds)) 201 printf(", readable"); 202 if (wfds != NULL && FD_ISSET(wfd, wfds)) 203 printf(", writeable"); 204 printf("\n"); 205 cleanup: 206 free(rfds); 207 free(wfds); 208 } 209 210 void 211 sigalrm(int dummy) 212 { 213 /* Just cause EINTR */ 214 return; 215 } 216 217 void 218 usage(void) 219 { 220 fprintf(stderr, "usage: %s fifoname\n", __progname); 221 exit(1); 222 } 223