]> git.lizzy.rs Git - plan9front.git/blob - sys/src/ape/lib/bsd/listen.c
import updated compilers from sources
[plan9front.git] / sys / src / ape / lib / bsd / listen.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 <string.h>
8 #include <errno.h>
9 #include <sys/stat.h>
10 #include <signal.h>
11
12 /* socket extensions */
13 #include <sys/uio.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <sys/un.h>
17
18 /* plan 9 */
19 #include "lib.h"
20 #include "sys9.h"
21
22 #include "priv.h"
23
24 extern int      _muxsid;
25 extern void     _killmuxsid(void);
26
27 /*
28  * replace the fd with a pipe and start a process to
29  * accept calls in.  this is all to make select work.
30  */
31 static int
32 listenproc(Rock *r, int fd)
33 {
34         Rock *nr;
35         char *net;
36         int cfd, nfd, dfd;
37         int pfd[2];
38         struct stat d;
39         char *p;
40         char listen[Ctlsize];
41         char name[Ctlsize];
42
43         switch(r->stype){
44         case SOCK_DGRAM:
45                 net = "udp";
46                 break;
47         case SOCK_STREAM:
48                 net = "tcp";
49                 break;
50         }
51
52         strcpy(listen, r->ctl);
53         p = strrchr(listen, '/');
54         if(p == 0)
55                 return -1;
56         strcpy(p+1, "listen");
57
58         if(pipe(pfd) < 0)
59                 return -1;
60
61         /* replace fd with a pipe */
62         nfd = dup(fd);
63         dup2(pfd[0], fd);
64         close(pfd[0]);
65         fstat(fd, &d);
66         r->inode = d.st_ino;
67         r->dev = d.st_dev;
68
69         /* start listening process */
70         switch(fork()){
71         case -1:
72                 close(pfd[1]);
73                 close(nfd);
74                 return -1;
75         case 0:
76                 if(_muxsid == -1) {
77                         _RFORK(RFNOTEG);
78                         _muxsid = getpgrp();
79                 } else
80                         setpgid(getpid(), _muxsid);
81                 _RENDEZVOUS(2, _muxsid);
82                 break;
83         default:
84                 atexit(_killmuxsid);
85                 _muxsid = _RENDEZVOUS(2, 0);
86                 close(pfd[1]);
87                 close(nfd);
88                 return 0;
89         }
90
91 /*      for(fd = 0; fd < 30; fd++)
92                 if(fd != nfd && fd != pfd[1])
93                         close(fd);/**/
94
95         for(;;){
96                 cfd = open(listen, O_RDWR);
97                 if(cfd < 0)
98                         break;
99
100                 dfd = _sock_data(cfd, net, r->domain, r->stype, r->protocol, &nr);
101                 if(dfd < 0)
102                         break;
103
104                 if(write(pfd[1], nr->ctl, strlen(nr->ctl)) < 0)
105                         break;
106                 if(read(pfd[1], name, sizeof(name)) <= 0)
107                         break;
108
109                 close(dfd);
110         }
111         exit(0);
112         return 0;
113 }
114
115 int
116 listen(fd, backlog)
117         int fd;
118         int backlog;
119 {
120         Rock *r;
121         int n, cfd;
122         char msg[128];
123         struct sockaddr_in *lip;
124         struct sockaddr_un *lunix;
125
126         r = _sock_findrock(fd, 0);
127         if(r == 0){
128                 errno = ENOTSOCK;
129                 return -1;
130         }
131
132         switch(r->domain){
133         case PF_INET:
134                 cfd = open(r->ctl, O_RDWR);
135                 if(cfd < 0){
136                         errno = EBADF;
137                         return -1;
138                 }
139                 lip = (struct sockaddr_in*)&r->addr;
140                 if(lip->sin_port >= 0) {
141                         if(write(cfd, "bind 0", 6) < 0) {
142                                 errno = EGREG;
143                                 close(cfd);
144                                 return -1;
145                         }
146                         snprintf(msg, sizeof msg, "announce %d",
147                                 ntohs(lip->sin_port));
148                 }
149                 else
150                         strcpy(msg, "announce *");
151                 n = write(cfd, msg, strlen(msg));
152                 if(n < 0){
153                         errno = EOPNOTSUPP;     /* Improve error reporting!!! */
154                         close(cfd);
155                         return -1;
156                 }
157                 close(cfd);
158
159                 return listenproc(r, fd);
160         case PF_UNIX:
161                 if(r->other < 0){
162                         errno = EGREG;
163                         return -1;
164                 }
165                 lunix = (struct sockaddr_un*)&r->addr;
166                 if(_sock_srv(lunix->sun_path, r->other) < 0){
167                         _syserrno();
168                         r->other = -1;
169                         return -1;
170                 }
171                 r->other = -1;
172                 return 0;
173         default:
174                 errno = EAFNOSUPPORT;
175                 return -1;
176         }
177 }