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