]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/bsd/accept.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / ape / lib / bsd / accept.c
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 *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*)&nr->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 }