]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/bsd/accept.c
ape: Add mkstemp to /sys/src/ape/lib/ap/gen/mkfile
[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         char name[Ctlsize];
24         char file[8+Ctlsize+1];
25         char *p, *net;
26
27         r = _sock_findrock(fd, 0);
28         if(r == 0){
29                 errno = ENOTSOCK;
30                 return -1;
31         }
32
33         switch(r->domain){
34         case PF_INET:
35         case PF_INET6:
36                 switch(r->stype){
37                 case SOCK_DGRAM:
38                         net = "udp";
39                         break;
40                 case SOCK_STREAM:
41                         net = "tcp";
42                         break;
43                 case SOCK_RDM:
44                         net = "il";
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                         return -1;
52                 name[n] = 0;
53                 cfd = open(name, O_RDWR);
54                 if(cfd < 0)
55                         return -1;
56
57                 nfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
58                 if(nfd < 0)
59                         return -1;
60
61                 if(write(fd, "OK", 2) < 0){
62                         close(nfd);
63                         return -1;
64                 }
65                 _sock_ingetaddr(nr, &nr->raddr, 0, "remote");   
66                 break;
67         case PF_UNIX:
68                 if(r->other >= 0){
69                         errno = EGREG;
70                         return -1;
71                 }
72
73                 for(;;){
74                         /* read path to new connection */
75                         n = read(fd, name, sizeof(name) - 1);
76                         if(n < 0)
77                                 return -1;
78                         if(n == 0)
79                                 continue;
80                         name[n] = 0;
81
82                         /* open new connection */
83                         _sock_srvname(file, name);
84                         nfd = open(file, O_RDWR);
85                         if(nfd < 0)
86                                 continue;
87
88                         /* confirm opening on new connection */
89                         if(write(nfd, name, strlen(name)) > 0)
90                                 break;
91
92                         close(nfd);
93                 }
94
95                 nr = _sock_newrock(nfd);
96                 if(nr == 0){
97                         close(nfd);
98                         return -1;
99                 }
100                 nr->domain = r->domain;
101                 nr->stype = r->stype;
102                 nr->protocol = r->protocol;
103                 nr->raddr = r->addr;
104                 break;
105         default:
106                 errno = EOPNOTSUPP;
107                 return -1;
108         }
109
110         if(a != 0)
111                 getpeername(nfd, a, alen);
112
113         return nfd;
114 }