telnetd.c revision 69387
1/* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34#ifndef lint 35static const char copyright[] = 36"@(#) Copyright (c) 1989, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38#endif /* not lint */ 39 40#ifndef lint 41#if 0 42static const char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; 43#endif 44static const char rcsid[] = 45 "$FreeBSD: head/contrib/telnet/telnetd/telnetd.c 69387 2000-11-30 13:10:01Z asmodai $"; 46#endif /* not lint */ 47 48#include "telnetd.h" 49#include "pathnames.h" 50 51#if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) 52/* 53 * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can 54 * use it to tell us to turn off all the socket security code, 55 * since that is only used in UNICOS 7.0 and later. 56 */ 57# undef _SC_CRAY_SECURE_SYS 58#endif 59 60#include <err.h> 61#include <arpa/inet.h> 62 63#include <libutil.h> 64#include <utmp.h> 65 66#if defined(_SC_CRAY_SECURE_SYS) 67#include <sys/sysv.h> 68#include <sys/secdev.h> 69# ifdef SO_SEC_MULTI /* 8.0 code */ 70#include <sys/secparm.h> 71#include <sys/usrv.h> 72# endif /* SO_SEC_MULTI */ 73 74/* wrapper for KAME-special getnameinfo() */ 75#ifndef NI_WITHSCOPEID 76#define NI_WITHSCOPEID 0 77#endif 78 79int secflag; 80char tty_dev[16]; 81struct secdev dv; 82struct sysv sysv; 83# ifdef SO_SEC_MULTI /* 8.0 code */ 84struct socksec ss; 85# else /* SO_SEC_MULTI */ /* 7.0 code */ 86struct socket_security ss; 87# endif /* SO_SEC_MULTI */ 88#endif /* _SC_CRAY_SECURE_SYS */ 89 90#if defined(AUTHENTICATION) 91#include <libtelnet/auth.h> 92int auth_level = 0; 93#endif 94#if defined(ENCRYPTION) 95#include <libtelnet/encrypt.h> 96#endif 97#include <libtelnet/misc.h> 98#if defined(SecurID) 99int require_SecurID = 0; 100#endif 101 102char remote_hostname[MAXHOSTNAMELEN]; 103int utmp_len = sizeof(remote_hostname) - 1; 104int registerd_host_only = 0; 105 106#ifdef STREAMSPTY 107# include <stropts.h> 108# include <termio.h> 109/* make sure we don't get the bsd version */ 110# include "/usr/include/sys/tty.h" 111# include <sys/ptyvar.h> 112 113/* 114 * Because of the way ptyibuf is used with streams messages, we need 115 * ptyibuf+1 to be on a full-word boundary. The following wierdness 116 * is simply to make that happen. 117 */ 118long ptyibufbuf[BUFSIZ/sizeof(long)+1]; 119char *ptyibuf = ((char *)&ptyibufbuf[1])-1; 120char *ptyip = ((char *)&ptyibufbuf[1])-1; 121char ptyibuf2[BUFSIZ]; 122unsigned char ctlbuf[BUFSIZ]; 123struct strbuf strbufc, strbufd; 124 125#else /* ! STREAMPTY */ 126 127/* 128 * I/O data buffers, 129 * pointers, and counters. 130 */ 131char ptyibuf[BUFSIZ], *ptyip = ptyibuf; 132char ptyibuf2[BUFSIZ]; 133 134# include <termcap.h> 135 136int readstream(int p, char *ibuf, int bufsize); 137void doit(struct sockaddr *who); 138int terminaltypeok(char *s); 139void startslave(char *host, int autologin, char *autoname); 140 141#endif /* ! STREAMPTY */ 142 143int hostinfo = 1; /* do we print login banner? */ 144 145#ifdef CRAY 146extern int newmap; /* nonzero if \n maps to ^M^J */ 147int lowpty = 0, highpty; /* low, high pty numbers */ 148#endif /* CRAY */ 149 150int debug = 0; 151int keepalive = 1; 152char *altlogin; 153 154void doit __P((struct sockaddr *)); 155int terminaltypeok __P((char *)); 156void startslave __P((char *, int, char *)); 157extern void usage P((void)); 158 159/* 160 * The string to pass to getopt(). We do it this way so 161 * that only the actual options that we support will be 162 * passed off to getopt(). 163 */ 164char valid_opts[] = { 165 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', 166 '4', '6', 167#ifdef AUTHENTICATION 168 'a', ':', 'X', ':', 169#endif 170#ifdef BFTPDAEMON 171 'B', 172#endif 173#ifdef DIAGNOSTICS 174 'D', ':', 175#endif 176#ifdef ENCRYPTION 177 'e', ':', 178#endif 179#if defined(CRAY) && defined(NEWINIT) 180 'I', ':', 181#endif 182#ifdef LINEMODE 183 'l', 184#endif 185#ifdef CRAY 186 'r', ':', 187#endif 188#ifdef SecurID 189 's', 190#endif 191 '\0' 192}; 193 194int family = AF_INET; 195 196int 197main(argc, argv) 198 char *argv[]; 199{ 200 struct sockaddr_storage from; 201 int on = 1, fromlen; 202 register int ch; 203#if defined(IPPROTO_IP) && defined(IP_TOS) 204 int tos = -1; 205#endif 206 207 pfrontp = pbackp = ptyobuf; 208 netip = netibuf; 209 nfrontp = nbackp = netobuf; 210#ifdef ENCRYPTION 211 nclearto = 0; 212#endif /* ENCRYPTION */ 213 214 /* 215 * This initialization causes linemode to default to a configuration 216 * that works on all telnet clients, including the FreeBSD client. 217 * This is not quite the same as the telnet client issuing a "mode 218 * character" command, but has most of the same benefits, and is 219 * preferable since some clients (like usofts) don't have the 220 * mode character command anyway and linemode breaks things. 221 * The most notable symptom of fix is that csh "set filec" operations 222 * like <ESC> (filename completion) and ^D (choices) keys now work 223 * in telnet sessions and can be used more than once on the same line. 224 * CR/LF handling is also corrected in some termio modes. This 225 * change resolves problem reports bin/771 and bin/1037. 226 */ 227 228 linemode=1; /*Default to mode that works on bulk of clients*/ 229 230#ifdef CRAY 231 /* 232 * Get number of pty's before trying to process options, 233 * which may include changing pty range. 234 */ 235 highpty = getnpty(); 236#endif /* CRAY */ 237 238 while ((ch = getopt(argc, argv, valid_opts)) != -1) { 239 switch(ch) { 240 241#ifdef AUTHENTICATION 242 case 'a': 243 /* 244 * Check for required authentication level 245 */ 246 if (strcmp(optarg, "debug") == 0) { 247 extern int auth_debug_mode; 248 auth_debug_mode = 1; 249 } else if (strcasecmp(optarg, "none") == 0) { 250 auth_level = 0; 251 } else if (strcasecmp(optarg, "other") == 0) { 252 auth_level = AUTH_OTHER; 253 } else if (strcasecmp(optarg, "user") == 0) { 254 auth_level = AUTH_USER; 255 } else if (strcasecmp(optarg, "valid") == 0) { 256 auth_level = AUTH_VALID; 257 } else if (strcasecmp(optarg, "off") == 0) { 258 /* 259 * This hack turns off authentication 260 */ 261 auth_level = -1; 262 } else { 263 warnx("unknown authorization level for -a"); 264 } 265 break; 266#endif /* AUTHENTICATION */ 267 268#ifdef BFTPDAEMON 269 case 'B': 270 bftpd++; 271 break; 272#endif /* BFTPDAEMON */ 273 274 case 'd': 275 if (strcmp(optarg, "ebug") == 0) { 276 debug++; 277 break; 278 } 279 usage(); 280 /* NOTREACHED */ 281 break; 282 283#ifdef DIAGNOSTICS 284 case 'D': 285 /* 286 * Check for desired diagnostics capabilities. 287 */ 288 if (!strcmp(optarg, "report")) { 289 diagnostic |= TD_REPORT|TD_OPTIONS; 290 } else if (!strcmp(optarg, "exercise")) { 291 diagnostic |= TD_EXERCISE; 292 } else if (!strcmp(optarg, "netdata")) { 293 diagnostic |= TD_NETDATA; 294 } else if (!strcmp(optarg, "ptydata")) { 295 diagnostic |= TD_PTYDATA; 296 } else if (!strcmp(optarg, "options")) { 297 diagnostic |= TD_OPTIONS; 298 } else { 299 usage(); 300 /* NOT REACHED */ 301 } 302 break; 303#endif /* DIAGNOSTICS */ 304 305#ifdef ENCRYPTION 306 case 'e': 307 if (strcmp(optarg, "debug") == 0) { 308 extern int encrypt_debug_mode; 309 encrypt_debug_mode = 1; 310 break; 311 } 312 usage(); 313 /* NOTREACHED */ 314 break; 315#endif /* ENCRYPTION */ 316 317 case 'h': 318 hostinfo = 0; 319 break; 320 321#if defined(CRAY) && defined(NEWINIT) 322 case 'I': 323 { 324 extern char *gen_id; 325 gen_id = optarg; 326 break; 327 } 328#endif /* defined(CRAY) && defined(NEWINIT) */ 329 330#ifdef LINEMODE 331 case 'l': 332 alwayslinemode = 1; 333 break; 334#endif /* LINEMODE */ 335 336 case 'k': 337#if defined(LINEMODE) && defined(KLUDGELINEMODE) 338 lmodetype = NO_AUTOKLUDGE; 339#else 340 /* ignore -k option if built without kludge linemode */ 341#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 342 break; 343 344 case 'n': 345 keepalive = 0; 346 break; 347 348 case 'p': 349 altlogin = optarg; 350 break; 351 352#ifdef CRAY 353 case 'r': 354 { 355 char *strchr(); 356 char *c; 357 358 /* 359 * Allow the specification of alterations 360 * to the pty search range. It is legal to 361 * specify only one, and not change the 362 * other from its default. 363 */ 364 c = strchr(optarg, '-'); 365 if (c) { 366 *c++ = '\0'; 367 highpty = atoi(c); 368 } 369 if (*optarg != '\0') 370 lowpty = atoi(optarg); 371 if ((lowpty > highpty) || (lowpty < 0) || 372 (highpty > 32767)) { 373 usage(); 374 /* NOT REACHED */ 375 } 376 break; 377 } 378#endif /* CRAY */ 379 380#ifdef SecurID 381 case 's': 382 /* SecurID required */ 383 require_SecurID = 1; 384 break; 385#endif /* SecurID */ 386 case 'S': 387#ifdef HAS_GETTOS 388 if ((tos = parsetos(optarg, "tcp")) < 0) 389 warnx("%s%s%s", 390 "bad TOS argument '", optarg, 391 "'; will try to use default TOS"); 392#else 393 warnx("TOS option unavailable; -S flag not supported"); 394#endif 395 break; 396 397 case 'u': 398 utmp_len = atoi(optarg); 399 if (utmp_len < 0) 400 utmp_len = -utmp_len; 401 if (utmp_len >= sizeof(remote_hostname)) 402 utmp_len = sizeof(remote_hostname) - 1; 403 break; 404 405 case 'U': 406 registerd_host_only = 1; 407 break; 408 409#ifdef AUTHENTICATION 410 case 'X': 411 /* 412 * Check for invalid authentication types 413 */ 414 auth_disable_name(optarg); 415 break; 416#endif /* AUTHENTICATION */ 417 418 case '4': 419 family = AF_INET; 420 break; 421 422#ifdef INET6 423 case '6': 424 family = AF_INET6; 425 break; 426#endif 427 428 default: 429 warnx("%c: unknown option", ch); 430 /* FALLTHROUGH */ 431 case '?': 432 usage(); 433 /* NOTREACHED */ 434 } 435 } 436 437 argc -= optind; 438 argv += optind; 439 440 if (debug) { 441 int s, ns, foo, error; 442 char *service = "telnet"; 443 struct addrinfo hints, *res; 444 445 if (argc > 1) { 446 usage(); 447 /* NOT REACHED */ 448 } else if (argc == 1) 449 service = *argv; 450 451 memset(&hints, 0, sizeof(hints)); 452 hints.ai_flags = AI_PASSIVE; 453 hints.ai_family = family; 454 hints.ai_socktype = SOCK_STREAM; 455 hints.ai_protocol = 0; 456 error = getaddrinfo(NULL, service, &hints, &res); 457 458 if (error) { 459 errx(1, "tcp/%s: %s\n", service, gai_strerror(error)); 460 if (error == EAI_SYSTEM) 461 errx(1, "tcp/%s: %s\n", service, strerror(errno)); 462 usage(); 463 } 464 465 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); 466 if (s < 0) 467 err(1, "socket"); 468 (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 469 (char *)&on, sizeof(on)); 470 if (bind(s, res->ai_addr, res->ai_addrlen) < 0) 471 err(1, "bind"); 472 if (listen(s, 1) < 0) 473 err(1, "listen"); 474 foo = res->ai_addrlen; 475 ns = accept(s, res->ai_addr, &foo); 476 if (ns < 0) 477 err(1, "accept"); 478 (void) dup2(ns, 0); 479 (void) close(ns); 480 (void) close(s); 481#ifdef convex 482 } else if (argc == 1) { 483 ; /* VOID*/ /* Just ignore the host/port name */ 484#endif 485 } else if (argc > 0) { 486 usage(); 487 /* NOT REACHED */ 488 } 489 490#if defined(_SC_CRAY_SECURE_SYS) 491 secflag = sysconf(_SC_CRAY_SECURE_SYS); 492 493 /* 494 * Get socket's security label 495 */ 496 if (secflag) { 497 int szss = sizeof(ss); 498#ifdef SO_SEC_MULTI /* 8.0 code */ 499 int sock_multi; 500 int szi = sizeof(int); 501#endif /* SO_SEC_MULTI */ 502 503 memset((char *)&dv, 0, sizeof(dv)); 504 505 if (getsysv(&sysv, sizeof(struct sysv)) != 0) 506 err(1, "getsysv"); 507 508 /* 509 * Get socket security label and set device values 510 * {security label to be set on ttyp device} 511 */ 512#ifdef SO_SEC_MULTI /* 8.0 code */ 513 if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, 514 (char *)&ss, &szss) < 0) || 515 (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, 516 (char *)&sock_multi, &szi) < 0)) { 517 err(1, "getsockopt"); 518 } else { 519 dv.dv_actlvl = ss.ss_actlabel.lt_level; 520 dv.dv_actcmp = ss.ss_actlabel.lt_compart; 521 if (!sock_multi) { 522 dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; 523 dv.dv_valcmp = dv.dv_actcmp; 524 } else { 525 dv.dv_minlvl = ss.ss_minlabel.lt_level; 526 dv.dv_maxlvl = ss.ss_maxlabel.lt_level; 527 dv.dv_valcmp = ss.ss_maxlabel.lt_compart; 528 } 529 dv.dv_devflg = 0; 530 } 531#else /* SO_SEC_MULTI */ /* 7.0 code */ 532 if (getsockopt(0, SOL_SOCKET, SO_SECURITY, 533 (char *)&ss, &szss) >= 0) { 534 dv.dv_actlvl = ss.ss_slevel; 535 dv.dv_actcmp = ss.ss_compart; 536 dv.dv_minlvl = ss.ss_minlvl; 537 dv.dv_maxlvl = ss.ss_maxlvl; 538 dv.dv_valcmp = ss.ss_maxcmp; 539 } 540#endif /* SO_SEC_MULTI */ 541 } 542#endif /* _SC_CRAY_SECURE_SYS */ 543 544 openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); 545 fromlen = sizeof (from); 546 if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { 547 warn("getpeername"); 548 _exit(1); 549 } 550 if (keepalive && 551 setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, 552 (char *)&on, sizeof (on)) < 0) { 553 syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); 554 } 555 556#if defined(IPPROTO_IP) && defined(IP_TOS) 557 if (from.ss_family == AF_INET) { 558# if defined(HAS_GETTOS) 559 struct tosent *tp; 560 if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) 561 tos = tp->t_tos; 562# endif 563 if (tos < 0) 564 tos = 020; /* Low Delay bit */ 565 if (tos 566 && (setsockopt(0, IPPROTO_IP, IP_TOS, 567 (char *)&tos, sizeof(tos)) < 0) 568 && (errno != ENOPROTOOPT) ) 569 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 570 } 571#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ 572 net = 0; 573 doit((struct sockaddr *)&from); 574 /* NOTREACHED */ 575 return(0); 576} /* end of main */ 577 578 void 579usage() 580{ 581 fprintf(stderr, "usage: telnetd"); 582#ifdef AUTHENTICATION 583 fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); 584#endif 585#ifdef BFTPDAEMON 586 fprintf(stderr, " [-B]"); 587#endif 588 fprintf(stderr, " [-debug]"); 589#ifdef DIAGNOSTICS 590 fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); 591#endif 592#ifdef AUTHENTICATION 593 fprintf(stderr, " [-edebug]"); 594#endif 595 fprintf(stderr, " [-h]"); 596#if defined(CRAY) && defined(NEWINIT) 597 fprintf(stderr, " [-Iinitid]"); 598#endif 599#if defined(LINEMODE) && defined(KLUDGELINEMODE) 600 fprintf(stderr, " [-k]"); 601#endif 602#ifdef LINEMODE 603 fprintf(stderr, " [-l]"); 604#endif 605 fprintf(stderr, " [-n]"); 606#ifdef CRAY 607 fprintf(stderr, " [-r[lowpty]-[highpty]]"); 608#endif 609 fprintf(stderr, "\n\t"); 610#ifdef SecurID 611 fprintf(stderr, " [-s]"); 612#endif 613#ifdef HAS_GETTOS 614 fprintf(stderr, " [-S tos]"); 615#endif 616#ifdef AUTHENTICATION 617 fprintf(stderr, " [-X auth-type]"); 618#endif 619 fprintf(stderr, " [-u utmp_hostname_length] [-U]"); 620 fprintf(stderr, " [port]\n"); 621 exit(1); 622} 623 624/* 625 * getterminaltype 626 * 627 * Ask the other end to send along its terminal type and speed. 628 * Output is the variable terminaltype filled in. 629 */ 630static unsigned char ttytype_sbbuf[] = { 631 IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE 632}; 633 634 int 635getterminaltype(name) 636 char *name; 637{ 638 int retval = -1; 639 void _gettermname(); 640 641 settimer(baseline); 642#if defined(AUTHENTICATION) 643 /* 644 * Handle the Authentication option before we do anything else. 645 */ 646 send_do(TELOPT_AUTHENTICATION, 1); 647 while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) 648 ttloop(); 649 if (his_state_is_will(TELOPT_AUTHENTICATION)) { 650 retval = auth_wait(name); 651 } 652#endif 653 654#ifdef ENCRYPTION 655 send_will(TELOPT_ENCRYPT, 1); 656#endif /* ENCRYPTION */ 657 send_do(TELOPT_TTYPE, 1); 658 send_do(TELOPT_TSPEED, 1); 659 send_do(TELOPT_XDISPLOC, 1); 660 send_do(TELOPT_NEW_ENVIRON, 1); 661 send_do(TELOPT_OLD_ENVIRON, 1); 662 while ( 663#ifdef ENCRYPTION 664 his_do_dont_is_changing(TELOPT_ENCRYPT) || 665#endif /* ENCRYPTION */ 666 his_will_wont_is_changing(TELOPT_TTYPE) || 667 his_will_wont_is_changing(TELOPT_TSPEED) || 668 his_will_wont_is_changing(TELOPT_XDISPLOC) || 669 his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || 670 his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { 671 ttloop(); 672 } 673#ifdef ENCRYPTION 674 /* 675 * Wait for the negotiation of what type of encryption we can 676 * send with. If autoencrypt is not set, this will just return. 677 */ 678 if (his_state_is_will(TELOPT_ENCRYPT)) { 679 encrypt_wait(); 680 } 681#endif /* ENCRYPTION */ 682 if (his_state_is_will(TELOPT_TSPEED)) { 683 static unsigned char sb[] = 684 { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; 685 686 memmove(nfrontp, sb, sizeof sb); 687 nfrontp += sizeof sb; 688 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 689 } 690 if (his_state_is_will(TELOPT_XDISPLOC)) { 691 static unsigned char sb[] = 692 { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; 693 694 memmove(nfrontp, sb, sizeof sb); 695 nfrontp += sizeof sb; 696 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 697 } 698 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 699 static unsigned char sb[] = 700 { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; 701 702 memmove(nfrontp, sb, sizeof sb); 703 nfrontp += sizeof sb; 704 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 705 } 706 else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 707 static unsigned char sb[] = 708 { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; 709 710 memmove(nfrontp, sb, sizeof sb); 711 nfrontp += sizeof sb; 712 DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); 713 } 714 if (his_state_is_will(TELOPT_TTYPE)) { 715 716 memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); 717 nfrontp += sizeof ttytype_sbbuf; 718 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 719 sizeof ttytype_sbbuf - 2);); 720 } 721 if (his_state_is_will(TELOPT_TSPEED)) { 722 while (sequenceIs(tspeedsubopt, baseline)) 723 ttloop(); 724 } 725 if (his_state_is_will(TELOPT_XDISPLOC)) { 726 while (sequenceIs(xdisplocsubopt, baseline)) 727 ttloop(); 728 } 729 if (his_state_is_will(TELOPT_NEW_ENVIRON)) { 730 while (sequenceIs(environsubopt, baseline)) 731 ttloop(); 732 } 733 if (his_state_is_will(TELOPT_OLD_ENVIRON)) { 734 while (sequenceIs(oenvironsubopt, baseline)) 735 ttloop(); 736 } 737 if (his_state_is_will(TELOPT_TTYPE)) { 738 char first[256], last[256]; 739 740 while (sequenceIs(ttypesubopt, baseline)) 741 ttloop(); 742 743 /* 744 * If the other side has already disabled the option, then 745 * we have to just go with what we (might) have already gotten. 746 */ 747 if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { 748 (void) strncpy(first, terminaltype, sizeof(first)-1); 749 first[sizeof(first)-1] = '\0'; 750 for(;;) { 751 /* 752 * Save the unknown name, and request the next name. 753 */ 754 (void) strncpy(last, terminaltype, sizeof(last)-1); 755 last[sizeof(last)-1] = '\0'; 756 _gettermname(); 757 if (terminaltypeok(terminaltype)) 758 break; 759 if ((strncmp(last, terminaltype, sizeof(last)) == 0) || 760 his_state_is_wont(TELOPT_TTYPE)) { 761 /* 762 * We've hit the end. If this is the same as 763 * the first name, just go with it. 764 */ 765 if (strncmp(first, terminaltype, sizeof(first)) == 0) 766 break; 767 /* 768 * Get the terminal name one more time, so that 769 * RFC1091 compliant telnets will cycle back to 770 * the start of the list. 771 */ 772 _gettermname(); 773 if (strncmp(first, terminaltype, sizeof(first)) != 0) { 774 (void) strncpy(terminaltype, first, sizeof(terminaltype)-1); 775 terminaltype[sizeof(terminaltype)-1] = '\0'; 776 } 777 break; 778 } 779 } 780 } 781 } 782 return(retval); 783} /* end of getterminaltype */ 784 785 void 786_gettermname() 787{ 788 /* 789 * If the client turned off the option, 790 * we can't send another request, so we 791 * just return. 792 */ 793 if (his_state_is_wont(TELOPT_TTYPE)) 794 return; 795 settimer(baseline); 796 memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); 797 nfrontp += sizeof ttytype_sbbuf; 798 DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, 799 sizeof ttytype_sbbuf - 2);); 800 while (sequenceIs(ttypesubopt, baseline)) 801 ttloop(); 802} 803 804 int 805terminaltypeok(s) 806 char *s; 807{ 808 char buf[1024]; 809 810 if (terminaltype == NULL) 811 return(1); 812 813 /* 814 * tgetent() will return 1 if the type is known, and 815 * 0 if it is not known. If it returns -1, it couldn't 816 * open the database. But if we can't open the database, 817 * it won't help to say we failed, because we won't be 818 * able to verify anything else. So, we treat -1 like 1. 819 */ 820 if (tgetent(buf, s) == 0) 821 return(0); 822 return(1); 823} 824 825#ifndef MAXHOSTNAMELEN 826#define MAXHOSTNAMELEN 256 827#endif /* MAXHOSTNAMELEN */ 828 829char *hostname; 830char host_name[MAXHOSTNAMELEN]; 831 832extern void telnet P((int, int, char *)); 833 834int level; 835char user_name[256]; 836/* 837 * Get a pty, scan input lines. 838 */ 839 void 840doit(who) 841 struct sockaddr *who; 842{ 843 int err; 844 int ptynum; 845 846 /* 847 * Find an available pty to use. 848 */ 849#ifndef convex 850 pty = getpty(&ptynum); 851 if (pty < 0) 852 fatal(net, "All network ports in use"); 853#else 854 for (;;) { 855 char *lp; 856 extern char *line, *getpty(); 857 858 if ((lp = getpty()) == NULL) 859 fatal(net, "Out of ptys"); 860 861 if ((pty = open(lp, 2)) >= 0) { 862 strlcpy(line,lp,sizeof(line)); 863 line[5] = 't'; 864 break; 865 } 866 } 867#endif 868 869#if defined(_SC_CRAY_SECURE_SYS) 870 /* 871 * set ttyp line security label 872 */ 873 if (secflag) { 874 char slave_dev[16]; 875 876 sprintf(tty_dev, "/dev/pty/%03d", ptynum); 877 if (setdevs(tty_dev, &dv) < 0) 878 fatal(net, "cannot set pty security"); 879 sprintf(slave_dev, "/dev/ttyp%03d", ptynum); 880 if (setdevs(slave_dev, &dv) < 0) 881 fatal(net, "cannot set tty security"); 882 } 883#endif /* _SC_CRAY_SECURE_SYS */ 884 885 /* get name of connected client */ 886 if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1, 887 who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only) 888 fatal(net, "Couldn't resolve your address into a host name.\r\n\ 889 Please contact your net administrator"); 890 remote_hostname[sizeof(remote_hostname) - 1] = '\0'; 891 892 trimdomain(remote_hostname, UT_HOSTSIZE); 893 if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len) 894 err = getnameinfo(who, who->sa_len, remote_hostname, 895 sizeof(remote_hostname), NULL, 0, 896 NI_NUMERICHOST|NI_WITHSCOPEID); 897 /* XXX: do 'err' check */ 898 899 (void) gethostname(host_name, sizeof(host_name) - 1); 900 host_name[sizeof(host_name) - 1] = '\0'; 901 hostname = host_name; 902 903#if defined(AUTHENTICATION) || defined(ENCRYPTION) 904 auth_encrypt_init(hostname, remote_hostname, "TELNETD", 1); 905#endif 906 907 init_env(); 908 /* 909 * get terminal type. 910 */ 911 *user_name = 0; 912 level = getterminaltype(user_name); 913 setenv("TERM", terminaltype ? terminaltype : "network", 1); 914 915#if defined(_SC_CRAY_SECURE_SYS) 916 if (secflag) { 917 if (setulvl(dv.dv_actlvl) < 0) 918 fatal(net,"cannot setulvl()"); 919 if (setucmp(dv.dv_actcmp) < 0) 920 fatal(net, "cannot setucmp()"); 921 } 922#endif /* _SC_CRAY_SECURE_SYS */ 923 924 telnet(net, pty, remote_hostname); /* begin server process */ 925 926 /*NOTREACHED*/ 927} /* end of doit */ 928 929#if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) 930 int 931Xterm_output(ibufp, obuf, icountp, ocount) 932 char **ibufp, *obuf; 933 int *icountp, ocount; 934{ 935 int ret; 936 ret = term_output(*ibufp, obuf, *icountp, ocount); 937 *ibufp += *icountp; 938 *icountp = 0; 939 return(ret); 940} 941#define term_output Xterm_output 942#endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */ 943 944/* 945 * Main loop. Select from pty and network, and 946 * hand data to telnet receiver finite state machine. 947 */ 948 void 949telnet(f, p, host) 950 int f, p; 951 char *host; 952{ 953 int on = 1; 954#define TABBUFSIZ 512 955 char defent[TABBUFSIZ]; 956 char defstrs[TABBUFSIZ]; 957#undef TABBUFSIZ 958 char *HE; 959 char *HN; 960 char *IM; 961 void netflush(); 962 int nfd; 963 964 /* 965 * Initialize the slc mapping table. 966 */ 967 get_slc_defaults(); 968 969 /* 970 * Do some tests where it is desireable to wait for a response. 971 * Rather than doing them slowly, one at a time, do them all 972 * at once. 973 */ 974 if (my_state_is_wont(TELOPT_SGA)) 975 send_will(TELOPT_SGA, 1); 976 /* 977 * Is the client side a 4.2 (NOT 4.3) system? We need to know this 978 * because 4.2 clients are unable to deal with TCP urgent data. 979 * 980 * To find out, we send out a "DO ECHO". If the remote system 981 * answers "WILL ECHO" it is probably a 4.2 client, and we note 982 * that fact ("WILL ECHO" ==> that the client will echo what 983 * WE, the server, sends it; it does NOT mean that the client will 984 * echo the terminal input). 985 */ 986 send_do(TELOPT_ECHO, 1); 987 988#ifdef LINEMODE 989 if (his_state_is_wont(TELOPT_LINEMODE)) { 990 /* Query the peer for linemode support by trying to negotiate 991 * the linemode option. 992 */ 993 linemode = 0; 994 editmode = 0; 995 send_do(TELOPT_LINEMODE, 1); /* send do linemode */ 996 } 997#endif /* LINEMODE */ 998 999 /* 1000 * Send along a couple of other options that we wish to negotiate. 1001 */ 1002 send_do(TELOPT_NAWS, 1); 1003 send_will(TELOPT_STATUS, 1); 1004 flowmode = 1; /* default flow control state */ 1005 restartany = -1; /* uninitialized... */ 1006 send_do(TELOPT_LFLOW, 1); 1007 1008 /* 1009 * Spin, waiting for a response from the DO ECHO. However, 1010 * some REALLY DUMB telnets out there might not respond 1011 * to the DO ECHO. So, we spin looking for NAWS, (most dumb 1012 * telnets so far seem to respond with WONT for a DO that 1013 * they don't understand...) because by the time we get the 1014 * response, it will already have processed the DO ECHO. 1015 * Kludge upon kludge. 1016 */ 1017 while (his_will_wont_is_changing(TELOPT_NAWS)) 1018 ttloop(); 1019 1020 /* 1021 * But... 1022 * The client might have sent a WILL NAWS as part of its 1023 * startup code; if so, we'll be here before we get the 1024 * response to the DO ECHO. We'll make the assumption 1025 * that any implementation that understands about NAWS 1026 * is a modern enough implementation that it will respond 1027 * to our DO ECHO request; hence we'll do another spin 1028 * waiting for the ECHO option to settle down, which is 1029 * what we wanted to do in the first place... 1030 */ 1031 if (his_want_state_is_will(TELOPT_ECHO) && 1032 his_state_is_will(TELOPT_NAWS)) { 1033 while (his_will_wont_is_changing(TELOPT_ECHO)) 1034 ttloop(); 1035 } 1036 /* 1037 * On the off chance that the telnet client is broken and does not 1038 * respond to the DO ECHO we sent, (after all, we did send the 1039 * DO NAWS negotiation after the DO ECHO, and we won't get here 1040 * until a response to the DO NAWS comes back) simulate the 1041 * receipt of a will echo. This will also send a WONT ECHO 1042 * to the client, since we assume that the client failed to 1043 * respond because it believes that it is already in DO ECHO 1044 * mode, which we do not want. 1045 */ 1046 if (his_want_state_is_will(TELOPT_ECHO)) { 1047 DIAG(TD_OPTIONS, 1048 {sprintf(nfrontp, "td: simulating recv\r\n"); 1049 nfrontp += strlen(nfrontp);}); 1050 willoption(TELOPT_ECHO); 1051 } 1052 1053 /* 1054 * Finally, to clean things up, we turn on our echo. This 1055 * will break stupid 4.2 telnets out of local terminal echo. 1056 */ 1057 1058 if (my_state_is_wont(TELOPT_ECHO)) 1059 send_will(TELOPT_ECHO, 1); 1060 1061#ifndef STREAMSPTY 1062 /* 1063 * Turn on packet mode 1064 */ 1065 (void) ioctl(p, TIOCPKT, (char *)&on); 1066#endif 1067 1068#if defined(LINEMODE) && defined(KLUDGELINEMODE) 1069 /* 1070 * Continuing line mode support. If client does not support 1071 * real linemode, attempt to negotiate kludge linemode by sending 1072 * the do timing mark sequence. 1073 */ 1074 if (lmodetype < REAL_LINEMODE) 1075 send_do(TELOPT_TM, 1); 1076#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ 1077 1078 /* 1079 * Call telrcv() once to pick up anything received during 1080 * terminal type negotiation, 4.2/4.3 determination, and 1081 * linemode negotiation. 1082 */ 1083 telrcv(); 1084 1085 (void) ioctl(f, FIONBIO, (char *)&on); 1086 (void) ioctl(p, FIONBIO, (char *)&on); 1087#if defined(CRAY2) && defined(UNICOS5) 1088 init_termdriver(f, p, interrupt, sendbrk); 1089#endif 1090 1091#if defined(SO_OOBINLINE) 1092 (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, 1093 (char *)&on, sizeof on); 1094#endif /* defined(SO_OOBINLINE) */ 1095 1096#ifdef SIGTSTP 1097 (void) signal(SIGTSTP, SIG_IGN); 1098#endif 1099#ifdef SIGTTOU 1100 /* 1101 * Ignoring SIGTTOU keeps the kernel from blocking us 1102 * in ttioct() in /sys/tty.c. 1103 */ 1104 (void) signal(SIGTTOU, SIG_IGN); 1105#endif 1106 1107 (void) signal(SIGCHLD, cleanup); 1108 1109#if defined(CRAY2) && defined(UNICOS5) 1110 /* 1111 * Cray-2 will send a signal when pty modes are changed by slave 1112 * side. Set up signal handler now. 1113 */ 1114 if ((int)signal(SIGUSR1, termstat) < 0) 1115 warn("signal"); 1116 else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) 1117 warn("ioctl:TCSIGME"); 1118 /* 1119 * Make processing loop check terminal characteristics early on. 1120 */ 1121 termstat(); 1122#endif 1123 1124#ifdef TIOCNOTTY 1125 { 1126 register int t; 1127 t = open(_PATH_TTY, O_RDWR); 1128 if (t >= 0) { 1129 (void) ioctl(t, TIOCNOTTY, (char *)0); 1130 (void) close(t); 1131 } 1132 } 1133#endif 1134 1135#if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) 1136 (void) setsid(); 1137 ioctl(p, TIOCSCTTY, 0); 1138#endif 1139 1140 /* 1141 * Show banner that getty never gave. 1142 * 1143 * We put the banner in the pty input buffer. This way, it 1144 * gets carriage return null processing, etc., just like all 1145 * other pty --> client data. 1146 */ 1147 1148#if !defined(CRAY) || !defined(NEWINIT) 1149 if (getenv("USER")) 1150 hostinfo = 0; 1151#endif 1152 1153 if (getent(defent, "default") == 1) { 1154 char *Getstr(); 1155 char *cp=defstrs; 1156 1157 HE = Getstr("he", &cp); 1158 HN = Getstr("hn", &cp); 1159 IM = Getstr("im", &cp); 1160 if (HN && *HN) 1161 (void) strlcpy(host_name, HN, sizeof(host_name)); 1162 if (IM == 0) 1163 IM = ""; 1164 } else { 1165 IM = DEFAULT_IM; 1166 HE = 0; 1167 } 1168 edithost(HE, host_name); 1169 if (hostinfo && *IM) 1170 putf(IM, ptyibuf2); 1171 1172 if (pcc) 1173 (void) strncat(ptyibuf2, ptyip, pcc+1); 1174 ptyip = ptyibuf2; 1175 pcc = strlen(ptyip); 1176#ifdef LINEMODE 1177 /* 1178 * Last check to make sure all our states are correct. 1179 */ 1180 init_termbuf(); 1181 localstat(); 1182#endif /* LINEMODE */ 1183 1184 DIAG(TD_REPORT, 1185 {sprintf(nfrontp, "td: Entering processing loop\r\n"); 1186 nfrontp += strlen(nfrontp);}); 1187 1188 /* 1189 * Startup the login process on the slave side of the terminal 1190 * now. We delay this until here to insure option negotiation 1191 * is complete. 1192 */ 1193 startslave(host, level, user_name); 1194 1195 nfd = ((f > p) ? f : p) + 1; 1196 for (;;) { 1197 fd_set ibits, obits, xbits; 1198 register int c; 1199 1200 if (ncc < 0 && pcc < 0) 1201 break; 1202 1203#if defined(CRAY2) && defined(UNICOS5) 1204 if (needtermstat) 1205 _termstat(); 1206#endif /* defined(CRAY2) && defined(UNICOS5) */ 1207 FD_ZERO(&ibits); 1208 FD_ZERO(&obits); 1209 FD_ZERO(&xbits); 1210 /* 1211 * Never look for input if there's still 1212 * stuff in the corresponding output buffer 1213 */ 1214 if (nfrontp - nbackp || pcc > 0) { 1215 FD_SET(f, &obits); 1216 } else { 1217 FD_SET(p, &ibits); 1218 } 1219 if (pfrontp - pbackp || ncc > 0) { 1220 FD_SET(p, &obits); 1221 } else { 1222 FD_SET(f, &ibits); 1223 } 1224 if (!SYNCHing) { 1225 FD_SET(f, &xbits); 1226 } 1227 if ((c = select(nfd, &ibits, &obits, &xbits, 1228 (struct timeval *)0)) < 1) { 1229 if (c == -1) { 1230 if (errno == EINTR) { 1231 continue; 1232 } 1233 } 1234 sleep(5); 1235 continue; 1236 } 1237 1238 /* 1239 * Any urgent data? 1240 */ 1241 if (FD_ISSET(net, &xbits)) { 1242 SYNCHing = 1; 1243 } 1244 1245 /* 1246 * Something to read from the network... 1247 */ 1248 if (FD_ISSET(net, &ibits)) { 1249#if !defined(SO_OOBINLINE) 1250 /* 1251 * In 4.2 (and 4.3 beta) systems, the 1252 * OOB indication and data handling in the kernel 1253 * is such that if two separate TCP Urgent requests 1254 * come in, one byte of TCP data will be overlaid. 1255 * This is fatal for Telnet, but we try to live 1256 * with it. 1257 * 1258 * In addition, in 4.2 (and...), a special protocol 1259 * is needed to pick up the TCP Urgent data in 1260 * the correct sequence. 1261 * 1262 * What we do is: if we think we are in urgent 1263 * mode, we look to see if we are "at the mark". 1264 * If we are, we do an OOB receive. If we run 1265 * this twice, we will do the OOB receive twice, 1266 * but the second will fail, since the second 1267 * time we were "at the mark", but there wasn't 1268 * any data there (the kernel doesn't reset 1269 * "at the mark" until we do a normal read). 1270 * Once we've read the OOB data, we go ahead 1271 * and do normal reads. 1272 * 1273 * There is also another problem, which is that 1274 * since the OOB byte we read doesn't put us 1275 * out of OOB state, and since that byte is most 1276 * likely the TELNET DM (data mark), we would 1277 * stay in the TELNET SYNCH (SYNCHing) state. 1278 * So, clocks to the rescue. If we've "just" 1279 * received a DM, then we test for the 1280 * presence of OOB data when the receive OOB 1281 * fails (and AFTER we did the normal mode read 1282 * to clear "at the mark"). 1283 */ 1284 if (SYNCHing) { 1285 int atmark; 1286 1287 (void) ioctl(net, SIOCATMARK, (char *)&atmark); 1288 if (atmark) { 1289 ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); 1290 if ((ncc == -1) && (errno == EINVAL)) { 1291 ncc = read(net, netibuf, sizeof (netibuf)); 1292 if (sequenceIs(didnetreceive, gotDM)) { 1293 SYNCHing = stilloob(net); 1294 } 1295 } 1296 } else { 1297 ncc = read(net, netibuf, sizeof (netibuf)); 1298 } 1299 } else { 1300 ncc = read(net, netibuf, sizeof (netibuf)); 1301 } 1302 settimer(didnetreceive); 1303#else /* !defined(SO_OOBINLINE)) */ 1304 ncc = read(net, netibuf, sizeof (netibuf)); 1305#endif /* !defined(SO_OOBINLINE)) */ 1306 if (ncc < 0 && errno == EWOULDBLOCK) 1307 ncc = 0; 1308 else { 1309 if (ncc <= 0) { 1310 break; 1311 } 1312 netip = netibuf; 1313 } 1314 DIAG((TD_REPORT | TD_NETDATA), 1315 {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); 1316 nfrontp += strlen(nfrontp);}); 1317 DIAG(TD_NETDATA, printdata("nd", netip, ncc)); 1318 } 1319 1320 /* 1321 * Something to read from the pty... 1322 */ 1323 if (FD_ISSET(p, &ibits)) { 1324#ifndef STREAMSPTY 1325 pcc = read(p, ptyibuf, BUFSIZ); 1326#else 1327 pcc = readstream(p, ptyibuf, BUFSIZ); 1328#endif 1329 /* 1330 * On some systems, if we try to read something 1331 * off the master side before the slave side is 1332 * opened, we get EIO. 1333 */ 1334 if (pcc < 0 && (errno == EWOULDBLOCK || 1335#ifdef EAGAIN 1336 errno == EAGAIN || 1337#endif 1338 errno == EIO)) { 1339 pcc = 0; 1340 } else { 1341 if (pcc <= 0) 1342 break; 1343#if !defined(CRAY2) || !defined(UNICOS5) 1344#ifdef LINEMODE 1345 /* 1346 * If ioctl from pty, pass it through net 1347 */ 1348 if (ptyibuf[0] & TIOCPKT_IOCTL) { 1349 copy_termbuf(ptyibuf+1, pcc-1); 1350 localstat(); 1351 pcc = 1; 1352 } 1353#endif /* LINEMODE */ 1354 if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { 1355 netclear(); /* clear buffer back */ 1356#ifndef NO_URGENT 1357 /* 1358 * There are client telnets on some 1359 * operating systems get screwed up 1360 * royally if we send them urgent 1361 * mode data. 1362 */ 1363 *nfrontp++ = IAC; 1364 *nfrontp++ = DM; 1365 neturg = nfrontp-1; /* off by one XXX */ 1366 DIAG(TD_OPTIONS, 1367 printoption("td: send IAC", DM)); 1368 1369#endif 1370 } 1371 if (his_state_is_will(TELOPT_LFLOW) && 1372 (ptyibuf[0] & 1373 (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { 1374 int newflow = 1375 ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; 1376 if (newflow != flowmode) { 1377 flowmode = newflow; 1378 (void) sprintf(nfrontp, 1379 "%c%c%c%c%c%c", 1380 IAC, SB, TELOPT_LFLOW, 1381 flowmode ? LFLOW_ON 1382 : LFLOW_OFF, 1383 IAC, SE); 1384 nfrontp += 6; 1385 DIAG(TD_OPTIONS, printsub('>', 1386 (unsigned char *)nfrontp-4, 1387 4);); 1388 } 1389 } 1390 pcc--; 1391 ptyip = ptyibuf+1; 1392#else /* defined(CRAY2) && defined(UNICOS5) */ 1393 if (!uselinemode) { 1394 unpcc = pcc; 1395 unptyip = ptyibuf; 1396 pcc = term_output(&unptyip, ptyibuf2, 1397 &unpcc, BUFSIZ); 1398 ptyip = ptyibuf2; 1399 } else 1400 ptyip = ptyibuf; 1401#endif /* defined(CRAY2) && defined(UNICOS5) */ 1402 } 1403 } 1404 1405 while (pcc > 0) { 1406 if ((&netobuf[BUFSIZ] - nfrontp) < 2) 1407 break; 1408 c = *ptyip++ & 0377, pcc--; 1409 if (c == IAC) 1410 *nfrontp++ = c; 1411#if defined(CRAY2) && defined(UNICOS5) 1412 else if (c == '\n' && 1413 my_state_is_wont(TELOPT_BINARY) && newmap) 1414 *nfrontp++ = '\r'; 1415#endif /* defined(CRAY2) && defined(UNICOS5) */ 1416 *nfrontp++ = c; 1417 if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { 1418 if (pcc > 0 && ((*ptyip & 0377) == '\n')) { 1419 *nfrontp++ = *ptyip++ & 0377; 1420 pcc--; 1421 } else 1422 *nfrontp++ = '\0'; 1423 } 1424 } 1425#if defined(CRAY2) && defined(UNICOS5) 1426 /* 1427 * If chars were left over from the terminal driver, 1428 * note their existence. 1429 */ 1430 if (!uselinemode && unpcc) { 1431 pcc = unpcc; 1432 unpcc = 0; 1433 ptyip = unptyip; 1434 } 1435#endif /* defined(CRAY2) && defined(UNICOS5) */ 1436 1437 if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) 1438 netflush(); 1439 if (ncc > 0) 1440 telrcv(); 1441 if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) 1442 ptyflush(); 1443 } 1444 cleanup(0); 1445} /* end of telnet */ 1446 1447#ifndef TCSIG 1448# ifdef TIOCSIG 1449# define TCSIG TIOCSIG 1450# endif 1451#endif 1452 1453#ifdef STREAMSPTY 1454 1455int flowison = -1; /* current state of flow: -1 is unknown */ 1456 1457int readstream(p, ibuf, bufsize) 1458 int p; 1459 char *ibuf; 1460 int bufsize; 1461{ 1462 int flags = 0; 1463 int ret = 0; 1464 struct termios *tsp; 1465 struct termio *tp; 1466 struct iocblk *ip; 1467 char vstop, vstart; 1468 int ixon; 1469 int newflow; 1470 1471 strbufc.maxlen = BUFSIZ; 1472 strbufc.buf = (char *)ctlbuf; 1473 strbufd.maxlen = bufsize-1; 1474 strbufd.len = 0; 1475 strbufd.buf = ibuf+1; 1476 ibuf[0] = 0; 1477 1478 ret = getmsg(p, &strbufc, &strbufd, &flags); 1479 if (ret < 0) /* error of some sort -- probably EAGAIN */ 1480 return(-1); 1481 1482 if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { 1483 /* data message */ 1484 if (strbufd.len > 0) { /* real data */ 1485 return(strbufd.len + 1); /* count header char */ 1486 } else { 1487 /* nothing there */ 1488 errno = EAGAIN; 1489 return(-1); 1490 } 1491 } 1492 1493 /* 1494 * It's a control message. Return 1, to look at the flag we set 1495 */ 1496 1497 switch (ctlbuf[0]) { 1498 case M_FLUSH: 1499 if (ibuf[1] & FLUSHW) 1500 ibuf[0] = TIOCPKT_FLUSHWRITE; 1501 return(1); 1502 1503 case M_IOCTL: 1504 ip = (struct iocblk *) (ibuf+1); 1505 1506 switch (ip->ioc_cmd) { 1507 case TCSETS: 1508 case TCSETSW: 1509 case TCSETSF: 1510 tsp = (struct termios *) 1511 (ibuf+1 + sizeof(struct iocblk)); 1512 vstop = tsp->c_cc[VSTOP]; 1513 vstart = tsp->c_cc[VSTART]; 1514 ixon = tsp->c_iflag & IXON; 1515 break; 1516 case TCSETA: 1517 case TCSETAW: 1518 case TCSETAF: 1519 tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); 1520 vstop = tp->c_cc[VSTOP]; 1521 vstart = tp->c_cc[VSTART]; 1522 ixon = tp->c_iflag & IXON; 1523 break; 1524 default: 1525 errno = EAGAIN; 1526 return(-1); 1527 } 1528 1529 newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; 1530 if (newflow != flowison) { /* it's a change */ 1531 flowison = newflow; 1532 ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; 1533 return(1); 1534 } 1535 } 1536 1537 /* nothing worth doing anything about */ 1538 errno = EAGAIN; 1539 return(-1); 1540} 1541#endif /* STREAMSPTY */ 1542 1543/* 1544 * Send interrupt to process on other side of pty. 1545 * If it is in raw mode, just write NULL; 1546 * otherwise, write intr char. 1547 */ 1548 void 1549interrupt() 1550{ 1551 ptyflush(); /* half-hearted */ 1552 1553#if defined(STREAMSPTY) && defined(TIOCSIGNAL) 1554 /* Streams PTY style ioctl to post a signal */ 1555 { 1556 int sig = SIGINT; 1557 (void) ioctl(pty, TIOCSIGNAL, &sig); 1558 (void) ioctl(pty, I_FLUSH, FLUSHR); 1559 } 1560#else 1561#ifdef TCSIG 1562 (void) ioctl(pty, TCSIG, (char *)SIGINT); 1563#else /* TCSIG */ 1564 init_termbuf(); 1565 *pfrontp++ = slctab[SLC_IP].sptr ? 1566 (unsigned char)*slctab[SLC_IP].sptr : '\177'; 1567#endif /* TCSIG */ 1568#endif 1569} 1570 1571/* 1572 * Send quit to process on other side of pty. 1573 * If it is in raw mode, just write NULL; 1574 * otherwise, write quit char. 1575 */ 1576 void 1577sendbrk() 1578{ 1579 ptyflush(); /* half-hearted */ 1580#ifdef TCSIG 1581 (void) ioctl(pty, TCSIG, (char *)SIGQUIT); 1582#else /* TCSIG */ 1583 init_termbuf(); 1584 *pfrontp++ = slctab[SLC_ABORT].sptr ? 1585 (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; 1586#endif /* TCSIG */ 1587} 1588 1589 void 1590sendsusp() 1591{ 1592#ifdef SIGTSTP 1593 ptyflush(); /* half-hearted */ 1594# ifdef TCSIG 1595 (void) ioctl(pty, TCSIG, (char *)SIGTSTP); 1596# else /* TCSIG */ 1597 *pfrontp++ = slctab[SLC_SUSP].sptr ? 1598 (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; 1599# endif /* TCSIG */ 1600#endif /* SIGTSTP */ 1601} 1602 1603/* 1604 * When we get an AYT, if ^T is enabled, use that. Otherwise, 1605 * just send back "[Yes]". 1606 */ 1607 void 1608recv_ayt() 1609{ 1610#if defined(SIGINFO) && defined(TCSIG) 1611 if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { 1612 (void) ioctl(pty, TCSIG, (char *)SIGINFO); 1613 return; 1614 } 1615#endif 1616 (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); 1617 nfrontp += 9; 1618} 1619 1620 void 1621doeof() 1622{ 1623 init_termbuf(); 1624 1625#if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) 1626 if (!tty_isediting()) { 1627 extern char oldeofc; 1628 *pfrontp++ = oldeofc; 1629 return; 1630 } 1631#endif 1632 *pfrontp++ = slctab[SLC_EOF].sptr ? 1633 (unsigned char)*slctab[SLC_EOF].sptr : '\004'; 1634} 1635