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
main(int argc,char * argv[])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
xwaitpid(pid_t pid)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
sighandler(int signo)107 sighandler(int signo)
108 {
109
110 gotsigpipe = signo;
111 }
112
113 static __dead void
usage(void)114 usage(void)
115 {
116
117 fprintf(stderr, "usage: pipe [-iv] test-case\n");
118 exit(1);
119 }
120