1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/time.h>
4
5 #include <arpa/inet.h>
6 #include <netinet/in.h>
7
8 #include <err.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15
16 #define READ_BLOCK_TIME 5 /* unit: sec */
17
18 static void
sig_alarm(int sig __unused)19 sig_alarm(int sig __unused)
20 {
21 #define PANIC_STRING "read blocks\n"
22
23 write(2, PANIC_STRING, strlen(PANIC_STRING));
24 abort();
25 }
26
27 static void
usage(const char * cmd)28 usage(const char *cmd)
29 {
30 fprintf(stderr, "%s -p port\n", cmd);
31 exit(1);
32 }
33
34 int
main(int argc,char * argv[])35 main(int argc, char *argv[])
36 {
37 struct sockaddr_in in;
38 struct itimerval it;
39 int s, n, error, port, opt;
40 char buf;
41
42 port = 0;
43 while ((opt = getopt(argc, argv, "p:")) != -1) {
44 char *endptr;
45
46 switch (opt) {
47 case 'p':
48 port = strtol(optarg, &endptr, 0);
49 if (*endptr != '\0')
50 errx(1, "invalid -p argument");
51 break;
52
53 default:
54 usage(argv[0]);
55 }
56 }
57 if (port <= 0)
58 usage(argv[0]);
59
60 s = socket(AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
61 if (s < 0)
62 err(1, "socket failed");
63
64 memset(&in, 0, sizeof(in));
65 in.sin_family = AF_INET;
66 in.sin_port = htons(port);
67 if (bind(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
68 err(1, "bind %d failed", port);
69
70 memset(&it, 0, sizeof(it));
71 it.it_value.tv_sec = READ_BLOCK_TIME;
72 if (signal(SIGALRM, sig_alarm) == SIG_ERR)
73 err(1, "signal failed");
74 if (setitimer(ITIMER_REAL, &it, NULL) < 0)
75 err(1, "setitimer failed");
76
77 n = read(s, &buf, 1);
78 if (n < 0) {
79 error = errno;
80 if (error != EAGAIN) {
81 warnx("invalid errno %d", error);
82 abort();
83 }
84 } else {
85 warnx("read works");
86 abort();
87 }
88
89 fprintf(stderr, "passed\n");
90 exit(0);
91 }
92