Merge branch 'vendor/TNFTP'
[dragonfly.git] / test / socket / accept / nonblock / accept_nblock.c
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 }