|
|
1.1 ! root 1: #ifndef lint ! 2: static char RCSid[] = "$Header: gaptelnetd.c,v 2.0 85/11/21 07:23:06 jqj Exp $"; ! 3: #endif ! 4: /* ! 5: * server for GAP-style (TransportObject=server,teletype) telnet connections ! 6: * Note that we support only GAP version 3 ! 7: */ ! 8: ! 9: /* $Log: gaptelnetd.c,v $ ! 10: * Revision 2.0 85/11/21 07:23:06 jqj ! 11: * 4.3BSD standard release ! 12: * ! 13: * Revision 1.3 85/11/21 06:53:22 jqj ! 14: * symbolic values for connection type ! 15: * ! 16: * Revision 1.2 85/11/08 17:17:13 bill ! 17: * version on bullwinkle ! 18: * ! 19: * Revision 1.3 85/08/05 09:58:00 jqj ! 20: * fixed for Interlisp -- data from Interlisp appears with dt==0 (wrong!) ! 21: * also, Interlisp trys to connect to a tty rather than a ttyHost. ! 22: * increased inactivity timeout to 4 hrs ! 23: * ! 24: * Revision 1.2 85/05/23 06:22:18 jqj ! 25: * *** empty log message *** ! 26: * ! 27: * Revision 1.1 85/05/22 09:46:52 jqj ! 28: * Initial revision ! 29: */ ! 30: #include <stdio.h> ! 31: #include <signal.h> ! 32: #include <sgtty.h> ! 33: #include <sys/types.h> ! 34: #include <sys/time.h> ! 35: #include <sys/uio.h> ! 36: #include <sys/socket.h> ! 37: #include <netns/ns.h> ! 38: #include <netns/idp.h> ! 39: #include <netns/sp.h> ! 40: #include <sys/wait.h> ! 41: #include <xnscourier/realcourierconnection.h> ! 42: #include "GAP3.h" ! 43: #include "gapcontrols.h" ! 44: #include <xnscourier/except.h> ! 45: #include <errno.h> ! 46: ! 47: #define BELL '\07' ! 48: #define BANNER "\r\n\r\n4.3 BSD UNIX (%s)\r\n\r\r\n\r" ! 49: ! 50: int pty, net; ! 51: extern CourierConnection *_serverConnection; ! 52: char buf[sizeof(struct sphdr)+SPPMAXDATA]; ! 53: struct sphdr our_sphdr; ! 54: struct iovec our_iovec[2] = {{((caddr_t)&our_sphdr), sizeof(our_sphdr)}}; ! 55: /* ! 56: * I/O data buffers, pointers, and counters. ! 57: */ ! 58: char ptyibuf[512], *ptyip = ptyibuf; ! 59: char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf; ! 60: char *netip = buf; ! 61: char netobuf[512], *nfrontp = netobuf, *nbackp = netobuf; ! 62: int pcc, ncc; ! 63: char line[12]; ! 64: extern char **environ; ! 65: extern int errno; ! 66: ! 67: char *envinit[3]; ! 68: char wsenv[50]; ! 69: ! 70: /* ! 71: * session parameters ! 72: */ ! 73: Cardinal frametimeout; /* 0 or time in seconds to wait */ ! 74: ! 75: ! 76: /* ! 77: * This modified version of the server is necessary since GAP specifies ! 78: * that the telnet data-transfer session occurs after the RPC to create ! 79: * it has returned! ! 80: */ ! 81: Server(skipcount,skippedwords) ! 82: int skipcount; ! 83: Unspecified skippedwords[]; ! 84: { ! 85: Cardinal _procedure; ! 86: register Unspecified *_buf; ! 87: LongCardinal programnum; ! 88: Cardinal versionnum; ! 89: Cardinal _n; ! 90: ! 91: #ifdef DEBUG ! 92: BUGOUT("Server: %d %d",skipcount,skippedwords); ! 93: #endif ! 94: for (;;) { ! 95: _buf = ReceiveCallMessage(&_procedure, skipcount, skippedwords); ! 96: DURING switch (_procedure) { ! 97: case 3: ! 98: server_GAP3_Delete(_buf); ! 99: break; ! 100: case 2: ! 101: server_GAP3_Create(_buf); ! 102: net = _serverConnection->fd; ! 103: gaptelnet(); /* returns on connection close */ ! 104: break; ! 105: case 0: ! 106: server_GAP3_Reset(_buf); ! 107: break; ! 108: default: ! 109: NoSuchProcedureValue("GAP", _procedure); ! 110: break; ! 111: } HANDLER { ! 112: Deallocate(_buf); ! 113: switch (Exception.Code) { ! 114: case GAP3_serviceNotFound: ! 115: case GAP3_userNotAuthorized: ! 116: case GAP3_userNotAuthenticated: ! 117: case GAP3_serviceTooBusy: ! 118: case GAP3_terminalAddressInvalid: ! 119: case GAP3_terminalAddressInUse: ! 120: case GAP3_controllerDoesNotExist: ! 121: case GAP3_controllerAlreadyExists: ! 122: case GAP3_gapCommunicationError: ! 123: case GAP3_gapNotExported: ! 124: case GAP3_bugInGAPCode: ! 125: case GAP3_tooManyGateStreams: ! 126: case GAP3_inconsistentParams: ! 127: case GAP3_transmissionMediumUnavailable: ! 128: case GAP3_dialingHardwareProblem: ! 129: case GAP3_noDialingHardware: ! 130: case GAP3_badAddressFormat: ! 131: case GAP3_mediumConnectFailed: ! 132: case GAP3_illegalTransport: ! 133: case GAP3_noCommunicationHardware: ! 134: case GAP3_unimplemented: ! 135: _buf = Allocate(0); ! 136: SendAbortMessage(Exception.Code-ERROR_OFFSET, 0, _buf); ! 137: break; ! 138: default: ! 139: _buf = Allocate(0); ! 140: SendRejectMessage(unspecifiedError, 0, _buf); ! 141: break; ! 142: } ! 143: } END_HANDLER; ! 144: Deallocate(_buf); ! 145: for (;;) { ! 146: skipcount = LookAheadCallMsg(&programnum, &versionnum, ! 147: skippedwords); ! 148: if (skipcount < 0) return(0); /* timed out */ ! 149: if (programnum != 3 || versionnum != 3) ! 150: ExecCourierProgram(programnum, versionnum, ! 151: skipcount, skippedwords); ! 152: } /* loop if can't exec that program */ ! 153: } ! 154: } ! 155: ! 156: void ! 157: GAP3_Delete(session) ! 158: GAP3_SessionHandle session; ! 159: { ! 160: } ! 161: ! 162: void ! 163: GAP3_Reset() ! 164: { ! 165: } ! 166: ! 167: GAP3_CreateResults ! 168: GAP3_Create(conn, BDTproc, sessionparams, transports, ! 169: createTimeout, credentials, verifier) ! 170: CourierConnection *conn; ! 171: int BDTproc; ! 172: GAP3_SessionParameterObject sessionparams; ! 173: struct {Cardinal length; ! 174: GAP3_TransportObject *sequence; ! 175: } transports; ! 176: GAP3_WaitTime createTimeout; ! 177: Authentication1_Credentials credentials; ! 178: Authentication1_Verifier verifier; ! 179: { ! 180: GAP3_CreateResults result; ! 181: char *c1, *c2, *host; ! 182: int t, pid; ! 183: struct sgttyb b; ! 184: char *xntoa(), *wsname(); ! 185: struct sockaddr_ns who; ! 186: int whosize = sizeof(who); ! 187: LongCardinal servicetype; ! 188: GAP3_CommParamObject *cp; ! 189: GAP3_Duplexity duplexity; /* fullDuplex, halfDuplex */ ! 190: ! 191: #ifdef DEBUG ! 192: BUGOUT("CREATE"); ! 193: #endif ! 194: switch (sessionparams.designator) { ! 195: case oldTty: ! 196: case oldTtyHost: ! 197: frametimeout = sessionparams.oldTtyHost_case.frameTimeout/1000; ! 198: /* could set other parameters here */ ! 199: break; ! 200: case tty: ! 201: case ttyHost: ! 202: frametimeout = sessionparams.ttyHost_case.frameTimeout/1000; ! 203: /* could set other parameters here */ ! 204: break; ! 205: default: ! 206: raise(GAP3_unimplemented, 0); ! 207: /*NOTREACHED*/ ! 208: } ! 209: if (transports.length != 2) { ! 210: raise(GAP3_illegalTransport); ! 211: /*NOTREACHED*/ ! 212: } ! 213: switch (transports.sequence[0].designator) { ! 214: case service: ! 215: servicetype = transports.sequence[0].service_case.id; ! 216: switch (servicetype) { ! 217: case TTYService_any: /* 0 */ ! 218: servicetype = TTYService_sa; ! 219: case TTYService_sa: /* 1 */ ! 220: case TTYService_exec: /* 2 */ ! 221: case TTYService_its: /* 3 */ ! 222: break; ! 223: default: ! 224: raise(GAP3_serviceNotFound, 0); ! 225: /*NOTREACHED*/ ! 226: } ! 227: duplexity = fullduplex;/* services are allways fulldup */ ! 228: break; ! 229: case rs232c: /* maybe some day */ ! 230: cp = &transports.sequence[0].rs232c_case.commParams; ! 231: if (cp->accessDetail.designator == directConn) { ! 232: duplexity = cp->accessDetail.directConn_case.duplex; ! 233: servicetype = TTYService_sa; /* fake it */ ! 234: break; ! 235: } ! 236: raise(GAP3_noCommunicationHardware, 0); ! 237: /*NOTREACHED*/ ! 238: default: ! 239: raise(GAP3_illegalTransport, 0); ! 240: /*NOTREACHED*/ ! 241: } ! 242: if (transports.sequence[1].designator != teletype) ! 243: raise(GAP3_illegalTransport, 0); ! 244: /* ignore createTimeout */ ! 245: /* ignore credentials and verifier */ ! 246: ! 247: for (c1 = "pq"; *c1 != 0; c1++) ! 248: for (c2 = "0123456789abcdef"; *c2 != 0; c2++) { ! 249: sprintf(line, "/dev/pty%c%c", *c1, *c2); ! 250: pty = open(line, 2); ! 251: if (pty < 0) continue; ! 252: line[strlen("/dev/")] = 't'; ! 253: t = open(line, 2); ! 254: if (t > 0) goto gotpty; ! 255: close(pty); ! 256: } ! 257: raise(GAP3_serviceTooBusy, 0); ! 258: /*NOTREACHED*/ ! 259: gotpty: ! 260: getpeername(_serverConnection->fd, &who, &whosize); ! 261: host = wsname(who.sns_addr); ! 262: #ifdef DEBUG ! 263: BUGOUT("gotpty <%s> %d <%s>",line, pty, host); ! 264: #endif ! 265: ioctl(t, TIOCGETP, &b); ! 266: b.sg_flags = CRMOD|XTABS|ANYP; ! 267: ioctl(t, TIOCSETP, &b); ! 268: ioctl(pty, TIOCGETP, &b); ! 269: if (duplexity == fullduplex) ! 270: b.sg_flags |= ECHO; ! 271: else ! 272: b.sg_flags &= ~ECHO; ! 273: ioctl(pty, TIOCSETP, &b); ! 274: /* we do the fork now so we can return failures as REPORTS */ ! 275: pid = fork(); ! 276: if (pid < 0) { ! 277: close(pty); close(t); ! 278: raise(GAP3_serviceTooBusy, 0); ! 279: /*NOTREACHED*/ ! 280: } ! 281: else if (pid == 0) { /* in the execed fork */ ! 282: sleep(1); /* let parent get ready for us */ ! 283: close(_serverConnection->fd); /* close net */ ! 284: close(pty); ! 285: dup2(t, 0); ! 286: dup2(t, 1); ! 287: dup2(t, 2); ! 288: if (t > 2) close(t); ! 289: envinit[0] = "TERM=network"; ! 290: envinit[1] = sprintf(wsenv, "WORKSTATION=%s", ! 291: xntoa(who.sns_addr)); ! 292: envinit[2] = (char*) 0; ! 293: #ifdef DEBUG ! 294: BUGOUT("about to exec /bin/login"); ! 295: #endif ! 296: execl("/bin/login","login", "-h", host, 0); ! 297: #ifdef DEBUG ! 298: BUGOUT("exec of /bin/login failed"); ! 299: #endif ! 300: perror("/bin/login"); ! 301: exit(1); ! 302: /*NOTREACHED*/ ! 303: } ! 304: close(t); ! 305: #ifdef DEBUG ! 306: BUGOUT("fork successful"); ! 307: #endif ! 308: result.session[0] = pid; ! 309: return(result); ! 310: } ! 311: ! 312: jmp_buf childdiedbuf; ! 313: ! 314: /* ! 315: * Main loop. Select from pty and network, and ! 316: * hand data to telnet receiver finite state machine. ! 317: * Returns 0 on orderly shutdown, 1 on abnormal shutdown. ! 318: */ ! 319: gaptelnet() ! 320: { ! 321: int on = 1; ! 322: char hostname[32]; ! 323: int childdied(); ! 324: int ibits = 0, obits = 0; ! 325: register int c; ! 326: struct sphdr *si = (struct sphdr *)buf; ! 327: static struct timeval timeout = {600,0}; ! 328: int keepalives = 0; ! 329: int i; ! 330: ! 331: #ifdef DEBUG ! 332: BUGOUT("gaptelnet net=%d,pty=%d",net,pty); ! 333: #endif ! 334: if (setjmp(childdiedbuf) != 0) ! 335: return(0); /* child died */ ! 336: signal(SIGCHLD, childdied); ! 337: signal(SIGTSTP, SIG_IGN); ! 338: ioctl(net, FIONBIO, &on); ! 339: ioctl(pty, FIONBIO, &on); ! 340: ! 341: ! 342: /* ! 343: * Show banner that getty never gave. ! 344: */ ! 345: gethostname(hostname, sizeof (hostname)); ! 346: sprintf(nfrontp, BANNER, hostname); ! 347: nfrontp += strlen(nfrontp); ! 348: /* ! 349: * Send status message indicating we're ready to go ! 350: */ ! 351: changeSPPopts(net, GAPCTLnone, 1); ! 352: sendoobdata(GAPCTLmediumUp); ! 353: for (;;) { ! 354: #ifdef DEBUG ! 355: BUGOUT("looping in gaptelnet"); ! 356: #endif ! 357: ibits = obits = 0; ! 358: /* ! 359: * Never look for input if there's still ! 360: * stuff in the corresponding output buffer ! 361: */ ! 362: if (nfrontp - nbackp || pcc > 0) ! 363: obits |= (1 << net); ! 364: else ! 365: ibits |= (1 << pty); ! 366: if (pfrontp - pbackp || ncc > 0) ! 367: obits |= (1 << pty); ! 368: else ! 369: ibits |= (1 << net); ! 370: if (ncc < 0 && pcc < 0) ! 371: break; ! 372: timeout.tv_sec = 14400; /* 4 hrs. */ ! 373: timeout.tv_usec = 0; ! 374: select(16, &ibits, &obits, 0, &timeout); ! 375: if (ibits == 0 && obits == 0) { ! 376: /* timeout means no activity for a long time */ ! 377: #ifdef DEBUG ! 378: BUGOUT("timeout from select"); ! 379: #endif ! 380: if (keepalives++ < 2) { ! 381: /* first time through send warning */ ! 382: if (nfrontp == nbackp && pcc == 0) { ! 383: /* but only if not blocked on output */ ! 384: #define WARNING "\r\nYou've been idle much too long. Respond or log off.\r\n" ! 385: strcpy(nfrontp, WARNING); ! 386: nfrontp += sizeof(WARNING); ! 387: } ! 388: sleep(5); ! 389: continue; ! 390: } ! 391: #ifdef DEBUG ! 392: BUGOUT("keepalive expired -- calling cleanup"); ! 393: #endif ! 394: /* keepalive count has expired */ ! 395: cleanup(); ! 396: return(1); ! 397: } ! 398: ! 399: /* ! 400: * Something to read from the network... ! 401: */ ! 402: if (ibits & (1 << net)) { ! 403: ncc = read(net, buf, sizeof(buf)); ! 404: #ifdef DEBUG ! 405: BUGOUT("read %d from net, cc=0%o,dt=0%o", ! 406: ncc-sizeof(struct sphdr), si->sp_cc, si->sp_dt); ! 407: #endif ! 408: if (ncc < 0 && errno == EWOULDBLOCK) ! 409: ncc = 0; ! 410: else if (ncc < sizeof(struct sphdr)) { ! 411: #ifdef DEBUG ! 412: BUGOUT("short read, %d. calling cleanup",ncc); ! 413: #endif ! 414: cleanup(); /* will probably fail or block */ ! 415: return(1); ! 416: } ! 417: else if (si->sp_cc & SP_OB) { ! 418: #ifdef DEBUG ! 419: BUGOUT("Got OOB control 0%o", ! 420: (u_char) buf[sizeof(struct sphdr)]); ! 421: #endif ! 422: /* a status or OOB control */ ! 423: switch ((u_char) buf[sizeof(struct sphdr)]) { ! 424: case GAPCTLinterrupt: ! 425: /* shove interrupt char in buffer */ ! 426: interrupt(); ! 427: break; /* from switch */ ! 428: case GAPCTLareYouThere: ! 429: sendoobdata(GAPCTLiAmHere); ! 430: break; /* from switch */ ! 431: default: ! 432: /* Ignore other controls instead of: ! 433: * sendoobdata( ! 434: * GAPCTLunexpectedRemoteBehavior); ! 435: */ ! 436: break; /* from switch */ ! 437: } ! 438: ncc = 0; /* no chars here */ ! 439: } ! 440: else if (si->sp_dt==GAPCTLnone || ! 441: si->sp_dt==0) { ! 442: /* the normal case */ ! 443: /* N.B. the standard says dt should be 0300 ! 444: * i.e. GAPCTLnone, but Interlisp CHAT ! 445: * generates 0, so we accept that too. ! 446: */ ! 447: ncc -= sizeof(struct sphdr); ! 448: #ifdef DEBUG ! 449: BUGOUT("Now ncc == %d",ncc); ! 450: #endif ! 451: netip = buf + sizeof(struct sphdr); ! 452: keepalives = 0; ! 453: } ! 454: else if(si->sp_dt==GAPCTLcleanup) { ! 455: #ifdef DEBUG ! 456: BUGOUT("got CLEANUP packet. Done"); ! 457: #endif ! 458: cleanup(); /* normal termination */ ! 459: return(0); ! 460: } ! 461: else if (si->sp_dt==SPPSST_END) { ! 462: /* got premature termination */ ! 463: quitquit(net, pty); ! 464: return(1); ! 465: } ! 466: else { ! 467: /* some other inband ctl */ ! 468: #ifdef DEBUG ! 469: BUGOUT("ignoring IB packet, data = 0%o...", ! 470: (u_char) buf[sizeof(struct sphdr)]); ! 471: #endif ! 472: } ! 473: } ! 474: ! 475: /* ! 476: * Something to read from the pty... ! 477: */ ! 478: if (ibits & (1 << pty)) { ! 479: if (frametimeout > 0) sleep(frametimeout); ! 480: pcc = read(pty, ptyibuf, sizeof(ptyibuf)); ! 481: #ifdef DEBUG ! 482: BUGOUT("read from pty %d",pcc); ! 483: #endif ! 484: if (pcc < 0 && errno == EWOULDBLOCK) ! 485: pcc = 0; ! 486: else if (pcc <= 0) { ! 487: #ifdef DEBUG ! 488: BUGOUT("short read from pty. Calling cleanup"); ! 489: #endif ! 490: cleanup(); ! 491: return(1); /* ?? abnormal termination */ ! 492: } ! 493: ptyip = ptyibuf; ! 494: } ! 495: ! 496: while (pcc > 0) { ! 497: if ((&netobuf[sizeof(netobuf)] - nfrontp) < 2) ! 498: break; ! 499: *nfrontp++ = *ptyip++ & 0377; pcc--; ! 500: } ! 501: if ((obits & (1 << net)) && (nfrontp - nbackp) > 0) ! 502: netflush(); ! 503: while (ncc > 0) { ! 504: if ((&ptyobuf[sizeof(ptyobuf)] - pfrontp) < 2) break; ! 505: *pfrontp++ = *netip++ & 0377; ! 506: ncc--; ! 507: } ! 508: if ((obits & (1 << pty)) && (pfrontp - pbackp) > 0) ! 509: ptyflush(); ! 510: } ! 511: /* we should never get to here */ ! 512: #ifdef DEBUG ! 513: BUGOUT("broke out of for(;;) somehow. calling cleanup"); ! 514: #endif ! 515: cleanup(); ! 516: return(0); ! 517: } ! 518: ! 519: /* ! 520: * Send out of band data to other end of network ! 521: */ ! 522: sendoobdata(value) ! 523: u_char value; ! 524: { ! 525: struct { ! 526: struct sphdr hdr; ! 527: char val; ! 528: } oob; ! 529: oob.hdr = our_sphdr; ! 530: oob.val = value; ! 531: #ifdef DEBUG ! 532: BUGOUT("sendoobdata 0%o",value); ! 533: #endif ! 534: send(net, &oob, sizeof(oob), MSG_OOB); ! 535: } ! 536: ! 537: /* ! 538: * Send interrupt to process on other side of pty. ! 539: * If it is in raw mode, just write NULL; ! 540: * otherwise, write intr char. ! 541: */ ! 542: interrupt() ! 543: { ! 544: struct sgttyb b; ! 545: struct tchars tchars; ! 546: ! 547: ptyflush(); /* half-hearted */ ! 548: ioctl(pty, TIOCGETP, &b); ! 549: if (b.sg_flags & RAW) { ! 550: *pfrontp++ = '\0'; ! 551: return; ! 552: } ! 553: *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? ! 554: '\177' : tchars.t_intrc; ! 555: } ! 556: ! 557: ptyflush() ! 558: { ! 559: register int n; ! 560: ! 561: if ((n = pfrontp - pbackp) > 0) ! 562: n = write(pty, pbackp, n); ! 563: #ifdef DEBUG ! 564: BUGOUT("ptyflush wrote %d",n); ! 565: #endif ! 566: if (n < 0) ! 567: return; ! 568: pbackp += n; ! 569: if (pbackp >= pfrontp) /* actually, > is an error */ ! 570: pbackp = pfrontp = ptyobuf; ! 571: } ! 572: ! 573: netflush() ! 574: { ! 575: register int n; ! 576: ! 577: if ((n = nfrontp - nbackp) > 0) { ! 578: our_iovec[1].iov_len = ((n > SPPMAXDATA) ? SPPMAXDATA : n); ! 579: our_iovec[1].iov_base = nbackp; ! 580: n = writev(net, our_iovec, 2) - sizeof(struct sphdr); ! 581: } ! 582: #ifdef DEBUG ! 583: BUGOUT("netflush wrote %d",n); ! 584: if (our_iovec[0].iov_base != (char*)&our_sphdr) ! 585: BUGOUT("Oops: our_iovec clobbered"); ! 586: BUGOUT("header: %d %d, %d %d %d %d %d %d", ! 587: our_sphdr.sp_cc, our_sphdr.sp_dt, ! 588: our_sphdr.sp_sid, our_sphdr.sp_did, our_sphdr.sp_seq, ! 589: our_sphdr.sp_ack, our_sphdr.sp_alo); ! 590: #endif ! 591: if (n < 0) { ! 592: if (errno == EWOULDBLOCK) ! 593: return; ! 594: /* should blow this guy away... */ ! 595: return; ! 596: } ! 597: nbackp += n; ! 598: if (nbackp >= nfrontp) /* actually , > is an error */ ! 599: nbackp = nfrontp = netobuf; ! 600: } ! 601: ! 602: /* ! 603: * handle receipt of an SPPSST_END packet ! 604: * This is currently an error, since client didn't send "cleanup" first ! 605: */ ! 606: quitquit() ! 607: { ! 608: #ifdef DEBUG ! 609: BUGOUT("quitquit"); ! 610: #endif ! 611: changeSPPopts(net, SPPSST_ENDREPLY, 1); ! 612: write(net, &our_sphdr, sizeof(our_sphdr)); ! 613: sleep(3); ! 614: ! 615: rmut(); ! 616: vhangup(); /* XXX */ ! 617: shutdown(net, 1); ! 618: close(net); ! 619: } ! 620: ! 621: /* ! 622: * shut down the data connection for one reason or another ! 623: */ ! 624: cleanup() ! 625: { ! 626: int fdmask; ! 627: struct timeval timeout; ! 628: struct sphdr *si = (struct sphdr *)buf; ! 629: int off = 0; ! 630: ! 631: signal(SIGCHLD, SIG_IGN); ! 632: sendoobdata(GAPCTLcleanup); ! 633: changeSPPopts(net, SPPSST_END, 1); ! 634: if (write(net, &our_sphdr, sizeof(our_sphdr)) < 0) { ! 635: fdmask = 1<<net; ! 636: timeout.tv_sec = 10; ! 637: while (select(net+1,&fdmask,(int*)0, (int*)0, &timeout) > 0 && ! 638: read(net,buf,sizeof(buf)) >= sizeof(struct sphdr)) { ! 639: #ifdef DEBUG ! 640: BUGOUT("cleanup -- got packet"); ! 641: #endif ! 642: if ((!(si->sp_cc & SP_OB)) ! 643: && si->sp_dt == SPPSST_ENDREPLY) { ! 644: changeSPPopts(net, SPPSST_ENDREPLY, 1); ! 645: write(net, &our_sphdr, sizeof(our_sphdr)); ! 646: #ifdef DEBUG ! 647: BUGOUT("cleanup -- wrote ENDREPLY"); ! 648: #endif ! 649: sleep(1); ! 650: changeSPPopts(net,0,0); ! 651: ioctl(net, FIONBIO, &off); ! 652: rmut(); ! 653: vhangup(); /* XXX */ ! 654: return; ! 655: } ! 656: /* loop: ignore everything except ENDREPLY */ ! 657: fdmask = 1<<net; ! 658: timeout.tv_sec = 10; ! 659: } ! 660: /* timed out or read failed */ ! 661: changeSPPopts(net, SPPSST_ENDREPLY, 1); ! 662: write(net, &our_sphdr, sizeof(our_sphdr)); ! 663: sleep(1); ! 664: } ! 665: shutdown(net, 1); ! 666: close(net); ! 667: rmut(); ! 668: vhangup(); /* XXX */ ! 669: } ! 670: ! 671: /* ! 672: * SIGCHLD interrupt handler ! 673: */ ! 674: childdied() ! 675: { ! 676: #ifdef DEBUG ! 677: BUGOUT("child died"); ! 678: #endif ! 679: cleanup(); ! 680: longjmp(childdiedbuf, -1); ! 681: } ! 682: ! 683: changeSPPopts(s, stream, eom) ! 684: int s; /* SPP socket */ ! 685: u_char stream; /* datastream type */ ! 686: char eom; /* Boolean EOM */ ! 687: { ! 688: our_sphdr.sp_dt = stream; ! 689: our_sphdr.sp_cc = (eom ? SP_EM : 0); ! 690: } ! 691: ! 692: ! 693: #include <utmp.h> ! 694: ! 695: struct utmp wtmp; ! 696: char wtmpf[] = "/usr/adm/wtmp"; ! 697: char utmp[] = "/etc/utmp"; ! 698: #define SCPYN(a, b) strncpy(a, b, sizeof (a)) ! 699: #define SCMPN(a, b) strncmp(a, b, sizeof (a)) ! 700: ! 701: rmut() ! 702: { ! 703: register f; ! 704: int found = 0; ! 705: ! 706: f = open(utmp, 2); ! 707: if (f >= 0) { ! 708: while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) { ! 709: if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) ! 710: continue; ! 711: lseek(f, -(long)sizeof (wtmp), 1); ! 712: SCPYN(wtmp.ut_name, ""); ! 713: SCPYN(wtmp.ut_host, ""); ! 714: time(&wtmp.ut_time); ! 715: write(f, (char *)&wtmp, sizeof (wtmp)); ! 716: found++; ! 717: } ! 718: close(f); ! 719: } ! 720: if (found) { ! 721: f = open(wtmpf, 1); ! 722: if (f >= 0) { ! 723: SCPYN(wtmp.ut_line, line+5); ! 724: SCPYN(wtmp.ut_name, ""); ! 725: SCPYN(wtmp.ut_host, ""); ! 726: time(&wtmp.ut_time); ! 727: lseek(f, (long)0, 2); ! 728: write(f, (char *)&wtmp, sizeof (wtmp)); ! 729: close(f); ! 730: } ! 731: } ! 732: chmod(line, 0666); ! 733: chown(line, 0, 0); ! 734: line[strlen("/dev/")] = 'p'; ! 735: chmod(line, 0666); ! 736: chown(line, 0, 0); ! 737: } ! 738: ! 739: /* ! 740: * Convert network-format xns address ! 741: * to ascii ! 742: * --Replace this with a clearinghouse name lookup someday. ! 743: */ ! 744: char * ! 745: wsname(addr) ! 746: struct ns_addr addr; ! 747: { ! 748: static char b[50]; ! 749: char temp[10]; ! 750: int i; ! 751: ! 752: /* net */ ! 753: sprintf(b, "%D.", ntohl(ns_netof(addr))); ! 754: /* skip leading zeros */ ! 755: for(i=0; (addr.x_host.c_host[i] == (char) 0); i++) ; ! 756: /* print the rest */ ! 757: for(; i < 6; i++) { ! 758: sprintf(temp,"%x", addr.x_host.c_host[i]); ! 759: strcat(b, temp); ! 760: if(i != 5) strcat(b, ":"); ! 761: } ! 762: return (b); ! 763: } ! 764: ! 765: /* ! 766: * generate an xns address that "DE" can parse. ! 767: * This goes in the environment. Should be the same as above ! 768: */ ! 769: char * ! 770: xntoa(addr) ! 771: struct ns_addr addr; ! 772: { ! 773: static char b[50]; ! 774: char temp[10]; ! 775: int i; ! 776: ! 777: /* net */ ! 778: sprintf(b, "%X#", ntohl(ns_netof(addr))); ! 779: /* print the rest */ ! 780: for(i=0; i < 6; i++) { ! 781: sprintf(temp,"%x", addr.x_host.c_host[i]); ! 782: strcat(b, temp); ! 783: if(i != 5) strcat(b, "."); ! 784: } ! 785: return (b); ! 786: } ! 787: ! 788: #ifdef DEBUG ! 789: BUGOUT(str,a,b,c,d,e,f,g,h) ! 790: char *str; ! 791: { ! 792: FILE *fd; ! 793: fd = fopen("/tmp/GAP3d.log","a"); ! 794: fprintf(fd,str,a,b,c,d,e,f,g,h); ! 795: putc('\n',fd); ! 796: fclose(fd); ! 797: } ! 798: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.