|
|
1.1 root 1: #include <sys/param.h>
2: #include <stdio.h>
3: #include <sys/filio.h>
4: #include <signal.h>
5: #include <ipc.h>
6: #include <libc.h>
7: #include <wait.h>
8: #include "defs.h"
9:
10: /* preeclared */
11: void dodialout();
12: void dodialin();
13: void doopen();
14: void docreat();
15: void doredial();
16:
17: /* global */
18: int pid;
19: int debug;
20: int zombie;
21: int children;
22:
23: /* imported */
24: extern char *av0;
25: extern int net_dial();
26: extern int net_redial();
27: extern int net_announce();
28: extern void net_accept();
29: extern void net_reject();
30: extern ipcinfo *net_listen();
31: extern char *getlogin();
32:
33: static
34: deadbaby()
35: {
36: zombie = 1;
37: }
38:
39: static
40: ding()
41: {
42: }
43:
44: /* loop on calls out of the CPU */
45: void
46: dodialout(mtpt)
47: char *mtpt;
48: {
49: int fd;
50: long next;
51: long last, now;
52: int status;
53: int npid;
54:
55: signal(SIGPIPE, SIG_IGN);
56: pid = getpid();
57:
58: /*
59: * plug into local name space. Perform exponential backoff for
60: * reporting failure. Console paper is finite.
61: */
62: last = time((long *)0);
63: next = 30;
64: for(;;){
65: fd = ipccreat(mtpt, "");
66: if (fd>=0)
67: break;
68: now = time((long *)0);
69: if(now-last >= next){
70: logconsole("%s: can't announce as %s (%s)\n", av0, mtpt, errstr);
71: next = 2*next;
72: }
73: sleep(30);
74: }
75: chmod(mtpt, 0666);
76: logconsole("%s: announced to fs as %s\n", av0, mtpt);
77: fflush(stdout);
78:
79: /*
80: * loop on outgoing requests
81: */
82: for(;;) {
83: ipcinfo *ip;
84: int errs;
85:
86: /*
87: * eat zombies
88: */
89: if (zombie) {
90: zombie = 0;
91: while(children){
92: signal(SIGALRM, ding);
93: alarm(2);
94: npid = wait(&status);
95: signal(SIGCHLD, deadbaby);
96: alarm(0);
97: if(npid<0)
98: break;
99: children--;
100: }
101: }
102:
103: /*
104: * wait for a request, continue on interrupts
105: */
106: errs = 0;
107: while((ip = ipclisten(fd))==NULL){
108: if(errno!=EINTR && errs++>5) {
109: logevent("dialout: out broken listen\n");
110: close(fd);
111: return;
112: }
113: }
114: if(debug)
115: logevent("dialout: rcved\n");
116:
117: /*
118: * create new process for request
119: */
120: signal(SIGCHLD, deadbaby);
121: switch(fork()) {
122: case -1: /* whoops */
123: ipcreject(ip, errno, "no more processes");
124: logstatus("out", ip);
125: continue;
126: case 0:
127: close(fd);
128: break;
129: default:
130: children++;
131: (void)ABORT(0, "", ip);
132: continue;
133: }
134: if(debug)
135: logevent("dialout: forked\n");
136:
137: /*
138: * perform request
139: */
140: if (ip->flags & IPC_CREAT)
141: docreat(ip, mtpt);
142: else if (ip->flags & IPC_REDIAL)
143: doredial(ip, mtpt);
144: else
145: doopen(ip, mtpt);
146: if(debug)
147: logevent("dialout: done\n");
148: exit(0);
149: }
150: }
151:
152: /* establish a connection to a net name */
153: void
154: doopen(ip, mtpt)
155: ipcinfo *ip;
156: char *mtpt;
157: {
158: int fd;
159: static stretch myname;
160:
161: *av0 = 'D';
162:
163: /*
164: * dial out over the network
165: */
166: fd = net_dial(ip);
167: if (fd < 0) {
168: ipcreject(ip, errno, errstr);
169: logstatus("out", ip);
170: return;
171: }
172:
173: /*
174: * accept the request, passing back the network file descriptor
175: * and our local name in the form "network!machine!service".
176: */
177: _strcat(&myname, mtpt, "!", ipcname);
178: ipcdaccept(ip, fd, myname.ptr);
179:
180: errno = 0; errstr = "";
181: logstatus("out", ip);
182: close(fd);
183: }
184:
185: /* announce a new netname */
186: void
187: docreat(ip, mtpt)
188: ipcinfo *ip;
189: char *mtpt;
190: {
191: ipcinfo *netip;
192: int listenfd;
193: int toclient;
194: int pfd[2];
195: fd_set fds;
196: static stretch myname;
197:
198: /*
199: * no invisible gatewaying, it must be subject to authentication
200: */
201: if (ip->cfd >= 0) {
202: ipcreject(ip, EIO, "can't do remote ipccreat");
203: logstatus("out", ip);
204: return;
205: }
206:
207: *av0 = 'L';
208:
209: /*
210: * create a unique channel
211: * for communications with requestor
212: */
213: if (pipe(pfd) < 0) {
214: ipcreject(ip, errno, "can't create local channel");
215: logstatus("out", ip);
216: return;
217: }
218: toclient = pfd[1];
219:
220: /*
221: * dial out on network
222: */
223: listenfd = net_announce(ip);
224: if (listenfd < 0) {
225: close(pfd[0]);
226: close(pfd[1]);
227: ipcreject(ip, errno, errstr);
228: logstatus("out", ip);
229: return;
230: }
231:
232: /*
233: * accept the announce request. Return our address, if we have
234: * one in the form "network!machine!service"
235: */
236: _strcat(&myname, mtpt, "!", ipcname);
237: if (ipcdaccept(ip, pfd[0], myname.ptr) < 0)
238: return;
239: close(pfd[0]);
240: errno = 0; errstr = "";
241: logstatus("out", ip);
242:
243: /* loop waiting for in calls */
244: FD_ZERO(fds);
245: FD_SET(listenfd, fds);
246: FD_SET(toclient, fds);
247: while(1) {
248: fd_set rfds;
249: int rv;
250:
251: /* check for input or hang-up */
252: rfds = fds;
253: rv = select(NOFILE, &rfds, (fd_set*)0, 10000);
254: if (rv == 0)
255: continue;
256: else if (rv < 0)
257: break;
258: else if (FD_ISSET(toclient, rfds))
259: break;
260:
261: /* get request */
262: netip = net_listen(listenfd);
263: if (netip == NULL) {
264: logevent("net_listen error %d %s\n", errno, errstr);
265: ABORT(errno, errstr, ip);
266: break;
267: }
268:
269: /*
270: * make a new channel to the listener, and pass him
271: * one end.
272: */
273: if (pipe(pfd)<0) {
274: net_reject(netip, errno, "no more pipes");
275: logstatus("in", netip);
276: continue;
277: }
278: if (ioctl(toclient, FIOSNDFD, &(pfd[0]))<0) {
279: net_reject(netip, errno, "protocol botch");
280: logstatus("in", netip);
281: break;
282: }
283: close(pfd[0]);
284:
285: /*
286: * pass the request over the new channel. include name
287: * used to make the call.
288: */
289: if (ioctl(pfd[1], FIOSNDFD, &(netip->rfd))<0) {
290: net_reject(netip, errno, "protocol botch");
291: close(pfd[1]);
292: logstatus("in", netip);
293: continue;
294: }
295: close(netip->rfd);
296: netip->rfd = -1;
297: _strcat(&myname, mtpt, "!", ip->myname);
298: ip->myname = myname.ptr;
299: if (_info_write(pfd[1], netip) < 0) {
300: net_reject(netip, errno, "protocol botch");
301: close(pfd[1]);
302: logstatus("in", netip);
303: continue;
304: }
305:
306: /*
307: * get the client's reply and pass it on to the net
308: */
309: if (_reply_read(pfd[1]) < 0) {
310: /* didn't work, drop call */
311: net_reject(netip, errno, "protocol botch");
312: } else if(errno<0) {
313: /* client will handle the accept/reject */
314: close(netip->cfd);
315: } else if (errno) {
316: net_reject(netip, errno, errstr);
317: } else
318: net_accept(netip);
319: logstatus("in", netip);
320: close(pfd[1]);
321: }
322: return;
323: }
324:
325: /* redial a call */
326: void
327: doredial(ip, mtpt)
328: ipcinfo *ip;
329: char *mtpt;
330: {
331: *av0 = 'R';
332:
333: /*
334: * redial over the network
335: */
336: net_redial(ip);
337: ipcaccept(ip);
338: ABORT(0, (char *)0, ip);
339: logstatus("redial", ip);
340: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.