1 /* $OpenBSD: accept.c,v 1.6 2021/12/13 16:56:49 deraadt Exp $ */
2 /*
3 * Written by Artur Grabowski <art@openbsd.org>, 2002 Public Domain.
4 */
5 #include <sys/socket.h>
6 #include <sys/time.h>
7 #include <sys/wait.h>
8 #include <sys/un.h>
9
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <fcntl.h>
14 #include <err.h>
15 #include <signal.h>
16 #include <string.h>
17
18 #define SOCK_NAME "test-sock"
19
20 int child(void);
21
22 int
main(int argc,char * argv[])23 main(int argc, char *argv[])
24 {
25 int listensock, sock;
26 struct sockaddr_un sun, csun;
27 int csunlen;
28 int fd, lastfd;
29 int status;
30 int ischild = 0;
31
32 /*
33 * Create the listen socket.
34 */
35 if ((listensock = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
36 err(1, "socket");
37
38 unlink(SOCK_NAME);
39 memset(&sun, 0, sizeof(sun));
40 sun.sun_family = AF_LOCAL;
41 strlcpy(sun.sun_path, SOCK_NAME, sizeof sun.sun_path);
42
43
44 if (bind(listensock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
45 err(1, "bind");
46
47 if (listen(listensock, 1) == -1)
48 err(1, "listen");
49
50 switch (fork()) {
51 case -1:
52 err(1, "fork");
53 case 0:
54 return child();
55 }
56
57 while ((fd = open("/dev/null", O_RDONLY)) >= 0)
58 lastfd = fd;
59
60 switch (fork()) {
61 case -1:
62 err(1, "fork");
63 case 0:
64 ischild = 1;
65 close(lastfd); /* Close one fd so that accept can succeed */
66 sleep(2); /* sleep a bit so that we're the second to accept */
67 }
68
69 sock = accept(listensock, (struct sockaddr *)&csun, &csunlen);
70
71 if (!ischild && sock >= 0)
72 errx(1, "accept succeeded in parent");
73 if (ischild && sock < 0)
74 err(1, "accept failed in child");
75
76 while (!ischild && wait4(-1, &status, 0, NULL) > 0)
77 ;
78
79 return (0);
80 }
81
82 int
child()83 child()
84 {
85 int i, fd, sock;
86 struct sockaddr_un sun;
87
88 /*
89 * Create socket and connect to the receiver.
90 */
91 if ((sock = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
92 errx(1, "child socket");
93
94 (void) memset(&sun, 0, sizeof(sun));
95 sun.sun_family = AF_LOCAL;
96 (void) strlcpy(sun.sun_path, SOCK_NAME, sizeof sun.sun_path);
97
98 if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) == -1)
99 err(1, "child connect");
100
101 return (0);
102 }
103