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

Defined functions

BUGOUT defined in line 789; used 28 times
GAP3_Create defined in line 167; used 1 times
GAP3_Delete defined in line 156; never used
GAP3_Reset defined in line 162; never used
Server defined in line 81; never used
changeSPPopts defined in line 683; used 6 times
childdied defined in line 674; used 2 times
cleanup defined in line 624; used 6 times
gaptelnet defined in line 319; used 1 times
interrupt defined in line 542; used 1 times
netflush defined in line 573; used 1 times
ptyflush defined in line 557; used 2 times
quitquit defined in line 606; used 1 times
rmut defined in line 701; used 3 times
sendoobdata defined in line 522; used 3 times
wsname defined in line 744; used 2 times
xntoa defined in line 769; used 2 times

Defined variables

GAP3_CreateResults defined in line 167; used 1 times
RCSid defined in line 2; never used
buf defined in line 52; used 11 times
envinit defined in line 67; used 3 times
line defined in line 63; used 12 times
ncc defined in line 62; used 13 times
net defined in line 50; used 30 times
netip defined in line 60; used 2 times
netobuf defined in line 61; used 5 times
nfrontp defined in line 61; used 13 times
our_iovec defined in line 54; used 4 times
our_sphdr defined in line 53; used 21 times
pcc defined in line 62; used 10 times
pfrontp defined in line 59; used 9 times
pty defined in line 50; used 19 times
ptyibuf defined in line 58; used 4 times
ptyip defined in line 58; used 2 times
ptyobuf defined in line 59; used 5 times
utmp defined in line 697; used 1 times
wsenv defined in line 68; used 1 times
wtmp defined in line 695; used 17 times
wtmpf defined in line 696; used 1 times

Defined macros

BANNER defined in line 48; used 1 times
BELL defined in line 47; never used
SCMPN defined in line 699; used 1 times
SCPYN defined in line 698; used 5 times
WARNING defined in line 384; used 2 times
Last modified: 1986-03-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3676
Valid CSS Valid XHTML 1.0 Strict