1*6000Sroot /* telnet.c 4.1 82/02/28 */ 2*6000Sroot 3*6000Sroot /* 4*6000Sroot * User telnet program. 5*6000Sroot */ 6*6000Sroot #include <stdio.h> 7*6000Sroot #include <ctype.h> 8*6000Sroot #include <errno.h> 9*6000Sroot #include <signal.h> 10*6000Sroot #include <sgtty.h> 11*6000Sroot #include <setjmp.h> 12*6000Sroot #include <sys/types.h> 13*6000Sroot #include <sys/socket.h> 14*6000Sroot #include <net/in.h> 15*6000Sroot #include "telnet.h" 16*6000Sroot 17*6000Sroot #define ctrl(x) ((x) & 037) 18*6000Sroot #define strip(x) ((x)&0177) 19*6000Sroot #define INFINITY 10000000 20*6000Sroot #define swab(x) ((((x) >> 8) | ((x) << 8)) & 0xffff) 21*6000Sroot 22*6000Sroot char ttyobuf[BUFSIZ], *tfrontp = ttyobuf, *tbackp = ttyobuf; 23*6000Sroot char netobuf[BUFSIZ] = 24*6000Sroot { IAC, DO, TELOPT_ECHO, IAC, DO, TELOPT_SGA, 25*6000Sroot IAC, WONT, TELOPT_SGA }, 26*6000Sroot *nfrontp = netobuf + 9, *nbackp = netobuf; 27*6000Sroot 28*6000Sroot char hisopts[256]; 29*6000Sroot char myopts[256]; 30*6000Sroot 31*6000Sroot char doopt[] = { IAC, DO, '%', 'c', 0 }; 32*6000Sroot char dont[] = { IAC, DONT, '%', 'c', 0 }; 33*6000Sroot char will[] = { IAC, WILL, '%', 'c', 0 }; 34*6000Sroot char wont[] = { IAC, WONT, '%', 'c', 0 }; 35*6000Sroot 36*6000Sroot int connected; 37*6000Sroot int net; 38*6000Sroot char *prompt; 39*6000Sroot char escape = ctrl('_'); 40*6000Sroot 41*6000Sroot char line[200]; 42*6000Sroot int margc; 43*6000Sroot char *margv[20]; 44*6000Sroot 45*6000Sroot jmp_buf toplevel; 46*6000Sroot jmp_buf peerdied; 47*6000Sroot 48*6000Sroot extern int errno; 49*6000Sroot 50*6000Sroot int tn(), quit(), suspend(), bye(), help(); 51*6000Sroot int setescape(), status(), toggle(); 52*6000Sroot 53*6000Sroot #define HELPINDENT (sizeof("connect")) 54*6000Sroot 55*6000Sroot struct cmd { 56*6000Sroot char *name; 57*6000Sroot char *help; 58*6000Sroot int (*handler)(); 59*6000Sroot }; 60*6000Sroot 61*6000Sroot char ohelp[] = "connect to a site"; 62*6000Sroot char chelp[] = "close current connection"; 63*6000Sroot char qhelp[] = "exit telnet"; 64*6000Sroot char zhelp[] = "suspend telnet"; 65*6000Sroot char ehelp[] = "set escape character"; 66*6000Sroot char shelp[] = "print status information"; 67*6000Sroot char hhelp[] = "print help information"; 68*6000Sroot 69*6000Sroot struct cmd cmdtab[] = { 70*6000Sroot { "open", ohelp, tn }, 71*6000Sroot { "close", chelp, bye }, 72*6000Sroot { "quit", qhelp, quit }, 73*6000Sroot { "z", zhelp, suspend }, 74*6000Sroot { "escape", ehelp, setescape }, 75*6000Sroot { "status", shelp, status }, 76*6000Sroot { "?", hhelp, help }, 77*6000Sroot 0 78*6000Sroot }; 79*6000Sroot 80*6000Sroot struct sockaddr_in sin = { AF_INET, swab(IPPORT_TELNET) }; 81*6000Sroot 82*6000Sroot int intr(), deadpeer(); 83*6000Sroot char *control(); 84*6000Sroot struct cmd *getcmd(); 85*6000Sroot 86*6000Sroot main(argc, argv) 87*6000Sroot int argc; 88*6000Sroot char *argv[]; 89*6000Sroot { 90*6000Sroot setbuf(stdin, 0); 91*6000Sroot setbuf(stdout, 0); 92*6000Sroot prompt = argv[0]; 93*6000Sroot if (argc != 1) { 94*6000Sroot if (setjmp(toplevel) != 0) 95*6000Sroot exit(0); 96*6000Sroot tn(argc, argv); 97*6000Sroot } 98*6000Sroot setjmp(toplevel); 99*6000Sroot for (;;) 100*6000Sroot command(1); 101*6000Sroot } 102*6000Sroot 103*6000Sroot char host_name[100]; 104*6000Sroot 105*6000Sroot tn(argc, argv) 106*6000Sroot int argc; 107*6000Sroot char *argv[]; 108*6000Sroot { 109*6000Sroot register int c; 110*6000Sroot 111*6000Sroot if (connected) { 112*6000Sroot printf("?Already connected to %s\n", host_name); 113*6000Sroot return; 114*6000Sroot } 115*6000Sroot if (argc < 2) { 116*6000Sroot strcpy(line, "Connect "); 117*6000Sroot printf("(to) "); 118*6000Sroot gets(&line[strlen(line)]); 119*6000Sroot makeargv(); 120*6000Sroot argc = margc; 121*6000Sroot argv = margv; 122*6000Sroot } 123*6000Sroot if (argc > 3) { 124*6000Sroot printf("usage: %s host-name [port]\n", argv[0]); 125*6000Sroot return; 126*6000Sroot } 127*6000Sroot sin.sin_addr.s_addr = rhost(&argv[1]); 128*6000Sroot if (sin.sin_addr.s_addr == 0) { 129*6000Sroot printf("%s: unknown host\n", argv[1]); 130*6000Sroot return; 131*6000Sroot } 132*6000Sroot if ((net = socket(SOCK_STREAM, 0, 0, 0)) < 0) { 133*6000Sroot perror("socket"); 134*6000Sroot return; 135*6000Sroot } 136*6000Sroot if (argc == 3) 137*6000Sroot sin.sin_port = atoi(argv[2]); 138*6000Sroot sigset(SIGINT, intr); 139*6000Sroot sigset(SIGPIPE, deadpeer); 140*6000Sroot printf("Trying...\n"); 141*6000Sroot if (connect(net, &sin)) { 142*6000Sroot perror("connect"); 143*6000Sroot sigset(SIGINT, SIG_DFL); 144*6000Sroot return; 145*6000Sroot } 146*6000Sroot strcpy(host_name, argv[1]); 147*6000Sroot connected++; 148*6000Sroot call(status, "status", 0); 149*6000Sroot if (setjmp(peerdied) == 0) 150*6000Sroot telnet(net); 151*6000Sroot fprintf(stderr, "Connection closed by foreign host.\n"); 152*6000Sroot exit(1); 153*6000Sroot } 154*6000Sroot 155*6000Sroot /* 156*6000Sroot * Print status about the connection. 157*6000Sroot */ 158*6000Sroot /*VARARGS*/ 159*6000Sroot status() 160*6000Sroot { 161*6000Sroot if (connected) 162*6000Sroot printf("Connected to %s.\n", host_name); 163*6000Sroot else 164*6000Sroot printf("No connection.\n"); 165*6000Sroot printf("Escape character is '%s'.\n", control(escape)); 166*6000Sroot } 167*6000Sroot 168*6000Sroot makeargv() 169*6000Sroot { 170*6000Sroot register char *cp; 171*6000Sroot register char **argp = margv; 172*6000Sroot 173*6000Sroot margc = 0; 174*6000Sroot for (cp = line; *cp;) { 175*6000Sroot while (isspace(*cp)) 176*6000Sroot cp++; 177*6000Sroot if (*cp == '\0') 178*6000Sroot break; 179*6000Sroot *argp++ = cp; 180*6000Sroot margc += 1; 181*6000Sroot while (*cp != '\0' && !isspace(*cp)) 182*6000Sroot cp++; 183*6000Sroot if (*cp == '\0') 184*6000Sroot break; 185*6000Sroot *cp++ = '\0'; 186*6000Sroot } 187*6000Sroot *argp++ = 0; 188*6000Sroot } 189*6000Sroot 190*6000Sroot /*VARARGS*/ 191*6000Sroot suspend() 192*6000Sroot { 193*6000Sroot register int save; 194*6000Sroot 195*6000Sroot save = mode(0); 196*6000Sroot kill(0, SIGTSTP); /* get whole process group */ 197*6000Sroot mode(save); 198*6000Sroot } 199*6000Sroot 200*6000Sroot /*VARARGS*/ 201*6000Sroot bye() 202*6000Sroot { 203*6000Sroot int how = 2; 204*6000Sroot 205*6000Sroot mode(0); 206*6000Sroot if (connected) { 207*6000Sroot ioctl(net, SIOCDONE, &how); 208*6000Sroot printf("Connection closed.\n"); 209*6000Sroot close(net); 210*6000Sroot connected = 0; 211*6000Sroot } 212*6000Sroot } 213*6000Sroot 214*6000Sroot /*VARARGS*/ 215*6000Sroot quit() 216*6000Sroot { 217*6000Sroot call(bye, "bye", 0); 218*6000Sroot exit(0); 219*6000Sroot } 220*6000Sroot 221*6000Sroot /* 222*6000Sroot * Help command. 223*6000Sroot * Call each command handler with argc == 0 and argv[0] == name. 224*6000Sroot */ 225*6000Sroot help(argc, argv) 226*6000Sroot int argc; 227*6000Sroot char *argv[]; 228*6000Sroot { 229*6000Sroot register struct cmd *c; 230*6000Sroot 231*6000Sroot if (argc == 1) { 232*6000Sroot printf("Commands may be abbreviated. Commands are:\n\n"); 233*6000Sroot for (c = cmdtab; c->name; c++) 234*6000Sroot printf("%-*s\t%s\n", HELPINDENT, c->name, c->help); 235*6000Sroot return; 236*6000Sroot } 237*6000Sroot while (--argc > 0) { 238*6000Sroot register char *arg; 239*6000Sroot arg = *++argv; 240*6000Sroot c = getcmd(arg); 241*6000Sroot if (c == (struct cmd *)-1) 242*6000Sroot printf("?Ambiguous help command %s\n", arg); 243*6000Sroot else if (c == (struct cmd *)0) 244*6000Sroot printf("?Invalid help command %s\n", arg); 245*6000Sroot else 246*6000Sroot printf("%s\n", c->help); 247*6000Sroot } 248*6000Sroot } 249*6000Sroot 250*6000Sroot /* 251*6000Sroot * Call routine with argc, argv set from args (terminated by 0). 252*6000Sroot * VARARGS2 253*6000Sroot */ 254*6000Sroot call(routine, args) 255*6000Sroot int (*routine)(); 256*6000Sroot int args; 257*6000Sroot { 258*6000Sroot register int *argp; 259*6000Sroot register int argc; 260*6000Sroot 261*6000Sroot for (argc = 0, argp = &args; *argp++ != 0; argc++) 262*6000Sroot ; 263*6000Sroot (*routine)(argc, &args); 264*6000Sroot } 265*6000Sroot 266*6000Sroot mode(f) 267*6000Sroot register int f; 268*6000Sroot { 269*6000Sroot register int old; 270*6000Sroot struct sgttyb stbuf; 271*6000Sroot static int ttymode = 0; 272*6000Sroot int onoff; 273*6000Sroot 274*6000Sroot ioctl(fileno(stdin), TIOCGETP, &stbuf); 275*6000Sroot old = ttymode; 276*6000Sroot ttymode = f; 277*6000Sroot switch (f) { 278*6000Sroot case 0: 279*6000Sroot stbuf.sg_flags &= ~RAW; 280*6000Sroot stbuf.sg_flags |= ECHO|CRMOD; 281*6000Sroot onoff = 0; 282*6000Sroot break; 283*6000Sroot 284*6000Sroot case 1: 285*6000Sroot stbuf.sg_flags |= RAW; 286*6000Sroot stbuf.sg_flags &= ~(ECHO|CRMOD); 287*6000Sroot onoff = 1; 288*6000Sroot break; 289*6000Sroot 290*6000Sroot case 2: 291*6000Sroot stbuf.sg_flags |= RAW; 292*6000Sroot stbuf.sg_flags |= ECHO|CRMOD; 293*6000Sroot onoff = 1; 294*6000Sroot } 295*6000Sroot ioctl(fileno(stdin), TIOCSETN, &stbuf); 296*6000Sroot ioctl(fileno(stdin), FIONBIO, &onoff); 297*6000Sroot ioctl(fileno(stdout), FIONBIO, &onoff); 298*6000Sroot return (old); 299*6000Sroot } 300*6000Sroot 301*6000Sroot char sibuf[BUFSIZ], *sbp; 302*6000Sroot char tibuf[BUFSIZ], *tbp; 303*6000Sroot int scc, tcc; 304*6000Sroot 305*6000Sroot /* 306*6000Sroot * Select from tty and network... 307*6000Sroot */ 308*6000Sroot telnet(s) 309*6000Sroot int s; 310*6000Sroot { 311*6000Sroot register int c; 312*6000Sroot int tin = fileno(stdin), tout = fileno(stdout); 313*6000Sroot int on = 1; 314*6000Sroot 315*6000Sroot mode(1); 316*6000Sroot sprintf(nfrontp, doopt, TELOPT_ECHO); 317*6000Sroot nfrontp += sizeof(doopt) - 2; 318*6000Sroot sprintf(nfrontp, doopt, TELOPT_SGA); 319*6000Sroot nfrontp += sizeof(doopt) - 2; 320*6000Sroot sprintf(nfrontp, will, TELOPT_SGA); 321*6000Sroot nfrontp += sizeof(doopt) - 2; 322*6000Sroot ioctl(s, FIONBIO, &on); 323*6000Sroot for (;;) { 324*6000Sroot int ibits = 0, obits = 0; 325*6000Sroot 326*6000Sroot if (nfrontp - nbackp) 327*6000Sroot obits |= (1 << s); 328*6000Sroot else 329*6000Sroot ibits |= (1 << tin); 330*6000Sroot if (tfrontp - tbackp) 331*6000Sroot obits |= (1 << tout); 332*6000Sroot else 333*6000Sroot ibits |= (1 << s); 334*6000Sroot if (scc < 0 && tcc < 0) 335*6000Sroot break; 336*6000Sroot select(32, &ibits, &obits, INFINITY); 337*6000Sroot if (ibits == 0 && obits == 0) { 338*6000Sroot sleep(5); 339*6000Sroot continue; 340*6000Sroot } 341*6000Sroot 342*6000Sroot /* 343*6000Sroot * Something to read from the network... 344*6000Sroot */ 345*6000Sroot if (ibits & (1 << s)) { 346*6000Sroot scc = read(s, sibuf, sizeof(sibuf)); 347*6000Sroot if (scc < 0 && errno == EWOULDBLOCK) 348*6000Sroot scc = 0; 349*6000Sroot else { 350*6000Sroot if (scc <= 0) 351*6000Sroot break; 352*6000Sroot sbp = sibuf; 353*6000Sroot } 354*6000Sroot } 355*6000Sroot 356*6000Sroot /* 357*6000Sroot * Something to read from the tty... 358*6000Sroot */ 359*6000Sroot if (ibits & (1 << tin)) { 360*6000Sroot tcc = read(tin, tibuf, sizeof(tibuf)); 361*6000Sroot if (tcc < 0 && errno == EWOULDBLOCK) 362*6000Sroot tcc = 0; 363*6000Sroot else { 364*6000Sroot if (tcc <= 0) 365*6000Sroot break; 366*6000Sroot tbp = tibuf; 367*6000Sroot } 368*6000Sroot } 369*6000Sroot 370*6000Sroot while (tcc > 0) { 371*6000Sroot register int c; 372*6000Sroot 373*6000Sroot if ((&netobuf[BUFSIZ] - nfrontp) < 2) 374*6000Sroot break; 375*6000Sroot c = *tbp++ & 0377, tcc--; 376*6000Sroot if (strip(c) == escape) { 377*6000Sroot command(0); 378*6000Sroot tcc = 0; 379*6000Sroot break; 380*6000Sroot } 381*6000Sroot *nfrontp++ = c; 382*6000Sroot } 383*6000Sroot if ((obits & (1 << s)) && (nfrontp - nbackp) > 0) 384*6000Sroot netflush(s); 385*6000Sroot if (scc > 0) 386*6000Sroot telrcv(); 387*6000Sroot if ((obits & (1 << tout)) && (tfrontp - tbackp) > 0) 388*6000Sroot ttyflush(tout); 389*6000Sroot } 390*6000Sroot mode(0); 391*6000Sroot } 392*6000Sroot 393*6000Sroot command(top) 394*6000Sroot int top; 395*6000Sroot { 396*6000Sroot register struct cmd *c; 397*6000Sroot int oldmode, wasopen; 398*6000Sroot 399*6000Sroot oldmode = mode(0); 400*6000Sroot if (!top) 401*6000Sroot putchar('\n'); 402*6000Sroot else 403*6000Sroot sigset(SIGINT, SIG_DFL); 404*6000Sroot for (;;) { 405*6000Sroot printf("%s> ", prompt); 406*6000Sroot if (gets(line) == 0) 407*6000Sroot break; 408*6000Sroot if (line[0] == 0) 409*6000Sroot break; 410*6000Sroot makeargv(); 411*6000Sroot c = getcmd(margv[0]); 412*6000Sroot if (c == (struct cmd *)-1) { 413*6000Sroot printf("?Ambiguous command\n"); 414*6000Sroot continue; 415*6000Sroot } 416*6000Sroot if (c == 0) { 417*6000Sroot printf("?Invalid command\n"); 418*6000Sroot continue; 419*6000Sroot } 420*6000Sroot (*c->handler)(margc, margv); 421*6000Sroot if (c->handler != help) 422*6000Sroot break; 423*6000Sroot } 424*6000Sroot if (!top) { 425*6000Sroot if (!connected) 426*6000Sroot longjmp(toplevel, 1); 427*6000Sroot mode(oldmode); 428*6000Sroot } 429*6000Sroot } 430*6000Sroot 431*6000Sroot /* 432*6000Sroot * Telnet receiver states for fsm 433*6000Sroot */ 434*6000Sroot #define TS_DATA 0 435*6000Sroot #define TS_IAC 1 436*6000Sroot #define TS_WILL 2 437*6000Sroot #define TS_WONT 3 438*6000Sroot #define TS_DO 4 439*6000Sroot #define TS_DONT 5 440*6000Sroot 441*6000Sroot telrcv() 442*6000Sroot { 443*6000Sroot register int c; 444*6000Sroot static int state = TS_DATA; 445*6000Sroot 446*6000Sroot while (scc > 0) { 447*6000Sroot c = *sbp++ & 0377, scc--; 448*6000Sroot switch (state) { 449*6000Sroot 450*6000Sroot case TS_DATA: 451*6000Sroot if (c == IAC) 452*6000Sroot state = TS_IAC; 453*6000Sroot else 454*6000Sroot *tfrontp++ = c; 455*6000Sroot continue; 456*6000Sroot 457*6000Sroot case TS_IAC: 458*6000Sroot switch (c) { 459*6000Sroot 460*6000Sroot case WILL: 461*6000Sroot state = TS_WILL; 462*6000Sroot continue; 463*6000Sroot 464*6000Sroot case WONT: 465*6000Sroot state = TS_WONT; 466*6000Sroot continue; 467*6000Sroot 468*6000Sroot case DO: 469*6000Sroot state = TS_DO; 470*6000Sroot continue; 471*6000Sroot 472*6000Sroot case DONT: 473*6000Sroot state = TS_DONT; 474*6000Sroot continue; 475*6000Sroot 476*6000Sroot case DM: 477*6000Sroot ioctl(fileno(stdout), TIOCFLUSH, 0); 478*6000Sroot break; 479*6000Sroot 480*6000Sroot case NOP: 481*6000Sroot case GA: 482*6000Sroot break; 483*6000Sroot 484*6000Sroot default: 485*6000Sroot break; 486*6000Sroot } 487*6000Sroot state = TS_DATA; 488*6000Sroot continue; 489*6000Sroot 490*6000Sroot case TS_WILL: 491*6000Sroot if (!hisopts[c]) 492*6000Sroot willoption(c); 493*6000Sroot state = TS_DATA; 494*6000Sroot continue; 495*6000Sroot 496*6000Sroot case TS_WONT: 497*6000Sroot if (hisopts[c]) 498*6000Sroot wontoption(c); 499*6000Sroot state = TS_DATA; 500*6000Sroot continue; 501*6000Sroot 502*6000Sroot case TS_DO: 503*6000Sroot if (!myopts[c]) 504*6000Sroot dooption(c); 505*6000Sroot state = TS_DATA; 506*6000Sroot continue; 507*6000Sroot 508*6000Sroot case TS_DONT: 509*6000Sroot if (myopts[c]) { 510*6000Sroot myopts[c] = 0; 511*6000Sroot sprintf(nfrontp, wont, c); 512*6000Sroot nfrontp += sizeof(wont) - 2; 513*6000Sroot } 514*6000Sroot state = TS_DATA; 515*6000Sroot continue; 516*6000Sroot } 517*6000Sroot } 518*6000Sroot } 519*6000Sroot 520*6000Sroot willoption(option) 521*6000Sroot int option; 522*6000Sroot { 523*6000Sroot char *fmt; 524*6000Sroot 525*6000Sroot switch (option) { 526*6000Sroot 527*6000Sroot case TELOPT_ECHO: 528*6000Sroot mode(1); 529*6000Sroot 530*6000Sroot case TELOPT_SGA: 531*6000Sroot hisopts[option] = 1; 532*6000Sroot fmt = doopt; 533*6000Sroot break; 534*6000Sroot 535*6000Sroot case TELOPT_TM: 536*6000Sroot fmt = dont; 537*6000Sroot break; 538*6000Sroot 539*6000Sroot default: 540*6000Sroot fmt = dont; 541*6000Sroot break; 542*6000Sroot } 543*6000Sroot sprintf(nfrontp, dont, option); 544*6000Sroot nfrontp += sizeof(dont) - 2; 545*6000Sroot } 546*6000Sroot 547*6000Sroot wontoption(option) 548*6000Sroot int option; 549*6000Sroot { 550*6000Sroot char *fmt; 551*6000Sroot 552*6000Sroot switch (option) { 553*6000Sroot 554*6000Sroot case TELOPT_ECHO: 555*6000Sroot mode(2); 556*6000Sroot 557*6000Sroot case TELOPT_SGA: 558*6000Sroot hisopts[option] = 0; 559*6000Sroot fmt = dont; 560*6000Sroot break; 561*6000Sroot 562*6000Sroot default: 563*6000Sroot fmt = dont; 564*6000Sroot } 565*6000Sroot sprintf(nfrontp, fmt, option); 566*6000Sroot nfrontp += sizeof(doopt) - 2; 567*6000Sroot } 568*6000Sroot 569*6000Sroot dooption(option) 570*6000Sroot int option; 571*6000Sroot { 572*6000Sroot char *fmt; 573*6000Sroot 574*6000Sroot switch (option) { 575*6000Sroot 576*6000Sroot case TELOPT_TM: 577*6000Sroot fmt = wont; 578*6000Sroot break; 579*6000Sroot 580*6000Sroot case TELOPT_SGA: 581*6000Sroot fmt = will; 582*6000Sroot break; 583*6000Sroot 584*6000Sroot default: 585*6000Sroot fmt = wont; 586*6000Sroot break; 587*6000Sroot } 588*6000Sroot sprintf(nfrontp, fmt, option); 589*6000Sroot nfrontp += sizeof(doopt) - 2; 590*6000Sroot } 591*6000Sroot 592*6000Sroot /* 593*6000Sroot * Set the escape character. 594*6000Sroot */ 595*6000Sroot setescape(argc, argv) 596*6000Sroot int argc; 597*6000Sroot char *argv[]; 598*6000Sroot { 599*6000Sroot register char *arg; 600*6000Sroot char buf[50]; 601*6000Sroot 602*6000Sroot if (argc > 2) 603*6000Sroot arg = argv[1]; 604*6000Sroot else { 605*6000Sroot printf("new escape character: "); 606*6000Sroot gets(buf); 607*6000Sroot arg = buf; 608*6000Sroot } 609*6000Sroot if (arg[0] != '\0') 610*6000Sroot escape = arg[0]; 611*6000Sroot printf("Escape character is '%s'.\n", control(escape)); 612*6000Sroot } 613*6000Sroot 614*6000Sroot /* 615*6000Sroot * Construct a control character sequence 616*6000Sroot * for a special character. 617*6000Sroot */ 618*6000Sroot char * 619*6000Sroot control(c) 620*6000Sroot register int c; 621*6000Sroot { 622*6000Sroot static char buf[3]; 623*6000Sroot 624*6000Sroot if (c == 0177) 625*6000Sroot return ("^?"); 626*6000Sroot if (c >= 040) { 627*6000Sroot buf[0] = c; 628*6000Sroot buf[1] = 0; 629*6000Sroot } else { 630*6000Sroot buf[0] = '^'; 631*6000Sroot buf[1] = '@'+c; 632*6000Sroot buf[2] = 0; 633*6000Sroot } 634*6000Sroot return (buf); 635*6000Sroot } 636*6000Sroot 637*6000Sroot struct cmd * 638*6000Sroot getcmd(name) 639*6000Sroot register char *name; 640*6000Sroot { 641*6000Sroot register char *p, *q; 642*6000Sroot register struct cmd *c, *found; 643*6000Sroot register int nmatches, longest; 644*6000Sroot 645*6000Sroot longest = 0; 646*6000Sroot nmatches = 0; 647*6000Sroot found = 0; 648*6000Sroot for (c = cmdtab; p = c->name; c++) { 649*6000Sroot for (q = name; *q == *p++; q++) 650*6000Sroot if (*q == 0) /* exact match? */ 651*6000Sroot return (c); 652*6000Sroot if (!*q) { /* the name was a prefix */ 653*6000Sroot if (q - name > longest) { 654*6000Sroot longest = q - name; 655*6000Sroot nmatches = 1; 656*6000Sroot found = c; 657*6000Sroot } else if (q - name == longest) 658*6000Sroot nmatches++; 659*6000Sroot } 660*6000Sroot } 661*6000Sroot if (nmatches > 1) 662*6000Sroot return ((struct cmd *)-1); 663*6000Sroot return (found); 664*6000Sroot } 665*6000Sroot 666*6000Sroot deadpeer() 667*6000Sroot { 668*6000Sroot sigset(SIGPIPE, deadpeer); 669*6000Sroot mode(0); 670*6000Sroot longjmp(peerdied, -1); 671*6000Sroot } 672*6000Sroot 673*6000Sroot intr() 674*6000Sroot { 675*6000Sroot sigset(SIGINT, intr); 676*6000Sroot mode(0); 677*6000Sroot longjmp(toplevel, -1); 678*6000Sroot } 679*6000Sroot 680*6000Sroot ttyflush(fd) 681*6000Sroot { 682*6000Sroot int n; 683*6000Sroot 684*6000Sroot if ((n = tfrontp - tbackp) > 0) 685*6000Sroot n = write(fd, tbackp, n); 686*6000Sroot if (n < 0 && errno == EWOULDBLOCK) 687*6000Sroot n = 0; 688*6000Sroot tbackp += n; 689*6000Sroot if (tbackp == tfrontp) 690*6000Sroot tbackp = tfrontp = ttyobuf; 691*6000Sroot } 692*6000Sroot 693*6000Sroot netflush(fd) 694*6000Sroot { 695*6000Sroot int n; 696*6000Sroot 697*6000Sroot if ((n = nfrontp - nbackp) > 0) 698*6000Sroot n = write(fd, nbackp, n); 699*6000Sroot if (n < 0 && errno == EWOULDBLOCK) 700*6000Sroot n = 0; 701*6000Sroot nbackp += n; 702*6000Sroot if (nbackp == nfrontp) 703*6000Sroot nbackp = nfrontp = netobuf; 704*6000Sroot } 705