1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <sys/wait.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 static void
usage(const char * cmd)17 usage(const char *cmd)
18 {
19 fprintf(stderr, "%s -p port\n", cmd);
20 exit(1);
21 }
22
23 static void
connect_client(int port)24 connect_client(int port)
25 {
26 struct sockaddr_in in;
27 int s;
28
29 s = socket(AF_INET, SOCK_STREAM, 0);
30 if (s < 0)
31 err(1, "client socket failed");
32
33 memset(&in, 0, sizeof(in));
34 in.sin_family = AF_INET;
35 in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
36 in.sin_port = htons(port);
37 if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
38 err(1, "connect failed");
39
40 pause();
41 exit(0);
42 }
43
44 int
main(int argc,char * argv[])45 main(int argc, char *argv[])
46 {
47 struct sockaddr_in in;
48 int serv_s, s;
49 int opt, port, dummy, n, status, panic, ex;
50 pid_t pid;
51
52 ex = 1;
53 panic = 0;
54
55 port = 0;
56 while ((opt = getopt(argc, argv, "p:")) != -1) {
57 char *endptr;
58
59 switch (opt) {
60 case 'p':
61 port = strtol(optarg, &endptr, 0);
62 if (*endptr != '\0')
63 errx(1, "invalid -p");
64 break;
65
66 default:
67 usage(argv[0]);
68 }
69 }
70 if (port <= 0)
71 usage(argv[0]);
72
73 serv_s = socket(AF_INET, SOCK_STREAM, 0);
74 if (serv_s < 0)
75 err(1, "socket failed");
76
77 memset(&in, 0, sizeof(in));
78 in.sin_family = AF_INET;
79 in.sin_port = htons(port);
80 if (bind(serv_s, (const struct sockaddr *)&in, sizeof(in)) < 0)
81 err(1, "bind failed");
82
83 if (listen(serv_s, 0) < 0)
84 err(1, "listen failed");
85
86 pid = fork();
87 if (pid < 0) {
88 err(1, "fork failed");
89 } else if (pid == 0) {
90 connect_client(port);
91 abort();
92 }
93
94 s = accept4(serv_s, NULL, NULL, SOCK_NONBLOCK);
95 if (s < 0) {
96 warn("accept4 failed");
97 goto done;
98 }
99 panic = 1;
100
101 n = read(s, &dummy, sizeof(dummy));
102 if (n < 0) {
103 int error = errno;
104
105 if (error != EAGAIN) {
106 warnx("invaid errno %d", error);
107 goto done;
108 }
109 } else {
110 warnx("read works");
111 goto done;
112 }
113
114 ex = 0;
115 panic = 0;
116 fprintf(stderr, "passed\n");
117 done:
118 kill(pid, SIGKILL);
119 waitpid(pid, &status, 0);
120 if (panic)
121 abort();
122 exit(ex);
123 }
124