1: #ifndef lint
   2: static char *rcsid = "$Header: gaptelnet.c,v 2.0 85/11/21 07:23:04 jqj Exp $";
   3: #endif
   4: 
   5: /*
   6:  * XNS User telnet program.
   7:  */
   8: 
   9: /* $Log:	gaptelnet.c,v $
  10:  * Revision 2.0  85/11/21  07:23:04  jqj
  11:  * 4.3BSD standard release
  12:  *
  13:  * Revision 1.3  85/11/20  14:00:08  jqj
  14:  * added symbolic entries for Gap connection types
  15:  *
  16:  * Revision 1.2  85/05/22  09:46:37  jqj
  17:  * VAX 4.3beta baseline version
  18:  *
  19:  * Revision 1.2  85/05/22  09:46:37  jqj
  20:  * Beta-test GAP telnet
  21:  *
  22:  * based on tcp/telnet:
  23:  *	static char *rcsid = "$Header: gaptelnet.c,v 2.0 85/11/21 07:23:04 jqj Exp $";
  24:  *	static char sccsid[] = "@(#)telnet.c	4.24 (Berkeley) 7/20/83";
  25:  */
  26: 
  27: #include <sys/types.h>
  28: #include <sys/socket.h>
  29: #include <sys/ioctl.h>
  30: 
  31: #include <netns/ns.h>
  32: #include <netns/idp.h>
  33: #include <netns/sp.h>       /* for spphdr */
  34: #include <netns/spidp.h>
  35: 
  36: #include <stdio.h>
  37: #include <ctype.h>
  38: #include <errno.h>
  39: #include <signal.h>
  40: 
  41: #include <xnscourier/Clearinghouse2.h>
  42: #include "GAP3.h"
  43: #include "gapcontrols.h"
  44: #include <xnscourier/except.h>
  45: #include <xnscourier/CH.h>
  46: 
  47: #define strip(x)    ((x)&0177)
  48: 
  49: char    ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf;
  50: char    netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;
  51: 
  52: 
  53: int connected;
  54: CourierConnection *cconn;
  55: int net;
  56: FILE    *logfile;
  57: int debug = 0;
  58: int crmod = 0;
  59: char    *prompt;
  60: char    escape = CTRL(]);
  61: char    on = 1;
  62: 
  63: char    line[200];
  64: int margc;
  65: char    *margv[20];
  66: 
  67: jmp_buf toplevel;
  68: jmp_buf peerdied;
  69: 
  70: extern  int errno;
  71: 
  72: int tn(), quit(), suspend(), bye(), help();
  73: int setescape(), status(), toggle(), setoptions();
  74: int setcrmod(), setdebug(), setlog();
  75: 
  76: #define HELPINDENT (sizeof ("connect"))
  77: 
  78: struct cmd {
  79:     char    *name;      /* command name */
  80:     char    *help;      /* help string */
  81:     int (*handler)();   /* routine which executes command */
  82: };
  83: 
  84: char    openhelp[] =    "connect to a site";
  85: char    closehelp[] =   "close current connection";
  86: char    quithelp[] =    "exit telnet";
  87: char    zhelp[] =   "suspend telnet";
  88: char    debughelp[] =   "toggle debugging";
  89: char    escapehelp[] =  "set escape character";
  90: char    statushelp[] =  "print status information";
  91: char    helphelp[] =    "print help information";
  92: char    crmodhelp[] =   "toggle mapping of received carriage returns";
  93: char    loghelp[] = "toggle logging of session";
  94: 
  95: struct cmd cmdtab[] = {
  96:     { "open",   openhelp,   tn },
  97:     { "close",  closehelp,  bye },
  98:     { "quit",   quithelp,   quit },
  99:     { "z",      zhelp,      suspend },
 100:     { "escape", escapehelp, setescape },
 101:     { "status", statushelp, status },
 102: /*	{ "crmod",	crmodhelp,	setcrmod },	*/
 103:     { "debug",  debughelp,  setdebug },
 104:     { "log",    loghelp,    setlog },
 105:     { "?",      helphelp,   help },
 106:     0
 107: };
 108: 
 109: struct sockaddr_ns sin;
 110: 
 111: int intr(), deadpeer();
 112: char    *control();
 113: struct  cmd *getcmd();
 114: 
 115: struct  tchars otc;
 116: struct  ltchars oltc;
 117: struct  sgttyb ottyb;
 118: 
 119: char    *hostname;
 120: char    hnamebuf[45];
 121: 
 122: 
 123: main(argc, argv)
 124:     int argc;
 125:     char *argv[];
 126: {
 127:     ioctl(0, TIOCGETP, (char *)&ottyb);
 128:     ioctl(0, TIOCGETC, (char *)&otc);
 129:     ioctl(0, TIOCGLTC, (char *)&oltc);
 130:     setbuf(stdin, 0);
 131:     setbuf(stdout, 0);
 132:     prompt = argv[0];
 133:     if (argc > 1 && !strcmp(argv[1], "-d"))
 134:         debug = SO_DEBUG, argv++, argc--;
 135:     if (argc != 1) {
 136:         if (setjmp(toplevel) != 0)
 137:             exit(0);
 138:         tn(argc, argv);
 139:     }
 140:     setjmp(toplevel);
 141:     for (;;)
 142:         command(1);
 143: }
 144: 
 145: tn(argc, argv)
 146:     int argc;
 147:     char *argv[];
 148: {
 149:     register int c;
 150:     register struct ns_addr *host;
 151:     extern struct ns_addr *getXNSaddr();
 152:     Clearinghouse2_ObjectName hostoname, hdefault;
 153:     LongCardinal servicetype;
 154: 
 155:     if (connected) {
 156:         printf("?Already connected to %s\n", hostname);
 157:         return;
 158:     }
 159:     if (argc < 2) {
 160:         strcpy(line, "Connect ");
 161:         printf("(to) ");
 162:         gets(&line[strlen(line)]);
 163:         makeargv();
 164:         argc = margc;
 165:         argv = margv;
 166:     }
 167:     if (argc > 3) {
 168:         printf("usage: %s host-name [service-type]\n", argv[0]);
 169:         return;
 170:     }
 171:     if (argc == 2) servicetype = TTYService_sa; /* default to 1 */
 172:     else if (strcmp(argv[2],"sa") == 0) servicetype = TTYService_sa;
 173:     else if (strncmp(argv[2],"re",2) == 0 ||
 174:          strcmp(argv[2],"exec") == 0) servicetype = TTYService_exec;
 175:     else if (strcmp(argv[2],"its") == 0) servicetype = TTYService_its;
 176:     else servicetype = atoi(argv[2]);
 177:     CH_NameDefault(&hdefault);
 178:     hostoname = CH_StringToName(argv[1], &hdefault);
 179:     if ((host = CH_LookupAddrDN(hostoname,0,hnamebuf,sizeof(hnamebuf)))) {
 180:         sin.sns_family = AF_NS;
 181:         host->x_port = htons(IDPPORT_COURIER);
 182:         bcopy(host, (caddr_t)&sin.sns_addr, sizeof(host));
 183:         /* hnamebuf is filled in by CH_LookupAddrDN */
 184:         hostname = hnamebuf;
 185:     } else if ((host = getXNSaddr(argv[1]))) {
 186:         sin.sns_family = AF_NS;
 187:         bcopy(host, (caddr_t)&sin.sns_addr, sizeof(host));
 188:         strcpy(hnamebuf, argv[1]);
 189:         hostname = hnamebuf;
 190:     } else {
 191:         printf("%s: unknown host\n", argv[1]);
 192:         return;
 193:     }
 194:     cconn = CourierOpen(host);
 195:     if(cconn == NULL) {
 196:         fprintf(stderr,"Courier connection failed\n");
 197:         return;
 198:     }
 199:     net = *(int*)cconn;
 200:     signal(SIGINT, intr);
 201:     signal(SIGPIPE, deadpeer);
 202:     printf("Trying...\n");
 203:     if (createsession(cconn,servicetype) < 0)
 204:       return;
 205:     connected++;
 206:     call(status, "status", 0);
 207:     sleep(1);
 208:     if (setjmp(peerdied) == 0)
 209:         telnet(net);
 210:     fprintf(stderr, "\nConnection closed by foreign host.\n");
 211:     exit(1);
 212: }
 213: 
 214: /*
 215:  * create a session
 216:  */
 217: createsession(cconn, servicetype)
 218:     CourierConnection *cconn;
 219:     LongCardinal servicetype;
 220: {
 221:     GAP3_SessionParameterObject pobj;
 222:     GAP3_TransportObject tobjs[2];
 223:     GAP3_CommParamObject *cp;
 224:     struct {
 225:         Cardinal length;
 226:         GAP3_TransportObject *sequence;
 227:     } tobjlist;
 228:     Authentication1_Credentials creds;
 229:     Authentication1_Verifier verifier;
 230: 
 231:     pobj.designator = oldTtyHost; /* 11 */
 232:     pobj.oldTtyHost_case.charLength = seven;
 233:     pobj.oldTtyHost_case.parity = none;
 234:     pobj.oldTtyHost_case.stopBits = oneStopBit;
 235:     pobj.oldTtyHost_case.frameTimeout = 20;
 236: /*
 237: 	tobjs[0].designator = rs232c;
 238: 	cp = &tobjs[0].rs232c_case.commParams;
 239: 	cp->accessDetail.designator = directConn;
 240: 	cp->accessDetail.directConn_case.duplex = fullduplex;
 241: 	cp->accessDetail.directConn_case.lineType = asynchronous;
 242: 	cp->accessDetail.directConn_case.lineSpeed = bps300;
 243: 	tobjs[0].rs232c_case.preemptOthers = preemptInactive;
 244: 	tobjs[0].rs232c_case.preemptMe = preemptInactive;
 245: 	tobjs[0].rs232c_case.phoneNumber = "";
 246: 	tobjs[0].rs232c_case.line.designator = reserveNeeded;
 247: 	tobjs[0].rs232c_case.line.reserveNeeded_case.lineNumber = 1;
 248: */
 249:     tobjs[0].designator = service;
 250:     tobjs[0].service_case.id = servicetype; /* 1 == SA */
 251: 
 252:     tobjs[1].designator = teletype;
 253:     tobjlist.length = 2;
 254:     tobjlist.sequence = tobjs;
 255:     MakeSimpleCredsAndVerifier(0, 0, &creds, &verifier);
 256:     DURING
 257:       (void) GAP3_Create(cconn, NULL, pobj, tobjlist, 0, creds, verifier);
 258:     HANDLER {
 259:         char *msg;
 260:         switch (Exception.Code) {
 261:         case GAP3_mediumConnectFailed:
 262:             msg = "medium connect failed";
 263:             break;
 264:         case GAP3_illegalTransport:
 265:             msg = "illegal transport type";
 266:             break;
 267:         case GAP3_tooManyGateStreams:
 268:         case GAP3_serviceTooBusy:
 269:             msg = "insufficient resources";
 270:             break;
 271:         case GAP3_serviceNotFound:
 272:             msg = "service type not found";
 273:             break;
 274:         case GAP3_userNotAuthenticated:
 275:         case GAP3_userNotAuthorized:
 276:             msg = "authentication problem";
 277:             break;
 278:         case REJECT_ERROR:
 279:             switch (CourierErrArgs(rejectionDetails,designator)){
 280:             case noSuchProgramNumber:
 281:                 msg = "server does not support GAP";
 282:                 break;
 283:             case noSuchVersionNumber:
 284:                 msg = "server does not support our GAP version";
 285:                 break;
 286:             default:
 287:                 msg = "connection rejected";
 288:             }
 289:             break;
 290:         case PROTOCOL_VIOLATION:
 291:             msg = "protocol violation by remote server";
 292:             break;
 293:         default:
 294:             msg = "some random error";
 295:             break;
 296:         }
 297:         fprintf(stderr,"Error creating connection, %s\n",
 298:             msg);
 299:         return(-1);
 300:     } END_HANDLER;
 301:     return(0);
 302: }
 303: 
 304: /*
 305:  * Print status about the connection.
 306:  */
 307: /*VARARGS*/
 308: status()
 309: {
 310:     if (connected)
 311:         printf("Connected to %s.\n", hostname);
 312:     else
 313:         printf("No connection.\n");
 314:     printf("Escape character is '%s'.\n", control(escape));
 315:     fflush(stdout);
 316: }
 317: 
 318: makeargv()
 319: {
 320:     register char *cp;
 321:     register char **argp = margv;
 322: 
 323:     margc = 0;
 324:     for (cp = line; *cp;) {
 325:         while (isspace(*cp))
 326:             cp++;
 327:         if (*cp == '\0')
 328:             break;
 329:         *argp++ = cp;
 330:         margc += 1;
 331:         while (*cp != '\0' && !isspace(*cp))
 332:             cp++;
 333:         if (*cp == '\0')
 334:             break;
 335:         *cp++ = '\0';
 336:     }
 337:     *argp++ = 0;
 338: }
 339: 
 340: /*VARARGS*/
 341: suspend()
 342: {
 343:     register int save;
 344: 
 345:     save = mode(0);
 346:     kill(0, SIGTSTP);
 347:     /* reget parameters in case they were changed */
 348:     ioctl(0, TIOCGETP, (char *)&ottyb);
 349:     ioctl(0, TIOCGETC, (char *)&otc);
 350:     ioctl(0, TIOCGLTC, (char *)&oltc);
 351:     (void) mode(save);
 352: }
 353: 
 354: /*VARARGS*/
 355: bye()
 356: {
 357:     register char *op;
 358: 
 359:     (void) mode(0);
 360:     if (connected) {
 361:         sendoobdata(GAPCTLcleanup);
 362:         setsockopt(net, NSPROTO_SPP, SO_HEADERS_ON_OUTPUT, &on,
 363:                sizeof(on));
 364:         sppclose(net);
 365:         printf("Connection closed.\n");
 366:         connected = 0;
 367:     }
 368: }
 369: 
 370: /*VARARGS*/
 371: quit()
 372: {
 373:     call(bye, "bye", 0);
 374:     exit(0);
 375: }
 376: 
 377: /*
 378:  * Toggle debugging
 379:  */
 380: setdebug(argc, argv)
 381: {
 382:     debug = ~debug;
 383: }
 384: 
 385: /*
 386:  * Toggle logging
 387:  */
 388: setlog(argc, argv)
 389:     int argc;
 390:     char *argv[];
 391: {
 392:     if (argc > 2)
 393:         printf("Syntax: %s [filename]\n",argv[0]);
 394:     else if (logfile != (FILE*) 0) {
 395:         /* currently logging */
 396:         fclose(logfile);
 397:         printf("Log file closed\n");
 398:         logfile = (FILE*) 0;
 399:         if (argc == 2 && (logfile = fopen(argv[1],"a")) != (FILE*)0)
 400:             printf("Logging to %s\n",argv[1]);
 401:     } else {
 402:         /* not currently logging */
 403:         if (argc == 1)
 404:             printf("Logging already disabled\n");
 405:         else if (argc == 2 &&
 406:              (logfile = fopen(argv[1],"a")) != (FILE*)0 )
 407:             printf("Logging to %s\n",argv[1]);
 408:     }
 409: }
 410: 
 411: /*
 412:  * Help command.
 413:  */
 414: help(argc, argv)
 415:     int argc;
 416:     char *argv[];
 417: {
 418:     register struct cmd *c;
 419: 
 420:     if (argc == 1) {
 421:         printf("Commands may be abbreviated.  Commands are:\n\n");
 422:         for (c = cmdtab; c->name; c++)
 423:             printf("%-*s\t%s\n", HELPINDENT, c->name, c->help);
 424:         return;
 425:     }
 426:     while (--argc > 0) {
 427:         register char *arg;
 428:         arg = *++argv;
 429:         c = getcmd(arg);
 430:         if (c == (struct cmd *)-1)
 431:             printf("?Ambiguous help command %s\n", arg);
 432:         else if (c == (struct cmd *)0)
 433:             printf("?Invalid help command %s\n", arg);
 434:         else
 435:             printf("%s\n", c->help);
 436:     }
 437: }
 438: 
 439: /*
 440:  * Call routine with argc, argv set from args (terminated by 0).
 441:  * VARARGS2
 442:  */
 443: call(routine, args)
 444:     int (*routine)();
 445:     int args;
 446: {
 447:     register int *argp;
 448:     register int argc;
 449: 
 450:     for (argc = 0, argp = &args; *argp++ != 0; argc++)
 451:         ;
 452:     (*routine)(argc, &args);
 453: }
 454: 
 455: struct  tchars notc =   { -1, -1, -1, -1, -1, -1 };
 456: struct  ltchars noltc = { -1, -1, -1, -1, -1, -1 };
 457: 
 458: mode(f)
 459:     register int f;
 460: {
 461:     static int prevmode = 0;
 462:     struct tchars *tc;
 463:     struct ltchars *ltc;
 464:     struct sgttyb sb;
 465:     int onoff, old;
 466: 
 467:     if (prevmode == f)
 468:         return (f);
 469:     old = prevmode;
 470:     prevmode = f;
 471:     sb = ottyb;
 472:     switch (f) {
 473: 
 474:     case 0:
 475:         onoff = 0;
 476:         tc = &otc;
 477:         ltc = &oltc;
 478:         break;
 479: 
 480:     case 1:
 481:     case 2:
 482:         sb.sg_flags |= CBREAK;
 483:         if (f == 1)
 484:             sb.sg_flags &= ~(ECHO|CRMOD);
 485:         else
 486:             sb.sg_flags |= ECHO|CRMOD;
 487:         sb.sg_erase = sb.sg_kill = -1;
 488:         tc = &notc;
 489:         ltc = &noltc;
 490:         onoff = 1;
 491:         break;
 492: 
 493:     default:
 494:         return;
 495:     }
 496:     ioctl(fileno(stdin), TIOCSLTC, (char *)ltc);
 497:     ioctl(fileno(stdin), TIOCSETC, (char *)tc);
 498:     ioctl(fileno(stdin), TIOCSETP, (char *)&sb);
 499:     ioctl(fileno(stdin), FIONBIO, &onoff);
 500:     ioctl(fileno(stdout), FIONBIO, &onoff);
 501:     return (old);
 502: }
 503: 
 504: struct {struct sphdr hdr;
 505:     char data[BUFSIZ];
 506: } sibuf;
 507: char    *sbp;
 508: char    tibuf[BUFSIZ], *tbp;
 509: int scc, tcc;
 510: 
 511: /*
 512:  * Select from tty and network...
 513:  */
 514: telnet(s)
 515:     int s;
 516: {
 517:     register int c;
 518:     int tin = fileno(stdin), tout = fileno(stdout);
 519:     int on = 1;
 520:     int ibits, obits;
 521: 
 522:     (void) mode(1);
 523:     ioctl(s, FIONBIO, &on);
 524:     changeSPPopts(net, GAPCTLnone, 1); /* datastream "normal", eom */
 525:     for (;;) {
 526:         ibits = obits = 0;
 527:         if (nfrontp - nbackp)
 528:             obits |= (1 << s);
 529:         else
 530:             ibits |= (1 << tin);
 531:         if (tfrontp - tbackp)
 532:             obits |= (1 << tout);
 533:         else
 534:             ibits |= (1 << s);
 535:         if (scc < 0 && tcc < 0)
 536:             break;
 537:         select(16, &ibits, &obits, 0, 0);
 538:         if (ibits == 0 && obits == 0) {
 539:             sleep(5);
 540:             continue;
 541:         }
 542: 
 543:         /*
 544: 		 * Something to read from the network...
 545: 		 */
 546:         if (ibits & (1 << s)) {
 547:             scc = read(s, &sibuf, sizeof (sibuf))
 548:               - sizeof(struct sphdr);
 549: #ifdef DEBUG
 550:             if (debug)
 551:               printf("reading %d bytes from net\n", scc);
 552: #endif
 553:             if (scc < 0 && errno == EWOULDBLOCK)
 554:                 scc = 0;
 555:             else if (scc < 0)
 556:                 break; /* protocol violation? */
 557:             else if (sibuf.hdr.sp_cc & SP_OB) {
 558:                 /* status or OOB control */
 559:                 switch ((u_char) *sibuf.data) {
 560:                 case GAPCTLareYouThere:
 561:                     sendoobdata(GAPCTLiAmHere);
 562:                     break;
 563:                 case GAPCTLmediumDown:
 564:                     (void) mode(0);
 565:                     longjmp(peerdied, -1);
 566:                     /*NOTREACHED*/
 567:                 default:
 568:                     /* ignore others */
 569:                     break;
 570:                 }
 571:                 scc = 0;
 572:             }
 573:             else if (sibuf.hdr.sp_dt == GAPCTLnone) {
 574:                 /* normal case */
 575:                 sbp = sibuf.data;
 576:             }
 577:             else if(sibuf.hdr.sp_dt == GAPCTLcleanup){
 578:                 sendoobdata(GAPCTLcleanup);
 579:                 /* should get an END next */
 580:                 scc = 0;
 581:             }
 582:             else if(sibuf.hdr.sp_dt == SPPSST_END) {
 583:                 setsockopt(net, NSPROTO_SPP,
 584:                     SO_HEADERS_ON_OUTPUT,
 585:                     &on, sizeof(on));
 586:                 sppclosereply(net);
 587:                 (void) mode(0);
 588:                 longjmp(peerdied, -1);
 589:                 /*NOTREACHED*/
 590:             }
 591:         }
 592: 
 593:         /*
 594: 		 * Something to read from the tty...
 595: 		 */
 596:         if (ibits & (1 << tin)) {
 597:             tcc = read(tin, tibuf, sizeof (tibuf));
 598:             if (tcc < 0 && errno == EWOULDBLOCK)
 599:                 tcc = 0;
 600:             else {
 601:                 if (tcc <= 0)
 602:                     break;
 603:                 tbp = tibuf;
 604:             }
 605:         }
 606: 
 607:         while (tcc > 0) {
 608:             register int c;
 609: 
 610:             if ((&netobuf[BUFSIZ] - nfrontp) < 2)
 611:                 break;
 612:             c = *tbp++ & 0377, tcc--;
 613:             if (strip(c) == escape) {
 614:                 command(0);
 615:                 tcc = 0;
 616:                 break;
 617:             }
 618:             switch (c) {
 619:             case '\n':
 620:                 /* *nfrontp++ = '\r'; */
 621:                 *nfrontp++ = '\n';
 622:                 break;
 623:             case '\r':
 624:                 *nfrontp++ = '\r';
 625:                 /*	*nfrontp++ = '\n'; */
 626:                 break;
 627:             default:
 628:                 *nfrontp++ = c;
 629:                 break;
 630:             }
 631:         }
 632:         if ((obits & (1 << s)) && (nfrontp - nbackp) > 0)
 633:             netflush(s);
 634:         while (scc > 0) {
 635:             register int c;
 636:             c = *sbp++&0377; scc--;
 637:             *tfrontp++ = c;
 638:         }
 639:         if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0)
 640:             ttyflush(tout);
 641:     }
 642:     (void) mode(0);
 643: }
 644: 
 645: command(top)
 646:     int top;
 647: {
 648:     register struct cmd *c;
 649:     int oldmode, wasopen;
 650: 
 651:     oldmode = mode(0);
 652:     if (!top)
 653:         putchar('\n');
 654:     else
 655:         signal(SIGINT, SIG_DFL);
 656:     for (;;) {
 657:         printf("%s> ", prompt);
 658:         if (gets(line) == 0) {
 659:             if (feof(stdin)) {
 660:                 clearerr(stdin);
 661:                 putchar('\n');
 662:             }
 663:             break;
 664:         }
 665:         if (line[0] == 0)
 666:             break;
 667:         makeargv();
 668:         c = getcmd(margv[0]);
 669:         if (c == (struct cmd *)-1) {
 670:             printf("?Ambiguous command\n");
 671:             continue;
 672:         }
 673:         if (c == 0) {
 674:             printf("?Invalid command\n");
 675:             continue;
 676:         }
 677:         (*c->handler)(margc, margv);
 678:         if (c->handler != help)
 679:             break;
 680:     }
 681:     if (!top) {
 682:         if (!connected)
 683:             longjmp(toplevel, 1);
 684:         (void) mode(oldmode);
 685:     }
 686: }
 687: 
 688: /*
 689:  * Set the escape character.
 690:  */
 691: setescape(argc, argv)
 692:     int argc;
 693:     char *argv[];
 694: {
 695:     register char *arg;
 696:     char buf[50];
 697: 
 698:     if (argc > 2)
 699:         arg = argv[1];
 700:     else {
 701:         printf("new escape character: ");
 702:         gets(buf);
 703:         arg = buf;
 704:     }
 705:     if (arg[0] != '\0')
 706:         escape = arg[0];
 707:     printf("Escape character is '%s'.\n", control(escape));
 708:     fflush(stdout);
 709: }
 710: 
 711: /*
 712:  * Construct a control character sequence
 713:  * for a special character.
 714:  */
 715: char *
 716: control(c)
 717:     register int c;
 718: {
 719:     static char buf[3];
 720: 
 721:     if (c == 0177)
 722:         return ("^?");
 723:     if (c >= 040) {
 724:         buf[0] = c;
 725:         buf[1] = 0;
 726:     } else {
 727:         buf[0] = '^';
 728:         buf[1] = '@'+c;
 729:         buf[2] = 0;
 730:     }
 731:     return (buf);
 732: }
 733: 
 734: struct cmd *
 735: getcmd(name)
 736:     register char *name;
 737: {
 738:     register char *p, *q;
 739:     register struct cmd *c, *found;
 740:     register int nmatches, longest;
 741: 
 742:     longest = 0;
 743:     nmatches = 0;
 744:     found = 0;
 745:     for (c = cmdtab; p = c->name; c++) {
 746:         for (q = name; *q == *p++; q++)
 747:             if (*q == 0)        /* exact match? */
 748:                 return (c);
 749:         if (!*q) {          /* the name was a prefix */
 750:             if (q - name > longest) {
 751:                 longest = q - name;
 752:                 nmatches = 1;
 753:                 found = c;
 754:             } else if (q - name == longest)
 755:                 nmatches++;
 756:         }
 757:     }
 758:     if (nmatches > 1)
 759:         return ((struct cmd *)-1);
 760:     return (found);
 761: }
 762: 
 763: deadpeer()
 764: {
 765:     (void) mode(0);
 766:     longjmp(peerdied, -1);
 767: }
 768: 
 769: intr()
 770: {
 771:     (void) mode(0);
 772:     longjmp(toplevel, -1);
 773: }
 774: 
 775: ttyflush(fd)
 776: {
 777:     register int n;
 778: 
 779:     if ((n = tfrontp - tbackp) > 0) {
 780:         if (logfile != (FILE*)0)
 781:             fwrite(tbackp, 1, n, logfile);
 782:         n = write(fd, tbackp, n);
 783:     }
 784:     if (n < 0)
 785:         return;
 786:     tbackp += n;
 787:     if (tbackp == tfrontp)
 788:         tbackp = tfrontp = ttyobuf;
 789: }
 790: 
 791: netflush(fd)
 792: {
 793:     int n;
 794: 
 795:     if ((n = nfrontp - nbackp) > 0)
 796:         n = write(fd, nbackp, n);
 797: #ifdef DEBUG
 798:     if (debug)
 799:       printf("writing %d of %d bytes to net\n", n, nfrontp-nbackp);
 800: #endif
 801:     if (n < 0) {
 802:         if (errno != ENOBUFS && errno != EWOULDBLOCK) {
 803:             (void) mode(0);
 804:             perror(hostname);
 805:             close(fd);
 806:             longjmp(peerdied, -1);
 807:             /*NOTREACHED*/
 808:         }
 809:         n = 0;
 810:     }
 811:     nbackp += n;
 812:     if (nbackp == nfrontp)
 813:         nbackp = nfrontp = netobuf;
 814: }
 815: 
 816: /*
 817:  * Send out of band data to other end of network
 818:  */
 819: sendoobdata(value)
 820:     char value;
 821: {
 822:     send(net, &value, 1, MSG_OOB);
 823: }
 824: 
 825: changeSPPopts(s, stream, eom)
 826:     int s;          /* SPP socket */
 827:     u_char stream;      /* datastream type */
 828:     char eom;       /* Boolean EOM */
 829: {
 830:     struct sphdr sphdr;
 831:     int off = 0;
 832: 
 833:     sphdr.sp_dt = stream;
 834:     sphdr.sp_cc = (eom ? SP_EM : 0);
 835:     setsockopt(s, NSPROTO_SPP, SO_HEADERS_ON_OUTPUT, &off, sizeof(off));
 836:     setsockopt(s, NSPROTO_SPP, SO_DEFAULT_HEADERS, &sphdr, sizeof(sphdr));
 837: }

