|
|
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.