140858Sbostic /*- 240858Sbostic * Copyright (c) 1983, 1990 The Regents of the University of California. 335539Sbostic * All rights reserved. 435539Sbostic * 5*42763Sbostic * %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*42763Sbostic static char sccsid[] = "@(#)rlogin.c 5.28 (Berkeley) 06/01/90"; 1635539Sbostic #endif /* not lint */ 1721595Sdist 1812990Ssam /* 1940858Sbostic * $Source: mit/rlogin/RCS/rlogin.c,v $ 20*42763Sbostic * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall 21*42763Sbostic * Exp Locker: kfall $ 2240858Sbostic */ 2340858Sbostic 2440858Sbostic /* 2512990Ssam * rlogin - remote login 2612990Ssam */ 2726981Skarels #include <sys/param.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> 4542058Sbostic #include <string.h> 466444Swnj 4740858Sbostic #ifdef KERBEROS 4841760Skfall #include <kerberosIV/des.h> 4940683Sbostic #include <kerberosIV/krb.h> 5036511Skfall 5140858Sbostic CREDENTIALS cred; 5240858Sbostic Key_schedule schedule; 5340858Sbostic int use_kerberos = 1, encrypt; 5440858Sbostic char dst_realm_buf[REALM_SZ], *dest_realm = NULL; 5540858Sbostic extern char *krb_realmofhost(); 5640858Sbostic #endif 5724726Smckusick 5840858Sbostic #ifndef TIOCPKT_WINDOW 5940858Sbostic #define TIOCPKT_WINDOW 0x80 6040858Sbostic #endif 6129729Smckusick 6240858Sbostic /* concession to Sun */ 6340858Sbostic #ifndef SIGUSR1 6440858Sbostic #define SIGUSR1 30 6526981Skarels #endif 6640858Sbostic 6740858Sbostic extern int errno; 6840858Sbostic int eight, litout, rem; 6940858Sbostic char cmdchar; 7040858Sbostic char *speeds[] = { 7140858Sbostic "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", 7240858Sbostic "1800", "2400", "4800", "9600", "19200", "38400" 7340858Sbostic }; 7440858Sbostic 7526981Skarels #ifdef sun 7626981Skarels struct winsize { 7726981Skarels unsigned short ws_row, ws_col; 7826981Skarels unsigned short ws_xpixel, ws_ypixel; 7926981Skarels }; 8040858Sbostic #endif 8118358Ssam struct winsize winsize; 826444Swnj 8340858Sbostic #ifndef sun 8440858Sbostic #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) 8540858Sbostic #endif 8629729Smckusick 8740858Sbostic void exit(); 8829729Smckusick 896444Swnj main(argc, argv) 906444Swnj int argc; 916444Swnj char **argv; 926444Swnj { 9340858Sbostic extern char *optarg; 9440858Sbostic extern int optind; 9540858Sbostic struct passwd *pw; 9640858Sbostic struct servent *sp; 976444Swnj struct sgttyb ttyb; 9840858Sbostic long omask; 9940858Sbostic int argoff, ch, dflag, one, uid; 10040858Sbostic char *host, *p, *user, term[1024]; 10140858Sbostic void lostpeer(); 10240858Sbostic char *getenv(); 1036444Swnj 10440858Sbostic argoff = dflag = 0; 10540858Sbostic one = 1; 10640858Sbostic host = user = NULL; 10740858Sbostic cmdchar = '~'; 10840858Sbostic 10940858Sbostic if (p = rindex(argv[0], '/')) 11040858Sbostic ++p; 1116444Swnj else 11240858Sbostic p = argv[0]; 11340858Sbostic 11440858Sbostic if (strcmp(p, "rlogin")) 11540858Sbostic host = p; 11640858Sbostic 11740858Sbostic /* handle "rlogin host flags" */ 11840858Sbostic if (!host && argc > 2 && argv[1][0] != '-') { 11940858Sbostic host = argv[1]; 12040858Sbostic argoff = 1; 1216444Swnj } 12236511Skfall 12340858Sbostic #ifdef KERBEROS 12440868Sbostic #define OPTIONS "8KLde:k:l:x" 12540858Sbostic #else 12640868Sbostic #define OPTIONS "8KLde:l:" 12740858Sbostic #endif 12840858Sbostic while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) 12940858Sbostic switch(ch) { 13040858Sbostic case '8': 13140858Sbostic eight = 1; 13240858Sbostic break; 13340868Sbostic case 'K': 13440868Sbostic #ifdef KERBEROS 13540868Sbostic use_kerberos = 0; 13640868Sbostic #endif 13740868Sbostic break; 13840858Sbostic case 'L': 13940858Sbostic litout = 1; 14040858Sbostic break; 14140858Sbostic case 'd': 14240858Sbostic dflag = 1; 14340858Sbostic break; 14440858Sbostic case 'e': 14540858Sbostic cmdchar = optarg[0]; 14640858Sbostic break; 14740858Sbostic #ifdef KERBEROS 14840858Sbostic case 'k': 14940858Sbostic dest_realm = dst_realm_buf; 15040858Sbostic (void)strncpy(dest_realm, optarg, REALM_SZ); 15140858Sbostic break; 15240858Sbostic #endif 15340858Sbostic case 'l': 15440858Sbostic user = optarg; 15540858Sbostic break; 15640858Sbostic #ifdef KERBEROS 15740858Sbostic case 'x': 15840858Sbostic encrypt = 1; 15940858Sbostic des_set_key(cred.session, schedule); 16040858Sbostic break; 16140858Sbostic #endif 16240858Sbostic case '?': 16340858Sbostic default: 16440858Sbostic usage(); 16536524Skfall } 16640858Sbostic optind += argoff; 16740858Sbostic argc -= optind; 16840858Sbostic argv += optind; 16936524Skfall 17040858Sbostic /* if haven't gotten a host yet, do so */ 17140858Sbostic if (!host && !(host = *argv++)) 17240858Sbostic usage(); 17336511Skfall 17440858Sbostic if (*argv) 17540858Sbostic usage(); 17640858Sbostic 17740858Sbostic if (!(pw = getpwuid(uid = getuid()))) { 17840858Sbostic (void)fprintf(stderr, "rlogin: unknown user id.\n"); 1796444Swnj exit(1); 1806444Swnj } 18140858Sbostic if (!user) 18240858Sbostic user = pw->pw_name; 18340858Sbostic 18440868Sbostic sp = NULL; 18540858Sbostic #ifdef KERBEROS 18640868Sbostic if (use_kerberos) { 18740868Sbostic sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp"); 18840868Sbostic if (sp == NULL) { 18940868Sbostic use_kerberos = 0; 19040868Sbostic warning("can't get entry for %s/tcp service", 19140868Sbostic encrypt ? "eklogin" : "klogin"); 19240868Sbostic } 19336512Skfall } 19436512Skfall #endif 19540868Sbostic if (sp == NULL) 19640868Sbostic sp = getservbyname("login", "tcp"); 19740858Sbostic if (sp == NULL) { 19840858Sbostic (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); 19940858Sbostic exit(1); 2009365Ssam } 20140858Sbostic 20240858Sbostic (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); 20318358Ssam if (ioctl(0, TIOCGETP, &ttyb) == 0) { 20440858Sbostic (void)strcat(term, "/"); 20540858Sbostic (void)strcat(term, speeds[ttyb.sg_ospeed]); 2066444Swnj } 20740858Sbostic 20840858Sbostic (void)get_window_size(0, &winsize); 20940858Sbostic 21040858Sbostic (void)signal(SIGPIPE, lostpeer); 21129729Smckusick /* will use SIGUSR1 for window size hack, so hold it off */ 21240858Sbostic omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); 21336511Skfall 21440858Sbostic #ifdef KERBEROS 21536512Skfall try_connect: 21640858Sbostic if (use_kerberos) { 21736512Skfall rem = KSUCCESS; 21840858Sbostic errno = 0; 21938728Skfall if (dest_realm == NULL) 22038728Skfall dest_realm = krb_realmofhost(host); 22138728Skfall 22240858Sbostic if (encrypt) 22340858Sbostic rem = krcmd_mutual(&host, sp->s_port, user, term, 0, 22440858Sbostic dest_realm, &cred, schedule); 22540858Sbostic else 22640858Sbostic rem = krcmd(&host, sp->s_port, user, term, 0, 22740858Sbostic dest_realm); 22838728Skfall if (rem < 0) { 22936512Skfall use_kerberos = 0; 23036628Skfall sp = getservbyname("login", "tcp"); 23140858Sbostic if (sp == NULL) { 23240858Sbostic (void)fprintf(stderr, 23340858Sbostic "rlogin: unknown service login/tcp.\n"); 23436628Skfall exit(1); 23536628Skfall } 23638728Skfall if (errno == ECONNREFUSED) 23740858Sbostic warning("remote host doesn't support Kerberos"); 23838728Skfall if (errno == ENOENT) 23940858Sbostic warning("can't provide Kerberos auth data"); 24036512Skfall goto try_connect; 24136512Skfall } 24236511Skfall } else { 24340858Sbostic if (encrypt) { 24440858Sbostic (void)fprintf(stderr, 24540858Sbostic "rlogin: the -x flag requires Kerberos authentication.\n"); 24636512Skfall exit(1); 24736512Skfall } 24840858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 24936511Skfall } 25036512Skfall #else 25140858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 25236512Skfall #endif 25336511Skfall 25440858Sbostic if (rem < 0) 25536511Skfall exit(1); 25636511Skfall 25740858Sbostic if (dflag && 25840858Sbostic setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) 25940858Sbostic (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", 26040858Sbostic strerror(errno)); 26140858Sbostic 26240858Sbostic (void)setuid(uid); 26340858Sbostic doit(omask); 2649365Ssam /*NOTREACHED*/ 2656444Swnj } 2666444Swnj 26740858Sbostic int child, defflags, deflflags, tabflag; 26840858Sbostic char deferase, defkill; 26940858Sbostic struct tchars deftc; 27040858Sbostic struct ltchars defltc; 27140858Sbostic struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 27240858Sbostic struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 2736444Swnj 27440858Sbostic doit(omask) 27540858Sbostic long omask; 2766444Swnj { 27713075Ssam struct sgttyb sb; 27840858Sbostic void catch_child(), copytochild(), exit(), writeroob(); 2796444Swnj 28040858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 28113075Ssam defflags = sb.sg_flags; 28212155Ssam tabflag = defflags & TBDELAY; 2839962Ssam defflags &= ECHO | CRMOD; 28413075Ssam deferase = sb.sg_erase; 28513075Ssam defkill = sb.sg_kill; 28640858Sbostic (void)ioctl(0, TIOCLGET, (char *)&deflflags); 28740858Sbostic (void)ioctl(0, TIOCGETC, (char *)&deftc); 28813075Ssam notc.t_startc = deftc.t_startc; 28913075Ssam notc.t_stopc = deftc.t_stopc; 29040858Sbostic (void)ioctl(0, TIOCGLTC, (char *)&defltc); 29140858Sbostic (void)signal(SIGINT, SIG_IGN); 29229729Smckusick setsignal(SIGHUP, exit); 29329729Smckusick setsignal(SIGQUIT, exit); 2949365Ssam child = fork(); 2959365Ssam if (child == -1) { 29640858Sbostic (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); 29725424Skarels done(1); 2989365Ssam } 2999365Ssam if (child == 0) { 30024726Smckusick mode(1); 30140858Sbostic if (reader(omask) == 0) { 30240858Sbostic msg("connection closed."); 30325424Skarels exit(0); 30425424Skarels } 30512155Ssam sleep(1); 30640858Sbostic msg("\007connection closed."); 30740858Sbostic exit(1); 3086444Swnj } 30929729Smckusick 31029729Smckusick /* 31140858Sbostic * We may still own the socket, and may have a pending SIGURG (or might 31240858Sbostic * receive one soon) that we really want to send to the reader. Set a 31340858Sbostic * trap that simply copies such signals to the child. 31429729Smckusick */ 31540858Sbostic (void)signal(SIGURG, copytochild); 31640858Sbostic (void)signal(SIGUSR1, writeroob); 31740858Sbostic (void)sigsetmask(omask); 31840858Sbostic (void)signal(SIGCHLD, catch_child); 3199365Ssam writer(); 32040858Sbostic msg("closed connection."); 32125424Skarels done(0); 3226444Swnj } 3236444Swnj 32440858Sbostic /* trap a signal, unless it is being ignored. */ 32529729Smckusick setsignal(sig, act) 32640858Sbostic int sig; 32740858Sbostic void (*act)(); 32829729Smckusick { 32929729Smckusick int omask = sigblock(sigmask(sig)); 33029729Smckusick 33129729Smckusick if (signal(sig, act) == SIG_IGN) 33240858Sbostic (void)signal(sig, SIG_IGN); 33340858Sbostic (void)sigsetmask(omask); 33429729Smckusick } 33529729Smckusick 33625424Skarels done(status) 33725424Skarels int status; 3386444Swnj { 33929729Smckusick int w; 3406444Swnj 3416444Swnj mode(0); 34229729Smckusick if (child > 0) { 34340858Sbostic /* make sure catch_child does not snap it up */ 34440858Sbostic (void)signal(SIGCHLD, SIG_DFL); 34529729Smckusick if (kill(child, SIGKILL) >= 0) 34640858Sbostic while ((w = wait((union wait *)0)) > 0 && w != child); 34729729Smckusick } 34825424Skarels exit(status); 3496444Swnj } 3506444Swnj 35140858Sbostic int dosigwinch; 35229729Smckusick 35329729Smckusick /* 35424726Smckusick * This is called when the reader process gets the out-of-band (urgent) 35524726Smckusick * request to turn on the window-changing protocol. 35624726Smckusick */ 35740858Sbostic void 35824726Smckusick writeroob() 35924726Smckusick { 36040858Sbostic void sigwinch(); 36124726Smckusick 36225341Smckusick if (dosigwinch == 0) { 36324919Smckusick sendwindow(); 36440858Sbostic (void)signal(SIGWINCH, sigwinch); 36525341Smckusick } 36624726Smckusick dosigwinch = 1; 36724726Smckusick } 36824726Smckusick 36940858Sbostic void 37040858Sbostic catch_child() 37111803Sedward { 37211803Sedward union wait status; 37311803Sedward int pid; 37411803Sedward 37540858Sbostic for (;;) { 37640858Sbostic pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); 37740858Sbostic if (pid == 0) 37840858Sbostic return; 37940858Sbostic /* if the child (reader) dies, just quit */ 38040858Sbostic if (pid < 0 || pid == child && !WIFSTOPPED(status)) 38140858Sbostic done((int)(status.w_termsig | status.w_retcode)); 38240858Sbostic } 38340858Sbostic /* NOTREACHED */ 38411803Sedward } 38511803Sedward 3866444Swnj /* 3879365Ssam * writer: write to remote: 0 -> line. 3889365Ssam * ~. terminate 3899365Ssam * ~^Z suspend rlogin process. 39010415Ssam * ~^Y suspend rlogin process, but leave reader alone. 3916444Swnj */ 3929365Ssam writer() 3936444Swnj { 39423530Sbloom char c; 39540858Sbostic register int bol, local, n; 3966444Swnj 39740858Sbostic bol = 1; /* beginning of line */ 39840858Sbostic local = 0; 39911803Sedward for (;;) { 40040858Sbostic n = read(STDIN_FILENO, &c, 1); 40118358Ssam if (n <= 0) { 40218358Ssam if (n < 0 && errno == EINTR) 40318358Ssam continue; 40411803Sedward break; 40518358Ssam } 4069365Ssam /* 40740858Sbostic * If we're at the beginning of the line and recognize a 40840858Sbostic * command character, then we echo locally. Otherwise, 40940858Sbostic * characters are echo'd remotely. If the command character 41040858Sbostic * is doubled, this acts as a force and local echo is 41140858Sbostic * suppressed. 4129365Ssam */ 41323530Sbloom if (bol) { 41423530Sbloom bol = 0; 41523530Sbloom if (c == cmdchar) { 41623530Sbloom bol = 0; 41723530Sbloom local = 1; 41823530Sbloom continue; 4196444Swnj } 42023530Sbloom } else if (local) { 42123530Sbloom local = 0; 42223530Sbloom if (c == '.' || c == deftc.t_eofc) { 42323530Sbloom echo(c); 42423530Sbloom break; 4256444Swnj } 42623530Sbloom if (c == defltc.t_suspc || c == defltc.t_dsuspc) { 42723530Sbloom bol = 1; 42823530Sbloom echo(c); 42923530Sbloom stop(c); 43023530Sbloom continue; 43123530Sbloom } 43236511Skfall if (c != cmdchar) { 43340858Sbostic #ifdef KERBEROS 43440858Sbostic if (encrypt) { 43540858Sbostic (void)des_write(rem, &cmdchar, 1); 43636511Skfall } else 43736511Skfall #endif 43840858Sbostic (void)write(rem, &cmdchar, 1); 43936511Skfall } 4406444Swnj } 44136511Skfall 44240858Sbostic #ifdef KERBEROS 44340858Sbostic if (encrypt) { 44436511Skfall if (des_write(rem, &c, 1) == 0) { 44540858Sbostic msg("line gone"); 44636511Skfall break; 44736511Skfall } 44836511Skfall } else 44936511Skfall #endif 45036511Skfall if (write(rem, &c, 1) == 0) { 45140858Sbostic msg("line gone"); 45236511Skfall break; 45336511Skfall } 45423530Sbloom bol = c == defkill || c == deftc.t_eofc || 45525424Skarels c == deftc.t_intrc || c == defltc.t_suspc || 45623530Sbloom c == '\r' || c == '\n'; 4576444Swnj } 4586444Swnj } 4596444Swnj 46023530Sbloom echo(c) 46123530Sbloom register char c; 46223530Sbloom { 46340858Sbostic register char *p; 46423530Sbloom char buf[8]; 46523530Sbloom 46640858Sbostic p = buf; 46723530Sbloom c &= 0177; 46823530Sbloom *p++ = cmdchar; 46923530Sbloom if (c < ' ') { 47023530Sbloom *p++ = '^'; 47123530Sbloom *p++ = c + '@'; 47223530Sbloom } else if (c == 0177) { 47323530Sbloom *p++ = '^'; 47423530Sbloom *p++ = '?'; 47523530Sbloom } else 47623530Sbloom *p++ = c; 47723530Sbloom *p++ = '\r'; 47823530Sbloom *p++ = '\n'; 47940858Sbostic (void)write(1, buf, p - buf); 48023530Sbloom } 48123530Sbloom 48218358Ssam stop(cmdc) 48318358Ssam char cmdc; 48418358Ssam { 48518358Ssam mode(0); 48640858Sbostic (void)signal(SIGCHLD, SIG_IGN); 48740858Sbostic (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); 48840858Sbostic (void)signal(SIGCHLD, catch_child); 48918358Ssam mode(1); 49018358Ssam sigwinch(); /* check for size changes */ 49118358Ssam } 49218358Ssam 49340858Sbostic void 49418358Ssam sigwinch() 49518358Ssam { 49618358Ssam struct winsize ws; 49718358Ssam 49829729Smckusick if (dosigwinch && get_window_size(0, &ws) == 0 && 49940858Sbostic bcmp(&ws, &winsize, sizeof(ws))) { 50018358Ssam winsize = ws; 50124726Smckusick sendwindow(); 50218358Ssam } 50318358Ssam } 50418358Ssam 50524726Smckusick /* 50624726Smckusick * Send the window size to the server via the magic escape 50724726Smckusick */ 50824726Smckusick sendwindow() 50924726Smckusick { 51040858Sbostic struct winsize *wp; 51124726Smckusick char obuf[4 + sizeof (struct winsize)]; 51224726Smckusick 51340858Sbostic wp = (struct winsize *)(obuf+4); 51424726Smckusick obuf[0] = 0377; 51524726Smckusick obuf[1] = 0377; 51624726Smckusick obuf[2] = 's'; 51724726Smckusick obuf[3] = 's'; 51824726Smckusick wp->ws_row = htons(winsize.ws_row); 51924726Smckusick wp->ws_col = htons(winsize.ws_col); 52024726Smckusick wp->ws_xpixel = htons(winsize.ws_xpixel); 52124726Smckusick wp->ws_ypixel = htons(winsize.ws_ypixel); 52236511Skfall 52340858Sbostic #ifdef KERBEROS 52436511Skfall if(encrypt) 52540858Sbostic (void)des_write(rem, obuf, sizeof(obuf)); 52636511Skfall else 52736511Skfall #endif 52840858Sbostic (void)write(rem, obuf, sizeof(obuf)); 52924726Smckusick } 53024726Smckusick 53125424Skarels /* 53225424Skarels * reader: read from remote: line -> 1 53325424Skarels */ 53425424Skarels #define READING 1 53525424Skarels #define WRITING 2 53625424Skarels 53740858Sbostic jmp_buf rcvtop; 53840858Sbostic int ppid, rcvcnt, rcvstate; 53940858Sbostic char rcvbuf[8 * 1024]; 54025424Skarels 54140858Sbostic void 5426444Swnj oob() 5436444Swnj { 54440858Sbostic struct sgttyb sb; 54540858Sbostic int atmark, n, out, rcvd; 5469365Ssam char waste[BUFSIZ], mark; 5476444Swnj 54842230Sbostic out = O_RDWR; 54940858Sbostic rcvd = 0; 55025424Skarels while (recv(rem, &mark, 1, MSG_OOB) < 0) 55125424Skarels switch (errno) { 55225424Skarels case EWOULDBLOCK: 55325424Skarels /* 55440858Sbostic * Urgent data not here yet. It may not be possible 55540858Sbostic * to send it yet if we are blocked for output and 55640858Sbostic * our input buffer is full. 55725424Skarels */ 55825424Skarels if (rcvcnt < sizeof(rcvbuf)) { 55925424Skarels n = read(rem, rcvbuf + rcvcnt, 56040858Sbostic sizeof(rcvbuf) - rcvcnt); 56125424Skarels if (n <= 0) 56225424Skarels return; 56325424Skarels rcvd += n; 56425424Skarels } else { 56525424Skarels n = read(rem, waste, sizeof(waste)); 56625424Skarels if (n <= 0) 56725424Skarels return; 56825424Skarels } 56925424Skarels continue; 57025424Skarels default: 57125424Skarels return; 5726444Swnj } 57325424Skarels if (mark & TIOCPKT_WINDOW) { 57440858Sbostic /* Let server know about window size changes */ 57540858Sbostic (void)kill(ppid, SIGUSR1); 57624726Smckusick } 57725424Skarels if (!eight && (mark & TIOCPKT_NOSTOP)) { 57840858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 57924726Smckusick sb.sg_flags &= ~CBREAK; 58024726Smckusick sb.sg_flags |= RAW; 58140858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 58213075Ssam notc.t_stopc = -1; 58313075Ssam notc.t_startc = -1; 58440858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5856444Swnj } 58625424Skarels if (!eight && (mark & TIOCPKT_DOSTOP)) { 58740858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 58824726Smckusick sb.sg_flags &= ~RAW; 58924726Smckusick sb.sg_flags |= CBREAK; 59040858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 59113075Ssam notc.t_stopc = deftc.t_stopc; 59213075Ssam notc.t_startc = deftc.t_startc; 59340858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5946444Swnj } 59525424Skarels if (mark & TIOCPKT_FLUSHWRITE) { 59640858Sbostic (void)ioctl(1, TIOCFLUSH, (char *)&out); 59725424Skarels for (;;) { 59825424Skarels if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 59940858Sbostic (void)fprintf(stderr, "rlogin: ioctl: %s.\n", 60040858Sbostic strerror(errno)); 60125424Skarels break; 60225424Skarels } 60325424Skarels if (atmark) 60425424Skarels break; 60525424Skarels n = read(rem, waste, sizeof (waste)); 60625424Skarels if (n <= 0) 60725424Skarels break; 60825424Skarels } 60925424Skarels /* 61040858Sbostic * Don't want any pending data to be output, so clear the recv 61140858Sbostic * buffer. If we were hanging on a write when interrupted, 61240858Sbostic * don't want it to restart. If we were reading, restart 61340858Sbostic * anyway. 61425424Skarels */ 61525424Skarels rcvcnt = 0; 61625424Skarels longjmp(rcvtop, 1); 61725424Skarels } 61829729Smckusick 61940858Sbostic /* oob does not do FLUSHREAD (alas!) */ 62029729Smckusick 62129729Smckusick /* 62240858Sbostic * If we filled the receive buffer while a read was pending, longjmp 62340858Sbostic * to the top to restart appropriately. Don't abort a pending write, 62440858Sbostic * however, or we won't know how much was written. 62525424Skarels */ 62625424Skarels if (rcvd && rcvstate == READING) 62725424Skarels longjmp(rcvtop, 1); 6286444Swnj } 6296444Swnj 63040858Sbostic /* reader: read from remote: line -> 1 */ 63140858Sbostic reader(omask) 63240858Sbostic int omask; 6336444Swnj { 63440858Sbostic void oob(); 63540858Sbostic 63626981Skarels #if !defined(BSD) || BSD < 43 63726981Skarels int pid = -getpid(); 63826981Skarels #else 63925424Skarels int pid = getpid(); 64026981Skarels #endif 64125424Skarels int n, remaining; 64225424Skarels char *bufp = rcvbuf; 6436444Swnj 64440858Sbostic (void)signal(SIGTTOU, SIG_IGN); 64540858Sbostic (void)signal(SIGURG, oob); 64626981Skarels ppid = getppid(); 64740858Sbostic (void)fcntl(rem, F_SETOWN, pid); 64840858Sbostic (void)setjmp(rcvtop); 64940858Sbostic (void)sigsetmask(omask); 6506444Swnj for (;;) { 65125424Skarels while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { 65225424Skarels rcvstate = WRITING; 65325424Skarels n = write(1, bufp, remaining); 65425424Skarels if (n < 0) { 65525424Skarels if (errno != EINTR) 65640858Sbostic return(-1); 65725424Skarels continue; 65825424Skarels } 65925424Skarels bufp += n; 66025424Skarels } 66125424Skarels bufp = rcvbuf; 66225424Skarels rcvcnt = 0; 66325424Skarels rcvstate = READING; 66436511Skfall 66540858Sbostic #ifdef KERBEROS 66640858Sbostic if (encrypt) 66736511Skfall rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf)); 66836511Skfall else 66936511Skfall #endif 67036511Skfall rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); 67125424Skarels if (rcvcnt == 0) 67225424Skarels return (0); 67325424Skarels if (rcvcnt < 0) { 6749365Ssam if (errno == EINTR) 6756444Swnj continue; 67640858Sbostic (void)fprintf(stderr, "rlogin: read: %s.\n", 67740858Sbostic strerror(errno)); 67840858Sbostic return(-1); 6796444Swnj } 6806444Swnj } 6816444Swnj } 6826444Swnj 6836444Swnj mode(f) 6846444Swnj { 68513075Ssam struct ltchars *ltc; 68613075Ssam struct sgttyb sb; 68740858Sbostic struct tchars *tc; 68840858Sbostic int lflags; 6899365Ssam 69040858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 69140858Sbostic (void)ioctl(0, TIOCLGET, (char *)&lflags); 69240858Sbostic switch(f) { 6939962Ssam case 0: 69413075Ssam sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); 69513075Ssam sb.sg_flags |= defflags|tabflag; 6969962Ssam tc = &deftc; 69713075Ssam ltc = &defltc; 69813075Ssam sb.sg_kill = defkill; 69913075Ssam sb.sg_erase = deferase; 70021583Sbloom lflags = deflflags; 7019962Ssam break; 7029962Ssam case 1: 70313075Ssam sb.sg_flags |= (eight ? RAW : CBREAK); 70413075Ssam sb.sg_flags &= ~defflags; 70512155Ssam /* preserve tab delays, but turn off XTABS */ 70613075Ssam if ((sb.sg_flags & TBDELAY) == XTABS) 70713075Ssam sb.sg_flags &= ~TBDELAY; 7089962Ssam tc = ¬c; 70913075Ssam ltc = &noltc; 71013075Ssam sb.sg_kill = sb.sg_erase = -1; 71121583Sbloom if (litout) 71221583Sbloom lflags |= LLITOUT; 7139962Ssam break; 7149962Ssam default: 7159962Ssam return; 7166444Swnj } 71740858Sbostic (void)ioctl(0, TIOCSLTC, (char *)ltc); 71840858Sbostic (void)ioctl(0, TIOCSETC, (char *)tc); 71940858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 72040858Sbostic (void)ioctl(0, TIOCLSET, (char *)&lflags); 7216444Swnj } 7226444Swnj 72340858Sbostic void 72440858Sbostic lostpeer() 7256444Swnj { 72640858Sbostic (void)signal(SIGPIPE, SIG_IGN); 72740858Sbostic msg("\007connection closed."); 72840858Sbostic done(1); 72940858Sbostic } 73029729Smckusick 73140858Sbostic /* copy SIGURGs to the child process. */ 73240858Sbostic void 73340858Sbostic copytochild() 73440858Sbostic { 73540858Sbostic (void)kill(child, SIGURG); 7366444Swnj } 7376444Swnj 73840858Sbostic msg(str) 73940858Sbostic char *str; 7406444Swnj { 74140858Sbostic (void)fprintf(stderr, "rlogin: %s\r\n", str); 74240858Sbostic } 74329729Smckusick 74440858Sbostic #ifdef KERBEROS 74540858Sbostic /* VARARGS */ 74640858Sbostic warning(va_alist) 74740858Sbostic va_dcl 74840858Sbostic { 74940858Sbostic va_list ap; 75040858Sbostic char *fmt; 75140858Sbostic 75240858Sbostic (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); 75340858Sbostic va_start(ap); 75440858Sbostic fmt = va_arg(ap, char *); 75540858Sbostic vfprintf(stderr, fmt, ap); 75640858Sbostic va_end(ap); 75740858Sbostic (void)fprintf(stderr, ".\n"); 7586444Swnj } 75940858Sbostic #endif 76036512Skfall 76140858Sbostic usage() 76236512Skfall { 76340858Sbostic (void)fprintf(stderr, 76440858Sbostic "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", 76540858Sbostic #ifdef KERBEROS 76640858Sbostic "8Lx", " [-k realm] "); 76740858Sbostic #else 76840858Sbostic "8L", " "); 76940858Sbostic #endif 77040858Sbostic exit(1); 77136512Skfall } 77240858Sbostic 77340858Sbostic /* 77440858Sbostic * The following routine provides compatibility (such as it is) between 4.2BSD 77540858Sbostic * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. 77640858Sbostic */ 77740858Sbostic #ifdef sun 77840858Sbostic int 77940858Sbostic get_window_size(fd, wp) 78040858Sbostic int fd; 78140858Sbostic struct winsize *wp; 78240858Sbostic { 78340858Sbostic struct ttysize ts; 78440858Sbostic int error; 78540858Sbostic 78640858Sbostic if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) 78740858Sbostic return(error); 78840858Sbostic wp->ws_row = ts.ts_lines; 78940858Sbostic wp->ws_col = ts.ts_cols; 79040858Sbostic wp->ws_xpixel = 0; 79140858Sbostic wp->ws_ypixel = 0; 79240858Sbostic return(0); 79340858Sbostic } 79440858Sbostic #endif 795