xref: /csrg-svn/usr.bin/rlogin/rlogin.c (revision 26189)
121595Sdist /*
221595Sdist  * Copyright (c) 1983 Regents of the University of California.
321595Sdist  * All rights reserved.  The Berkeley software License Agreement
421595Sdist  * specifies the terms and conditions for redistribution.
521595Sdist  */
621595Sdist 
76444Swnj #ifndef lint
821595Sdist char copyright[] =
921595Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
1021595Sdist  All rights reserved.\n";
1121595Sdist #endif not lint
126444Swnj 
1321595Sdist #ifndef lint
14*26189Slepreau static char sccsid[] = "@(#)rlogin.c	5.9 (Berkeley) 02/17/86";
1521595Sdist #endif not lint
1621595Sdist 
1712990Ssam /*
1812990Ssam  * rlogin - remote login
1912990Ssam  */
206444Swnj #include <sys/types.h>
2125424Skarels #include <sys/errno.h>
2224727Smckusick #include <sys/file.h>
236444Swnj #include <sys/socket.h>
2413620Ssam #include <sys/wait.h>
259365Ssam 
269207Ssam #include <netinet/in.h>
279365Ssam 
289365Ssam #include <stdio.h>
299365Ssam #include <sgtty.h>
306444Swnj #include <errno.h>
316444Swnj #include <pwd.h>
329365Ssam #include <signal.h>
3325424Skarels #include <setjmp.h>
349365Ssam #include <netdb.h>
356444Swnj 
3624726Smckusick # ifndef TIOCPKT_WINDOW
3724726Smckusick # define TIOCPKT_WINDOW 0x80
3824726Smckusick # endif TIOCPKT_WINDOW
3924726Smckusick 
406444Swnj char	*index(), *rindex(), *malloc(), *getenv();
416444Swnj struct	passwd *getpwuid();
429365Ssam char	*name;
436444Swnj int	rem;
446444Swnj char	cmdchar = '~';
456444Swnj int	eight;
4621583Sbloom int	litout;
476444Swnj char	*speeds[] =
486444Swnj     { "0", "50", "75", "110", "134", "150", "200", "300",
496444Swnj       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
5018358Ssam char	term[256] = "network";
519365Ssam extern	int errno;
529365Ssam int	lostpeer();
5324726Smckusick int	dosigwinch = 0;
5418358Ssam struct	winsize winsize;
5524726Smckusick int	sigwinch(), oob();
566444Swnj 
576444Swnj main(argc, argv)
586444Swnj 	int argc;
596444Swnj 	char **argv;
606444Swnj {
619365Ssam 	char *host, *cp;
626444Swnj 	struct sgttyb ttyb;
636444Swnj 	struct passwd *pwd;
649365Ssam 	struct servent *sp;
6524726Smckusick 	int uid, options = 0, oldmask;
6617449Slepreau 	int on = 1;
676444Swnj 
686444Swnj 	host = rindex(argv[0], '/');
696444Swnj 	if (host)
706444Swnj 		host++;
716444Swnj 	else
726444Swnj 		host = argv[0];
736444Swnj 	argv++, --argc;
746444Swnj 	if (!strcmp(host, "rlogin"))
756444Swnj 		host = *argv++, --argc;
766444Swnj another:
7710839Ssam 	if (argc > 0 && !strcmp(*argv, "-d")) {
786444Swnj 		argv++, argc--;
7910415Ssam 		options |= SO_DEBUG;
806444Swnj 		goto another;
816444Swnj 	}
8210839Ssam 	if (argc > 0 && !strcmp(*argv, "-l")) {
836444Swnj 		argv++, argc--;
846444Swnj 		if (argc == 0)
856444Swnj 			goto usage;
866444Swnj 		name = *argv++; argc--;
876444Swnj 		goto another;
886444Swnj 	}
8910839Ssam 	if (argc > 0 && !strncmp(*argv, "-e", 2)) {
906444Swnj 		cmdchar = argv[0][2];
916444Swnj 		argv++, argc--;
926444Swnj 		goto another;
936444Swnj 	}
9410839Ssam 	if (argc > 0 && !strcmp(*argv, "-8")) {
956444Swnj 		eight = 1;
966444Swnj 		argv++, argc--;
976444Swnj 		goto another;
986444Swnj 	}
9921583Sbloom 	if (argc > 0 && !strcmp(*argv, "-L")) {
10021583Sbloom 		litout = 1;
10121583Sbloom 		argv++, argc--;
10221583Sbloom 		goto another;
10321583Sbloom 	}
1046444Swnj 	if (host == 0)
1056444Swnj 		goto usage;
1066444Swnj 	if (argc > 0)
1076444Swnj 		goto usage;
1086444Swnj 	pwd = getpwuid(getuid());
1096444Swnj 	if (pwd == 0) {
1106444Swnj 		fprintf(stderr, "Who are you?\n");
1116444Swnj 		exit(1);
1126444Swnj 	}
1139365Ssam 	sp = getservbyname("login", "tcp");
1149365Ssam 	if (sp == 0) {
1159365Ssam 		fprintf(stderr, "rlogin: login/tcp: unknown service\n");
1169365Ssam 		exit(2);
1179365Ssam 	}
1189241Ssam 	cp = getenv("TERM");
1199241Ssam 	if (cp)
1209241Ssam 		strcpy(term, cp);
12118358Ssam 	if (ioctl(0, TIOCGETP, &ttyb) == 0) {
1226444Swnj 		strcat(term, "/");
1236444Swnj 		strcat(term, speeds[ttyb.sg_ospeed]);
1246444Swnj 	}
12524726Smckusick 	(void) ioctl(0, TIOCGWINSZ, &winsize);
12612990Ssam 	signal(SIGPIPE, lostpeer);
12724726Smckusick 	signal(SIGURG, oob);
12824726Smckusick 	oldmask = sigblock(sigmask(SIGURG));
1299365Ssam         rem = rcmd(&host, sp->s_port, pwd->pw_name,
1306444Swnj 	    name ? name : pwd->pw_name, term, 0);
1316444Swnj         if (rem < 0)
1326444Swnj                 exit(1);
13310415Ssam 	if (options & SO_DEBUG &&
13417449Slepreau 	    setsockopt(rem, SOL_SOCKET, SO_DEBUG, &on, sizeof (on)) < 0)
13510415Ssam 		perror("rlogin: setsockopt (SO_DEBUG)");
1369365Ssam 	uid = getuid();
1379365Ssam 	if (setuid(uid) < 0) {
1389365Ssam 		perror("rlogin: setuid");
1399365Ssam 		exit(1);
1409365Ssam 	}
14124726Smckusick 	doit(oldmask);
1429365Ssam 	/*NOTREACHED*/
1436444Swnj usage:
1446444Swnj 	fprintf(stderr,
14525341Smckusick 	    "usage: rlogin host [ -ex ] [ -l username ] [ -8 ] [ -L ]\n");
1466444Swnj 	exit(1);
1476444Swnj }
1486444Swnj 
1496444Swnj #define CRLF "\r\n"
1506444Swnj 
1519365Ssam int	child;
15211803Sedward int	catchild();
15324726Smckusick int	writeroob();
1549365Ssam 
15513075Ssam int	defflags, tabflag;
15621583Sbloom int	deflflags;
15713075Ssam char	deferase, defkill;
15813075Ssam struct	tchars deftc;
15913075Ssam struct	ltchars defltc;
16013075Ssam struct	tchars notc =	{ -1, -1, -1, -1, -1, -1 };
16113075Ssam struct	ltchars noltc =	{ -1, -1, -1, -1, -1, -1 };
1626444Swnj 
16324726Smckusick doit(oldmask)
1646444Swnj {
1656444Swnj 	int exit();
16613075Ssam 	struct sgttyb sb;
1676444Swnj 
16813075Ssam 	ioctl(0, TIOCGETP, (char *)&sb);
16913075Ssam 	defflags = sb.sg_flags;
17012155Ssam 	tabflag = defflags & TBDELAY;
1719962Ssam 	defflags &= ECHO | CRMOD;
17213075Ssam 	deferase = sb.sg_erase;
17313075Ssam 	defkill = sb.sg_kill;
17421583Sbloom 	ioctl(0, TIOCLGET, (char *)&deflflags);
17513075Ssam 	ioctl(0, TIOCGETC, (char *)&deftc);
17613075Ssam 	notc.t_startc = deftc.t_startc;
17713075Ssam 	notc.t_stopc = deftc.t_stopc;
17813075Ssam 	ioctl(0, TIOCGLTC, (char *)&defltc);
17924726Smckusick 	signal(SIGINT, SIG_IGN);
18012990Ssam 	signal(SIGHUP, exit);
18112990Ssam 	signal(SIGQUIT, exit);
1829365Ssam 	child = fork();
1839365Ssam 	if (child == -1) {
1849365Ssam 		perror("rlogin: fork");
18525424Skarels 		done(1);
1869365Ssam 	}
1879365Ssam 	if (child == 0) {
18824726Smckusick 		mode(1);
18924726Smckusick 		sigsetmask(oldmask);
19025424Skarels 		if (reader() == 0) {
19125424Skarels 			prf("Connection closed.");
19225424Skarels 			exit(0);
19325424Skarels 		}
19412155Ssam 		sleep(1);
19512155Ssam 		prf("\007Connection closed.");
1966444Swnj 		exit(3);
1976444Swnj 	}
19824726Smckusick 	signal(SIGURG, writeroob);
19924726Smckusick 	sigsetmask(oldmask);
20012990Ssam 	signal(SIGCHLD, catchild);
2019365Ssam 	writer();
20212155Ssam 	prf("Closed connection.");
20325424Skarels 	done(0);
2046444Swnj }
2056444Swnj 
20625424Skarels done(status)
20725424Skarels 	int status;
2086444Swnj {
2096444Swnj 
2106444Swnj 	mode(0);
2119365Ssam 	if (child > 0 && kill(child, SIGKILL) >= 0)
2129365Ssam 		wait((int *)0);
21325424Skarels 	exit(status);
2146444Swnj }
2156444Swnj 
21624726Smckusick /*
21724726Smckusick  * This is called when the reader process gets the out-of-band (urgent)
21824726Smckusick  * request to turn on the window-changing protocol.
21924726Smckusick  */
22024726Smckusick writeroob()
22124726Smckusick {
22224726Smckusick 
22325341Smckusick 	if (dosigwinch == 0) {
22424919Smckusick 		sendwindow();
22525341Smckusick 		signal(SIGWINCH, sigwinch);
22625341Smckusick 	}
22724726Smckusick 	dosigwinch = 1;
22824726Smckusick }
22924726Smckusick 
23011803Sedward catchild()
23111803Sedward {
23211803Sedward 	union wait status;
23311803Sedward 	int pid;
23411803Sedward 
23511803Sedward again:
23611803Sedward 	pid = wait3(&status, WNOHANG|WUNTRACED, 0);
23711803Sedward 	if (pid == 0)
23811803Sedward 		return;
23911803Sedward 	/*
24011803Sedward 	 * if the child (reader) dies, just quit
24111803Sedward 	 */
24211803Sedward 	if (pid < 0 || pid == child && !WIFSTOPPED(status))
24325424Skarels 		done(status.w_termsig | status.w_retcode);
24411803Sedward 	goto again;
24511803Sedward }
24611803Sedward 
2476444Swnj /*
2489365Ssam  * writer: write to remote: 0 -> line.
2499365Ssam  * ~.	terminate
2509365Ssam  * ~^Z	suspend rlogin process.
25110415Ssam  * ~^Y  suspend rlogin process, but leave reader alone.
2526444Swnj  */
2539365Ssam writer()
2546444Swnj {
25523530Sbloom 	char c;
25611803Sedward 	register n;
25723530Sbloom 	register bol = 1;               /* beginning of line */
25823530Sbloom 	register local = 0;
2596444Swnj 
26011803Sedward 	for (;;) {
26111803Sedward 		n = read(0, &c, 1);
26218358Ssam 		if (n <= 0) {
26318358Ssam 			if (n < 0 && errno == EINTR)
26418358Ssam 				continue;
26511803Sedward 			break;
26618358Ssam 		}
2679365Ssam 		/*
2689365Ssam 		 * If we're at the beginning of the line
2699365Ssam 		 * and recognize a command character, then
2709365Ssam 		 * we echo locally.  Otherwise, characters
2719365Ssam 		 * are echo'd remotely.  If the command
2729365Ssam 		 * character is doubled, this acts as a
2739365Ssam 		 * force and local echo is suppressed.
2749365Ssam 		 */
27523530Sbloom 		if (bol) {
27623530Sbloom 			bol = 0;
27723530Sbloom 			if (c == cmdchar) {
27823530Sbloom 				bol = 0;
27923530Sbloom 				local = 1;
28023530Sbloom 				continue;
2816444Swnj 			}
28223530Sbloom 		} else if (local) {
28323530Sbloom 			local = 0;
28423530Sbloom 			if (c == '.' || c == deftc.t_eofc) {
28523530Sbloom 				echo(c);
28623530Sbloom 				break;
2876444Swnj 			}
28823530Sbloom 			if (c == defltc.t_suspc || c == defltc.t_dsuspc) {
28923530Sbloom 				bol = 1;
29023530Sbloom 				echo(c);
29123530Sbloom 				stop(c);
29223530Sbloom 				continue;
29323530Sbloom 			}
29423530Sbloom 			if (c != cmdchar)
29523530Sbloom 				write(rem, &cmdchar, 1);
2966444Swnj 		}
29723530Sbloom 		if (write(rem, &c, 1) == 0) {
29823530Sbloom 			prf("line gone");
29923530Sbloom 			break;
3006444Swnj 		}
30123530Sbloom 		bol = c == defkill || c == deftc.t_eofc ||
30225424Skarels 		    c == deftc.t_intrc || c == defltc.t_suspc ||
30323530Sbloom 		    c == '\r' || c == '\n';
3046444Swnj 	}
3056444Swnj }
3066444Swnj 
30723530Sbloom echo(c)
30823530Sbloom register char c;
30923530Sbloom {
31023530Sbloom 	char buf[8];
31123530Sbloom 	register char *p = buf;
31223530Sbloom 
31323530Sbloom 	c &= 0177;
31423530Sbloom 	*p++ = cmdchar;
31523530Sbloom 	if (c < ' ') {
31623530Sbloom 		*p++ = '^';
31723530Sbloom 		*p++ = c + '@';
31823530Sbloom 	} else if (c == 0177) {
31923530Sbloom 		*p++ = '^';
32023530Sbloom 		*p++ = '?';
32123530Sbloom 	} else
32223530Sbloom 		*p++ = c;
32323530Sbloom 	*p++ = '\r';
32423530Sbloom 	*p++ = '\n';
32523530Sbloom 	write(1, buf, p - buf);
32623530Sbloom }
32723530Sbloom 
32818358Ssam stop(cmdc)
32918358Ssam 	char cmdc;
33018358Ssam {
33118358Ssam 	mode(0);
33218358Ssam 	signal(SIGCHLD, SIG_IGN);
33318358Ssam 	kill(cmdc == defltc.t_suspc ? 0 : getpid(), SIGTSTP);
33418358Ssam 	signal(SIGCHLD, catchild);
33518358Ssam 	mode(1);
33618358Ssam 	sigwinch();			/* check for size changes */
33718358Ssam }
33818358Ssam 
33918358Ssam sigwinch()
34018358Ssam {
34118358Ssam 	struct winsize ws;
34218358Ssam 
34325341Smckusick 	if (dosigwinch && ioctl(0, TIOCGWINSZ, &ws) == 0 &&
34418358Ssam 	    bcmp(&ws, &winsize, sizeof (ws))) {
34518358Ssam 		winsize = ws;
34624726Smckusick 		sendwindow();
34718358Ssam 	}
34818358Ssam }
34918358Ssam 
35024726Smckusick /*
35124726Smckusick  * Send the window size to the server via the magic escape
35224726Smckusick  */
35324726Smckusick sendwindow()
35424726Smckusick {
35524726Smckusick 	char obuf[4 + sizeof (struct winsize)];
35624726Smckusick 	struct winsize *wp = (struct winsize *)(obuf+4);
35724726Smckusick 
35824726Smckusick 	obuf[0] = 0377;
35924726Smckusick 	obuf[1] = 0377;
36024726Smckusick 	obuf[2] = 's';
36124726Smckusick 	obuf[3] = 's';
36224726Smckusick 	wp->ws_row = htons(winsize.ws_row);
36324726Smckusick 	wp->ws_col = htons(winsize.ws_col);
36424726Smckusick 	wp->ws_xpixel = htons(winsize.ws_xpixel);
36524726Smckusick 	wp->ws_ypixel = htons(winsize.ws_ypixel);
36624726Smckusick 	(void) write(rem, obuf, sizeof(obuf));
36724726Smckusick }
36824726Smckusick 
36925424Skarels /*
37025424Skarels  * reader: read from remote: line -> 1
37125424Skarels  */
37225424Skarels #define	READING	1
37325424Skarels #define	WRITING	2
37425424Skarels 
37525424Skarels char	rcvbuf[8 * 1024];
37625424Skarels int	rcvcnt;
37725424Skarels int	rcvstate;
37825424Skarels jmp_buf	rcvtop;
37925424Skarels 
3806444Swnj oob()
3816444Swnj {
38225424Skarels 	int out = FWRITE, atmark, n;
38325424Skarels 	int rcvd = 0;
3849365Ssam 	char waste[BUFSIZ], mark;
38524726Smckusick 	struct sgttyb sb;
3866444Swnj 
38725424Skarels 	while (recv(rem, &mark, 1, MSG_OOB) < 0)
38825424Skarels 		switch (errno) {
38925424Skarels 
39025424Skarels 		case EWOULDBLOCK:
39125424Skarels 			/*
39225424Skarels 			 * Urgent data not here yet.
39325424Skarels 			 * It may not be possible to send it yet
39425424Skarels 			 * if we are blocked for output
39525424Skarels 			 * and our input buffer is full.
39625424Skarels 			 */
39725424Skarels 			if (rcvcnt < sizeof(rcvbuf)) {
39825424Skarels 				n = read(rem, rcvbuf + rcvcnt,
39925424Skarels 					sizeof(rcvbuf) - rcvcnt);
40025424Skarels 				if (n <= 0)
40125424Skarels 					return;
40225424Skarels 				rcvd += n;
40325424Skarels 			} else {
40425424Skarels 				n = read(rem, waste, sizeof(waste));
40525424Skarels 				if (n <= 0)
40625424Skarels 					return;
40725424Skarels 			}
40825424Skarels 			continue;
40925424Skarels 
41025424Skarels 		default:
41125424Skarels 			return;
4126444Swnj 	}
41325424Skarels 	if (mark & TIOCPKT_WINDOW) {
41424726Smckusick 		/*
41524726Smckusick 		 * Let server know about window size changes
41624726Smckusick 		 */
41724726Smckusick 		kill(getppid(), SIGURG);
41824726Smckusick 	}
41925424Skarels 	if (!eight && (mark & TIOCPKT_NOSTOP)) {
42024726Smckusick 		ioctl(0, TIOCGETP, (char *)&sb);
42124726Smckusick 		sb.sg_flags &= ~CBREAK;
42224726Smckusick 		sb.sg_flags |= RAW;
42324726Smckusick 		ioctl(0, TIOCSETN, (char *)&sb);
42413075Ssam 		notc.t_stopc = -1;
42513075Ssam 		notc.t_startc = -1;
42613075Ssam 		ioctl(0, TIOCSETC, (char *)&notc);
4276444Swnj 	}
42825424Skarels 	if (!eight && (mark & TIOCPKT_DOSTOP)) {
42924726Smckusick 		ioctl(0, TIOCGETP, (char *)&sb);
43024726Smckusick 		sb.sg_flags &= ~RAW;
43124726Smckusick 		sb.sg_flags |= CBREAK;
43224726Smckusick 		ioctl(0, TIOCSETN, (char *)&sb);
43313075Ssam 		notc.t_stopc = deftc.t_stopc;
43413075Ssam 		notc.t_startc = deftc.t_startc;
43513075Ssam 		ioctl(0, TIOCSETC, (char *)&notc);
4366444Swnj 	}
43725424Skarels 	if (mark & TIOCPKT_FLUSHWRITE) {
43825424Skarels 		ioctl(1, TIOCFLUSH, (char *)&out);
43925424Skarels 		for (;;) {
44025424Skarels 			if (ioctl(rem, SIOCATMARK, &atmark) < 0) {
44125424Skarels 				perror("ioctl");
44225424Skarels 				break;
44325424Skarels 			}
44425424Skarels 			if (atmark)
44525424Skarels 				break;
44625424Skarels 			n = read(rem, waste, sizeof (waste));
44725424Skarels 			if (n <= 0)
44825424Skarels 				break;
44925424Skarels 		}
45025424Skarels 		/*
45125424Skarels 		 * Don't want any pending data to be output,
45225424Skarels 		 * so clear the recv buffer.
45325424Skarels 		 * If we were hanging on a write when interrupted,
45425424Skarels 		 * don't want it to restart.  If we were reading,
45525424Skarels 		 * restart anyway.
45625424Skarels 		 */
45725424Skarels 		rcvcnt = 0;
45825424Skarels 		longjmp(rcvtop, 1);
45925424Skarels 	}
46025424Skarels 	/*
46125424Skarels 	 * If we filled the receive buffer while a read was pending,
46225424Skarels 	 * longjmp to the top to restart appropriately.  Don't abort
46325424Skarels 	 * a pending write, however, or we won't know how much was written.
46425424Skarels 	 */
46525424Skarels 	if (rcvd && rcvstate == READING)
46625424Skarels 		longjmp(rcvtop, 1);
4676444Swnj }
4686444Swnj 
4699365Ssam /*
4709365Ssam  * reader: read from remote: line -> 1
4719365Ssam  */
4729365Ssam reader()
4736444Swnj {
47425424Skarels 	int pid = getpid();
47525424Skarels 	int n, remaining;
47625424Skarels 	char *bufp = rcvbuf;
4776444Swnj 
47823530Sbloom 	signal(SIGTTOU, SIG_IGN);
47925424Skarels 	fcntl(rem, F_SETOWN, pid);
48025424Skarels 	(void) setjmp(rcvtop);
4816444Swnj 	for (;;) {
48225424Skarels 		while ((remaining = rcvcnt - (bufp - rcvbuf)) > 0) {
48325424Skarels 			rcvstate = WRITING;
48425424Skarels 			n = write(1, bufp, remaining);
48525424Skarels 			if (n < 0) {
48625424Skarels 				if (errno != EINTR)
487*26189Slepreau 					return (-1);
48825424Skarels 				continue;
48925424Skarels 			}
49025424Skarels 			bufp += n;
49125424Skarels 		}
49225424Skarels 		bufp = rcvbuf;
49325424Skarels 		rcvcnt = 0;
49425424Skarels 		rcvstate = READING;
49525424Skarels 		rcvcnt = read(rem, rcvbuf, sizeof (rcvbuf));
49625424Skarels 		if (rcvcnt == 0)
49725424Skarels 			return (0);
49825424Skarels 		if (rcvcnt < 0) {
4999365Ssam 			if (errno == EINTR)
5006444Swnj 				continue;
50125424Skarels 			return (-1);
5026444Swnj 		}
5036444Swnj 	}
5046444Swnj }
5056444Swnj 
5066444Swnj mode(f)
5076444Swnj {
50813075Ssam 	struct tchars *tc;
50913075Ssam 	struct ltchars *ltc;
51013075Ssam 	struct sgttyb sb;
51121583Sbloom 	int	lflags;
5129365Ssam 
51313075Ssam 	ioctl(0, TIOCGETP, (char *)&sb);
51421583Sbloom 	ioctl(0, TIOCLGET, (char *)&lflags);
5159962Ssam 	switch (f) {
5169962Ssam 
5179962Ssam 	case 0:
51813075Ssam 		sb.sg_flags &= ~(CBREAK|RAW|TBDELAY);
51913075Ssam 		sb.sg_flags |= defflags|tabflag;
5209962Ssam 		tc = &deftc;
52113075Ssam 		ltc = &defltc;
52213075Ssam 		sb.sg_kill = defkill;
52313075Ssam 		sb.sg_erase = deferase;
52421583Sbloom 		lflags = deflflags;
5259962Ssam 		break;
5269962Ssam 
5279962Ssam 	case 1:
52813075Ssam 		sb.sg_flags |= (eight ? RAW : CBREAK);
52913075Ssam 		sb.sg_flags &= ~defflags;
53012155Ssam 		/* preserve tab delays, but turn off XTABS */
53113075Ssam 		if ((sb.sg_flags & TBDELAY) == XTABS)
53213075Ssam 			sb.sg_flags &= ~TBDELAY;
5339962Ssam 		tc = &notc;
53413075Ssam 		ltc = &noltc;
53513075Ssam 		sb.sg_kill = sb.sg_erase = -1;
53621583Sbloom 		if (litout)
53721583Sbloom 			lflags |= LLITOUT;
5389962Ssam 		break;
5399962Ssam 
5409962Ssam 	default:
5419962Ssam 		return;
5426444Swnj 	}
54313075Ssam 	ioctl(0, TIOCSLTC, (char *)ltc);
54413075Ssam 	ioctl(0, TIOCSETC, (char *)tc);
54513075Ssam 	ioctl(0, TIOCSETN, (char *)&sb);
54621583Sbloom 	ioctl(0, TIOCLSET, (char *)&lflags);
5476444Swnj }
5486444Swnj 
5499365Ssam /*VARARGS*/
55024726Smckusick prf(f, a1, a2, a3, a4, a5)
5519365Ssam 	char *f;
5526444Swnj {
55324726Smckusick 	fprintf(stderr, f, a1, a2, a3, a4, a5);
5546444Swnj 	fprintf(stderr, CRLF);
5556444Swnj }
5566444Swnj 
5579365Ssam lostpeer()
5586444Swnj {
55912990Ssam 	signal(SIGPIPE, SIG_IGN);
56012155Ssam 	prf("\007Connection closed.");
56125424Skarels 	done(1);
5626444Swnj }
563