1 /* $OpenBSD: pipe.c,v 1.3 2019/12/24 09:37:53 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 verbose = 0; 34 35 int 36 main(int argc, char *argv[]) 37 { 38 struct { 39 const char *t_name; 40 int (*t_fn)(void); 41 } tests[] = { 42 { "kqueue-read", test_kqueue_read }, 43 { "kqueue-read-eof", test_kqueue_read_eof }, 44 { "kqueue-write", test_kqueue_write }, 45 { "kqueue-write-eof", test_kqueue_write_eof }, 46 { "ping-pong", test_ping_pong }, 47 { "run-down-write-big", test_run_down_write_big }, 48 { "run-down-write-small", test_run_down_write_small }, 49 { "thundering-herd-read-signal", test_thundering_herd_read_signal }, 50 { "thundering-herd-read-wakeup", test_thundering_herd_read_wakeup }, 51 { "thundering-herd-write-signal", test_thundering_herd_write_signal }, 52 { "thundering-herd-write-wakeup", test_thundering_herd_write_wakeup }, 53 54 { NULL, NULL }, 55 }; 56 int ch, i; 57 58 while ((ch = getopt(argc, argv, "v")) != -1) { 59 switch (ch) { 60 case 'v': 61 verbose = 1; 62 break; 63 default: 64 usage(); 65 } 66 } 67 argc -= optind; 68 argv += optind; 69 if (argc != 1) 70 usage(); 71 72 if (signal(SIGPIPE, sighandler) == SIG_ERR) 73 err(1, "signal"); 74 75 for (i = 0; tests[i].t_name != NULL; i++) { 76 if (strcmp(argv[0], tests[i].t_name)) 77 continue; 78 79 return tests[i].t_fn(); 80 } 81 warnx("%s: no such test", argv[0]); 82 83 return 1; 84 } 85 86 int 87 xwaitpid(pid_t pid) 88 { 89 int status; 90 91 if (waitpid(pid, &status, 0) == -1) 92 err(1, "waitpid"); 93 if (WIFEXITED(status)) 94 return WEXITSTATUS(status); 95 if (WIFSIGNALED(status)) 96 return WTERMSIG(status); 97 return 0; 98 } 99 100 static void 101 sighandler(int signo) 102 { 103 104 gotsigpipe = signo; 105 } 106 107 static __dead void 108 usage(void) 109 { 110 111 fprintf(stderr, "usage: pipe test-case\n"); 112 exit(1); 113 } 114