1*40858Sbostic /*- 2*40858Sbostic * Copyright (c) 1983, 1990 The Regents of the University of California. 335539Sbostic * All rights reserved. 435539Sbostic * 5*40858Sbostic %sccs.include.redist.c% 621595Sdist */ 721595Sdist 86444Swnj #ifndef lint 921595Sdist char copyright[] = 10*40858Sbostic "@(#) 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*40858Sbostic static char sccsid[] = "@(#)rlogin.c 5.23 (Berkeley) 04/09/90"; 1635539Sbostic #endif /* not lint */ 1721595Sdist 1812990Ssam /* 19*40858Sbostic * $Source: mit/rlogin/RCS/rlogin.c,v $ 20*40858Sbostic * $Header: mit/rlogin/RCS/rlogin.c,v 5.2 89/07/26 12:11:21 kfall Exp Locker: kfall $ 21*40858Sbostic */ 22*40858Sbostic 23*40858Sbostic /* 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> 30*40858Sbostic #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> 36*40858Sbostic #include <netdb.h> 379365Ssam 389365Ssam #include <sgtty.h> 39*40858Sbostic #include <setjmp.h> 406444Swnj #include <errno.h> 41*40858Sbostic #include <varargs.h> 426444Swnj #include <pwd.h> 43*40858Sbostic #include <stdio.h> 44*40858Sbostic #include <unistd.h> 45*40858Sbostic #include <strings.h> 466444Swnj 47*40858Sbostic #ifdef KERBEROS 4840683Sbostic #include <kerberosIV/krb.h> 4936511Skfall 50*40858Sbostic CREDENTIALS cred; 51*40858Sbostic Key_schedule schedule; 52*40858Sbostic int use_kerberos = 1, encrypt; 53*40858Sbostic char dst_realm_buf[REALM_SZ], *dest_realm = NULL; 54*40858Sbostic extern char *krb_realmofhost(); 55*40858Sbostic #endif 5624726Smckusick 57*40858Sbostic #ifndef TIOCPKT_WINDOW 58*40858Sbostic #define TIOCPKT_WINDOW 0x80 59*40858Sbostic #endif 6029729Smckusick 61*40858Sbostic /* concession to Sun */ 62*40858Sbostic #ifndef SIGUSR1 63*40858Sbostic #define SIGUSR1 30 6426981Skarels #endif 65*40858Sbostic 66*40858Sbostic extern int errno; 67*40858Sbostic int eight, litout, rem; 68*40858Sbostic char cmdchar; 69*40858Sbostic char *speeds[] = { 70*40858Sbostic "0", "50", "75", "110", "134", "150", "200", "300", "600", "1200", 71*40858Sbostic "1800", "2400", "4800", "9600", "19200", "38400" 72*40858Sbostic }; 73*40858Sbostic 7426981Skarels #ifdef sun 7526981Skarels struct winsize { 7626981Skarels unsigned short ws_row, ws_col; 7726981Skarels unsigned short ws_xpixel, ws_ypixel; 7826981Skarels }; 79*40858Sbostic #endif 8018358Ssam struct winsize winsize; 816444Swnj 82*40858Sbostic #ifndef sun 83*40858Sbostic #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) 84*40858Sbostic #endif 8529729Smckusick 86*40858Sbostic void exit(); 8729729Smckusick 886444Swnj main(argc, argv) 896444Swnj int argc; 906444Swnj char **argv; 916444Swnj { 92*40858Sbostic extern char *optarg; 93*40858Sbostic extern int optind; 94*40858Sbostic struct passwd *pw; 95*40858Sbostic struct servent *sp; 966444Swnj struct sgttyb ttyb; 97*40858Sbostic long omask; 98*40858Sbostic int argoff, ch, dflag, one, uid; 99*40858Sbostic char *host, *p, *user, term[1024]; 100*40858Sbostic void lostpeer(); 101*40858Sbostic char *getenv(); 1026444Swnj 103*40858Sbostic argoff = dflag = 0; 104*40858Sbostic one = 1; 105*40858Sbostic host = user = NULL; 106*40858Sbostic cmdchar = '~'; 107*40858Sbostic 108*40858Sbostic if (p = rindex(argv[0], '/')) 109*40858Sbostic ++p; 1106444Swnj else 111*40858Sbostic p = argv[0]; 112*40858Sbostic 113*40858Sbostic if (strcmp(p, "rlogin")) 114*40858Sbostic host = p; 115*40858Sbostic 116*40858Sbostic /* handle "rlogin host flags" */ 117*40858Sbostic if (!host && argc > 2 && argv[1][0] != '-') { 118*40858Sbostic host = argv[1]; 119*40858Sbostic argoff = 1; 1206444Swnj } 12136511Skfall 122*40858Sbostic #ifdef KERBEROS 123*40858Sbostic #define OPTIONS "8Lde:k:l:x" 124*40858Sbostic #else 125*40858Sbostic #define OPTIONS "8Lde:l:" 126*40858Sbostic #endif 127*40858Sbostic while ((ch = getopt(argc - argoff, argv + argoff, OPTIONS)) != EOF) 128*40858Sbostic switch(ch) { 129*40858Sbostic case '8': 130*40858Sbostic eight = 1; 131*40858Sbostic break; 132*40858Sbostic case 'L': 133*40858Sbostic litout = 1; 134*40858Sbostic break; 135*40858Sbostic case 'd': 136*40858Sbostic dflag = 1; 137*40858Sbostic break; 138*40858Sbostic case 'e': 139*40858Sbostic cmdchar = optarg[0]; 140*40858Sbostic break; 141*40858Sbostic #ifdef KERBEROS 142*40858Sbostic case 'k': 143*40858Sbostic dest_realm = dst_realm_buf; 144*40858Sbostic (void)strncpy(dest_realm, optarg, REALM_SZ); 145*40858Sbostic break; 146*40858Sbostic #endif 147*40858Sbostic case 'l': 148*40858Sbostic user = optarg; 149*40858Sbostic break; 150*40858Sbostic #ifdef KERBEROS 151*40858Sbostic case 'x': 152*40858Sbostic encrypt = 1; 153*40858Sbostic des_set_key(cred.session, schedule); 154*40858Sbostic break; 155*40858Sbostic #endif 156*40858Sbostic case '?': 157*40858Sbostic default: 158*40858Sbostic usage(); 15936524Skfall } 160*40858Sbostic optind += argoff; 161*40858Sbostic argc -= optind; 162*40858Sbostic argv += optind; 16336524Skfall 164*40858Sbostic /* if haven't gotten a host yet, do so */ 165*40858Sbostic if (!host && !(host = *argv++)) 166*40858Sbostic usage(); 16736511Skfall 168*40858Sbostic if (*argv) 169*40858Sbostic usage(); 170*40858Sbostic 171*40858Sbostic if (!(pw = getpwuid(uid = getuid()))) { 172*40858Sbostic (void)fprintf(stderr, "rlogin: unknown user id.\n"); 1736444Swnj exit(1); 1746444Swnj } 175*40858Sbostic if (!user) 176*40858Sbostic user = pw->pw_name; 177*40858Sbostic 178*40858Sbostic #ifdef KERBEROS 17936716Skfall sp = getservbyname((encrypt ? "eklogin" : "klogin"), "tcp"); 18036512Skfall if(sp == NULL) { 18136512Skfall use_kerberos = 0; 182*40858Sbostic warning("can't get entry for %s/tcp service", 183*40858Sbostic encrypt ? "eklogin" : "klogin"); 18436512Skfall sp = getservbyname("login", "tcp"); 18536512Skfall } 18636512Skfall #else 1879365Ssam sp = getservbyname("login", "tcp"); 18836512Skfall #endif 189*40858Sbostic if (sp == NULL) { 190*40858Sbostic (void)fprintf(stderr, "rlogin: login/tcp: unknown service.\n"); 191*40858Sbostic exit(1); 1929365Ssam } 193*40858Sbostic 194*40858Sbostic (void)strcpy(term, (p = getenv("TERM")) ? p : "network"); 19518358Ssam if (ioctl(0, TIOCGETP, &ttyb) == 0) { 196*40858Sbostic (void)strcat(term, "/"); 197*40858Sbostic (void)strcat(term, speeds[ttyb.sg_ospeed]); 1986444Swnj } 199*40858Sbostic 200*40858Sbostic (void)get_window_size(0, &winsize); 201*40858Sbostic 202*40858Sbostic (void)signal(SIGPIPE, lostpeer); 20329729Smckusick /* will use SIGUSR1 for window size hack, so hold it off */ 204*40858Sbostic omask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); 20536511Skfall 206*40858Sbostic #ifdef KERBEROS 20736512Skfall try_connect: 208*40858Sbostic if (use_kerberos) { 20936512Skfall rem = KSUCCESS; 210*40858Sbostic errno = 0; 21138728Skfall if (dest_realm == NULL) 21238728Skfall dest_realm = krb_realmofhost(host); 21338728Skfall 214*40858Sbostic if (encrypt) 215*40858Sbostic rem = krcmd_mutual(&host, sp->s_port, user, term, 0, 216*40858Sbostic dest_realm, &cred, schedule); 217*40858Sbostic else 218*40858Sbostic rem = krcmd(&host, sp->s_port, user, term, 0, 219*40858Sbostic dest_realm); 22038728Skfall if (rem < 0) { 22136512Skfall use_kerberos = 0; 22236628Skfall sp = getservbyname("login", "tcp"); 223*40858Sbostic if (sp == NULL) { 224*40858Sbostic (void)fprintf(stderr, 225*40858Sbostic "rlogin: unknown service login/tcp.\n"); 22636628Skfall exit(1); 22736628Skfall } 22838728Skfall if (errno == ECONNREFUSED) 229*40858Sbostic warning("remote host doesn't support Kerberos"); 23038728Skfall if (errno == ENOENT) 231*40858Sbostic warning("can't provide Kerberos auth data"); 23236512Skfall goto try_connect; 23336512Skfall } 23436511Skfall } else { 235*40858Sbostic if (encrypt) { 236*40858Sbostic (void)fprintf(stderr, 237*40858Sbostic "rlogin: the -x flag requires Kerberos authentication.\n"); 23836512Skfall exit(1); 23936512Skfall } 240*40858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 24136511Skfall } 24236512Skfall #else 243*40858Sbostic rem = rcmd(&host, sp->s_port, pw->pw_name, user, term, 0); 24436512Skfall #endif 24536511Skfall 246*40858Sbostic if (rem < 0) 24736511Skfall exit(1); 24836511Skfall 249*40858Sbostic if (dflag && 250*40858Sbostic setsockopt(rem, SOL_SOCKET, SO_DEBUG, &one, sizeof(one)) < 0) 251*40858Sbostic (void)fprintf(stderr, "rlogin: setsockopt: %s.\n", 252*40858Sbostic strerror(errno)); 253*40858Sbostic 254*40858Sbostic (void)setuid(uid); 255*40858Sbostic doit(omask); 2569365Ssam /*NOTREACHED*/ 2576444Swnj } 2586444Swnj 259*40858Sbostic int child, defflags, deflflags, tabflag; 260*40858Sbostic char deferase, defkill; 261*40858Sbostic struct tchars deftc; 262*40858Sbostic struct ltchars defltc; 263*40858Sbostic struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 264*40858Sbostic struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 2656444Swnj 266*40858Sbostic doit(omask) 267*40858Sbostic long omask; 2686444Swnj { 26913075Ssam struct sgttyb sb; 270*40858Sbostic void catch_child(), copytochild(), exit(), writeroob(); 2716444Swnj 272*40858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 27313075Ssam defflags = sb.sg_flags; 27412155Ssam tabflag = defflags & TBDELAY; 2759962Ssam defflags &= ECHO | CRMOD; 27613075Ssam deferase = sb.sg_erase; 27713075Ssam defkill = sb.sg_kill; 278*40858Sbostic (void)ioctl(0, TIOCLGET, (char *)&deflflags); 279*40858Sbostic (void)ioctl(0, TIOCGETC, (char *)&deftc); 28013075Ssam notc.t_startc = deftc.t_startc; 28113075Ssam notc.t_stopc = deftc.t_stopc; 282*40858Sbostic (void)ioctl(0, TIOCGLTC, (char *)&defltc); 283*40858Sbostic (void)signal(SIGINT, SIG_IGN); 28429729Smckusick setsignal(SIGHUP, exit); 28529729Smckusick setsignal(SIGQUIT, exit); 2869365Ssam child = fork(); 2879365Ssam if (child == -1) { 288*40858Sbostic (void)fprintf(stderr, "rlogin: fork: %s.\n", strerror(errno)); 28925424Skarels done(1); 2909365Ssam } 2919365Ssam if (child == 0) { 29224726Smckusick mode(1); 293*40858Sbostic if (reader(omask) == 0) { 294*40858Sbostic msg("connection closed."); 29525424Skarels exit(0); 29625424Skarels } 29712155Ssam sleep(1); 298*40858Sbostic msg("\007connection closed."); 299*40858Sbostic exit(1); 3006444Swnj } 30129729Smckusick 30229729Smckusick /* 303*40858Sbostic * We may still own the socket, and may have a pending SIGURG (or might 304*40858Sbostic * receive one soon) that we really want to send to the reader. Set a 305*40858Sbostic * trap that simply copies such signals to the child. 30629729Smckusick */ 307*40858Sbostic (void)signal(SIGURG, copytochild); 308*40858Sbostic (void)signal(SIGUSR1, writeroob); 309*40858Sbostic (void)sigsetmask(omask); 310*40858Sbostic (void)signal(SIGCHLD, catch_child); 3119365Ssam writer(); 312*40858Sbostic msg("closed connection."); 31325424Skarels done(0); 3146444Swnj } 3156444Swnj 316*40858Sbostic /* trap a signal, unless it is being ignored. */ 31729729Smckusick setsignal(sig, act) 318*40858Sbostic int sig; 319*40858Sbostic void (*act)(); 32029729Smckusick { 32129729Smckusick int omask = sigblock(sigmask(sig)); 32229729Smckusick 32329729Smckusick if (signal(sig, act) == SIG_IGN) 324*40858Sbostic (void)signal(sig, SIG_IGN); 325*40858Sbostic (void)sigsetmask(omask); 32629729Smckusick } 32729729Smckusick 32825424Skarels done(status) 32925424Skarels int status; 3306444Swnj { 33129729Smckusick int w; 3326444Swnj 3336444Swnj mode(0); 33429729Smckusick if (child > 0) { 335*40858Sbostic /* make sure catch_child does not snap it up */ 336*40858Sbostic (void)signal(SIGCHLD, SIG_DFL); 33729729Smckusick if (kill(child, SIGKILL) >= 0) 338*40858Sbostic while ((w = wait((union wait *)0)) > 0 && w != child); 33929729Smckusick } 34025424Skarels exit(status); 3416444Swnj } 3426444Swnj 343*40858Sbostic int dosigwinch; 34429729Smckusick 34529729Smckusick /* 34624726Smckusick * This is called when the reader process gets the out-of-band (urgent) 34724726Smckusick * request to turn on the window-changing protocol. 34824726Smckusick */ 349*40858Sbostic void 35024726Smckusick writeroob() 35124726Smckusick { 352*40858Sbostic void sigwinch(); 35324726Smckusick 35425341Smckusick if (dosigwinch == 0) { 35524919Smckusick sendwindow(); 356*40858Sbostic (void)signal(SIGWINCH, sigwinch); 35725341Smckusick } 35824726Smckusick dosigwinch = 1; 35924726Smckusick } 36024726Smckusick 361*40858Sbostic void 362*40858Sbostic catch_child() 36311803Sedward { 36411803Sedward union wait status; 36511803Sedward int pid; 36611803Sedward 367*40858Sbostic for (;;) { 368*40858Sbostic pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); 369*40858Sbostic if (pid == 0) 370*40858Sbostic return; 371*40858Sbostic /* if the child (reader) dies, just quit */ 372*40858Sbostic if (pid < 0 || pid == child && !WIFSTOPPED(status)) 373*40858Sbostic done((int)(status.w_termsig | status.w_retcode)); 374*40858Sbostic } 375*40858Sbostic /* NOTREACHED */ 37611803Sedward } 37711803Sedward 3786444Swnj /* 3799365Ssam * writer: write to remote: 0 -> line. 3809365Ssam * ~. terminate 3819365Ssam * ~^Z suspend rlogin process. 38210415Ssam * ~^Y suspend rlogin process, but leave reader alone. 3836444Swnj */ 3849365Ssam writer() 3856444Swnj { 38623530Sbloom char c; 387*40858Sbostic register int bol, local, n; 3886444Swnj 389*40858Sbostic bol = 1; /* beginning of line */ 390*40858Sbostic local = 0; 39111803Sedward for (;;) { 392*40858Sbostic n = read(STDIN_FILENO, &c, 1); 39318358Ssam if (n <= 0) { 39418358Ssam if (n < 0 && errno == EINTR) 39518358Ssam continue; 39611803Sedward break; 39718358Ssam } 3989365Ssam /* 399*40858Sbostic * If we're at the beginning of the line and recognize a 400*40858Sbostic * command character, then we echo locally. Otherwise, 401*40858Sbostic * characters are echo'd remotely. If the command character 402*40858Sbostic * is doubled, this acts as a force and local echo is 403*40858Sbostic * suppressed. 4049365Ssam */ 40523530Sbloom if (bol) { 40623530Sbloom bol = 0; 40723530Sbloom if (c == cmdchar) { 40823530Sbloom bol = 0; 40923530Sbloom local = 1; 41023530Sbloom continue; 4116444Swnj } 41223530Sbloom } else if (local) { 41323530Sbloom local = 0; 41423530Sbloom if (c == '.' || c == deftc.t_eofc) { 41523530Sbloom echo(c); 41623530Sbloom break; 4176444Swnj } 41823530Sbloom if (c == defltc.t_suspc || c == defltc.t_dsuspc) { 41923530Sbloom bol = 1; 42023530Sbloom echo(c); 42123530Sbloom stop(c); 42223530Sbloom continue; 42323530Sbloom } 42436511Skfall if (c != cmdchar) { 425*40858Sbostic #ifdef KERBEROS 426*40858Sbostic if (encrypt) { 427*40858Sbostic (void)des_write(rem, &cmdchar, 1); 42836511Skfall } else 42936511Skfall #endif 430*40858Sbostic (void)write(rem, &cmdchar, 1); 43136511Skfall } 4326444Swnj } 43336511Skfall 434*40858Sbostic #ifdef KERBEROS 435*40858Sbostic if (encrypt) { 43636511Skfall if (des_write(rem, &c, 1) == 0) { 437*40858Sbostic msg("line gone"); 43836511Skfall break; 43936511Skfall } 44036511Skfall } else 44136511Skfall #endif 44236511Skfall if (write(rem, &c, 1) == 0) { 443*40858Sbostic msg("line gone"); 44436511Skfall break; 44536511Skfall } 44623530Sbloom bol = c == defkill || c == deftc.t_eofc || 44725424Skarels c == deftc.t_intrc || c == defltc.t_suspc || 44823530Sbloom c == '\r' || c == '\n'; 4496444Swnj } 4506444Swnj } 4516444Swnj 45223530Sbloom echo(c) 45323530Sbloom register char c; 45423530Sbloom { 455*40858Sbostic register char *p; 45623530Sbloom char buf[8]; 45723530Sbloom 458*40858Sbostic p = buf; 45923530Sbloom c &= 0177; 46023530Sbloom *p++ = cmdchar; 46123530Sbloom if (c < ' ') { 46223530Sbloom *p++ = '^'; 46323530Sbloom *p++ = c + '@'; 46423530Sbloom } else if (c == 0177) { 46523530Sbloom *p++ = '^'; 46623530Sbloom *p++ = '?'; 46723530Sbloom } else 46823530Sbloom *p++ = c; 46923530Sbloom *p++ = '\r'; 47023530Sbloom *p++ = '\n'; 471*40858Sbostic (void)write(1, buf, p - buf); 47223530Sbloom } 47323530Sbloom 47418358Ssam stop(cmdc) 47518358Ssam char cmdc; 47618358Ssam { 47718358Ssam mode(0); 478*40858Sbostic (void)signal(SIGCHLD, SIG_IGN); 479*40858Sbostic (void)kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); 480*40858Sbostic (void)signal(SIGCHLD, catch_child); 48118358Ssam mode(1); 48218358Ssam sigwinch(); /* check for size changes */ 48318358Ssam } 48418358Ssam 485*40858Sbostic void 48618358Ssam sigwinch() 48718358Ssam { 48818358Ssam struct winsize ws; 48918358Ssam 49029729Smckusick if (dosigwinch && get_window_size(0, &ws) == 0 && 491*40858Sbostic bcmp(&ws, &winsize, sizeof(ws))) { 49218358Ssam winsize = ws; 49324726Smckusick sendwindow(); 49418358Ssam } 49518358Ssam } 49618358Ssam 49724726Smckusick /* 49824726Smckusick * Send the window size to the server via the magic escape 49924726Smckusick */ 50024726Smckusick sendwindow() 50124726Smckusick { 502*40858Sbostic struct winsize *wp; 50324726Smckusick char obuf[4 + sizeof (struct winsize)]; 50424726Smckusick 505*40858Sbostic wp = (struct winsize *)(obuf+4); 50624726Smckusick obuf[0] = 0377; 50724726Smckusick obuf[1] = 0377; 50824726Smckusick obuf[2] = 's'; 50924726Smckusick obuf[3] = 's'; 51024726Smckusick wp->ws_row = htons(winsize.ws_row); 51124726Smckusick wp->ws_col = htons(winsize.ws_col); 51224726Smckusick wp->ws_xpixel = htons(winsize.ws_xpixel); 51324726Smckusick wp->ws_ypixel = htons(winsize.ws_ypixel); 51436511Skfall 515*40858Sbostic #ifdef KERBEROS 51636511Skfall if(encrypt) 517*40858Sbostic (void)des_write(rem, obuf, sizeof(obuf)); 51836511Skfall else 51936511Skfall #endif 520*40858Sbostic (void)write(rem, obuf, sizeof(obuf)); 52124726Smckusick } 52224726Smckusick 52325424Skarels /* 52425424Skarels * reader: read from remote: line -> 1 52525424Skarels */ 52625424Skarels #define READING 1 52725424Skarels #define WRITING 2 52825424Skarels 529*40858Sbostic jmp_buf rcvtop; 530*40858Sbostic int ppid, rcvcnt, rcvstate; 531*40858Sbostic char rcvbuf[8 * 1024]; 53225424Skarels 533*40858Sbostic void 5346444Swnj oob() 5356444Swnj { 536*40858Sbostic struct sgttyb sb; 537*40858Sbostic int atmark, n, out, rcvd; 5389365Ssam char waste[BUFSIZ], mark; 5396444Swnj 540*40858Sbostic out = FWRITE; 541*40858Sbostic rcvd = 0; 54225424Skarels while (recv(rem, &mark, 1, MSG_OOB) < 0) 54325424Skarels switch (errno) { 54425424Skarels case EWOULDBLOCK: 54525424Skarels /* 546*40858Sbostic * Urgent data not here yet. It may not be possible 547*40858Sbostic * to send it yet if we are blocked for output and 548*40858Sbostic * our input buffer is full. 54925424Skarels */ 55025424Skarels if (rcvcnt < sizeof(rcvbuf)) { 55125424Skarels n = read(rem, rcvbuf + rcvcnt, 552*40858Sbostic sizeof(rcvbuf) - rcvcnt); 55325424Skarels if (n <= 0) 55425424Skarels return; 55525424Skarels rcvd += n; 55625424Skarels } else { 55725424Skarels n = read(rem, waste, sizeof(waste)); 55825424Skarels if (n <= 0) 55925424Skarels return; 56025424Skarels } 56125424Skarels continue; 56225424Skarels default: 56325424Skarels return; 5646444Swnj } 56525424Skarels if (mark & TIOCPKT_WINDOW) { 566*40858Sbostic /* Let server know about window size changes */ 567*40858Sbostic (void)kill(ppid, SIGUSR1); 56824726Smckusick } 56925424Skarels if (!eight && (mark & TIOCPKT_NOSTOP)) { 570*40858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 57124726Smckusick sb.sg_flags &= ~CBREAK; 57224726Smckusick sb.sg_flags |= RAW; 573*40858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 57413075Ssam notc.t_stopc = -1; 57513075Ssam notc.t_startc = -1; 576*40858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5776444Swnj } 57825424Skarels if (!eight && (mark & TIOCPKT_DOSTOP)) { 579*40858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 58024726Smckusick sb.sg_flags &= ~RAW; 58124726Smckusick sb.sg_flags |= CBREAK; 582*40858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 58313075Ssam notc.t_stopc = deftc.t_stopc; 58413075Ssam notc.t_startc = deftc.t_startc; 585*40858Sbostic (void)ioctl(0, TIOCSETC, (char *)¬c); 5866444Swnj } 58725424Skarels if (mark & TIOCPKT_FLUSHWRITE) { 588*40858Sbostic (void)ioctl(1, TIOCFLUSH, (char *)&out); 58925424Skarels for (;;) { 59025424Skarels if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 591*40858Sbostic (void)fprintf(stderr, "rlogin: ioctl: %s.\n", 592*40858Sbostic strerror(errno)); 59325424Skarels break; 59425424Skarels } 59525424Skarels if (atmark) 59625424Skarels break; 59725424Skarels n = read(rem, waste, sizeof (waste)); 59825424Skarels if (n <= 0) 59925424Skarels break; 60025424Skarels } 60125424Skarels /* 602*40858Sbostic * Don't want any pending data to be output, so clear the recv 603*40858Sbostic * buffer. If we were hanging on a write when interrupted, 604*40858Sbostic * don't want it to restart. If we were reading, restart 605*40858Sbostic * anyway. 60625424Skarels */ 60725424Skarels rcvcnt = 0; 60825424Skarels longjmp(rcvtop, 1); 60925424Skarels } 61029729Smckusick 611*40858Sbostic /* oob does not do FLUSHREAD (alas!) */ 61229729Smckusick 61329729Smckusick /* 614*40858Sbostic * If we filled the receive buffer while a read was pending, longjmp 615*40858Sbostic * to the top to restart appropriately. Don't abort a pending write, 616*40858Sbostic * however, or we won't know how much was written. 61725424Skarels */ 61825424Skarels if (rcvd && rcvstate == READING) 61925424Skarels longjmp(rcvtop, 1); 6206444Swnj } 6216444Swnj 622*40858Sbostic /* reader: read from remote: line -> 1 */ 623*40858Sbostic reader(omask) 624*40858Sbostic int omask; 6256444Swnj { 626*40858Sbostic void oob(); 627*40858Sbostic 62826981Skarels #if !defined(BSD) || BSD < 43 62926981Skarels int pid = -getpid(); 63026981Skarels #else 63125424Skarels int pid = getpid(); 63226981Skarels #endif 63325424Skarels int n, remaining; 63425424Skarels char *bufp = rcvbuf; 6356444Swnj 636*40858Sbostic (void)signal(SIGTTOU, SIG_IGN); 637*40858Sbostic (void)signal(SIGURG, oob); 63826981Skarels ppid = getppid(); 639*40858Sbostic (void)fcntl(rem, F_SETOWN, pid); 640*40858Sbostic (void)setjmp(rcvtop); 641*40858Sbostic (void)sigsetmask(omask); 6426444Swnj for (;;) { 64325424Skarels while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { 64425424Skarels rcvstate = WRITING; 64525424Skarels n = write(1, bufp, remaining); 64625424Skarels if (n < 0) { 64725424Skarels if (errno != EINTR) 648*40858Sbostic return(-1); 64925424Skarels continue; 65025424Skarels } 65125424Skarels bufp += n; 65225424Skarels } 65325424Skarels bufp = rcvbuf; 65425424Skarels rcvcnt = 0; 65525424Skarels rcvstate = READING; 65636511Skfall 657*40858Sbostic #ifdef KERBEROS 658*40858Sbostic if (encrypt) 65936511Skfall rcvcnt = des_read(rem, rcvbuf, sizeof(rcvbuf)); 66036511Skfall else 66136511Skfall #endif 66236511Skfall rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); 66325424Skarels if (rcvcnt == 0) 66425424Skarels return (0); 66525424Skarels if (rcvcnt < 0) { 6669365Ssam if (errno == EINTR) 6676444Swnj continue; 668*40858Sbostic (void)fprintf(stderr, "rlogin: read: %s.\n", 669*40858Sbostic strerror(errno)); 670*40858Sbostic return(-1); 6716444Swnj } 6726444Swnj } 6736444Swnj } 6746444Swnj 6756444Swnj mode(f) 6766444Swnj { 67713075Ssam struct ltchars *ltc; 67813075Ssam struct sgttyb sb; 679*40858Sbostic struct tchars *tc; 680*40858Sbostic int lflags; 6819365Ssam 682*40858Sbostic (void)ioctl(0, TIOCGETP, (char *)&sb); 683*40858Sbostic (void)ioctl(0, TIOCLGET, (char *)&lflags); 684*40858Sbostic switch(f) { 6859962Ssam case 0: 68613075Ssam sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); 68713075Ssam sb.sg_flags |= defflags|tabflag; 6889962Ssam tc = &deftc; 68913075Ssam ltc = &defltc; 69013075Ssam sb.sg_kill = defkill; 69113075Ssam sb.sg_erase = deferase; 69221583Sbloom lflags = deflflags; 6939962Ssam break; 6949962Ssam case 1: 69513075Ssam sb.sg_flags |= (eight ? RAW : CBREAK); 69613075Ssam sb.sg_flags &= ~defflags; 69712155Ssam /* preserve tab delays, but turn off XTABS */ 69813075Ssam if ((sb.sg_flags & TBDELAY) == XTABS) 69913075Ssam sb.sg_flags &= ~TBDELAY; 7009962Ssam tc = ¬c; 70113075Ssam ltc = &noltc; 70213075Ssam sb.sg_kill = sb.sg_erase = -1; 70321583Sbloom if (litout) 70421583Sbloom lflags |= LLITOUT; 7059962Ssam break; 7069962Ssam default: 7079962Ssam return; 7086444Swnj } 709*40858Sbostic (void)ioctl(0, TIOCSLTC, (char *)ltc); 710*40858Sbostic (void)ioctl(0, TIOCSETC, (char *)tc); 711*40858Sbostic (void)ioctl(0, TIOCSETN, (char *)&sb); 712*40858Sbostic (void)ioctl(0, TIOCLSET, (char *)&lflags); 7136444Swnj } 7146444Swnj 715*40858Sbostic void 716*40858Sbostic lostpeer() 7176444Swnj { 718*40858Sbostic (void)signal(SIGPIPE, SIG_IGN); 719*40858Sbostic msg("\007connection closed."); 720*40858Sbostic done(1); 721*40858Sbostic } 72229729Smckusick 723*40858Sbostic /* copy SIGURGs to the child process. */ 724*40858Sbostic void 725*40858Sbostic copytochild() 726*40858Sbostic { 727*40858Sbostic (void)kill(child, SIGURG); 7286444Swnj } 7296444Swnj 730*40858Sbostic msg(str) 731*40858Sbostic char *str; 7326444Swnj { 733*40858Sbostic (void)fprintf(stderr, "rlogin: %s\r\n", str); 734*40858Sbostic } 73529729Smckusick 736*40858Sbostic #ifdef KERBEROS 737*40858Sbostic /* VARARGS */ 738*40858Sbostic warning(va_alist) 739*40858Sbostic va_dcl 740*40858Sbostic { 741*40858Sbostic va_list ap; 742*40858Sbostic char *fmt; 743*40858Sbostic 744*40858Sbostic (void)fprintf(stderr, "rlogin: warning, using standard rlogin: "); 745*40858Sbostic va_start(ap); 746*40858Sbostic fmt = va_arg(ap, char *); 747*40858Sbostic vfprintf(stderr, fmt, ap); 748*40858Sbostic va_end(ap); 749*40858Sbostic (void)fprintf(stderr, ".\n"); 7506444Swnj } 751*40858Sbostic #endif 75236512Skfall 753*40858Sbostic usage() 75436512Skfall { 755*40858Sbostic (void)fprintf(stderr, 756*40858Sbostic "usage: rlogin [ -%s]%s[-e char] [ -l username ] host\n", 757*40858Sbostic #ifdef KERBEROS 758*40858Sbostic "8Lx", " [-k realm] "); 759*40858Sbostic #else 760*40858Sbostic "8L", " "); 761*40858Sbostic #endif 762*40858Sbostic exit(1); 76336512Skfall } 764*40858Sbostic 765*40858Sbostic /* 766*40858Sbostic * The following routine provides compatibility (such as it is) between 4.2BSD 767*40858Sbostic * Suns and others. Suns have only a `ttysize', so we convert it to a winsize. 768*40858Sbostic */ 769*40858Sbostic #ifdef sun 770*40858Sbostic int 771*40858Sbostic get_window_size(fd, wp) 772*40858Sbostic int fd; 773*40858Sbostic struct winsize *wp; 774*40858Sbostic { 775*40858Sbostic struct ttysize ts; 776*40858Sbostic int error; 777*40858Sbostic 778*40858Sbostic if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) 779*40858Sbostic return(error); 780*40858Sbostic wp->ws_row = ts.ts_lines; 781*40858Sbostic wp->ws_col = ts.ts_cols; 782*40858Sbostic wp->ws_xpixel = 0; 783*40858Sbostic wp->ws_ypixel = 0; 784*40858Sbostic return(0); 785*40858Sbostic } 786*40858Sbostic #endif 787