140858Sbostic /*- 240858Sbostic * Copyright (c) 1983, 1990 The Regents of the University of California. 335539Sbostic * All rights reserved. 435539Sbostic * 540858Sbostic %sccs.include.redist.c% 621595Sdist */ 721595Sdist 86444Swnj #ifndef lint 921595Sdist char copyright[] = 1040858Sbostic "@(#) Copyright (c) 1983, 1990 The Regents of the University of California.\n\ 1121595Sdist All rights reserved.\n"; 1235539Sbostic #endif /* not lint */ 136444Swnj 1421595Sdist #ifndef lint 15*40868Sbostic static char sccsid[] = "@(#)rlogin.c 5.24 (Berkeley) 04/10/90"; 1635539Sbostic #endif /* not lint */ 1721595Sdist 1812990Ssam /* 1940858Sbostic * $Source: mit/rlogin/RCS/rlogin.c,v $ 2040858Sbostic * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall Exp Locker: kfall $ 2140858Sbostic */ 2240858Sbostic 2340858Sbostic /* 2412990Ssam * rlogin - remote login 2512990Ssam */ 2626981Skarels #include <sys/param.h> 2725424Skarels #include <sys/errno.h> 2824727Smckusick #include <sys/file.h> 296444Swnj #include <sys/socket.h> 3040858Sbostic #include <sys/signal.h> 3129729Smckusick #include <sys/time.h> 3229729Smckusick #include <sys/resource.h> 3313620Ssam #include <sys/wait.h> 349365Ssam 359207Ssam #include <netinet/in.h> 3640858Sbostic #include <netdb.h> 379365Ssam 389365Ssam #include <sgtty.h> 3940858Sbostic #include <setjmp.h> 406444Swnj #include <errno.h> 4140858Sbostic #include <varargs.h> 426444Swnj #include <pwd.h> 4340858Sbostic #include <stdio.h> 4440858Sbostic #include <unistd.h> 4540858Sbostic #include <strings.h> 466444Swnj 4740858Sbostic #ifdef KERBEROS 4840683Sbostic #include <kerberosIV/krb.h> 4936511Skfall 5040858Sbostic CREDENTIALS cred; 5140858Sbostic Key_schedule schedule; 5240858Sbostic int use_kerberos = 1, encrypt; 5340858Sbostic char dst_realm_buf[REALM_SZ], *dest_realm = NULL; 5440858Sbostic extern char *krb_realmofhost(); 5540858Sbostic #endif 5624726Smckusick 5740858Sbostic #ifndef TIOCPKT_WINDOW 5840858Sbostic #define TIOCPKT_WINDOW 0x80 5940858Sbostic #endif 6029729Smckusick 6140858Sbostic /* concession to Sun */ 6240858Sbostic #ifndef SIGUSR1 6340858Sbostic #define SIGUSR1 30 6426981Skarels #endif 6540858Sbostic 6640858Sbostic extern int errno; 6740858Sbostic int eight, litout, rem; 6840858Sbostic char cmdchar; 6940858Sbostic char *speeds[] = { 7040858Sbostic "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", 7140858Sbostic "1800", "2400", "4800", "9600", "19200", "38400" 7240858Sbostic }; 7340858Sbostic 7426981Skarels #ifdef sun 7526981Skarels struct winsize { 7626981Skarels unsigned short ws_row, ws_col; 7726981Skarels unsigned short ws_xpixel, ws_ypixel; 7826981Skarels }; 7940858Sbostic #endif 8018358Ssam struct winsize winsize; 816444Swnj 8240858Sbostic #ifndef sun 8340858Sbostic #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) 8440858Sbostic #endif 8529729Smckusick 8640858Sbostic void exit(); 8729729Smckusick 886444Swnj main(argc, argv) 896444Swnj int argc; 906444Swnj char **argv; 916444Swnj { 9240858Sbostic extern char *optarg; 9340858Sbostic extern int optind; 9440858Sbostic struct passwd *pw; 9540858Sbostic struct servent *sp; 966444Swnj struct sgttyb ttyb; 9740858Sbostic long omask; 9840858Sbostic int argoff, ch, dflag, one, uid; 9940858Sbostic char *host, *p, *user, term[1024]; 10040858Sbostic void lostpeer(); 10140858Sbostic char *getenv(); 1026444Swnj 10340858Sbostic argoff = dflag = 0; 10440858Sbostic one = 1; 10540858Sbostic host = user = NULL; 10640858Sbostic cmdchar = '~'; 10740858Sbostic 10840858Sbostic if (p = rindex(argv[0], '/')) 10940858Sbostic ++p; 1106444Swnj else 11140858Sbostic p = argv[0]; 11240858Sbostic 11340858Sbostic if (strcmp(p, "rlogin")) 11440858Sbostic host = p; 11540858Sbostic 11640858Sbostic /* handle "rlogin host flags" */ 11740858Sbostic if (!host && argc > 2 && argv[1][0] != '-') { 11840858Sbostic host = argv[1]; 11940858Sbostic argoff = 1; 1206444Swnj } 12136511Skfall 12240858Sbostic #ifdef KERBEROS 123*40868Sbostic #define OPTIONS "8KLde:k:l:x" 12440858Sbostic #else 125*40868Sbostic #define OPTIONS "8KLde:l:" 12640858Sbostic #endif 12740858Sbostic while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) 12840858Sbostic switch(ch) { 12940858Sbostic case '8': 13040858Sbostic eight = 1; 13140858Sbostic break; 132*40868Sbostic case 'K': 133*40868Sbostic #ifdef KERBEROS 134*40868Sbostic use_kerberos = 0; 135*40868Sbostic #endif 136*40868Sbostic break; 13740858Sbostic case 'L': 13840858Sbostic litout = 1; 13940858Sbostic break; 14040858Sbostic case 'd': 14140858Sbostic dflag = 1; 14240858Sbostic break; 14340858Sbostic case 'e': 14440858Sbostic cmdchar = optarg[0]; 14540858Sbostic break; 14640858Sbostic #ifdef KERBEROS 14740858Sbostic case 'k': 14840858Sbostic dest_realm = dst_realm_buf; 14940858Sbostic (void)strncpy(dest_realm, optarg, REALM_SZ); 15040858Sbostic break; 15140858Sbostic #endif 15240858Sbostic case 'l': 15340858Sbostic user = optarg; 15440858Sbostic break; 15540858Sbostic #ifdef KERBEROS 15640858Sbostic case 'x': 15740858Sbostic encrypt = 1; 15840858Sbostic des_set_key(cred.session, schedule); 15940858Sbostic break; 16040858Sbostic #endif 16140858Sbostic case '?': 16240858Sbostic default: 16340858Sbostic usage(); 16436524Skfall } 16540858Sbostic optind += argoff; 16640858Sbostic argc -= optind; 16740858Sbostic argv += optind; 16836524Skfall 16940858Sbostic /* if haven't gotten a host yet, do so */ 17040858Sbostic if (!host && !(host = *argv++)) 17140858Sbostic usage(); 17236511Skfall 17340858Sbostic if (*argv) 17440858Sbostic usage(); 17540858Sbostic 17640858Sbostic if (!(pw = getpwuid(uid = getuid()))) { 17740858Sbostic (void)fprintf(stderr, "rlogin: unknown user id.\n"); 1786444Swnj exit(1); 1796444Swnj } 18040858Sbostic if (!user) 18140858Sbostic user = pw->pw_name; 18240858Sbostic 183*40868Sbostic sp = NULL; 18440858Sbostic #ifdef KERBEROS 185*40868Sbostic if (use_kerberos) { 186*40868Sbostic sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp"); 187*40868Sbostic if (sp == NULL) { 188*40868Sbostic use_kerberos = 0; 189*40868Sbostic warning("can't get entry for %s/tcp service", 190*40868Sbostic encrypt ? "eklogin" : "klogin"); 191*40868Sbostic } 19236512Skfall } 19336512Skfall #endif 194*40868Sbostic if (sp == NULL) 195*40868Sbostic sp = getservbyname("login", "tcp"); 19640858Sbostic if (sp == NULL) { 19740858Sbostic (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); 19840858Sbostic exit(1); 1999365Ssam } 20040858Sbostic 20140858Sbostic (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); 20218358Ssam if (ioctl(0, TIOCGETP, &ttyb) == 0) { 20340858Sbostic (void)strcat(term, "/"); 20440858Sbostic (void)strcat(term, speeds[ttyb.sg_ospeed]); 2056444Swnj } 20640858Sbostic 20740858Sbostic (void)get_window_size(0, &winsize); 20840858Sbostic 20940858Sbostic (void)signal(SIGPIPE, lostpeer); 21029729Smckusick /* will use SIGUSR1 for window size hack, so hold it off */ 21140858Sbostic omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); 21236511Skfall 21340858Sbostic #ifdef KERBEROS 21436512Skfall try_connect: 21540858Sbostic if (use_kerberos) { 21636512Skfall rem = KSUCCESS; 21740858Sbostic errno = 0; 21838728Skfall if (dest_realm == NULL) 21938728Skfall dest_realm = krb_realmofhost(host); 22038728Skfall 22140858Sbostic if (encrypt) 22240858Sbostic rem = krcmd_mutual(&host, sp->s_port, user, term, 0, 22340858Sbostic dest_realm, &cred, schedule); 22440858Sbostic else 22540858Sbostic rem = krcmd(&host, sp->s_port, user, term, 0, 22640858Sbostic dest_realm); 22738728Skfall if (rem < 0) { 22836512Skfall use_kerberos = 0; 22936628Skfall sp = getservbyname("login", "tcp"); 23040858Sbostic if (sp == NULL) { 23140858Sbostic (void)fprintf(stderr, 23240858Sbostic "rlogin: unknown service login/tcp.\n"); 23336628Skfall exit(1); 23436628Skfall } 23538728Skfall if (errno == ECONNREFUSED) 23640858Sbostic warning("remote host doesn't support Kerberos"); 23738728Skfall if (errno == ENOENT) 23840858Sbostic warning("can't provide Kerberos auth data"); 23936512Skfall goto try_connect; 24036512Skfall } 24136511Skfall } else { 24240858Sbostic if (encrypt) { 24340858Sbostic (void)fprintf(stderr, 24440858Sbostic "rlogin: the -x flag requires Kerberos authentication.\n"); 24536512Skfall exit(1); 24636512Skfall } 24740858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 24836511Skfall } 24936512Skfall #else 25040858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 25136512Skfall #endif 25236511Skfall 25340858Sbostic if (rem < 0) 25436511Skfall exit(1); 25536511Skfall 25640858Sbostic if (dflag && 25740858Sbostic setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) 25840858Sbostic (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", 25940858Sbostic strerror(errno)); 26040858Sbostic 26140858Sbostic (void)setuid(uid); 26240858Sbostic doit(omask); 2639365Ssam /*NOTREACHED*/ 2646444Swnj } 2656444Swnj 26640858Sbostic int child, defflags, deflflags, tabflag; 26740858Sbostic char deferase, defkill; 26840858Sbostic struct tchars deftc; 26940858Sbostic struct ltchars defltc; 27040858Sbostic struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 27140858Sbostic struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 2726444Swnj 27340858Sbostic doit(omask) 27440858Sbostic long omask; 2756444Swnj { 27613075Ssam struct sgttyb sb; 27740858Sbostic void catch_child(), copytochild(), exit(), writeroob(); 2786444Swnj 27940858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 28013075Ssam defflags = sb.sg_flags; 28112155Ssam tabflag = defflags & TBDELAY; 2829962Ssam defflags &= ECHO | CRMOD; 28313075Ssam deferase = sb.sg_erase; 28413075Ssam defkill = sb.sg_kill; 28540858Sbostic (void)ioctl(0, TIOCLGET, (char *)&deflflags); 28640858Sbostic (void)ioctl(0, TIOCGETC, (char *)&deftc); 28713075Ssam notc.t_startc = deftc.t_startc; 28813075Ssam notc.t_stopc = deftc.t_stopc; 28940858Sbostic (void)ioctl(0, TIOCGLTC, (char *)&defltc); 29040858Sbostic (void)signal(SIGINT, SIG_IGN); 29129729Smckusick setsignal(SIGHUP, exit); 29229729Smckusick setsignal(SIGQUIT, exit); 2939365Ssam child = fork(); 2949365Ssam if (child == -1) { 29540858Sbostic (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); 29625424Skarels done(1); 2979365Ssam } 2989365Ssam if (child == 0) { 29924726Smckusick mode(1); 30040858Sbostic if (reader(omask) == 0) { 30140858Sbostic msg("connection closed."); 30225424Skarels exit(0); 30325424Skarels } 30412155Ssam sleep(1); 30540858Sbostic msg("\007connection closed."); 30640858Sbostic exit(1); 3076444Swnj } 30829729Smckusick 30929729Smckusick /* 31040858Sbostic * We may still own the socket, and may have a pending SIGURG (or might 31140858Sbostic * receive one soon) that we really want to send to the reader. Set a 31240858Sbostic * trap that simply copies such signals to the child. 31329729Smckusick */ 31440858Sbostic (void)signal(SIGURG, copytochild); 31540858Sbostic (void)signal(SIGUSR1, writeroob); 31640858Sbostic (void)sigsetmask(omask); 31740858Sbostic (void)signal(SIGCHLD, catch_child); 3189365Ssam writer(); 31940858Sbostic msg("closed connection."); 32025424Skarels done(0); 3216444Swnj } 3226444Swnj 32340858Sbostic /* trap a signal, unless it is being ignored. */ 32429729Smckusick setsignal(sig, act) 32540858Sbostic int sig; 32640858Sbostic void (*act)(); 32729729Smckusick { 32829729Smckusick int omask = sigblock(sigmask(sig)); 32929729Smckusick 33029729Smckusick if (signal(sig, act) == SIG_IGN) 33140858Sbostic (void)signal(sig, SIG_IGN); 33240858Sbostic (void)sigsetmask(omask); 33329729Smckusick } 33429729Smckusick 33525424Skarels done(status) 33625424Skarels int status; 3376444Swnj { 33829729Smckusick int w; 3396444Swnj 3406444Swnj mode(0); 34129729Smckusick if (child > 0) { 34240858Sbostic /* make sure catch_child does not snap it up */ 34340858Sbostic (void)signal(SIGCHLD, SIG_DFL); 34429729Smckusick if (kill(child, SIGKILL) >= 0) 34540858Sbostic while ((w = wait((union wait *)0)) > 0 && w != child); 34629729Smckusick } 34725424Skarels exit(status); 3486444Swnj } 3496444Swnj 35040858Sbostic int dosigwinch; 35129729Smckusick 35229729Smckusick /* 35324726Smckusick * This is called when the reader process gets the out-of-band (urgent) 35424726Smckusick * request to turn on the window-changing protocol. 35524726Smckusick */ 35640858Sbostic void 35724726Smckusick writeroob() 35824726Smckusick { 35940858Sbostic void sigwinch(); 36024726Smckusick 36125341Smckusick if (dosigwinch == 0) { 36224919Smckusick sendwindow(); 36340858Sbostic (void)signal(SIGWINCH, sigwinch); 36425341Smckusick } 36524726Smckusick dosigwinch = 1; 36624726Smckusick } 36724726Smckusick 36840858Sbostic void 36940858Sbostic catch_child() 37011803Sedward { 37111803Sedward union wait status; 37211803Sedward int pid; 37311803Sedward 37440858Sbostic for (;;) { 37540858Sbostic pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); 37640858Sbostic if (pid == 0) 37740858Sbostic return; 37840858Sbostic /* if the child (reader) dies, just quit */ 37940858Sbostic if (pid < 0 || pid == child && !WIFSTOPPED(status)) 38040858Sbostic done((int)(status.w_termsig | status.w_retcode)); 38140858Sbostic } 38240858Sbostic /* NOTREACHED */ 38311803Sedward } 38411803Sedward 3856444Swnj /* 3869365Ssam * writer: write to remote: 0 -> line. 3879365Ssam * ~. terminate 3889365Ssam * ~^Z suspend rlogin process. 38910415Ssam * ~^Y suspend rlogin process, but leave reader alone. 3906444Swnj */ 3919365Ssam writer() 3926444Swnj { 39323530Sbloom char c; 39440858Sbostic register int bol, local, n; 3956444Swnj 39640858Sbostic bol = 1; /* beginning of line */ 39740858Sbostic local = 0; 39811803Sedward for (;;) { 39940858Sbostic n = read(STDIN_FILENO, &c, 1); 40018358Ssam if (n <= 0) { 40118358Ssam if (n < 0 && errno == EINTR) 40218358Ssam continue; 40311803Sedward break; 40418358Ssam } 4059365Ssam /* 40640858Sbostic * If we're at the beginning of the line and recognize a 40740858Sbostic * command character, then we echo locally. Otherwise, 40840858Sbostic * characters are echo'd remotely. If the command character 40940858Sbostic * is doubled, this acts as a force and local echo is 41040858Sbostic * suppressed. 4119365Ssam */ 41223530Sbloom if (bol) { 41323530Sbloom bol = 0; 41423530Sbloom if (c == cmdchar) { 41523530Sbloom bol = 0; 41623530Sbloom local = 1; 41723530Sbloom continue; 4186444Swnj } 41923530Sbloom } else if (local) { 42023530Sbloom local = 0; 42123530Sbloom if (c == '.' || c == deftc.t_eofc) { 42223530Sbloom echo(c); 42323530Sbloom break; 4246444Swnj } 42523530Sbloom if (c == defltc.t_suspc || c == defltc.t_dsuspc) { 42623530Sbloom bol = 1; 42723530Sbloom echo(c); 42823530Sbloom stop(c); 42923530Sbloom continue; 43023530Sbloom } 43136511Skfall if (c != cmdchar) { 43240858Sbostic #ifdef KERBEROS 43340858Sbostic if (encrypt) { 43440858Sbostic (void)des_write(rem, &cmdchar, 1); 43536511Skfall } else 43636511Skfall #endif 43740858Sbostic (void)write(rem, &cmdchar, 1); 43836511Skfall } 4396444Swnj } 44036511Skfall 44140858Sbostic #ifdef KERBEROS 44240858Sbostic if (encrypt) { 44336511Skfall if (des_write(rem, &c, 1) == 0) { 44440858Sbostic msg("line gone"); 44536511Skfall break; 44636511Skfall } 44736511Skfall } else 44836511Skfall #endif 44936511Skfall if (write(rem, &c, 1) == 0) { 45040858Sbostic msg("line gone"); 45136511Skfall break; 45236511Skfall } 45323530Sbloom bol = c == defkill || c == deftc.t_eofc || 45425424Skarels c == deftc.t_intrc || c == defltc.t_suspc || 45523530Sbloom c == '\r' || c == '\n'; 4566444Swnj } 4576444Swnj } 4586444Swnj 45923530Sbloom echo(c) 46023530Sbloom register char c; 46123530Sbloom { 46240858Sbostic register char *p; 46323530Sbloom char buf[8]; 46423530Sbloom 46540858Sbostic p = buf; 46623530Sbloom c &= 0177; 46723530Sbloom *p++ = cmdchar; 46823530Sbloom if (c < ' ') { 46923530Sbloom *p++ = '^'; 47023530Sbloom *p++ = c + '@'; 47123530Sbloom } else if (c == 0177) { 47223530Sbloom *p++ = '^'; 47323530Sbloom *p++ = '?'; 47423530Sbloom } else 47523530Sbloom *p++ = c; 47623530Sbloom *p++ = '\r'; 47723530Sbloom *p++ = '\n'; 47840858Sbostic (void)write(1, buf, p - buf); 47923530Sbloom } 48023530Sbloom 48118358Ssam stop(cmdc) 48218358Ssam char cmdc; 48318358Ssam { 48418358Ssam mode(0); 48540858Sbostic (void)signal(SIGCHLD, SIG_IGN); 48640858Sbostic (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); 48740858Sbostic (void)signal(SIGCHLD, catch_child); 48818358Ssam mode(1); 48918358Ssam sigwinch(); /* check for size changes */ 49018358Ssam } 49118358Ssam 49240858Sbostic void 49318358Ssam sigwinch() 49418358Ssam { 49518358Ssam struct winsize ws; 49618358Ssam 49729729Smckusick if (dosigwinch && get_window_size(0, &ws) == 0 && 49840858Sbostic bcmp(&ws, &winsize, sizeof(ws))) { 49918358Ssam winsize = ws; 50024726Smckusick sendwindow(); 50118358Ssam } 50218358Ssam } 50318358Ssam 50424726Smckusick /* 50524726Smckusick * Send the window size to the server via the magic escape 50624726Smckusick */ 50724726Smckusick sendwindow() 50824726Smckusick { 50940858Sbostic struct winsize *wp; 51024726Smckusick char obuf[4 + sizeof (struct winsize)]; 51124726Smckusick 51240858Sbostic wp = (struct winsize *)(obuf+4); 51324726Smckusick obuf[0] = 0377; 51424726Smckusick obuf[1] = 0377; 51524726Smckusick obuf[2] = 's'; 51624726Smckusick obuf[3] = 's'; 51724726Smckusick wp->ws_row = htons(winsize.ws_row); 51824726Smckusick wp->ws_col = htons(winsize.ws_col); 51924726Smckusick wp->ws_xpixel = htons(winsize.ws_xpixel); 52024726Smckusick wp->ws_ypixel = htons(winsize.ws_ypixel); 52136511Skfall 52240858Sbostic #ifdef KERBEROS 52336511Skfall if(encrypt) 52440858Sbostic (void)des_write(rem, obuf, sizeof(obuf)); 52536511Skfall else 52636511Skfall #endif 52740858Sbostic (void)write(rem, obuf, sizeof(obuf)); 52824726Smckusick } 52924726Smckusick 53025424Skarels /* 53125424Skarels * reader: read from remote: line -> 1 53225424Skarels */ 53325424Skarels #define READING 1 53425424Skarels #define WRITING 2 53525424Skarels 53640858Sbostic jmp_buf rcvtop; 53740858Sbostic int ppid, rcvcnt, rcvstate; 53840858Sbostic char rcvbuf[8 * 1024]; 53925424Skarels 54040858Sbostic void 5416444Swnj oob() 5426444Swnj { 54340858Sbostic struct sgttyb sb; 54440858Sbostic int atmark, n, out, rcvd; 5459365Ssam char waste[BUFSIZ], mark; 5466444Swnj 54740858Sbostic out = FWRITE; 54840858Sbostic rcvd = 0; 54925424Skarels while (recv(rem, &mark, 1, MSG_OOB) < 0) 55025424Skarels switch (errno) { 55125424Skarels case EWOULDBLOCK: 55225424Skarels /* 55340858Sbostic * Urgent data not here yet. It may not be possible 55440858Sbostic * to send it yet if we are blocked for output and 55540858Sbostic * our input buffer is full. 55625424Skarels */ 55725424Skarels if (rcvcnt < sizeof(rcvbuf)) { 55825424Skarels n = read(rem, rcvbuf + rcvcnt, 55940858Sbostic sizeof(rcvbuf) - rcvcnt); 56025424Skarels if (n <= 0) 56125424Skarels return; 56225424Skarels rcvd += n; 56325424Skarels } else { 56425424Skarels n = read(rem, waste, sizeof(waste)); 56525424Skarels if (n <= 0) 56625424Skarels return; 56725424Skarels } 56825424Skarels continue; 56925424Skarels default: 57025424Skarels return; 5716444Swnj } 57225424Skarels if (mark & TIOCPKT_WINDOW) { 57340858Sbostic /* Let server know about window size changes */ 57440858Sbostic (void)kill(ppid, SIGUSR1); 57524726Smckusick } 57625424Skarels if (!eight && (mark & TIOCPKT_NOSTOP)) { 57740858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 57824726Smckusick sb.sg_flags &= ~CBREAK; 57924726Smckusick sb.sg_flags |= RAW; 58040858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 58113075Ssam notc.t_stopc = -1; 58213075Ssam notc.t_startc = -1; 58340858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5846444Swnj } 58525424Skarels if (!eight && (mark & TIOCPKT_DOSTOP)) { 58640858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 58724726Smckusick sb.sg_flags &= ~RAW; 58824726Smckusick sb.sg_flags |= CBREAK; 58940858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 59013075Ssam notc.t_stopc = deftc.t_stopc; 59113075Ssam notc.t_startc = deftc.t_startc; 59240858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5936444Swnj } 59425424Skarels if (mark & TIOCPKT_FLUSHWRITE) { 59540858Sbostic (void)ioctl(1, TIOCFLUSH, (char *)&out); 59625424Skarels for (;;) { 59725424Skarels if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 59840858Sbostic (void)fprintf(stderr, "rlogin: ioctl: %s.\n", 59940858Sbostic strerror(errno)); 60025424Skarels break; 60125424Skarels } 60225424Skarels if (atmark) 60325424Skarels break; 60425424Skarels n = read(rem, waste, sizeof (waste)); 60525424Skarels if (n <= 0) 60625424Skarels break; 60725424Skarels } 60825424Skarels /* 60940858Sbostic * Don't want any pending data to be output, so clear the recv 61040858Sbostic * buffer. If we were hanging on a write when interrupted, 61140858Sbostic * don't want it to restart. If we were reading, restart 61240858Sbostic * anyway. 61325424Skarels */ 61425424Skarels rcvcnt = 0; 61525424Skarels longjmp(rcvtop, 1); 61625424Skarels } 61729729Smckusick 61840858Sbostic /* oob does not do FLUSHREAD (alas!) */ 61929729Smckusick 62029729Smckusick /* 62140858Sbostic * If we filled the receive buffer while a read was pending, longjmp 62240858Sbostic * to the top to restart appropriately. Don't abort a pending write, 62340858Sbostic * however, or we won't know how much was written. 62425424Skarels */ 62525424Skarels if (rcvd && rcvstate == READING) 62625424Skarels longjmp(rcvtop, 1); 6276444Swnj } 6286444Swnj 62940858Sbostic /* reader: read from remote: line -> 1 */ 63040858Sbostic reader(omask) 63140858Sbostic int omask; 6326444Swnj { 63340858Sbostic void oob(); 63440858Sbostic 63526981Skarels #if !defined(BSD) || BSD < 43 63626981Skarels int pid = -getpid(); 63726981Skarels #else 63825424Skarels int pid = getpid(); 63926981Skarels #endif 64025424Skarels int n, remaining; 64125424Skarels char *bufp = rcvbuf; 6426444Swnj 64340858Sbostic (void)signal(SIGTTOU, SIG_IGN); 64440858Sbostic (void)signal(SIGURG, oob); 64526981Skarels ppid = getppid(); 64640858Sbostic (void)fcntl(rem, F_SETOWN, pid); 64740858Sbostic (void)setjmp(rcvtop); 64840858Sbostic (void)sigsetmask(omask); 6496444Swnj for (;;) { 65025424Skarels while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { 65125424Skarels rcvstate = WRITING; 65225424Skarels n = write(1, bufp, remaining); 65325424Skarels if (n < 0) { 65425424Skarels if (errno != EINTR) 65540858Sbostic return(-1); 65625424Skarels continue; 65725424Skarels } 65825424Skarels bufp += n; 65925424Skarels } 66025424Skarels bufp = rcvbuf; 66125424Skarels rcvcnt = 0; 66225424Skarels rcvstate = READING; 66336511Skfall 66440858Sbostic #ifdef KERBEROS 66540858Sbostic if (encrypt) 66636511Skfall rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf)); 66736511Skfall else 66836511Skfall #endif 66936511Skfall rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); 67025424Skarels if (rcvcnt == 0) 67125424Skarels return (0); 67225424Skarels if (rcvcnt < 0) { 6739365Ssam if (errno == EINTR) 6746444Swnj continue; 67540858Sbostic (void)fprintf(stderr, "rlogin: read: %s.\n", 67640858Sbostic strerror(errno)); 67740858Sbostic return(-1); 6786444Swnj } 6796444Swnj } 6806444Swnj } 6816444Swnj 6826444Swnj mode(f) 6836444Swnj { 68413075Ssam struct ltchars *ltc; 68513075Ssam struct sgttyb sb; 68640858Sbostic struct tchars *tc; 68740858Sbostic int lflags; 6889365Ssam 68940858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 69040858Sbostic (void)ioctl(0, TIOCLGET, (char *)&lflags); 69140858Sbostic switch(f) { 6929962Ssam case 0: 69313075Ssam sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); 69413075Ssam sb.sg_flags |= defflags|tabflag; 6959962Ssam tc = &deftc; 69613075Ssam ltc = &defltc; 69713075Ssam sb.sg_kill = defkill; 69813075Ssam sb.sg_erase = deferase; 69921583Sbloom lflags = deflflags; 7009962Ssam break; 7019962Ssam case 1: 70213075Ssam sb.sg_flags |= (eight ? RAW : CBREAK); 70313075Ssam sb.sg_flags &= ~defflags; 70412155Ssam /* preserve tab delays, but turn off XTABS */ 70513075Ssam if ((sb.sg_flags & TBDELAY) == XTABS) 70613075Ssam sb.sg_flags &= ~TBDELAY; 7079962Ssam tc = ¬c; 70813075Ssam ltc = &noltc; 70913075Ssam sb.sg_kill = sb.sg_erase = -1; 71021583Sbloom if (litout) 71121583Sbloom lflags |= LLITOUT; 7129962Ssam break; 7139962Ssam default: 7149962Ssam return; 7156444Swnj } 71640858Sbostic (void)ioctl(0, TIOCSLTC, (char *)ltc); 71740858Sbostic (void)ioctl(0, TIOCSETC, (char *)tc); 71840858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 71940858Sbostic (void)ioctl(0, TIOCLSET, (char *)&lflags); 7206444Swnj } 7216444Swnj 72240858Sbostic void 72340858Sbostic lostpeer() 7246444Swnj { 72540858Sbostic (void)signal(SIGPIPE, SIG_IGN); 72640858Sbostic msg("\007connection closed."); 72740858Sbostic done(1); 72840858Sbostic } 72929729Smckusick 73040858Sbostic /* copy SIGURGs to the child process. */ 73140858Sbostic void 73240858Sbostic copytochild() 73340858Sbostic { 73440858Sbostic (void)kill(child, SIGURG); 7356444Swnj } 7366444Swnj 73740858Sbostic msg(str) 73840858Sbostic char *str; 7396444Swnj { 74040858Sbostic (void)fprintf(stderr, "rlogin: %s\r\n", str); 74140858Sbostic } 74229729Smckusick 74340858Sbostic #ifdef KERBEROS 74440858Sbostic /* VARARGS */ 74540858Sbostic warning(va_alist) 74640858Sbostic va_dcl 74740858Sbostic { 74840858Sbostic va_list ap; 74940858Sbostic char *fmt; 75040858Sbostic 75140858Sbostic (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); 75240858Sbostic va_start(ap); 75340858Sbostic fmt = va_arg(ap, char *); 75440858Sbostic vfprintf(stderr, fmt, ap); 75540858Sbostic va_end(ap); 75640858Sbostic (void)fprintf(stderr, ".\n"); 7576444Swnj } 75840858Sbostic #endif 75936512Skfall 76040858Sbostic usage() 76136512Skfall { 76240858Sbostic (void)fprintf(stderr, 76340858Sbostic "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", 76440858Sbostic #ifdef KERBEROS 76540858Sbostic "8Lx", " [-k realm] "); 76640858Sbostic #else 76740858Sbostic "8L", " "); 76840858Sbostic #endif 76940858Sbostic exit(1); 77036512Skfall } 77140858Sbostic 77240858Sbostic /* 77340858Sbostic * The following routine provides compatibility (such as it is) between 4.2BSD 77440858Sbostic * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. 77540858Sbostic */ 77640858Sbostic #ifdef sun 77740858Sbostic int 77840858Sbostic get_window_size(fd, wp) 77940858Sbostic int fd; 78040858Sbostic struct winsize *wp; 78140858Sbostic { 78240858Sbostic struct ttysize ts; 78340858Sbostic int error; 78440858Sbostic 78540858Sbostic if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) 78640858Sbostic return(error); 78740858Sbostic wp->ws_row = ts.ts_lines; 78840858Sbostic wp->ws_col = ts.ts_cols; 78940858Sbostic wp->ws_xpixel = 0; 79040858Sbostic wp->ws_ypixel = 0; 79140858Sbostic return(0); 79240858Sbostic } 79340858Sbostic #endif 794