121595Sdist /* 2*35539Sbostic * Copyright (c) 1983 The Regents of the University of California. 3*35539Sbostic * All rights reserved. 4*35539Sbostic * 5*35539Sbostic * Redistribution and use in source and binary forms are permitted 6*35539Sbostic * provided that the above copyright notice and this paragraph are 7*35539Sbostic * duplicated in all such forms and that any documentation, 8*35539Sbostic * advertising materials, and other materials related to such 9*35539Sbostic * distribution and use acknowledge that the software was developed 10*35539Sbostic * by the University of California, Berkeley. The name of the 11*35539Sbostic * University may not be used to endorse or promote products derived 12*35539Sbostic * from this software without specific prior written permission. 13*35539Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14*35539Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15*35539Sbostic * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1621595Sdist */ 1721595Sdist 186444Swnj #ifndef lint 1921595Sdist char copyright[] = 20*35539Sbostic "@(#) Copyright (c) 1983 The Regents of the University of California.\n\ 2121595Sdist All rights reserved.\n"; 22*35539Sbostic #endif /* not lint */ 236444Swnj 2421595Sdist #ifndef lint 25*35539Sbostic static char sccsid[] = "@(#)rlogin.c 5.12 (Berkeley) 09/19/88"; 26*35539Sbostic #endif /* not lint */ 2721595Sdist 2812990Ssam /* 2912990Ssam * rlogin - remote login 3012990Ssam */ 3126981Skarels #include <sys/param.h> 3225424Skarels #include <sys/errno.h> 3324727Smckusick #include <sys/file.h> 346444Swnj #include <sys/socket.h> 3529729Smckusick #include <sys/time.h> 3629729Smckusick #include <sys/resource.h> 3713620Ssam #include <sys/wait.h> 389365Ssam 399207Ssam #include <netinet/in.h> 409365Ssam 419365Ssam #include <stdio.h> 429365Ssam #include <sgtty.h> 436444Swnj #include <errno.h> 446444Swnj #include <pwd.h> 459365Ssam #include <signal.h> 4625424Skarels #include <setjmp.h> 479365Ssam #include <netdb.h> 486444Swnj 4924726Smckusick # ifndef TIOCPKT_WINDOW 5024726Smckusick # define TIOCPKT_WINDOW 0x80 5124726Smckusick # endif TIOCPKT_WINDOW 5224726Smckusick 5329729Smckusick /* concession to sun */ 5429729Smckusick # ifndef SIGUSR1 5529729Smckusick # define SIGUSR1 30 5629729Smckusick # endif SIGUSR1 5729729Smckusick 5829729Smckusick char *index(), *rindex(), *malloc(), *getenv(), *strcat(), *strcpy(); 596444Swnj struct passwd *getpwuid(); 609365Ssam char *name; 616444Swnj int rem; 626444Swnj char cmdchar = '~'; 636444Swnj int eight; 6421583Sbloom int litout; 656444Swnj char *speeds[] = 666444Swnj { "0", "50", "75", "110", "134", "150", "200", "300", 676444Swnj "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" }; 6818358Ssam char term[256] = "network"; 699365Ssam extern int errno; 709365Ssam int lostpeer(); 7124726Smckusick int dosigwinch = 0; 7226981Skarels #ifndef sigmask 7326981Skarels #define sigmask(m) (1 << ((m)-1)) 7426981Skarels #endif 7526981Skarels #ifdef sun 7626981Skarels struct winsize { 7726981Skarels unsigned short ws_row, ws_col; 7826981Skarels unsigned short ws_xpixel, ws_ypixel; 7926981Skarels }; 8029729Smckusick #endif sun 8118358Ssam struct winsize winsize; 8224726Smckusick int sigwinch(), oob(); 836444Swnj 8429729Smckusick /* 8529729Smckusick * The following routine provides compatibility (such as it is) 8629729Smckusick * between 4.2BSD Suns and others. Suns have only a `ttysize', 8729729Smckusick * so we convert it to a winsize. 8829729Smckusick */ 8929729Smckusick #ifdef sun 9029729Smckusick int 9129729Smckusick get_window_size(fd, wp) 9229729Smckusick int fd; 9329729Smckusick struct winsize *wp; 9429729Smckusick { 9529729Smckusick struct ttysize ts; 9629729Smckusick int error; 9729729Smckusick 9829729Smckusick if ((error = ioctl(0, TIOCGSIZE, &ts)) != 0) 9929729Smckusick return (error); 10029729Smckusick wp->ws_row = ts.ts_lines; 10129729Smckusick wp->ws_col = ts.ts_cols; 10229729Smckusick wp->ws_xpixel = 0; 10329729Smckusick wp->ws_ypixel = 0; 10429729Smckusick return (0); 10529729Smckusick } 10629729Smckusick #else sun 10729729Smckusick #define get_window_size(fd, wp) ioctl(fd, TIOCGWINSZ, wp) 10829729Smckusick #endif sun 10929729Smckusick 1106444Swnj main(argc, argv) 1116444Swnj int argc; 1126444Swnj char **argv; 1136444Swnj { 1149365Ssam char *host, *cp; 1156444Swnj struct sgttyb ttyb; 1166444Swnj struct passwd *pwd; 1179365Ssam struct servent *sp; 11824726Smckusick int uid, options = 0, oldmask; 11917449Slepreau int on = 1; 1206444Swnj 1216444Swnj host = rindex(argv[0], '/'); 1226444Swnj if (host) 1236444Swnj host++; 1246444Swnj else 1256444Swnj host = argv[0]; 1266444Swnj argv++, --argc; 1276444Swnj if (!strcmp(host, "rlogin")) 1286444Swnj host = *argv++, --argc; 1296444Swnj another: 13010839Ssam if (argc > 0 && !strcmp(*argv, "-d")) { 1316444Swnj argv++, argc--; 13210415Ssam options |= SO_DEBUG; 1336444Swnj goto another; 1346444Swnj } 13510839Ssam if (argc > 0 && !strcmp(*argv, "-l")) { 1366444Swnj argv++, argc--; 1376444Swnj if (argc == 0) 1386444Swnj goto usage; 1396444Swnj name = *argv++; argc--; 1406444Swnj goto another; 1416444Swnj } 14210839Ssam if (argc > 0 && !strncmp(*argv, "-e", 2)) { 1436444Swnj cmdchar = argv[0][2]; 1446444Swnj argv++, argc--; 1456444Swnj goto another; 1466444Swnj } 14710839Ssam if (argc > 0 && !strcmp(*argv, "-8")) { 1486444Swnj eight = 1; 1496444Swnj argv++, argc--; 1506444Swnj goto another; 1516444Swnj } 15221583Sbloom if (argc > 0 && !strcmp(*argv, "-L")) { 15321583Sbloom litout = 1; 15421583Sbloom argv++, argc--; 15521583Sbloom goto another; 15621583Sbloom } 1576444Swnj if (host == 0) 1586444Swnj goto usage; 1596444Swnj if (argc > 0) 1606444Swnj goto usage; 1616444Swnj pwd = getpwuid(getuid()); 1626444Swnj if (pwd == 0) { 1636444Swnj fprintf(stderr, "Who are you?\n"); 1646444Swnj exit(1); 1656444Swnj } 1669365Ssam sp = getservbyname("login", "tcp"); 1679365Ssam if (sp == 0) { 1689365Ssam fprintf(stderr, "rlogin: login/tcp: unknown service\n"); 1699365Ssam exit(2); 1709365Ssam } 1719241Ssam cp = getenv("TERM"); 1729241Ssam if (cp) 17329729Smckusick (void) strcpy(term, cp); 17418358Ssam if (ioctl(0, TIOCGETP, &ttyb) == 0) { 17529729Smckusick (void) strcat(term, "/"); 17629729Smckusick (void) strcat(term, speeds[ttyb.sg_ospeed]); 1776444Swnj } 17829729Smckusick (void) get_window_size(0, &winsize); 17929729Smckusick (void) signal(SIGPIPE, lostpeer); 18029729Smckusick /* will use SIGUSR1 for window size hack, so hold it off */ 18129729Smckusick oldmask = sigblock(sigmask(SIGURG) | sigmask(SIGUSR1)); 1829365Ssam rem = rcmd(&host, sp->s_port, pwd->pw_name, 1836444Swnj name ? name : pwd->pw_name, term, 0); 1846444Swnj if (rem < 0) 1856444Swnj exit(1); 18610415Ssam if (options & SO_DEBUG && 18717449Slepreau setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0) 18810415Ssam perror("rlogin: setsockopt (SO_DEBUG)"); 1899365Ssam uid = getuid(); 1909365Ssam if (setuid(uid) < 0) { 1919365Ssam perror("rlogin: setuid"); 1929365Ssam exit(1); 1939365Ssam } 19424726Smckusick doit(oldmask); 1959365Ssam /*NOTREACHED*/ 1966444Swnj usage: 1976444Swnj fprintf(stderr, 19825341Smckusick "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n"); 1996444Swnj exit(1); 2006444Swnj } 2016444Swnj 2026444Swnj #define CRLF "\r\n" 2036444Swnj 2049365Ssam int child; 20511803Sedward int catchild(); 20629729Smckusick int copytochild(), writeroob(); 2079365Ssam 20813075Ssam int defflags, tabflag; 20921583Sbloom int deflflags; 21013075Ssam char deferase, defkill; 21113075Ssam struct tchars deftc; 21213075Ssam struct ltchars defltc; 21313075Ssam struct tchars notc = { -1, -1, -1, -1, -1, -1 }; 21413075Ssam struct ltchars noltc = { -1, -1, -1, -1, -1, -1 }; 2156444Swnj 21624726Smckusick doit(oldmask) 2176444Swnj { 2186444Swnj int exit(); 21913075Ssam struct sgttyb sb; 2206444Swnj 22129729Smckusick (void) ioctl(0, TIOCGETP, (char *)&sb); 22213075Ssam defflags = sb.sg_flags; 22312155Ssam tabflag = defflags & TBDELAY; 2249962Ssam defflags &= ECHO | CRMOD; 22513075Ssam deferase = sb.sg_erase; 22613075Ssam defkill = sb.sg_kill; 22729729Smckusick (void) ioctl(0, TIOCLGET, (char *)&deflflags); 22829729Smckusick (void) ioctl(0, TIOCGETC, (char *)&deftc); 22913075Ssam notc.t_startc = deftc.t_startc; 23013075Ssam notc.t_stopc = deftc.t_stopc; 23129729Smckusick (void) ioctl(0, TIOCGLTC, (char *)&defltc); 23229729Smckusick (void) signal(SIGINT, SIG_IGN); 23329729Smckusick setsignal(SIGHUP, exit); 23429729Smckusick setsignal(SIGQUIT, exit); 2359365Ssam child = fork(); 2369365Ssam if (child == -1) { 2379365Ssam perror("rlogin: fork"); 23825424Skarels done(1); 2399365Ssam } 2409365Ssam if (child == 0) { 24124726Smckusick mode(1); 24229729Smckusick if (reader(oldmask) == 0) { 24325424Skarels prf("Connection closed."); 24425424Skarels exit(0); 24525424Skarels } 24612155Ssam sleep(1); 24712155Ssam prf("\007Connection closed."); 2486444Swnj exit(3); 2496444Swnj } 25029729Smckusick 25129729Smckusick /* 25229729Smckusick * We may still own the socket, and may have a pending SIGURG 25329729Smckusick * (or might receive one soon) that we really want to send to 25429729Smckusick * the reader. Set a trap that simply copies such signals to 25529729Smckusick * the child. 25629729Smckusick */ 25729729Smckusick (void) signal(SIGURG, copytochild); 25829729Smckusick (void) signal(SIGUSR1, writeroob); 25929729Smckusick (void) sigsetmask(oldmask); 26029729Smckusick (void) signal(SIGCHLD, catchild); 2619365Ssam writer(); 26212155Ssam prf("Closed connection."); 26325424Skarels done(0); 2646444Swnj } 2656444Swnj 26629729Smckusick /* 26729729Smckusick * Trap a signal, unless it is being ignored. 26829729Smckusick */ 26929729Smckusick setsignal(sig, act) 27029729Smckusick int sig, (*act)(); 27129729Smckusick { 27229729Smckusick int omask = sigblock(sigmask(sig)); 27329729Smckusick 27429729Smckusick if (signal(sig, act) == SIG_IGN) 27529729Smckusick (void) signal(sig, SIG_IGN); 27629729Smckusick (void) sigsetmask(omask); 27729729Smckusick } 27829729Smckusick 27925424Skarels done(status) 28025424Skarels int status; 2816444Swnj { 28229729Smckusick int w; 2836444Swnj 2846444Swnj mode(0); 28529729Smckusick if (child > 0) { 28629729Smckusick /* make sure catchild does not snap it up */ 28729729Smckusick (void) signal(SIGCHLD, SIG_DFL); 28829729Smckusick if (kill(child, SIGKILL) >= 0) 28929729Smckusick while ((w = wait((union wait *)0)) > 0 && w != child) 29029729Smckusick /*void*/; 29129729Smckusick } 29225424Skarels exit(status); 2936444Swnj } 2946444Swnj 29524726Smckusick /* 29629729Smckusick * Copy SIGURGs to the child process. 29729729Smckusick */ 29829729Smckusick copytochild() 29929729Smckusick { 30029729Smckusick 30129729Smckusick (void) kill(child, SIGURG); 30229729Smckusick } 30329729Smckusick 30429729Smckusick /* 30524726Smckusick * This is called when the reader process gets the out-of-band (urgent) 30624726Smckusick * request to turn on the window-changing protocol. 30724726Smckusick */ 30824726Smckusick writeroob() 30924726Smckusick { 31024726Smckusick 31125341Smckusick if (dosigwinch == 0) { 31224919Smckusick sendwindow(); 31329729Smckusick (void) signal(SIGWINCH, sigwinch); 31425341Smckusick } 31524726Smckusick dosigwinch = 1; 31624726Smckusick } 31724726Smckusick 31811803Sedward catchild() 31911803Sedward { 32011803Sedward union wait status; 32111803Sedward int pid; 32211803Sedward 32311803Sedward again: 32429729Smckusick pid = wait3(&status, WNOHANG|WUNTRACED, (struct rusage *)0); 32511803Sedward if (pid == 0) 32611803Sedward return; 32711803Sedward /* 32811803Sedward * if the child (reader) dies, just quit 32911803Sedward */ 33011803Sedward if (pid < 0 || pid == child && !WIFSTOPPED(status)) 33129729Smckusick done((int)(status.w_termsig | status.w_retcode)); 33211803Sedward goto again; 33311803Sedward } 33411803Sedward 3356444Swnj /* 3369365Ssam * writer: write to remote: 0 -> line. 3379365Ssam * ~. terminate 3389365Ssam * ~^Z suspend rlogin process. 33910415Ssam * ~^Y suspend rlogin process, but leave reader alone. 3406444Swnj */ 3419365Ssam writer() 3426444Swnj { 34323530Sbloom char c; 34411803Sedward register n; 34523530Sbloom register bol = 1; /* beginning of line */ 34623530Sbloom register local = 0; 3476444Swnj 34811803Sedward for (;;) { 34911803Sedward n = read(0, &c, 1); 35018358Ssam if (n <= 0) { 35118358Ssam if (n < 0 && errno == EINTR) 35218358Ssam continue; 35311803Sedward break; 35418358Ssam } 3559365Ssam /* 3569365Ssam * If we're at the beginning of the line 3579365Ssam * and recognize a command character, then 3589365Ssam * we echo locally. Otherwise, characters 3599365Ssam * are echo'd remotely. If the command 3609365Ssam * character is doubled, this acts as a 3619365Ssam * force and local echo is suppressed. 3629365Ssam */ 36323530Sbloom if (bol) { 36423530Sbloom bol = 0; 36523530Sbloom if (c == cmdchar) { 36623530Sbloom bol = 0; 36723530Sbloom local = 1; 36823530Sbloom continue; 3696444Swnj } 37023530Sbloom } else if (local) { 37123530Sbloom local = 0; 37223530Sbloom if (c == '.' || c == deftc.t_eofc) { 37323530Sbloom echo(c); 37423530Sbloom break; 3756444Swnj } 37623530Sbloom if (c == defltc.t_suspc || c == defltc.t_dsuspc) { 37723530Sbloom bol = 1; 37823530Sbloom echo(c); 37923530Sbloom stop(c); 38023530Sbloom continue; 38123530Sbloom } 38223530Sbloom if (c != cmdchar) 38329729Smckusick (void) write(rem, &cmdchar, 1); 3846444Swnj } 38523530Sbloom if (write(rem, &c, 1) == 0) { 38623530Sbloom prf("line gone"); 38723530Sbloom break; 3886444Swnj } 38923530Sbloom bol = c == defkill || c == deftc.t_eofc || 39025424Skarels c == deftc.t_intrc || c == defltc.t_suspc || 39123530Sbloom c == '\r' || c == '\n'; 3926444Swnj } 3936444Swnj } 3946444Swnj 39523530Sbloom echo(c) 39623530Sbloom register char c; 39723530Sbloom { 39823530Sbloom char buf[8]; 39923530Sbloom register char *p = buf; 40023530Sbloom 40123530Sbloom c &= 0177; 40223530Sbloom *p++ = cmdchar; 40323530Sbloom if (c < ' ') { 40423530Sbloom *p++ = '^'; 40523530Sbloom *p++ = c + '@'; 40623530Sbloom } else if (c == 0177) { 40723530Sbloom *p++ = '^'; 40823530Sbloom *p++ = '?'; 40923530Sbloom } else 41023530Sbloom *p++ = c; 41123530Sbloom *p++ = '\r'; 41223530Sbloom *p++ = '\n'; 41329729Smckusick (void) write(1, buf, p - buf); 41423530Sbloom } 41523530Sbloom 41618358Ssam stop(cmdc) 41718358Ssam char cmdc; 41818358Ssam { 41918358Ssam mode(0); 42029729Smckusick (void) signal(SIGCHLD, SIG_IGN); 42129729Smckusick (void) kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP); 42229729Smckusick (void) signal(SIGCHLD, catchild); 42318358Ssam mode(1); 42418358Ssam sigwinch(); /* check for size changes */ 42518358Ssam } 42618358Ssam 42718358Ssam sigwinch() 42818358Ssam { 42918358Ssam struct winsize ws; 43018358Ssam 43129729Smckusick if (dosigwinch && get_window_size(0, &ws) == 0 && 43218358Ssam bcmp(&ws, &winsize, sizeof (ws))) { 43318358Ssam winsize = ws; 43424726Smckusick sendwindow(); 43518358Ssam } 43618358Ssam } 43718358Ssam 43824726Smckusick /* 43924726Smckusick * Send the window size to the server via the magic escape 44024726Smckusick */ 44124726Smckusick sendwindow() 44224726Smckusick { 44324726Smckusick char obuf[4 + sizeof (struct winsize)]; 44424726Smckusick struct winsize *wp = (struct winsize *)(obuf+4); 44524726Smckusick 44624726Smckusick obuf[0] = 0377; 44724726Smckusick obuf[1] = 0377; 44824726Smckusick obuf[2] = 's'; 44924726Smckusick obuf[3] = 's'; 45024726Smckusick wp->ws_row = htons(winsize.ws_row); 45124726Smckusick wp->ws_col = htons(winsize.ws_col); 45224726Smckusick wp->ws_xpixel = htons(winsize.ws_xpixel); 45324726Smckusick wp->ws_ypixel = htons(winsize.ws_ypixel); 45424726Smckusick (void) write(rem, obuf, sizeof(obuf)); 45524726Smckusick } 45624726Smckusick 45725424Skarels /* 45825424Skarels * reader: read from remote: line -> 1 45925424Skarels */ 46025424Skarels #define READING 1 46125424Skarels #define WRITING 2 46225424Skarels 46325424Skarels char rcvbuf[8 * 1024]; 46425424Skarels int rcvcnt; 46525424Skarels int rcvstate; 46626981Skarels int ppid; 46725424Skarels jmp_buf rcvtop; 46825424Skarels 4696444Swnj oob() 4706444Swnj { 47125424Skarels int out = FWRITE, atmark, n; 47225424Skarels int rcvd = 0; 4739365Ssam char waste[BUFSIZ], mark; 47424726Smckusick struct sgttyb sb; 4756444Swnj 47625424Skarels while (recv(rem, &mark, 1, MSG_OOB) < 0) 47725424Skarels switch (errno) { 47825424Skarels 47925424Skarels case EWOULDBLOCK: 48025424Skarels /* 48125424Skarels * Urgent data not here yet. 48225424Skarels * It may not be possible to send it yet 48325424Skarels * if we are blocked for output 48425424Skarels * and our input buffer is full. 48525424Skarels */ 48625424Skarels if (rcvcnt < sizeof(rcvbuf)) { 48725424Skarels n = read(rem, rcvbuf + rcvcnt, 48825424Skarels sizeof(rcvbuf) - rcvcnt); 48925424Skarels if (n <= 0) 49025424Skarels return; 49125424Skarels rcvd += n; 49225424Skarels } else { 49325424Skarels n = read(rem, waste, sizeof(waste)); 49425424Skarels if (n <= 0) 49525424Skarels return; 49625424Skarels } 49725424Skarels continue; 49825424Skarels 49925424Skarels default: 50025424Skarels return; 5016444Swnj } 50225424Skarels if (mark & TIOCPKT_WINDOW) { 50324726Smckusick /* 50424726Smckusick * Let server know about window size changes 50524726Smckusick */ 50629729Smckusick (void) kill(ppid, SIGUSR1); 50724726Smckusick } 50825424Skarels if (!eight && (mark & TIOCPKT_NOSTOP)) { 50929729Smckusick (void) ioctl(0, TIOCGETP, (char *)&sb); 51024726Smckusick sb.sg_flags &= ~CBREAK; 51124726Smckusick sb.sg_flags |= RAW; 51229729Smckusick (void) ioctl(0, TIOCSETN, (char *)&sb); 51313075Ssam notc.t_stopc = -1; 51413075Ssam notc.t_startc = -1; 51529729Smckusick (void) ioctl(0, TIOCSETC, (char *)¬c); 5166444Swnj } 51725424Skarels if (!eight && (mark & TIOCPKT_DOSTOP)) { 51829729Smckusick (void) ioctl(0, TIOCGETP, (char *)&sb); 51924726Smckusick sb.sg_flags &= ~RAW; 52024726Smckusick sb.sg_flags |= CBREAK; 52129729Smckusick (void) ioctl(0, TIOCSETN, (char *)&sb); 52213075Ssam notc.t_stopc = deftc.t_stopc; 52313075Ssam notc.t_startc = deftc.t_startc; 52429729Smckusick (void) ioctl(0, TIOCSETC, (char *)¬c); 5256444Swnj } 52625424Skarels if (mark & TIOCPKT_FLUSHWRITE) { 52729729Smckusick (void) ioctl(1, TIOCFLUSH, (char *)&out); 52825424Skarels for (;;) { 52925424Skarels if (ioctl(rem, SIOCATMARK, &atmark) < 0) { 53025424Skarels perror("ioctl"); 53125424Skarels break; 53225424Skarels } 53325424Skarels if (atmark) 53425424Skarels break; 53525424Skarels n = read(rem, waste, sizeof (waste)); 53625424Skarels if (n <= 0) 53725424Skarels break; 53825424Skarels } 53925424Skarels /* 54025424Skarels * Don't want any pending data to be output, 54125424Skarels * so clear the recv buffer. 54225424Skarels * If we were hanging on a write when interrupted, 54325424Skarels * don't want it to restart. If we were reading, 54425424Skarels * restart anyway. 54525424Skarels */ 54625424Skarels rcvcnt = 0; 54725424Skarels longjmp(rcvtop, 1); 54825424Skarels } 54929729Smckusick 55025424Skarels /* 55129729Smckusick * oob does not do FLUSHREAD (alas!) 55229729Smckusick */ 55329729Smckusick 55429729Smckusick /* 55525424Skarels * If we filled the receive buffer while a read was pending, 55625424Skarels * longjmp to the top to restart appropriately. Don't abort 55725424Skarels * a pending write, however, or we won't know how much was written. 55825424Skarels */ 55925424Skarels if (rcvd && rcvstate == READING) 56025424Skarels longjmp(rcvtop, 1); 5616444Swnj } 5626444Swnj 5639365Ssam /* 5649365Ssam * reader: read from remote: line -> 1 5659365Ssam */ 56629729Smckusick reader(oldmask) 56729729Smckusick int oldmask; 5686444Swnj { 56926981Skarels #if !defined(BSD) || BSD < 43 57026981Skarels int pid = -getpid(); 57126981Skarels #else 57225424Skarels int pid = getpid(); 57326981Skarels #endif 57425424Skarels int n, remaining; 57525424Skarels char *bufp = rcvbuf; 5766444Swnj 57729729Smckusick (void) signal(SIGTTOU, SIG_IGN); 57829729Smckusick (void) signal(SIGURG, oob); 57926981Skarels ppid = getppid(); 58029729Smckusick (void) fcntl(rem, F_SETOWN, pid); 58125424Skarels (void) setjmp(rcvtop); 58229729Smckusick (void) sigsetmask(oldmask); 5836444Swnj for (;;) { 58425424Skarels while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) { 58525424Skarels rcvstate = WRITING; 58625424Skarels n = write(1, bufp, remaining); 58725424Skarels if (n < 0) { 58825424Skarels if (errno != EINTR) 58926189Slepreau return (-1); 59025424Skarels continue; 59125424Skarels } 59225424Skarels bufp += n; 59325424Skarels } 59425424Skarels bufp = rcvbuf; 59525424Skarels rcvcnt = 0; 59625424Skarels rcvstate = READING; 59725424Skarels rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf)); 59825424Skarels if (rcvcnt == 0) 59925424Skarels return (0); 60025424Skarels if (rcvcnt < 0) { 6019365Ssam if (errno == EINTR) 6026444Swnj continue; 60326981Skarels perror("read"); 60425424Skarels return (-1); 6056444Swnj } 6066444Swnj } 6076444Swnj } 6086444Swnj 6096444Swnj mode(f) 6106444Swnj { 61113075Ssam struct tchars *tc; 61213075Ssam struct ltchars *ltc; 61313075Ssam struct sgttyb sb; 61421583Sbloom int lflags; 6159365Ssam 61629729Smckusick (void) ioctl(0, TIOCGETP, (char *)&sb); 61729729Smckusick (void) ioctl(0, TIOCLGET, (char *)&lflags); 6189962Ssam switch (f) { 6199962Ssam 6209962Ssam case 0: 62113075Ssam sb.sg_flags &= ~(CBREAK|RAW|TBDELAY); 62213075Ssam sb.sg_flags |= defflags|tabflag; 6239962Ssam tc = &deftc; 62413075Ssam ltc = &defltc; 62513075Ssam sb.sg_kill = defkill; 62613075Ssam sb.sg_erase = deferase; 62721583Sbloom lflags = deflflags; 6289962Ssam break; 6299962Ssam 6309962Ssam case 1: 63113075Ssam sb.sg_flags |= (eight ? RAW : CBREAK); 63213075Ssam sb.sg_flags &= ~defflags; 63312155Ssam /* preserve tab delays, but turn off XTABS */ 63413075Ssam if ((sb.sg_flags & TBDELAY) == XTABS) 63513075Ssam sb.sg_flags &= ~TBDELAY; 6369962Ssam tc = ¬c; 63713075Ssam ltc = &noltc; 63813075Ssam sb.sg_kill = sb.sg_erase = -1; 63921583Sbloom if (litout) 64021583Sbloom lflags |= LLITOUT; 6419962Ssam break; 6429962Ssam 6439962Ssam default: 6449962Ssam return; 6456444Swnj } 64629729Smckusick (void) ioctl(0, TIOCSLTC, (char *)ltc); 64729729Smckusick (void) ioctl(0, TIOCSETC, (char *)tc); 64829729Smckusick (void) ioctl(0, TIOCSETN, (char *)&sb); 64929729Smckusick (void) ioctl(0, TIOCLSET, (char *)&lflags); 6506444Swnj } 6516444Swnj 6529365Ssam /*VARARGS*/ 65324726Smckusick prf(f, a1, a2, a3, a4, a5) 6549365Ssam char *f; 6556444Swnj { 65629729Smckusick 65724726Smckusick fprintf(stderr, f, a1, a2, a3, a4, a5); 6586444Swnj fprintf(stderr, CRLF); 6596444Swnj } 6606444Swnj 6619365Ssam lostpeer() 6626444Swnj { 66329729Smckusick 66429729Smckusick (void) signal(SIGPIPE, SIG_IGN); 66512155Ssam prf("\007Connection closed."); 66625424Skarels done(1); 6676444Swnj } 668