Defined functions

bye defined in line 355; used 3 times
call defined in line 443; used 2 times
changeSPPopts defined in line 825; used 1 times
command defined in line 645; used 2 times
control defined in line 715; used 3 times
createsession defined in line 217; used 1 times
deadpeer defined in line 763; used 2 times
getcmd defined in line 734; used 3 times
help defined in line 414; used 6 times
intr defined in line 769; used 2 times
main defined in line 123; never used
makeargv defined in line 318; used 2 times
mode defined in line 458; used 12 times
netflush defined in line 791; used 1 times
quit defined in line 371; used 2 times
sendoobdata defined in line 819; used 3 times
setdebug defined in line 380; used 2 times
setescape defined in line 691; used 2 times
setlog defined in line 388; used 2 times
status defined in line 308; used 3 times
suspend defined in line 341; used 2 times
telnet defined in line 514; used 1 times
tn defined in line 145; used 3 times
ttyflush defined in line 775; used 1 times

Defined variables

closehelp defined in line 85; used 1 times
  • in line 97
cmdtab defined in line 95; used 2 times
connected defined in line 53; used 6 times
crmod defined in line 58; never used
crmodhelp defined in line 92; never used
debug defined in line 57; used 5 times
debughelp defined in line 88; used 1 times
escape defined in line 60; used 4 times
escapehelp defined in line 89; used 1 times
helphelp defined in line 91; used 1 times
hnamebuf defined in line 120; used 5 times
hostname defined in line 119; used 5 times
line defined in line 63; used 6 times
loghelp defined in line 93; used 1 times
margc defined in line 64; used 4 times
margv defined in line 65; used 4 times
net defined in line 55; used 8 times
netobuf defined in line 50; used 4 times
nfrontp defined in line 50; used 10 times
noltc defined in line 456; used 1 times
notc defined in line 455; used 1 times
oltc defined in line 116; used 3 times
on defined in line 61; used 6 times
openhelp defined in line 84; used 1 times
  • in line 96
otc defined in line 115; used 3 times
ottyb defined in line 117; used 3 times
prompt defined in line 59; used 2 times
quithelp defined in line 86; used 1 times
  • in line 98
rcsid defined in line 2; never used
sbp defined in line 507; used 2 times
scc defined in line 509; used 10 times
sin defined in line 109; used 4 times
statushelp defined in line 90; used 1 times
tbp defined in line 508; used 2 times
tcc defined in line 509; used 8 times
tfrontp defined in line 49; used 6 times
tibuf defined in line 508; used 3 times
ttyobuf defined in line 49; used 3 times
zhelp defined in line 87; used 1 times
  • in line 99

Defined struct's

cmd defined in line 78; used 20 times

Defined macros

HELPINDENT defined in line 76; used 1 times
strip defined in line 47; used 1 times
Last modified: 1986-03-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3491
Valid CSS Valid XHTML 1.0 Strict