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