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[8+Ctlsize+1]; 26 char *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 default: 44 net = "gok"; 45 break; 46 } 47 48 /* get control file name from listener process */ 49 n = read(fd, name, sizeof(name)-1); 50 if(n <= 0){ 51 _syserrno(); 52 return -1; 53 } 54 name[n] = 0; 55 cfd = open(name, O_RDWR); 56 if(cfd < 0){ 57 _syserrno(); 58 return -1; 59 } 60 61 nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr); 62 if(nfd < 0){ 63 _syserrno(); 64 return -1; 65 } 66 67 if(write(fd, "OK", 2) < 0){ 68 close(nfd); 69 _syserrno(); 70 return -1; 71 } 72 73 /* get remote address */ 74 ip = (struct sockaddr_in*)&nr->raddr; 75 _sock_ingetaddr(nr, ip, &n, "remote"); 76 if(a){ 77 memmove(a, ip, sizeof(struct sockaddr_in)); 78 *alen = sizeof(struct sockaddr_in); 79 } 80 81 return nfd; 82 case PF_UNIX: 83 if(r->other >= 0){ 84 errno = EGREG; 85 return -1; 86 } 87 88 for(;;){ 89 /* read path to new connection */ 90 n = read(fd, name, sizeof(name) - 1); 91 if(n < 0) 92 return -1; 93 if(n == 0) 94 continue; 95 name[n] = 0; 96 97 /* open new connection */ 98 _sock_srvname(file, name); 99 nfd = open(file, O_RDWR); 100 if(nfd < 0) 101 continue; 102 103 /* confirm opening on new connection */ 104 if(write(nfd, name, strlen(name)) > 0) 105 break; 106 107 close(nfd); 108 } 109 110 nr = _sock_newrock(nfd); 111 if(nr == 0){ 112 close(nfd); 113 return -1; 114 } 115 nr->domain = r->domain; 116 nr->stype = r->stype; 117 nr->protocol = r->protocol; 118 119 return nfd; 120 default: 121 errno = EOPNOTSUPP; 122 return -1; 123 } 124 } 125