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 #define CHECKFD_CMD	"checkfd"
17 #define CHECKFD_PATH	"/usr/local/bin/" CHECKFD_CMD
18 
19 static void
20 usage(const char *cmd)
21 {
22 	fprintf(stderr, "%s -p port\n", cmd);
23 	exit(1);
24 }
25 
26 static void
27 connect_client(int port)
28 {
29 	struct sockaddr_in in;
30 	int s;
31 
32 	memset(&in, 0, sizeof(in));
33 	in.sin_family = AF_INET;
34 	in.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
35 	in.sin_port = htons(port);
36 
37 	s = socket(AF_INET, SOCK_STREAM, 0);
38 	if (s < 0)
39 		err(1, "client socket failed");
40 	if (connect(s, (const struct sockaddr *)&in, sizeof(in)) < 0)
41 		err(1, "connect failed");
42 
43 	pause();
44 	exit(0);
45 }
46 
47 int
48 main(int argc, char *argv[])
49 {
50 	pid_t pid;
51 	struct sockaddr_in in;
52 	int serv_s, s;
53 	int opt, port, status, ecode, error;
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 %s", optarg);
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 		/* NEVER REACHED */
93 	}
94 
95 	s = accept4(serv_s, NULL, NULL, SOCK_CLOEXEC);
96 	if (s < 0)
97 		error = errno;
98 	else
99 		error = 0;
100 
101 	/* Kill connect_client */
102 	kill(pid, SIGKILL);
103 	waitpid(pid, &status, 0);
104 
105 	if (error)
106 		errc(1, error, "accept4 failed");
107 
108 	pid = fork();
109 	if (pid < 0) {
110 		err(1, "fork failed");
111 	} else if (pid == 0) {
112 		char fd[8];
113 
114 		snprintf(fd, sizeof(fd), "%d", s);
115 		execl(CHECKFD_PATH, CHECKFD_CMD, fd, NULL);
116 	}
117 
118 	if (waitpid(pid, &status, 0) < 0)
119 		err(1, "waitpid failed");
120 	if (!WIFEXITED(status))
121 		errx(1, "not exited");
122 	ecode = WEXITSTATUS(status);
123 	if (ecode != 0) {
124 		warnx("exit code %d", ecode);
125 		abort();
126 	}
127 
128 	fprintf(stderr, "passed\n");
129 	exit(0);
130 }
131