|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1983, 1990 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms are permitted provided ! 6: * that: (1) source distributions retain this entire copyright notice and ! 7: * comment, and (2) distributions including binaries display the following ! 8: * acknowledgement: ``This product includes software developed by the ! 9: * University of California, Berkeley and its contributors'' in the ! 10: * documentation or other materials provided with the distribution and in ! 11: * all advertising materials mentioning features or use of this software. ! 12: * Neither the name of the University nor the names of its contributors may ! 13: * be used to endorse or promote products derived from this software without ! 14: * specific prior written permission. ! 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED ! 16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF ! 17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 18: */ ! 19: ! 20: #ifndef lint ! 21: char copyright[] = ! 22: "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\ ! 23: All rights reserved.\n"; ! 24: #endif /* not lint */ ! 25: ! 26: #ifndef lint ! 27: static char sccsid[] = "@(#)rlogin.c 5.32.1.1 (Berkeley) 10/21/90"; ! 28: #endif /* not lint */ ! 29: ! 30: /* ! 31: * $Source: mit/rlogin/RCS/rlogin.c,v $ ! 32: * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall ! 33: * Exp Locker: kfall $ ! 34: */ ! 35: ! 36: /* ! 37: * rlogin - remote login ! 38: */ ! 39: #include <sys/param.h> ! 40: #include <sys/file.h> ! 41: #include <sys/socket.h> ! 42: #include <sys/signal.h> ! 43: #include <sys/time.h> ! 44: #include <sys/resource.h> ! 45: #include <sys/wait.h> ! 46: ! 47: #include <netinet/in.h> ! 48: #include <netinet/in_systm.h> ! 49: #include <netinet/ip.h> ! 50: #include <netdb.h> ! 51: ! 52: #include <sgtty.h> ! 53: #include <setjmp.h> ! 54: #include <varargs.h> ! 55: #include <errno.h> ! 56: #include <pwd.h> ! 57: #include <stdio.h> ! 58: #include <unistd.h> ! 59: #include <string.h> ! 60: ! 61: #ifdef KERBEROS ! 62: #include <kerberosIV/des.h> ! 63: #include <kerberosIV/krb.h> ! 64: ! 65: CREDENTIALS cred; ! 66: Key_schedule schedule; ! 67: int use_kerberos = 1, encrypt; ! 68: char dst_realm_buf[REALM_SZ], *dest_realm = NULL; ! 69: extern char *krb_realmofhost(); ! 70: #endif ! 71: ! 72: #ifndef TIOCPKT_WINDOW ! 73: #define TIOCPKT_WINDOW 0x80 ! 74: #endif ! 75: ! 76: /* concession to Sun */ ! 77: #ifndef SIGUSR1 ! 78: #define SIGUSR1 30 ! 79: #endif ! 80: ! 81: extern int errno; ! 82: int eight, litout, rem; ! 83: ! 84: int noescape; ! 85: u_char escapechar = '~'; ! 86: ! 87: char *speeds[] = { ! 88: "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", ! 89: "1800", "2400", "4800", "9600", "19200", "38400" ! 90: }; ! 91: ! 92: #ifdef sun ! 93: struct winsize { ! 94: unsigned short ws_row, ws_col; ! 95: unsigned short ws_xpixel, ws_ypixel; ! 96: }; ! 97: #endif ! 98: struct winsize winsize; ! 99: ! 100: #ifndef sun ! 101: #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) ! 102: #endif ! 103: ! 104: void exit(); ! 105: ! 106: main(argc, argv) ! 107: int argc; ! 108: char **argv; ! 109: { ! 110: extern char *optarg; ! 111: extern int optind; ! 112: struct passwd *pw; ! 113: struct servent *sp; ! 114: struct sgttyb ttyb; ! 115: long omask; ! 116: int argoff, ch, dflag, one, uid; ! 117: char *host, *p, *user, term[1024]; ! 118: void lostpeer(); ! 119: u_char getescape(); ! 120: char *getenv(); ! 121: ! 122: argoff = dflag = 0; ! 123: one = 1; ! 124: host = user = NULL; ! 125: ! 126: if (p = rindex(argv[0], '/')) ! 127: ++p; ! 128: else ! 129: p = argv[0]; ! 130: ! 131: if (strcmp(p, "rlogin")) ! 132: host = p; ! 133: ! 134: /* handle "rlogin host flags" */ ! 135: if (!host && argc > 2 && argv[1][0] != '-') { ! 136: host = argv[1]; ! 137: argoff = 1; ! 138: } ! 139: ! 140: #ifdef KERBEROS ! 141: #define OPTIONS "8EKLde:k:l:x" ! 142: #else ! 143: #define OPTIONS "8EKLde:l:" ! 144: #endif ! 145: while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) ! 146: switch(ch) { ! 147: case '8': ! 148: eight = 1; ! 149: break; ! 150: case 'E': ! 151: noescape = 1; ! 152: break; ! 153: case 'K': ! 154: #ifdef KERBEROS ! 155: use_kerberos = 0; ! 156: #endif ! 157: break; ! 158: case 'L': ! 159: litout = 1; ! 160: break; ! 161: case 'd': ! 162: dflag = 1; ! 163: break; ! 164: case 'e': ! 165: escapechar = getescape(optarg); ! 166: break; ! 167: #ifdef KERBEROS ! 168: case 'k': ! 169: dest_realm = dst_realm_buf; ! 170: (void)strncpy(dest_realm, optarg, REALM_SZ); ! 171: break; ! 172: #endif ! 173: case 'l': ! 174: user = optarg; ! 175: break; ! 176: case '?': ! 177: default: ! 178: usage(); ! 179: } ! 180: optind += argoff; ! 181: argc -= optind; ! 182: argv += optind; ! 183: ! 184: /* if haven't gotten a host yet, do so */ ! 185: if (!host && !(host = *argv++)) ! 186: usage(); ! 187: ! 188: if (*argv) ! 189: usage(); ! 190: ! 191: if (!(pw = getpwuid(uid = getuid()))) { ! 192: (void)fprintf(stderr, "rlogin: unknown user id.\n"); ! 193: exit(1); ! 194: } ! 195: if (!user) ! 196: user = pw->pw_name; ! 197: ! 198: sp = NULL; ! 199: #ifdef KERBEROS ! 200: if (use_kerberos) { ! 201: sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp"); ! 202: if (sp == NULL) { ! 203: use_kerberos = 0; ! 204: warning("can't get entry for %s/tcp service", ! 205: encrypt ? "eklogin" : "klogin"); ! 206: } ! 207: } ! 208: #endif ! 209: if (sp == NULL) ! 210: sp = getservbyname("login", "tcp"); ! 211: if (sp == NULL) { ! 212: (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); ! 213: exit(1); ! 214: } ! 215: ! 216: (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); ! 217: if (ioctl(0, TIOCGETP, &ttyb) == 0) { ! 218: (void)strcat(term, "/"); ! 219: (void)strcat(term, speeds[ttyb.sg_ospeed]); ! 220: } ! 221: ! 222: (void)get_window_size(0, &winsize); ! 223: ! 224: (void)signal(SIGPIPE, lostpeer); ! 225: /* will use SIGUSR1 for window size hack, so hold it off */ ! 226: omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); ! 227: ! 228: #ifdef KERBEROS ! 229: try_connect: ! 230: if (use_kerberos) { ! 231: rem = KSUCCESS; ! 232: errno = 0; ! 233: if (dest_realm == NULL) ! 234: dest_realm = krb_realmofhost(host); ! 235: ! 236: rem = krcmd(&host, sp->s_port, user, term, 0, ! 237: dest_realm); ! 238: if (rem < 0) { ! 239: use_kerberos = 0; ! 240: sp = getservbyname("login", "tcp"); ! 241: if (sp == NULL) { ! 242: (void)fprintf(stderr, ! 243: "rlogin: unknown service login/tcp.\n"); ! 244: exit(1); ! 245: } ! 246: if (errno == ECONNREFUSED) ! 247: warning("remote host doesn't support Kerberos"); ! 248: if (errno == ENOENT) ! 249: warning("can't provide Kerberos auth data"); ! 250: goto try_connect; ! 251: } ! 252: } else { ! 253: rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); ! 254: } ! 255: #else ! 256: rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); ! 257: #endif /* KERBEROS */ ! 258: ! 259: if (rem < 0) ! 260: exit(1); ! 261: ! 262: if (dflag && ! 263: setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) ! 264: (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", ! 265: strerror(errno)); ! 266: one = IPTOS_LOWDELAY; ! 267: if (setsockopt(rem, IPPROTO_IP, IP_TOS, (char *)&one, sizeof(int)) < 0) ! 268: perror("rlogin: setsockopt TOS (ignored)"); ! 269: ! 270: (void)setuid(uid); ! 271: doit(omask); ! 272: /*NOTREACHED*/ ! 273: } ! 274: ! 275: int child, defflags, deflflags, tabflag; ! 276: char deferase, defkill; ! 277: struct tchars deftc; ! 278: struct ltchars defltc; ! 279: struct tchars notc = { -1, -1, -1, -1, -1, -1 }; ! 280: struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; ! 281: ! 282: doit(omask) ! 283: long omask; ! 284: { ! 285: struct sgttyb sb; ! 286: void catch_child(), copytochild(), exit(), writeroob(); ! 287: ! 288: (void)ioctl(0, TIOCGETP, (char *)&sb); ! 289: defflags = sb.sg_flags; ! 290: tabflag = defflags & TBDELAY; ! 291: defflags &= ECHO | CRMOD; ! 292: deferase = sb.sg_erase; ! 293: defkill = sb.sg_kill; ! 294: (void)ioctl(0, TIOCLGET, (char *)&deflflags); ! 295: (void)ioctl(0, TIOCGETC, (char *)&deftc); ! 296: notc.t_startc = deftc.t_startc; ! 297: notc.t_stopc = deftc.t_stopc; ! 298: (void)ioctl(0, TIOCGLTC, (char *)&defltc); ! 299: (void)signal(SIGINT, SIG_IGN); ! 300: setsignal(SIGHUP, exit); ! 301: setsignal(SIGQUIT, exit); ! 302: child = fork(); ! 303: if (child == -1) { ! 304: (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); ! 305: done(1); ! 306: } ! 307: if (child == 0) { ! 308: mode(1); ! 309: if (reader(omask) == 0) { ! 310: msg("connection closed."); ! 311: exit(0); ! 312: } ! 313: sleep(1); ! 314: msg("\007connection closed."); ! 315: exit(1); ! 316: } ! 317: ! 318: /* ! 319: * We may still own the socket, and may have a pending SIGURG (or might ! 320: * receive one soon) that we really want to send to the reader. Set a ! 321: * trap that simply copies such signals to the child. ! 322: */ ! 323: (void)signal(SIGURG, copytochild); ! 324: (void)signal(SIGUSR1, writeroob); ! 325: (void)sigsetmask(omask); ! 326: (void)signal(SIGCHLD, catch_child); ! 327: writer(); ! 328: msg("closed connection."); ! 329: done(0); ! 330: } ! 331: ! 332: /* trap a signal, unless it is being ignored. */ ! 333: setsignal(sig, act) ! 334: int sig; ! 335: void (*act)(); ! 336: { ! 337: int omask = sigblock(sigmask(sig)); ! 338: ! 339: if (signal(sig, act) == SIG_IGN) ! 340: (void)signal(sig, SIG_IGN); ! 341: (void)sigsetmask(omask); ! 342: } ! 343: ! 344: done(status) ! 345: int status; ! 346: { ! 347: int w; ! 348: ! 349: mode(0); ! 350: if (child > 0) { ! 351: /* make sure catch_child does not snap it up */ ! 352: (void)signal(SIGCHLD, SIG_DFL); ! 353: if (kill(child, SIGKILL) >= 0) ! 354: while ((w = wait((union wait *)0)) > 0 && w != child); ! 355: } ! 356: exit(status); ! 357: } ! 358: ! 359: int dosigwinch; ! 360: ! 361: /* ! 362: * This is called when the reader process gets the out-of-band (urgent) ! 363: * request to turn on the window-changing protocol. ! 364: */ ! 365: void ! 366: writeroob() ! 367: { ! 368: void sigwinch(); ! 369: ! 370: if (dosigwinch == 0) { ! 371: sendwindow(); ! 372: (void)signal(SIGWINCH, sigwinch); ! 373: } ! 374: dosigwinch = 1; ! 375: } ! 376: ! 377: void ! 378: catch_child() ! 379: { ! 380: union wait status; ! 381: int pid; ! 382: ! 383: for (;;) { ! 384: pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); ! 385: if (pid == 0) ! 386: return; ! 387: /* if the child (reader) dies, just quit */ ! 388: if (pid < 0 || pid == child && !WIFSTOPPED(status)) ! 389: done((int)(status.w_termsig | status.w_retcode)); ! 390: } ! 391: /* NOTREACHED */ ! 392: } ! 393: ! 394: /* ! 395: * writer: write to remote: 0 -> line. ! 396: * ~. terminate ! 397: * ~^Z suspend rlogin process. ! 398: * ~<delayed-suspend char> suspend rlogin process, but leave reader alone. ! 399: */ ! 400: writer() ! 401: { ! 402: register int bol, local, n; ! 403: char c; ! 404: ! 405: bol = 1; /* beginning of line */ ! 406: local = 0; ! 407: for (;;) { ! 408: n = read(STDIN_FILENO, &c, 1); ! 409: if (n <= 0) { ! 410: if (n < 0 && errno == EINTR) ! 411: continue; ! 412: break; ! 413: } ! 414: /* ! 415: * If we're at the beginning of the line and recognize a ! 416: * command character, then we echo locally. Otherwise, ! 417: * characters are echo'd remotely. If the command character ! 418: * is doubled, this acts as a force and local echo is ! 419: * suppressed. ! 420: */ ! 421: if (bol) { ! 422: bol = 0; ! 423: if (!noescape && c == escapechar) { ! 424: local = 1; ! 425: continue; ! 426: } ! 427: } else if (local) { ! 428: local = 0; ! 429: if (c == '.' || c == deftc.t_eofc) { ! 430: echo(c); ! 431: break; ! 432: } ! 433: if (c == defltc.t_suspc || c == defltc.t_dsuspc) { ! 434: bol = 1; ! 435: echo(c); ! 436: stop(c); ! 437: continue; ! 438: } ! 439: if (c != escapechar) ! 440: (void)write(rem, &escapechar, 1); ! 441: } ! 442: ! 443: if (write(rem, &c, 1) == 0) { ! 444: msg("line gone"); ! 445: break; ! 446: } ! 447: bol = c == defkill || c == deftc.t_eofc || ! 448: c == deftc.t_intrc || c == defltc.t_suspc || ! 449: c == '\r' || c == '\n'; ! 450: } ! 451: } ! 452: ! 453: echo(c) ! 454: register char c; ! 455: { ! 456: register char *p; ! 457: char buf[8]; ! 458: ! 459: p = buf; ! 460: c &= 0177; ! 461: *p++ = escapechar; ! 462: if (c < ' ') { ! 463: *p++ = '^'; ! 464: *p++ = c + '@'; ! 465: } else if (c == 0177) { ! 466: *p++ = '^'; ! 467: *p++ = '?'; ! 468: } else ! 469: *p++ = c; ! 470: *p++ = '\r'; ! 471: *p++ = '\n'; ! 472: (void)write(STDOUT_FILENO, buf, p - buf); ! 473: } ! 474: ! 475: stop(cmdc) ! 476: char cmdc; ! 477: { ! 478: mode(0); ! 479: (void)signal(SIGCHLD, SIG_IGN); ! 480: (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); ! 481: (void)signal(SIGCHLD, catch_child); ! 482: mode(1); ! 483: sigwinch(); /* check for size changes */ ! 484: } ! 485: ! 486: void ! 487: sigwinch() ! 488: { ! 489: struct winsize ws; ! 490: ! 491: if (dosigwinch && get_window_size(0, &ws) == 0 && ! 492: bcmp(&ws, &winsize, sizeof(ws))) { ! 493: winsize = ws; ! 494: sendwindow(); ! 495: } ! 496: } ! 497: ! 498: /* ! 499: * Send the window size to the server via the magic escape ! 500: */ ! 501: sendwindow() ! 502: { ! 503: struct winsize *wp; ! 504: char obuf[4 + sizeof (struct winsize)]; ! 505: ! 506: wp = (struct winsize *)(obuf+4); ! 507: obuf[0] = 0377; ! 508: obuf[1] = 0377; ! 509: obuf[2] = 's'; ! 510: obuf[3] = 's'; ! 511: wp->ws_row = htons(winsize.ws_row); ! 512: wp->ws_col = htons(winsize.ws_col); ! 513: wp->ws_xpixel = htons(winsize.ws_xpixel); ! 514: wp->ws_ypixel = htons(winsize.ws_ypixel); ! 515: ! 516: (void)write(rem, obuf, sizeof(obuf)); ! 517: } ! 518: ! 519: /* ! 520: * reader: read from remote: line -> 1 ! 521: */ ! 522: #define READING 1 ! 523: #define WRITING 2 ! 524: ! 525: jmp_buf rcvtop; ! 526: int ppid, rcvcnt, rcvstate; ! 527: char rcvbuf[8 * 1024]; ! 528: ! 529: void ! 530: oob() ! 531: { ! 532: struct sgttyb sb; ! 533: int atmark, n, out, rcvd; ! 534: char waste[BUFSIZ], mark; ! 535: ! 536: out = O_RDWR; ! 537: rcvd = 0; ! 538: while (recv(rem, &mark, 1, MSG_OOB) < 0) ! 539: switch (errno) { ! 540: case EWOULDBLOCK: ! 541: /* ! 542: * Urgent data not here yet. It may not be possible ! 543: * to send it yet if we are blocked for output and ! 544: * our input buffer is full. ! 545: */ ! 546: if (rcvcnt < sizeof(rcvbuf)) { ! 547: n = read(rem, rcvbuf + rcvcnt, ! 548: sizeof(rcvbuf) - rcvcnt); ! 549: if (n <= 0) ! 550: return; ! 551: rcvd += n; ! 552: } else { ! 553: n = read(rem, waste, sizeof(waste)); ! 554: if (n <= 0) ! 555: return; ! 556: } ! 557: continue; ! 558: default: ! 559: return; ! 560: } ! 561: if (mark & TIOCPKT_WINDOW) { ! 562: /* Let server know about window size changes */ ! 563: (void)kill(ppid, SIGUSR1); ! 564: } ! 565: if (!eight && (mark & TIOCPKT_NOSTOP)) { ! 566: (void)ioctl(0, TIOCGETP, (char *)&sb); ! 567: sb.sg_flags &= ~CBREAK; ! 568: sb.sg_flags |= RAW; ! 569: (void)ioctl(0, TIOCSETN, (char *)&sb); ! 570: notc.t_stopc = -1; ! 571: notc.t_startc = -1; ! 572: (void)ioctl(0, TIOCSETC, (char *)¬c); ! 573: } ! 574: if (!eight && (mark & TIOCPKT_DOSTOP)) { ! 575: (void)ioctl(0, TIOCGETP, (char *)&sb); ! 576: sb.sg_flags &= ~RAW; ! 577: sb.sg_flags |= CBREAK; ! 578: (void)ioctl(0, TIOCSETN, (char *)&sb); ! 579: notc.t_stopc = deftc.t_stopc; ! 580: notc.t_startc = deftc.t_startc; ! 581: (void)ioctl(0, TIOCSETC, (char *)¬c); ! 582: } ! 583: if (mark & TIOCPKT_FLUSHWRITE) { ! 584: (void)ioctl(1, TIOCFLUSH, (char *)&out); ! 585: for (;;) { ! 586: if (ioctl(rem, SIOCATMARK, &atmark) < 0) { ! 587: (void)fprintf(stderr, "rlogin: ioctl: %s.\n", ! 588: strerror(errno)); ! 589: break; ! 590: } ! 591: if (atmark) ! 592: break; ! 593: n = read(rem, waste, sizeof (waste)); ! 594: if (n <= 0) ! 595: break; ! 596: } ! 597: /* ! 598: * Don't want any pending data to be output, so clear the recv ! 599: * buffer. If we were hanging on a write when interrupted, ! 600: * don't want it to restart. If we were reading, restart ! 601: * anyway. ! 602: */ ! 603: rcvcnt = 0; ! 604: longjmp(rcvtop, 1); ! 605: } ! 606: ! 607: /* oob does not do FLUSHREAD (alas!) */ ! 608: ! 609: /* ! 610: * If we filled the receive buffer while a read was pending, longjmp ! 611: * to the top to restart appropriately. Don't abort a pending write, ! 612: * however, or we won't know how much was written. ! 613: */ ! 614: if (rcvd && rcvstate == READING) ! 615: longjmp(rcvtop, 1); ! 616: } ! 617: ! 618: /* reader: read from remote: line -> 1 */ ! 619: reader(omask) ! 620: int omask; ! 621: { ! 622: void oob(); ! 623: ! 624: #if !defined(BSD) || BSD < 43 ! 625: int pid = -getpid(); ! 626: #else ! 627: int pid = getpid(); ! 628: #endif ! 629: int n, remaining; ! 630: char *bufp = rcvbuf; ! 631: ! 632: (void)signal(SIGTTOU, SIG_IGN); ! 633: (void)signal(SIGURG, oob); ! 634: ppid = getppid(); ! 635: (void)fcntl(rem, F_SETOWN, pid); ! 636: (void)setjmp(rcvtop); ! 637: (void)sigsetmask(omask); ! 638: for (;;) { ! 639: while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { ! 640: rcvstate = WRITING; ! 641: n = write(STDOUT_FILENO, bufp, remaining); ! 642: if (n < 0) { ! 643: if (errno != EINTR) ! 644: return(-1); ! 645: continue; ! 646: } ! 647: bufp += n; ! 648: } ! 649: bufp = rcvbuf; ! 650: rcvcnt = 0; ! 651: rcvstate = READING; ! 652: ! 653: rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); ! 654: if (rcvcnt == 0) ! 655: return (0); ! 656: if (rcvcnt < 0) { ! 657: if (errno == EINTR) ! 658: continue; ! 659: (void)fprintf(stderr, "rlogin: read: %s.\n", ! 660: strerror(errno)); ! 661: return(-1); ! 662: } ! 663: } ! 664: } ! 665: ! 666: mode(f) ! 667: { ! 668: struct ltchars *ltc; ! 669: struct sgttyb sb; ! 670: struct tchars *tc; ! 671: int lflags; ! 672: ! 673: (void)ioctl(0, TIOCGETP, (char *)&sb); ! 674: (void)ioctl(0, TIOCLGET, (char *)&lflags); ! 675: switch(f) { ! 676: case 0: ! 677: sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); ! 678: sb.sg_flags |= defflags|tabflag; ! 679: tc = &deftc; ! 680: ltc = &defltc; ! 681: sb.sg_kill = defkill; ! 682: sb.sg_erase = deferase; ! 683: lflags = deflflags; ! 684: break; ! 685: case 1: ! 686: sb.sg_flags |= (eight ? RAW : CBREAK); ! 687: sb.sg_flags &= ~defflags; ! 688: /* preserve tab delays, but turn off XTABS */ ! 689: if ((sb.sg_flags & TBDELAY) == XTABS) ! 690: sb.sg_flags &= ~TBDELAY; ! 691: tc = ¬c; ! 692: ltc = &noltc; ! 693: sb.sg_kill = sb.sg_erase = -1; ! 694: if (litout) ! 695: lflags |= LLITOUT; ! 696: break; ! 697: default: ! 698: return; ! 699: } ! 700: (void)ioctl(0, TIOCSLTC, (char *)ltc); ! 701: (void)ioctl(0, TIOCSETC, (char *)tc); ! 702: (void)ioctl(0, TIOCSETN, (char *)&sb); ! 703: (void)ioctl(0, TIOCLSET, (char *)&lflags); ! 704: } ! 705: ! 706: void ! 707: lostpeer() ! 708: { ! 709: (void)signal(SIGPIPE, SIG_IGN); ! 710: msg("\007connection closed."); ! 711: done(1); ! 712: } ! 713: ! 714: /* copy SIGURGs to the child process. */ ! 715: void ! 716: copytochild() ! 717: { ! 718: (void)kill(child, SIGURG); ! 719: } ! 720: ! 721: msg(str) ! 722: char *str; ! 723: { ! 724: (void)fprintf(stderr, "rlogin: %s\r\n", str); ! 725: } ! 726: ! 727: #ifdef KERBEROS ! 728: /* VARARGS */ ! 729: warning(va_alist) ! 730: va_dcl ! 731: { ! 732: va_list ap; ! 733: char *fmt; ! 734: ! 735: (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); ! 736: va_start(ap); ! 737: fmt = va_arg(ap, char *); ! 738: vfprintf(stderr, fmt, ap); ! 739: va_end(ap); ! 740: (void)fprintf(stderr, ".\n"); ! 741: } ! 742: #endif ! 743: ! 744: usage() ! 745: { ! 746: (void)fprintf(stderr, ! 747: "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", ! 748: #ifdef KERBEROS ! 749: "8EL", " [-k realm] "); ! 750: #else ! 751: "8EL", " "); ! 752: #endif ! 753: exit(1); ! 754: } ! 755: ! 756: /* ! 757: * The following routine provides compatibility (such as it is) between 4.2BSD ! 758: * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. ! 759: */ ! 760: #ifdef sun ! 761: get_window_size(fd, wp) ! 762: int fd; ! 763: struct winsize *wp; ! 764: { ! 765: struct ttysize ts; ! 766: int error; ! 767: ! 768: if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) ! 769: return(error); ! 770: wp->ws_row = ts.ts_lines; ! 771: wp->ws_col = ts.ts_cols; ! 772: wp->ws_xpixel = 0; ! 773: wp->ws_ypixel = 0; ! 774: return(0); ! 775: } ! 776: #endif ! 777: ! 778: u_char ! 779: getescape(p) ! 780: register char *p; ! 781: { ! 782: long val; ! 783: int len; ! 784: ! 785: if ((len = strlen(p)) == 1) /* use any single char, including '\' */ ! 786: return((u_char)*p); ! 787: /* otherwise, \nnn */ ! 788: if (*p == '\\' && len >= 2 && len <= 4) { ! 789: val = strtol(++p, (char **)NULL, 8); ! 790: for (;;) { ! 791: if (!*++p) ! 792: return((u_char)val); ! 793: if (*p < '0' || *p > '8') ! 794: break; ! 795: } ! 796: } ! 797: msg("illegal option value -- e"); ! 798: usage(); ! 799: /* NOTREACHED */ ! 800: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.