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