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