1 /* $OpenBSD: pipe.c,v 1.5 2021/10/22 05:03:04 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 { "select-hup", test_select_hup }, 52 { "thundering-herd-read-signal", test_thundering_herd_read_signal }, 53 { "thundering-herd-read-wakeup", test_thundering_herd_read_wakeup }, 54 { "thundering-herd-write-signal", test_thundering_herd_write_signal }, 55 { "thundering-herd-write-wakeup", test_thundering_herd_write_wakeup }, 56 57 { NULL, NULL }, 58 }; 59 int ch, i; 60 61 while ((ch = getopt(argc, argv, "iv")) != -1) { 62 switch (ch) { 63 case 'i': 64 infinity = 1; 65 break; 66 case 'v': 67 verbose = 1; 68 break; 69 default: 70 usage(); 71 } 72 } 73 argc -= optind; 74 argv += optind; 75 if (argc != 1) 76 usage(); 77 78 if (signal(SIGPIPE, sighandler) == SIG_ERR) 79 err(1, "signal"); 80 81 for (i = 0; tests[i].t_name != NULL; i++) { 82 if (strcmp(argv[0], tests[i].t_name)) 83 continue; 84 85 return tests[i].t_fn(); 86 } 87 warnx("%s: no such test", argv[0]); 88 89 return 1; 90 } 91 92 int 93 xwaitpid(pid_t pid) 94 { 95 int status; 96 97 if (waitpid(pid, &status, 0) == -1) 98 err(1, "waitpid"); 99 if (WIFEXITED(status)) 100 return WEXITSTATUS(status); 101 if (WIFSIGNALED(status)) 102 return WTERMSIG(status); 103 return 0; 104 } 105 106 static void 107 sighandler(int signo) 108 { 109 110 gotsigpipe = signo; 111 } 112 113 static __dead void 114 usage(void) 115 { 116 117 fprintf(stderr, "usage: pipe [-iv] test-case\n"); 118 exit(1); 119 } 120