xref: /openbsd/regress/sys/kern/accept/accept.c (revision d415bd75)
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
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
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