|
|
1.1 ! root 1: #ifndef lint ! 2: static char sccsid[] = "@(#)telnet.c 4.24 (Berkeley) 7/20/83"; ! 3: #endif ! 4: ! 5: /* ! 6: * User telnet program. ! 7: */ ! 8: #include <sys/types.h> ! 9: #include <sys/socket.h> ! 10: #include <sys/ioctl.h> ! 11: ! 12: #include <netinet/in.h> ! 13: ! 14: #define TELOPTS ! 15: #include <arpa/telnet.h> ! 16: ! 17: #include <stdio.h> ! 18: #include <ctype.h> ! 19: #include <errno.h> ! 20: #include <signal.h> ! 21: #include <setjmp.h> ! 22: #include <netdb.h> ! 23: ! 24: #define strip(x) ((x)&0177) ! 25: ! 26: char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; ! 27: char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; ! 28: ! 29: char hisopts[256]; ! 30: char myopts[256]; ! 31: ! 32: char doopt[] = { IAC, DO, '%', 'c', 0 }; ! 33: char dont[] = { IAC, DONT, '%', 'c', 0 }; ! 34: char will[] = { IAC, WILL, '%', 'c', 0 }; ! 35: char wont[] = { IAC, WONT, '%', 'c', 0 }; ! 36: ! 37: int connected; ! 38: int net; ! 39: int showoptions = 0; ! 40: int options; ! 41: int debug = 0; ! 42: int crmod = 0; ! 43: char *prompt; ! 44: char escape = CTRL(]); ! 45: ! 46: char line[200]; ! 47: int margc; ! 48: char *margv[20]; ! 49: ! 50: jmp_buf toplevel; ! 51: jmp_buf peerdied; ! 52: ! 53: extern int errno; ! 54: ! 55: int tn(), quit(), suspend(), bye(), help(); ! 56: int setescape(), status(), toggle(), setoptions(); ! 57: int setcrmod(), setdebug(); ! 58: ! 59: #define HELPINDENT (sizeof ("connect")) ! 60: ! 61: struct cmd { ! 62: char *name; /* command name */ ! 63: char *help; /* help string */ ! 64: int (*handler)(); /* routine which executes command */ ! 65: }; ! 66: ! 67: char openhelp[] = "connect to a site"; ! 68: char closehelp[] = "close current connection"; ! 69: char quithelp[] = "exit telnet"; ! 70: char zhelp[] = "suspend telnet"; ! 71: char debughelp[] = "toggle debugging"; ! 72: char escapehelp[] = "set escape character"; ! 73: char statushelp[] = "print status information"; ! 74: char helphelp[] = "print help information"; ! 75: char optionshelp[] = "toggle viewing of options processing"; ! 76: char crmodhelp[] = "toggle mapping of received carriage returns"; ! 77: ! 78: struct cmd cmdtab[] = { ! 79: { "open", openhelp, tn }, ! 80: { "close", closehelp, bye }, ! 81: { "quit", quithelp, quit }, ! 82: { "z", zhelp, suspend }, ! 83: { "escape", escapehelp, setescape }, ! 84: { "status", statushelp, status }, ! 85: { "options", optionshelp, setoptions }, ! 86: { "crmod", crmodhelp, setcrmod }, ! 87: { "debug", debughelp, setdebug }, ! 88: { "?", helphelp, help }, ! 89: 0 ! 90: }; ! 91: ! 92: struct sockaddr_in sin; ! 93: ! 94: int intr(), deadpeer(); ! 95: char *control(); ! 96: struct cmd *getcmd(); ! 97: struct servent *sp; ! 98: ! 99: struct tchars otc; ! 100: struct ltchars oltc; ! 101: struct sgttyb ottyb; ! 102: ! 103: main(argc, argv) ! 104: int argc; ! 105: char *argv[]; ! 106: { ! 107: sp = getservbyname("telnet", "tcp"); ! 108: if (sp == 0) { ! 109: fprintf(stderr, "telnet: tcp/telnet: unknown service\n"); ! 110: exit(1); ! 111: } ! 112: ioctl(0, TIOCGETP, (char *)&ottyb); ! 113: ioctl(0, TIOCGETC, (char *)&otc); ! 114: ioctl(0, TIOCGLTC, (char *)&oltc); ! 115: setbuf(stdin, 0); ! 116: setbuf(stdout, 0); ! 117: prompt = argv[0]; ! 118: if (argc > 1 && !strcmp(argv[1], "-d")) ! 119: debug = SO_DEBUG, argv++, argc--; ! 120: if (argc != 1) { ! 121: if (setjmp(toplevel) != 0) ! 122: exit(0); ! 123: tn(argc, argv); ! 124: } ! 125: setjmp(toplevel); ! 126: for (;;) ! 127: command(1); ! 128: } ! 129: ! 130: char *hostname; ! 131: char hnamebuf[32]; ! 132: ! 133: tn(argc, argv) ! 134: int argc; ! 135: char *argv[]; ! 136: { ! 137: register int c; ! 138: register struct hostent *host; ! 139: ! 140: if (connected) { ! 141: printf("?Already connected to %s\n", hostname); ! 142: return; ! 143: } ! 144: if (argc < 2) { ! 145: strcpy(line, "Connect "); ! 146: printf("(to) "); ! 147: gets(&line[strlen(line)]); ! 148: makeargv(); ! 149: argc = margc; ! 150: argv = margv; ! 151: } ! 152: if (argc > 3) { ! 153: printf("usage: %s host-name [port]\n", argv[0]); ! 154: return; ! 155: } ! 156: host = gethostbyname(argv[1]); ! 157: if (host) { ! 158: sin.sin_family = host->h_addrtype; ! 159: bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length); ! 160: hostname = host->h_name; ! 161: } else { ! 162: sin.sin_family = AF_INET; ! 163: sin.sin_addr.s_addr = inet_addr(argv[1]); ! 164: if (sin.sin_addr.s_addr == -1) { ! 165: printf("%s: unknown host\n", argv[1]); ! 166: return; ! 167: } ! 168: strcpy(hnamebuf, argv[1]); ! 169: hostname = hnamebuf; ! 170: } ! 171: sin.sin_port = sp->s_port; ! 172: if (argc == 3) { ! 173: sin.sin_port = atoi(argv[2]); ! 174: if (sin.sin_port < 0) { ! 175: printf("%s: bad port number\n", argv[2]); ! 176: return; ! 177: } ! 178: sin.sin_port = htons(sin.sin_port); ! 179: } ! 180: net = socket(AF_INET, SOCK_STREAM, 0, 0); ! 181: if (net < 0) { ! 182: perror("telnet: socket"); ! 183: return; ! 184: } ! 185: if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) ! 186: perror("setsockopt (SO_DEBUG)"); ! 187: signal(SIGINT, intr); ! 188: signal(SIGPIPE, deadpeer); ! 189: printf("Trying...\n"); ! 190: if (connect(net, (caddr_t)&sin, sizeof (sin), 0) < 0) { ! 191: perror("telnet: connect"); ! 192: signal(SIGINT, SIG_DFL); ! 193: return; ! 194: } ! 195: connected++; ! 196: call(status, "status", 0); ! 197: if (setjmp(peerdied) == 0) ! 198: telnet(net); ! 199: fprintf(stderr, "Connection closed by foreign host.\n"); ! 200: exit(1); ! 201: } ! 202: ! 203: /* ! 204: * Print status about the connection. ! 205: */ ! 206: /*VARARGS*/ ! 207: status() ! 208: { ! 209: if (connected) ! 210: printf("Connected to %s.\n", hostname); ! 211: else ! 212: printf("No connection.\n"); ! 213: printf("Escape character is '%s'.\n", control(escape)); ! 214: fflush(stdout); ! 215: } ! 216: ! 217: makeargv() ! 218: { ! 219: register char *cp; ! 220: register char **argp = margv; ! 221: ! 222: margc = 0; ! 223: for (cp = line; *cp;) { ! 224: while (isspace(*cp)) ! 225: cp++; ! 226: if (*cp == '\0') ! 227: break; ! 228: *argp++ = cp; ! 229: margc += 1; ! 230: while (*cp != '\0' && !isspace(*cp)) ! 231: cp++; ! 232: if (*cp == '\0') ! 233: break; ! 234: *cp++ = '\0'; ! 235: } ! 236: *argp++ = 0; ! 237: } ! 238: ! 239: /*VARARGS*/ ! 240: suspend() ! 241: { ! 242: register int save; ! 243: ! 244: save = mode(0); ! 245: kill(0, SIGTSTP); ! 246: /* reget parameters in case they were changed */ ! 247: ioctl(0, TIOCGETP, (char *)&ottyb); ! 248: ioctl(0, TIOCGETC, (char *)&otc); ! 249: ioctl(0, TIOCGLTC, (char *)&oltc); ! 250: (void) mode(save); ! 251: } ! 252: ! 253: /*VARARGS*/ ! 254: bye() ! 255: { ! 256: register char *op; ! 257: ! 258: (void) mode(0); ! 259: if (connected) { ! 260: shutdown(net, 2); ! 261: printf("Connection closed.\n"); ! 262: close(net); ! 263: connected = 0; ! 264: /* reset his options */ ! 265: for (op = hisopts; op < &hisopts[256]; op++) ! 266: *op = 0; ! 267: } ! 268: } ! 269: ! 270: /*VARARGS*/ ! 271: quit() ! 272: { ! 273: call(bye, "bye", 0); ! 274: exit(0); ! 275: } ! 276: ! 277: /* ! 278: * Help command. ! 279: */ ! 280: help(argc, argv) ! 281: int argc; ! 282: char *argv[]; ! 283: { ! 284: register struct cmd *c; ! 285: ! 286: if (argc == 1) { ! 287: printf("Commands may be abbreviated. Commands are:\n\n"); ! 288: for (c = cmdtab; c->name; c++) ! 289: printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); ! 290: return; ! 291: } ! 292: while (--argc > 0) { ! 293: register char *arg; ! 294: arg = *++argv; ! 295: c = getcmd(arg); ! 296: if (c == (struct cmd *)-1) ! 297: printf("?Ambiguous help command %s\n", arg); ! 298: else if (c == (struct cmd *)0) ! 299: printf("?Invalid help command %s\n", arg); ! 300: else ! 301: printf("%s\n", c->help); ! 302: } ! 303: } ! 304: ! 305: /* ! 306: * Call routine with argc, argv set from args (terminated by 0). ! 307: * VARARGS2 ! 308: */ ! 309: call(routine, args) ! 310: int (*routine)(); ! 311: int args; ! 312: { ! 313: register int *argp; ! 314: register int argc; ! 315: ! 316: for (argc = 0, argp = &args; *argp++ != 0; argc++) ! 317: ; ! 318: (*routine)(argc, &args); ! 319: } ! 320: ! 321: struct tchars notc = { -1, -1, -1, -1, -1, -1 }; ! 322: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; ! 323: ! 324: mode(f) ! 325: register int f; ! 326: { ! 327: static int prevmode = 0; ! 328: struct tchars *tc; ! 329: struct ltchars *ltc; ! 330: struct sgttyb sb; ! 331: int onoff, old; ! 332: ! 333: if (prevmode == f) ! 334: return (f); ! 335: old = prevmode; ! 336: prevmode = f; ! 337: sb = ottyb; ! 338: switch (f) { ! 339: ! 340: case 0: ! 341: onoff = 0; ! 342: tc = &otc; ! 343: ltc = &oltc; ! 344: break; ! 345: ! 346: case 1: ! 347: case 2: ! 348: sb.sg_flags |= CBREAK; ! 349: if (f == 1) ! 350: sb.sg_flags &= ~(ECHO|CRMOD); ! 351: else ! 352: sb.sg_flags |= ECHO|CRMOD; ! 353: sb.sg_erase = sb.sg_kill = -1; ! 354: tc = ¬c; ! 355: ltc = &noltc; ! 356: onoff = 1; ! 357: break; ! 358: ! 359: default: ! 360: return; ! 361: } ! 362: ioctl(fileno(stdin), TIOCSLTC, (char *)ltc); ! 363: ioctl(fileno(stdin), TIOCSETC, (char *)tc); ! 364: ioctl(fileno(stdin), TIOCSETP, (char *)&sb); ! 365: ioctl(fileno(stdin), FIONBIO, &onoff); ! 366: ioctl(fileno(stdout), FIONBIO, &onoff); ! 367: return (old); ! 368: } ! 369: ! 370: char sibuf[BUFSIZ], *sbp; ! 371: char tibuf[BUFSIZ], *tbp; ! 372: int scc, tcc; ! 373: ! 374: /* ! 375: * Select from tty and network... ! 376: */ ! 377: telnet(s) ! 378: int s; ! 379: { ! 380: register int c; ! 381: int tin = fileno(stdin), tout = fileno(stdout); ! 382: int on = 1; ! 383: ! 384: (void) mode(2); ! 385: ioctl(s, FIONBIO, &on); ! 386: for (;;) { ! 387: int ibits = 0, obits = 0; ! 388: ! 389: if (nfrontp - nbackp) ! 390: obits |= (1 << s); ! 391: else ! 392: ibits |= (1 << tin); ! 393: if (tfrontp - tbackp) ! 394: obits |= (1 << tout); ! 395: else ! 396: ibits |= (1 << s); ! 397: if (scc < 0 && tcc < 0) ! 398: break; ! 399: select(16, &ibits, &obits, 0, 0); ! 400: if (ibits == 0 && obits == 0) { ! 401: sleep(5); ! 402: continue; ! 403: } ! 404: ! 405: /* ! 406: * Something to read from the network... ! 407: */ ! 408: if (ibits & (1 << s)) { ! 409: scc = read(s, sibuf, sizeof (sibuf)); ! 410: if (scc < 0 && errno == EWOULDBLOCK) ! 411: scc = 0; ! 412: else { ! 413: if (scc <= 0) ! 414: break; ! 415: sbp = sibuf; ! 416: } ! 417: } ! 418: ! 419: /* ! 420: * Something to read from the tty... ! 421: */ ! 422: if (ibits & (1 << tin)) { ! 423: tcc = read(tin, tibuf, sizeof (tibuf)); ! 424: if (tcc < 0 && errno == EWOULDBLOCK) ! 425: tcc = 0; ! 426: else { ! 427: if (tcc <= 0) ! 428: break; ! 429: tbp = tibuf; ! 430: } ! 431: } ! 432: ! 433: while (tcc > 0) { ! 434: register int c; ! 435: ! 436: if ((&netobuf[BUFSIZ] - nfrontp) < 2) ! 437: break; ! 438: c = *tbp++ & 0377, tcc--; ! 439: if (strip(c) == escape) { ! 440: command(0); ! 441: tcc = 0; ! 442: break; ! 443: } ! 444: if (c == IAC) ! 445: *nfrontp++ = c; ! 446: *nfrontp++ = c; ! 447: } ! 448: if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) ! 449: netflush(s); ! 450: if (scc > 0) ! 451: telrcv(); ! 452: if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) ! 453: ttyflush(tout); ! 454: } ! 455: (void) mode(0); ! 456: } ! 457: ! 458: command(top) ! 459: int top; ! 460: { ! 461: register struct cmd *c; ! 462: int oldmode, wasopen; ! 463: ! 464: oldmode = mode(0); ! 465: if (!top) ! 466: putchar('\n'); ! 467: else ! 468: signal(SIGINT, SIG_DFL); ! 469: for (;;) { ! 470: printf("%s> ", prompt); ! 471: if (gets(line) == 0) { ! 472: if (feof(stdin)) { ! 473: clearerr(stdin); ! 474: putchar('\n'); ! 475: } ! 476: break; ! 477: } ! 478: if (line[0] == 0) ! 479: break; ! 480: makeargv(); ! 481: c = getcmd(margv[0]); ! 482: if (c == (struct cmd *)-1) { ! 483: printf("?Ambiguous command\n"); ! 484: continue; ! 485: } ! 486: if (c == 0) { ! 487: printf("?Invalid command\n"); ! 488: continue; ! 489: } ! 490: (*c->handler)(margc, margv); ! 491: if (c->handler != help) ! 492: break; ! 493: } ! 494: if (!top) { ! 495: if (!connected) ! 496: longjmp(toplevel, 1); ! 497: (void) mode(oldmode); ! 498: } ! 499: } ! 500: ! 501: /* ! 502: * Telnet receiver states for fsm ! 503: */ ! 504: #define TS_DATA 0 ! 505: #define TS_IAC 1 ! 506: #define TS_WILL 2 ! 507: #define TS_WONT 3 ! 508: #define TS_DO 4 ! 509: #define TS_DONT 5 ! 510: ! 511: telrcv() ! 512: { ! 513: register int c; ! 514: static int state = TS_DATA; ! 515: ! 516: while (scc > 0) { ! 517: c = *sbp++ & 0377, scc--; ! 518: switch (state) { ! 519: ! 520: case TS_DATA: ! 521: if (c == IAC) { ! 522: state = TS_IAC; ! 523: continue; ! 524: } ! 525: *tfrontp++ = c; ! 526: /* ! 527: * This hack is needed since we can't set ! 528: * CRMOD on output only. Machines like MULTICS ! 529: * like to send \r without \n; since we must ! 530: * turn off CRMOD to get proper input, the mapping ! 531: * is done here (sigh). ! 532: */ ! 533: if (c == '\r' && crmod) ! 534: *tfrontp++ = '\n'; ! 535: continue; ! 536: ! 537: case TS_IAC: ! 538: switch (c) { ! 539: ! 540: case WILL: ! 541: state = TS_WILL; ! 542: continue; ! 543: ! 544: case WONT: ! 545: state = TS_WONT; ! 546: continue; ! 547: ! 548: case DO: ! 549: state = TS_DO; ! 550: continue; ! 551: ! 552: case DONT: ! 553: state = TS_DONT; ! 554: continue; ! 555: ! 556: case DM: ! 557: ioctl(fileno(stdout), TIOCFLUSH, 0); ! 558: break; ! 559: ! 560: case NOP: ! 561: case GA: ! 562: break; ! 563: ! 564: default: ! 565: break; ! 566: } ! 567: state = TS_DATA; ! 568: continue; ! 569: ! 570: case TS_WILL: ! 571: printoption("RCVD", will, c, !hisopts[c]); ! 572: if (!hisopts[c]) ! 573: willoption(c); ! 574: state = TS_DATA; ! 575: continue; ! 576: ! 577: case TS_WONT: ! 578: printoption("RCVD", wont, c, hisopts[c]); ! 579: if (hisopts[c]) ! 580: wontoption(c); ! 581: state = TS_DATA; ! 582: continue; ! 583: ! 584: case TS_DO: ! 585: printoption("RCVD", doopt, c, !myopts[c]); ! 586: if (!myopts[c]) ! 587: dooption(c); ! 588: state = TS_DATA; ! 589: continue; ! 590: ! 591: case TS_DONT: ! 592: printoption("RCVD", dont, c, myopts[c]); ! 593: if (myopts[c]) { ! 594: myopts[c] = 0; ! 595: sprintf(nfrontp, wont, c); ! 596: nfrontp += sizeof (wont) - 2; ! 597: printoption("SENT", wont, c); ! 598: } ! 599: state = TS_DATA; ! 600: continue; ! 601: } ! 602: } ! 603: } ! 604: ! 605: willoption(option) ! 606: int option; ! 607: { ! 608: char *fmt; ! 609: ! 610: switch (option) { ! 611: ! 612: case TELOPT_ECHO: ! 613: (void) mode(1); ! 614: ! 615: case TELOPT_SGA: ! 616: hisopts[option] = 1; ! 617: fmt = doopt; ! 618: break; ! 619: ! 620: case TELOPT_TM: ! 621: fmt = dont; ! 622: break; ! 623: ! 624: default: ! 625: fmt = dont; ! 626: break; ! 627: } ! 628: sprintf(nfrontp, fmt, option); ! 629: nfrontp += sizeof (dont) - 2; ! 630: printoption("SENT", fmt, option); ! 631: } ! 632: ! 633: wontoption(option) ! 634: int option; ! 635: { ! 636: char *fmt; ! 637: ! 638: switch (option) { ! 639: ! 640: case TELOPT_ECHO: ! 641: (void) mode(2); ! 642: ! 643: case TELOPT_SGA: ! 644: hisopts[option] = 0; ! 645: fmt = dont; ! 646: break; ! 647: ! 648: default: ! 649: fmt = dont; ! 650: } ! 651: sprintf(nfrontp, fmt, option); ! 652: nfrontp += sizeof (doopt) - 2; ! 653: printoption("SENT", fmt, option); ! 654: } ! 655: ! 656: dooption(option) ! 657: int option; ! 658: { ! 659: char *fmt; ! 660: ! 661: switch (option) { ! 662: ! 663: case TELOPT_TM: ! 664: fmt = wont; ! 665: break; ! 666: ! 667: case TELOPT_ECHO: ! 668: (void) mode(2); ! 669: fmt = will; ! 670: hisopts[option] = 0; ! 671: break; ! 672: ! 673: case TELOPT_SGA: ! 674: fmt = will; ! 675: break; ! 676: ! 677: default: ! 678: fmt = wont; ! 679: break; ! 680: } ! 681: sprintf(nfrontp, fmt, option); ! 682: nfrontp += sizeof (doopt) - 2; ! 683: printoption("SENT", fmt, option); ! 684: } ! 685: ! 686: /* ! 687: * Set the escape character. ! 688: */ ! 689: setescape(argc, argv) ! 690: int argc; ! 691: char *argv[]; ! 692: { ! 693: register char *arg; ! 694: char buf[50]; ! 695: ! 696: if (argc > 2) ! 697: arg = argv[1]; ! 698: else { ! 699: printf("new escape character: "); ! 700: gets(buf); ! 701: arg = buf; ! 702: } ! 703: if (arg[0] != '\0') ! 704: escape = arg[0]; ! 705: printf("Escape character is '%s'.\n", control(escape)); ! 706: fflush(stdout); ! 707: } ! 708: ! 709: /*VARARGS*/ ! 710: setoptions() ! 711: { ! 712: ! 713: showoptions = !showoptions; ! 714: printf("%s show option processing.\n", showoptions ? "Will" : "Wont"); ! 715: fflush(stdout); ! 716: } ! 717: ! 718: /*VARARGS*/ ! 719: setcrmod() ! 720: { ! 721: ! 722: crmod = !crmod; ! 723: printf("%s map carriage return on output.\n", crmod ? "Will" : "Wont"); ! 724: fflush(stdout); ! 725: } ! 726: ! 727: /*VARARGS*/ ! 728: setdebug() ! 729: { ! 730: ! 731: debug = !debug; ! 732: printf("%s turn on socket level debugging.\n", ! 733: debug ? "Will" : "Wont"); ! 734: fflush(stdout); ! 735: if (debug && net > 0 && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0) ! 736: perror("setsockopt (SO_DEBUG)"); ! 737: } ! 738: ! 739: /* ! 740: * Construct a control character sequence ! 741: * for a special character. ! 742: */ ! 743: char * ! 744: control(c) ! 745: register int c; ! 746: { ! 747: static char buf[3]; ! 748: ! 749: if (c == 0177) ! 750: return ("^?"); ! 751: if (c >= 040) { ! 752: buf[0] = c; ! 753: buf[1] = 0; ! 754: } else { ! 755: buf[0] = '^'; ! 756: buf[1] = '@'+c; ! 757: buf[2] = 0; ! 758: } ! 759: return (buf); ! 760: } ! 761: ! 762: struct cmd * ! 763: getcmd(name) ! 764: register char *name; ! 765: { ! 766: register char *p, *q; ! 767: register struct cmd *c, *found; ! 768: register int nmatches, longest; ! 769: ! 770: longest = 0; ! 771: nmatches = 0; ! 772: found = 0; ! 773: for (c = cmdtab; p = c->name; c++) { ! 774: for (q = name; *q == *p++; q++) ! 775: if (*q == 0) /* exact match? */ ! 776: return (c); ! 777: if (!*q) { /* the name was a prefix */ ! 778: if (q - name > longest) { ! 779: longest = q - name; ! 780: nmatches = 1; ! 781: found = c; ! 782: } else if (q - name == longest) ! 783: nmatches++; ! 784: } ! 785: } ! 786: if (nmatches > 1) ! 787: return ((struct cmd *)-1); ! 788: return (found); ! 789: } ! 790: ! 791: deadpeer() ! 792: { ! 793: (void) mode(0); ! 794: longjmp(peerdied, -1); ! 795: } ! 796: ! 797: intr() ! 798: { ! 799: (void) mode(0); ! 800: longjmp(toplevel, -1); ! 801: } ! 802: ! 803: ttyflush(fd) ! 804: { ! 805: int n; ! 806: ! 807: if ((n = tfrontp - tbackp) > 0) ! 808: n = write(fd, tbackp, n); ! 809: if (n < 0) ! 810: return; ! 811: tbackp += n; ! 812: if (tbackp == tfrontp) ! 813: tbackp = tfrontp = ttyobuf; ! 814: } ! 815: ! 816: netflush(fd) ! 817: { ! 818: int n; ! 819: ! 820: if ((n = nfrontp - nbackp) > 0) ! 821: n = write(fd, nbackp, n); ! 822: if (n < 0) { ! 823: if (errno != ENOBUFS && errno != EWOULDBLOCK) { ! 824: (void) mode(0); ! 825: perror(hostname); ! 826: close(fd); ! 827: longjmp(peerdied, -1); ! 828: /*NOTREACHED*/ ! 829: } ! 830: n = 0; ! 831: } ! 832: nbackp += n; ! 833: if (nbackp == nfrontp) ! 834: nbackp = nfrontp = netobuf; ! 835: } ! 836: ! 837: /*VARARGS*/ ! 838: printoption(direction, fmt, option, what) ! 839: char *direction, *fmt; ! 840: int option, what; ! 841: { ! 842: if (!showoptions) ! 843: return; ! 844: printf("%s ", direction); ! 845: if (fmt == doopt) ! 846: fmt = "do"; ! 847: else if (fmt == dont) ! 848: fmt = "dont"; ! 849: else if (fmt == will) ! 850: fmt = "will"; ! 851: else if (fmt == wont) ! 852: fmt = "wont"; ! 853: else ! 854: fmt = "???"; ! 855: if (option < TELOPT_SUPDUP) ! 856: printf("%s %s", fmt, telopts[option]); ! 857: else ! 858: printf("%s %d", fmt, option); ! 859: if (*direction == '<') { ! 860: printf("\r\n"); ! 861: return; ! 862: } ! 863: printf(" (%s)\r\n", what ? "reply" : "don't reply"); ! 864: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.