1 /* $OpenBSD: pipe.c,v 1.4 2020/06/29 18:25:37 anton Exp $ */ 2 3 /* 4 * Copyright (c) 2019 Anton Lindqvist <anton@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include <sys/wait.h> 20 21 #include <err.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 27 #include "pipe.h" 28 29 static void sighandler(int); 30 static __dead void usage(void); 31 32 sig_atomic_t gotsigpipe = 0; 33 int infinity = 0; 34 int verbose = 0; 35 36 int 37 main(int argc, char *argv[]) 38 { 39 struct { 40 const char *t_name; 41 int (*t_fn)(void); 42 } tests[] = { 43 { "close-race", test_close_race }, 44 { "kqueue-read", test_kqueue_read }, 45 { "kqueue-read-eof", test_kqueue_read_eof }, 46 { "kqueue-write", test_kqueue_write }, 47 { "kqueue-write-eof", test_kqueue_write_eof }, 48 { "ping-pong", test_ping_pong }, 49 { "run-down-write-big", test_run_down_write_big }, 50 { "run-down-write-small", test_run_down_write_small }, 51 { "thundering-herd-read-signal", test_thundering_herd_read_signal }, 52 { "thundering-herd-read-wakeup", test_thundering_herd_read_wakeup }, 53 { "thundering-herd-write-signal", test_thundering_herd_write_signal }, 54 { "thundering-herd-write-wakeup", test_thundering_herd_write_wakeup }, 55 56 { NULL, NULL }, 57 }; 58 int ch, i; 59 60 while ((ch = getopt(argc, argv, "iv")) != -1) { 61 switch (ch) { 62 case 'i': 63 infinity = 1; 64 break; 65 case 'v': 66 verbose = 1; 67 break; 68 default: 69 usage(); 70 } 71 } 72 argc -= optind; 73 argv += optind; 74 if (argc != 1) 75 usage(); 76 77 if (signal(SIGPIPE, sighandler) == SIG_ERR) 78 err(1, "signal"); 79 80 for (i = 0; tests[i].t_name != NULL; i++) { 81 if (strcmp(argv[0], tests[i].t_name)) 82 continue; 83 84 return tests[i].t_fn(); 85 } 86 warnx("%s: no such test", argv[0]); 87 88 return 1; 89 } 90 91 int 92 xwaitpid(pid_t pid) 93 { 94 int status; 95 96 if (waitpid(pid, &status, 0) == -1) 97 err(1, "waitpid"); 98 if (WIFEXITED(status)) 99 return WEXITSTATUS(status); 100 if (WIFSIGNALED(status)) 101 return WTERMSIG(status); 102 return 0; 103 } 104 105 static void 106 sighandler(int signo) 107 { 108 109 gotsigpipe = signo; 110 } 111 112 static __dead void 113 usage(void) 114 { 115 116 fprintf(stderr, "usage: pipe [-iv] test-case\n"); 117 exit(1); 118 } 119