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