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