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