|
|
1.1 ! root 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 = ¬c; ! 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.