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
accept(int fd,void * a,int * alen)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