1 /* posix */ 2 #include <sys/types.h> 3 #include <unistd.h> 4 #include <stdlib.h> 5 #include <stdio.h> 6 #include <fcntl.h> 7 #include <errno.h> 8 #include <string.h> 9 10 /* bsd extensions */ 11 #include <sys/uio.h> 12 #include <sys/socket.h> 13 #include <netinet/in.h> 14 #include <sys/un.h> 15 16 #include "priv.h" 17 18 int 19 accept(int fd, void *a, int *alen) 20 { 21 int n, nfd, cfd; 22 Rock *r, *nr; 23 struct sockaddr_in *ip; 24 char name[Ctlsize]; 25 char file[Ctlsize]; 26 char *p, *net; 27 28 r = _sock_findrock(fd, 0); 29 if(r == 0){ 30 errno = ENOTSOCK; 31 return -1; 32 } 33 34 switch(r->domain){ 35 case PF_INET: 36 switch(r->stype){ 37 case SOCK_DGRAM: 38 net = "udp"; 39 break; 40 case SOCK_STREAM: 41 net = "tcp"; 42 break; 43 } 44 45 /* get control file name from listener process */ 46 n = read(fd, name, sizeof(name)-1); 47 if(n <= 0){ 48 _syserrno(); 49 return -1; 50 } 51 name[n] = 0; 52 cfd = open(name, O_RDWR); 53 if(cfd < 0){ 54 _syserrno(); 55 return -1; 56 } 57 58 nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr); 59 if(nfd < 0){ 60 _syserrno(); 61 return -1; 62 } 63 64 if(write(fd, "OK", 2) < 0){ 65 close(nfd); 66 _syserrno(); 67 return -1; 68 } 69 70 /* get remote address */ 71 ip = (struct sockaddr_in*)&r->raddr; 72 _sock_ingetaddr(nr, ip, &n, "remote"); 73 if(a){ 74 memmove(a, ip, sizeof(struct sockaddr_in)); 75 *alen = sizeof(struct sockaddr_in); 76 } 77 78 return nfd; 79 case PF_UNIX: 80 if(r->other >= 0){ 81 errno = EGREG; 82 return -1; 83 } 84 85 for(;;){ 86 /* read path to new connection */ 87 n = read(fd, name, sizeof(name) - 1); 88 if(n < 0) 89 return -1; 90 if(n == 0) 91 continue; 92 name[n] = 0; 93 94 /* open new connection */ 95 _sock_srvname(file, name); 96 nfd = open(file, O_RDWR); 97 if(nfd < 0) 98 continue; 99 100 /* confirm opening on new connection */ 101 if(write(nfd, name, strlen(name)) > 0) 102 break; 103 104 close(nfd); 105 } 106 107 nr = _sock_newrock(nfd); 108 if(nr == 0){ 109 close(nfd); 110 return -1; 111 } 112 nr->domain = r->domain; 113 nr->stype = r->stype; 114 nr->protocol = r->protocol; 115 116 return nfd; 117 default: 118 errno = EOPNOTSUPP; 119 return -1; 120 } 121 } 122