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