xref: /csrg-svn/usr.bin/rlogin/rlogin.c (revision 6444)
1*6444Swnj #ifndef lint
2*6444Swnj static char sccsid[] = "@(#)rlogin.c	4.1 82/04/02";
3*6444Swnj #endif
4*6444Swnj 
5*6444Swnj #include <stdio.h>
6*6444Swnj #include <sgtty.h>
7*6444Swnj #include <sys/types.h>
8*6444Swnj #include <sys/socket.h>
9*6444Swnj #include <net/in.h>
10*6444Swnj #include <errno.h>
11*6444Swnj #include <pwd.h>
12*6444Swnj 
13*6444Swnj /*
14*6444Swnj  * rlogin - remote login; this is a hacked version of cu
15*6444Swnj  */
16*6444Swnj char	*index(), *rindex(), *malloc(), *getenv();
17*6444Swnj struct	passwd *getpwuid();
18*6444Swnj struct	passwd *pwd;
19*6444Swnj char	*name, *pass;
20*6444Swnj int	rem;
21*6444Swnj char	cmdchar = '~';
22*6444Swnj int	rcmdoptions = 0;
23*6444Swnj int	eight;
24*6444Swnj char	*speeds[] =
25*6444Swnj     { "0", "50", "75", "110", "134", "150", "200", "300",
26*6444Swnj       "600", "1200", "1800", "2400", "4800", "9600", "19200", "38400" };
27*6444Swnj char	term[64];
28*6444Swnj 
29*6444Swnj main(argc, argv)
30*6444Swnj 	int argc;
31*6444Swnj 	char **argv;
32*6444Swnj {
33*6444Swnj 	int pid;
34*6444Swnj 	char *host, *cp, **ap, buf[BUFSIZ];
35*6444Swnj 	register int cc;
36*6444Swnj 	struct sgttyb ttyb;
37*6444Swnj 	struct passwd *pwd;
38*6444Swnj 
39*6444Swnj 	host = rindex(argv[0], '/');
40*6444Swnj 	if (host)
41*6444Swnj 		host++;
42*6444Swnj 	else
43*6444Swnj 		host = argv[0];
44*6444Swnj 	argv++, --argc;
45*6444Swnj 	if (!strcmp(host, "rlogin"))
46*6444Swnj 		host = *argv++, --argc;
47*6444Swnj another:
48*6444Swnj 	if (!strcmp(*argv, "-d")) {
49*6444Swnj 		argv++, argc--;
50*6444Swnj 		rcmdoptions |= SO_DEBUG;
51*6444Swnj 		goto another;
52*6444Swnj 	}
53*6444Swnj 	if (!strcmp(*argv, "-l")) {
54*6444Swnj 		argv++, argc--;
55*6444Swnj 		if (argc == 0)
56*6444Swnj 			goto usage;
57*6444Swnj 		name = *argv++; argc--;
58*6444Swnj 		goto another;
59*6444Swnj 	}
60*6444Swnj 	if (!strncmp(*argv, "-e", 2)) {
61*6444Swnj 		cmdchar = argv[0][2];
62*6444Swnj 		argv++, argc--;
63*6444Swnj 		goto another;
64*6444Swnj 	}
65*6444Swnj 	if (!strcmp(*argv, "-8")) {
66*6444Swnj 		eight = 1;
67*6444Swnj 		argv++, argc--;
68*6444Swnj 		goto another;
69*6444Swnj 	}
70*6444Swnj 	if (host == 0)
71*6444Swnj 		goto usage;
72*6444Swnj 	if (argc > 0)
73*6444Swnj 		goto usage;
74*6444Swnj 	pwd = getpwuid(getuid());
75*6444Swnj 	if (pwd == 0) {
76*6444Swnj 		fprintf(stderr, "Who are you?\n");
77*6444Swnj 		exit(1);
78*6444Swnj 	}
79*6444Swnj 	cc = 0;
80*6444Swnj 	strcpy(term, getenv("TERM"));
81*6444Swnj 	if (gtty(0, &ttyb)==0) {
82*6444Swnj 		strcat(term, "/");
83*6444Swnj 		strcat(term, speeds[ttyb.sg_ospeed]);
84*6444Swnj 	}
85*6444Swnj         rem = rcmd(&host, IPPORT_LOGINSERVER, pwd->pw_name,
86*6444Swnj 	    name ? name : pwd->pw_name, term, 0);
87*6444Swnj         if (rem < 0)
88*6444Swnj                 exit(1);
89*6444Swnj 	setuid(getuid());
90*6444Swnj 	cumain();
91*6444Swnj 	exit(0);
92*6444Swnj usage:
93*6444Swnj 	fprintf(stderr,
94*6444Swnj 	    "usage: rlogin host [ -ex ] [ -l username ]\n");
95*6444Swnj 	exit(1);
96*6444Swnj }
97*6444Swnj 
98*6444Swnj #include <ctype.h>
99*6444Swnj #include <signal.h>
100*6444Swnj 
101*6444Swnj #define CRLF "\r\n"
102*6444Swnj #define wrc(ds) write(ds,&c,1)
103*6444Swnj 
104*6444Swnj char	tkill, terase;	/* current input kill & erase */
105*6444Swnj int	efk;		/* process of id of listener  */
106*6444Swnj char	c, oc;
107*6444Swnj int	pipes[] = {-1,-1};
108*6444Swnj int	intr, sig2();
109*6444Swnj int	parent;
110*6444Swnj 
111*6444Swnj int	nhup;
112*6444Swnj int	done();
113*6444Swnj 
114*6444Swnj struct tchars deftchars;
115*6444Swnj struct tchars notchars = { 0377, 0377, 'q'&037, 's'&037, 0377, 0377 };
116*6444Swnj struct ltchars defltchars;
117*6444Swnj struct ltchars noltchars = { 0377, 0377, 0377, 0377, 0377, 0377 };
118*6444Swnj char defkill, deferase;
119*6444Swnj 
120*6444Swnj cumain()
121*6444Swnj {
122*6444Swnj 	int fk;
123*6444Swnj 	int speed;
124*6444Swnj 	char *telno;
125*6444Swnj 	struct sgttyb stbuf;
126*6444Swnj 	int exit();
127*6444Swnj 
128*6444Swnj 	gtty(0, &stbuf);
129*6444Swnj 	defkill = stbuf.sg_kill;
130*6444Swnj 	deferase = stbuf.sg_erase;
131*6444Swnj 	ioctl(0, TIOCGETC, &deftchars);
132*6444Swnj 	ioctl(0, TIOCGLTC, &defltchars);
133*6444Swnj 	signal(SIGINT, exit);
134*6444Swnj 	signal(SIGHUP, exit);
135*6444Swnj 	signal(SIGQUIT, exit);
136*6444Swnj 	pipe(pipes);
137*6444Swnj 	parent = getpid();
138*6444Swnj 	fk = fork();
139*6444Swnj 	nhup = (int)signal(SIGINT, SIG_IGN);
140*6444Swnj 	if (fk == 0) {
141*6444Swnj 		rd();
142*6444Swnj 		sleep(1);
143*6444Swnj 		prf("\007Lost connection.");
144*6444Swnj 		exit(3);
145*6444Swnj 	}
146*6444Swnj 	signal(SIGCHLD, done);
147*6444Swnj 	mode(1);
148*6444Swnj 	efk = fk;
149*6444Swnj 	wr();
150*6444Swnj 	if (fk != -1) kill(fk, SIGKILL);
151*6444Swnj 	prf("Disconnected.");
152*6444Swnj 	done();
153*6444Swnj }
154*6444Swnj 
155*6444Swnj done()
156*6444Swnj {
157*6444Swnj 
158*6444Swnj 	mode(0);
159*6444Swnj 	wait((int *)NULL);
160*6444Swnj 	exit(0);
161*6444Swnj }
162*6444Swnj 
163*6444Swnj /*
164*6444Swnj  *	wr: write to remote: 0 -> line.
165*6444Swnj  *	~.	terminate
166*6444Swnj  *	~<file	send file
167*6444Swnj  *	~!	local login-style shell
168*6444Swnj  *	~!cmd	execute cmd locally
169*6444Swnj  *	~$proc	execute proc locally, send output to line
170*6444Swnj  *	~%cmd	execute builtin cmd (put and take)
171*6444Swnj  *	~^Z	suspend cu process.
172*6444Swnj  */
173*6444Swnj 
174*6444Swnj wr()
175*6444Swnj {
176*6444Swnj 	int ds,fk,lcl,x;
177*6444Swnj 	char *p,b[600];
178*6444Swnj 	for (;;) {
179*6444Swnj 		p=b;
180*6444Swnj 		while (rdc(0) == 1) {
181*6444Swnj 			if (p == b) lcl=(c == cmdchar);
182*6444Swnj 			if (p == b+1 && b[0] == cmdchar) lcl=(c!=cmdchar);
183*6444Swnj 			if (!lcl) {
184*6444Swnj 				c = oc;
185*6444Swnj 				if (wrc(rem) == 0) {
186*6444Swnj 					prf("line gone"); return;
187*6444Swnj 				}
188*6444Swnj 				if (eight == 0)
189*6444Swnj 					c &= 0177;
190*6444Swnj 			}
191*6444Swnj 			if (lcl) {
192*6444Swnj 				if (c == 0177) c=tkill;
193*6444Swnj 				if (c == '\r' || c == '\n') goto A;
194*6444Swnj 				wrc(0);
195*6444Swnj 			}
196*6444Swnj 			*p++=c;
197*6444Swnj 			if (c == terase) {
198*6444Swnj 				p=p-2;
199*6444Swnj 				if (p<b) p=b;
200*6444Swnj 			}
201*6444Swnj 			if (c == tkill || c == 0177 || c == '\4' || c == '\r' || c == '\n') p=b;
202*6444Swnj 		}
203*6444Swnj 		return;
204*6444Swnj A:
205*6444Swnj 		echo("");
206*6444Swnj 		*p=0;
207*6444Swnj 		switch (b[1]) {
208*6444Swnj 		case '.':
209*6444Swnj 		case '\004':
210*6444Swnj 			return;
211*6444Swnj 		case '!':
212*6444Swnj 		case '$':
213*6444Swnj 			fk = fork();
214*6444Swnj 			signal(SIGCHLD, SIG_DFL);
215*6444Swnj 			if (fk == 0) {
216*6444Swnj 				char *shell = getenv("SHELL");
217*6444Swnj 				if (shell == 0) shell = "/bin/sh";
218*6444Swnj 				close(1);
219*6444Swnj 				dup(b[1] == '$'? rem:2);
220*6444Swnj 				close(rem);
221*6444Swnj 				mode(0);
222*6444Swnj 				if (!nhup) signal(SIGINT, SIG_DFL);
223*6444Swnj 				if (b[2] == 0) execl(shell,shell,0);
224*6444Swnj 				/* if (b[2] == 0) execl(shell,"-",0); */
225*6444Swnj 				else execl(shell,"sh","-c",b+2,0);
226*6444Swnj 				prf("Can't execute shell");
227*6444Swnj 				exit(~0);
228*6444Swnj 			}
229*6444Swnj 			if (fk!=(-1)) {
230*6444Swnj 				while (wait(&x)!=fk);
231*6444Swnj 			}
232*6444Swnj 			signal(SIGCHLD, done);
233*6444Swnj 			mode(1);
234*6444Swnj 			if (b[1] == '!') echo("!");
235*6444Swnj 			break;
236*6444Swnj 		case '<':
237*6444Swnj 			if (b[2] == 0) break;
238*6444Swnj 			if ((ds=open(b+2,0))<0) {
239*6444Swnj 				prf("Can't divert %s",b+1);
240*6444Swnj 				break;
241*6444Swnj 			}
242*6444Swnj 			intr=x=0;
243*6444Swnj 			mode(2);
244*6444Swnj 			if (!nhup) signal(SIGINT, sig2);
245*6444Swnj 			while (!intr && rdc(ds) == 1) {
246*6444Swnj 				if (wrc(rem) == 0) {
247*6444Swnj 					x=1;
248*6444Swnj 					break;
249*6444Swnj 				}
250*6444Swnj 			}
251*6444Swnj 			signal(SIGINT, SIG_IGN);
252*6444Swnj 			close(ds);
253*6444Swnj 			mode(1);
254*6444Swnj 			if (x) return;
255*6444Swnj 			break;
256*6444Swnj 		case '>':
257*6444Swnj 		case ':':
258*6444Swnj 			{
259*6444Swnj 			register char *q;
260*6444Swnj 
261*6444Swnj 			q = b+1;
262*6444Swnj 			if(*q=='>') q++;
263*6444Swnj 			write(pipes[1],q,strlen(q)+1);
264*6444Swnj 			if (efk != -1) kill(efk,SIGEMT);
265*6444Swnj 			}
266*6444Swnj 			break;
267*6444Swnj #ifdef SIGTSTP
268*6444Swnj #define CTRLZ	26
269*6444Swnj 		case CTRLZ:
270*6444Swnj 			mode(0);
271*6444Swnj 			signal(SIGCHLD, SIG_IGN);
272*6444Swnj 			kill(0, SIGTSTP);
273*6444Swnj 			signal(SIGCHLD, done);
274*6444Swnj 			mode(1);
275*6444Swnj 			break;
276*6444Swnj #endif
277*6444Swnj 		case '%':
278*6444Swnj 			dopercen(&b[2]);
279*6444Swnj 			break;
280*6444Swnj 		default:
281*6444Swnj 			prf("Use `%c%c' to start line with `%c'", cmdchar, cmdchar, cmdchar);
282*6444Swnj 		}
283*6444Swnj 		continue;
284*6444Swnj 	}
285*6444Swnj }
286*6444Swnj 
287*6444Swnj dopercen(line)
288*6444Swnj register char *line;
289*6444Swnj {
290*6444Swnj 	char *args[10];
291*6444Swnj 	register narg, f;
292*6444Swnj 	int rcount;
293*6444Swnj 	for (narg = 0; narg < 10;) {
294*6444Swnj 		while(*line == ' ' || *line == '\t')
295*6444Swnj 			line++;
296*6444Swnj 		if (*line == '\0')
297*6444Swnj 			break;
298*6444Swnj 		args[narg++] = line;
299*6444Swnj 		while(*line != '\0' && *line != ' ' && *line != '\t')
300*6444Swnj 			line++;
301*6444Swnj 		if (*line == '\0')
302*6444Swnj 			break;
303*6444Swnj 		*line++ = '\0';
304*6444Swnj 	}
305*6444Swnj 	if (equal(args[0], "take")) {
306*6444Swnj 		if (narg < 2) {
307*6444Swnj 			prf("usage: %c%%take from [to]", cmdchar);
308*6444Swnj 			return;
309*6444Swnj 		}
310*6444Swnj 		if (narg < 3)
311*6444Swnj 			args[2] = args[1];
312*6444Swnj 		write(pipes[1], ">/dev/null",sizeof(">/dev/null"));
313*6444Swnj 		if (efk != -1) kill(efk,SIGEMT);
314*6444Swnj 		sleep(5);
315*6444Swnj 		wrln("echo '%c>:", cmdchar);
316*6444Swnj 		wrln(args[2]);
317*6444Swnj 		wrln("'; tee /dev/null <");
318*6444Swnj 		wrln(args[1]);
319*6444Swnj 		wrln(";echo '%c>'\n", cmdchar);
320*6444Swnj 		return;
321*6444Swnj 	} else if (equal(args[0], "put")) {
322*6444Swnj 		prf("%c%%put doesn't work yet (use rsh)", cmdchar);
323*6444Swnj 		return;
324*6444Swnj /*
325*6444Swnj 		if (narg < 2) {
326*6444Swnj 			prf("usage: %c%%put from [to]", cmdchar);
327*6444Swnj 			return;
328*6444Swnj 		}
329*6444Swnj 		if (narg < 3)
330*6444Swnj 			args[2] = args[1];
331*6444Swnj 		if ((f = open(args[1], 0)) < 0) {
332*6444Swnj 			prf("cannot open: %s", args[1]);
333*6444Swnj 			return;
334*6444Swnj 		}
335*6444Swnj 		wrln("stty -echo;cat >");
336*6444Swnj 		wrln(args[2]);
337*6444Swnj 		wrln(";stty echo\n");
338*6444Swnj 		sleep(5);
339*6444Swnj 		intr = 0;
340*6444Swnj 		if (!nhup)
341*6444Swnj 			signal(SIGINT, sig2);
342*6444Swnj 		mode(2);
343*6444Swnj 		rcount = 0;
344*6444Swnj 		while(!intr && rdc(f) == 1) {
345*6444Swnj 			rcount++;
346*6444Swnj 			if (c == tkill || c == terase)
347*6444Swnj 				wrln("\\");
348*6444Swnj 			if (wrc(rem) != 1) {
349*6444Swnj 				sleep(2);
350*6444Swnj 				if (wrc(rem) != 1) {
351*6444Swnj 					prf("character missed");
352*6444Swnj 					intr = 1;
353*6444Swnj 					break;
354*6444Swnj 				}
355*6444Swnj 			}
356*6444Swnj 		}
357*6444Swnj 		signal(SIGINT, SIG_IGN);
358*6444Swnj 		close(f);
359*6444Swnj 		if (intr) {
360*6444Swnj 			wrln("\n");
361*6444Swnj 			prf("stopped after %d bytes", rcount);
362*6444Swnj 		}
363*6444Swnj 		wrln("\004");
364*6444Swnj 		sleep(5);
365*6444Swnj 		mode(1);
366*6444Swnj 		return;
367*6444Swnj */
368*6444Swnj 	}
369*6444Swnj 	prf("%c%%%s unknown\n", cmdchar, args[0]);
370*6444Swnj }
371*6444Swnj 
372*6444Swnj equal(s1, s2)
373*6444Swnj register char *s1, *s2;
374*6444Swnj {
375*6444Swnj 	while (*s1++ == *s2)
376*6444Swnj 		if (*s2++ == '\0')
377*6444Swnj 			return(1);
378*6444Swnj 	return(0);
379*6444Swnj }
380*6444Swnj 
381*6444Swnj wrln(s, p1, p2, p3)
382*6444Swnj register char *s;
383*6444Swnj int p1, p2, p3;
384*6444Swnj {
385*6444Swnj 	char wbuf[256];
386*6444Swnj 
387*6444Swnj 	sprintf(wbuf, s, p1, p2, p3);
388*6444Swnj 	s = wbuf;
389*6444Swnj 	while (*s)
390*6444Swnj 		write(rem, s++, 1);
391*6444Swnj }
392*6444Swnj int ds,slnt;
393*6444Swnj int justrung;
394*6444Swnj 
395*6444Swnj /*
396*6444Swnj  *	rd: read from remote: line -> 1
397*6444Swnj  *	catch:
398*6444Swnj  *	~>[>][:][file]
399*6444Swnj  *	stuff from file...
400*6444Swnj  *	~>	(ends diversion)
401*6444Swnj  */
402*6444Swnj 
403*6444Swnj int ds,slnt,taking;
404*6444Swnj int justrung;
405*6444Swnj readmsg(){
406*6444Swnj 	static char dobuff[128], morejunk[256];
407*6444Swnj 	int n;
408*6444Swnj 	justrung = 1;
409*6444Swnj 	signal(SIGEMT,readmsg);
410*6444Swnj 	n = read(pipes[0],morejunk,256);
411*6444Swnj 	dodiver(morejunk);
412*6444Swnj }
413*6444Swnj 
414*6444Swnj dodiver(msg)
415*6444Swnj char *msg;
416*6444Swnj {
417*6444Swnj 	register char *cp = msg;
418*6444Swnj 
419*6444Swnj 	if (*cp=='>') cp++;
420*6444Swnj 	if (*cp==':') {
421*6444Swnj 		cp++;
422*6444Swnj 		if(*cp==0) {
423*6444Swnj 			slnt ^= 1;
424*6444Swnj 			return;
425*6444Swnj 		} else  {
426*6444Swnj 			slnt = 1;
427*6444Swnj 		}
428*6444Swnj 	}
429*6444Swnj 	if (ds >= 0) close(ds);
430*6444Swnj 	if (*cp==0) {
431*6444Swnj 		slnt = 0;
432*6444Swnj 		ds = -1;
433*6444Swnj 		return;
434*6444Swnj 	}
435*6444Swnj 	if (*msg!='>' || (ds=open(cp,1))<0) ds=creat(cp,0644);
436*6444Swnj 	lseek(ds, (long)0, 2);
437*6444Swnj 	if(ds < 0) prf("Creat failed:"), prf(cp);
438*6444Swnj 	if (ds<0) prf("Can't divert %s",cp+1);
439*6444Swnj }
440*6444Swnj 
441*6444Swnj 
442*6444Swnj /*
443*6444Swnj  *	rd: read from remote: line -> 1
444*6444Swnj  *	catch: diversion caught by interrupt routine
445*6444Swnj  */
446*6444Swnj 
447*6444Swnj #define ORDIN 0
448*6444Swnj #define SAWCR 1
449*6444Swnj #define EOL   2
450*6444Swnj #define SAWTL 3
451*6444Swnj #define DIVER 4
452*6444Swnj 
453*6444Swnj oob()
454*6444Swnj {
455*6444Swnj 	int mark, cc, out = 1+1;
456*6444Swnj 	char waste[512];
457*6444Swnj 
458*6444Swnj 	signal(SIGURG, oob);
459*6444Swnj 	ioctl(1, TIOCFLUSH, &out);
460*6444Swnj 	for (;;) {
461*6444Swnj 		if (ioctl(rem, SIOCATMARK, &mark) < 0) {
462*6444Swnj 			perror("ioctl");
463*6444Swnj 			break;
464*6444Swnj 		}
465*6444Swnj 		if (mark)
466*6444Swnj 			break;
467*6444Swnj 		cc = read(rem, waste, 512);
468*6444Swnj 	}
469*6444Swnj 	ioctl(rem, SIOCRCVOOB, &mark);
470*6444Swnj 	if (mark & TIOCPKT_NOSTOP) {
471*6444Swnj 		notchars.t_stopc = 0377;
472*6444Swnj 		notchars.t_startc = 0377;
473*6444Swnj 		ioctl(0, TIOCSETC, &notchars);
474*6444Swnj 	}
475*6444Swnj 	if (mark & TIOCPKT_DOSTOP) {
476*6444Swnj 		notchars.t_stopc = 's'&037;
477*6444Swnj 		notchars.t_startc = 'q'&037;
478*6444Swnj 		ioctl(0, TIOCSETC, &notchars);
479*6444Swnj 	}
480*6444Swnj }
481*6444Swnj 
482*6444Swnj rd()
483*6444Swnj {
484*6444Swnj 	extern int ds,slnt;
485*6444Swnj 	char rb[600], lb[600], *rlim, *llim, c;
486*6444Swnj 	register char *p,*q;
487*6444Swnj 	int cnt, state = 0, mustecho, oldslnt, readmsg();
488*6444Swnj 
489*6444Swnj 	signal(SIGEMT,readmsg);  /* set up child for catching diversion msgs
490*6444Swnj 				    from parent */
491*6444Swnj 	signal(SIGURG,oob);
492*6444Swnj 	{ int pid = -getpid();
493*6444Swnj 	  ioctl(rem, SIOCSPGRP, &pid); }
494*6444Swnj 	ds=(-1);
495*6444Swnj 	p = lb; llim = lb+600;
496*6444Swnj agin:
497*6444Swnj 	for (;;) {
498*6444Swnj 		extern errno;
499*6444Swnj 		errno = 0;
500*6444Swnj 		cnt = read(rem,rb,600);
501*6444Swnj 		if (cnt <= 0) {
502*6444Swnj 			if (errno == EINTR) {
503*6444Swnj 				errno = 0;
504*6444Swnj 				continue;
505*6444Swnj 			}
506*6444Swnj 			break;
507*6444Swnj 		}
508*6444Swnj 		if(!slnt) write(1,rb,cnt);
509*6444Swnj 		if(ds < 0) continue;
510*6444Swnj 		oldslnt = slnt;
511*6444Swnj 		for( q=rb, rlim = rb + cnt - 1; q <= rlim; ) {
512*6444Swnj 			if (eight == 0)
513*6444Swnj 			c &= 0177;
514*6444Swnj 			if(p < llim) *p++ = c;
515*6444Swnj 			switch(state) {
516*6444Swnj 			case ORDIN:
517*6444Swnj 				if(c=='\r') state = SAWCR;
518*6444Swnj 				break;
519*6444Swnj 			case SAWCR:
520*6444Swnj 				if(c=='\n') {
521*6444Swnj 					state = EOL;
522*6444Swnj 					p--;
523*6444Swnj 					p[-1] = '\n';
524*6444Swnj 				} else state = ORDIN;
525*6444Swnj 				break;
526*6444Swnj 			case EOL:
527*6444Swnj 				state = (c==cmdchar ? SAWTL :
528*6444Swnj 					 (c=='\r' ? SAWCR : ORDIN));
529*6444Swnj 				break;
530*6444Swnj 			case SAWTL:
531*6444Swnj 				state = (c=='>' ? DIVER :
532*6444Swnj 					 (c=='\r' ? SAWCR : ORDIN));
533*6444Swnj 				break;
534*6444Swnj 			case DIVER:
535*6444Swnj 				if(c=='\r') {
536*6444Swnj 					p--;
537*6444Swnj 				} else if (c=='\n') {
538*6444Swnj 					state = ORDIN;
539*6444Swnj 					p[-1] = 0;
540*6444Swnj 					dodiver(lb+2);
541*6444Swnj 					c = 0; p = lb;
542*6444Swnj 				}
543*6444Swnj 			}
544*6444Swnj 			if(slnt==0 && oldslnt) {
545*6444Swnj 				if(c=='\n') {
546*6444Swnj 					write(rem,lb,p-lb-1);
547*6444Swnj 					write(rem,CRLF,sizeof(CRLF));
548*6444Swnj 				} else if(q==rlim) {
549*6444Swnj 					write(rem,lb,p-lb);
550*6444Swnj 					c = '\n';  /*force flush to file*/
551*6444Swnj 				}
552*6444Swnj 			}
553*6444Swnj 			if(c=='\n') {
554*6444Swnj 				if(ds >= 0)
555*6444Swnj 					write(ds,lb,p-lb);
556*6444Swnj 				p = lb;
557*6444Swnj 			}
558*6444Swnj 		}
559*6444Swnj 	}
560*6444Swnj 	if(justrung) {
561*6444Swnj 		justrung = 0;
562*6444Swnj 		goto agin;
563*6444Swnj 	}
564*6444Swnj }
565*6444Swnj 
566*6444Swnj struct {char lobyte; char hibyte;};
567*6444Swnj mode(f)
568*6444Swnj {
569*6444Swnj 	struct sgttyb stbuf;
570*6444Swnj 	ioctl(0, TIOCGETP, &stbuf);
571*6444Swnj 	if (f == 0) {
572*6444Swnj 		stbuf.sg_flags &= ~CBREAK;
573*6444Swnj 		stbuf.sg_flags |= ECHO|CRMOD;
574*6444Swnj 		ioctl(0, TIOCSETC, &deftchars);
575*6444Swnj 		ioctl(0, TIOCSLTC, &defltchars);
576*6444Swnj 		stbuf.sg_kill = defkill;
577*6444Swnj 		stbuf.sg_erase = deferase;
578*6444Swnj 	}
579*6444Swnj 	if (f == 1) {
580*6444Swnj 		stbuf.sg_flags |= CBREAK;
581*6444Swnj 		stbuf.sg_flags &= ~(ECHO|CRMOD);
582*6444Swnj 		ioctl(0, TIOCSETC, &notchars);
583*6444Swnj 		ioctl(0, TIOCSLTC, &noltchars);
584*6444Swnj 		stbuf.sg_kill = 0377;
585*6444Swnj 		stbuf.sg_erase = 0377;
586*6444Swnj 	}
587*6444Swnj 	if (f == 2) {
588*6444Swnj 		stbuf.sg_flags &= ~CBREAK;
589*6444Swnj 		stbuf.sg_flags &= ~(ECHO|CRMOD);
590*6444Swnj 		ioctl(0, TIOCSETC, &deftchars);
591*6444Swnj 		ioctl(0, TIOCSLTC, &defltchars);
592*6444Swnj 		stbuf.sg_kill = 0377;
593*6444Swnj 		stbuf.sg_erase = 0377;
594*6444Swnj 	}
595*6444Swnj 	ioctl(0, TIOCSETN, &stbuf);
596*6444Swnj }
597*6444Swnj 
598*6444Swnj echo(s)
599*6444Swnj char *s;
600*6444Swnj {
601*6444Swnj 	char *p;
602*6444Swnj 	for (p=s;*p;p++);
603*6444Swnj 	if (p>s) write(0,s,p-s);
604*6444Swnj 	write(0,CRLF, sizeof(CRLF));
605*6444Swnj }
606*6444Swnj 
607*6444Swnj prf(f, a1, a2, a3)
608*6444Swnj char *f;
609*6444Swnj {
610*6444Swnj 	fprintf(stderr, f, a1, a2, a3);
611*6444Swnj 	fprintf(stderr, CRLF);
612*6444Swnj }
613*6444Swnj 
614*6444Swnj exists(devname)
615*6444Swnj char *devname;
616*6444Swnj {
617*6444Swnj 	if (access(devname, 0)==0)
618*6444Swnj 		return(1);
619*6444Swnj 	prf("%s does not exist", devname);
620*6444Swnj 	return(0);
621*6444Swnj }
622*6444Swnj 
623*6444Swnj rdc(ds)
624*6444Swnj {
625*6444Swnj 
626*6444Swnj 	ds=read(ds,&c,1);
627*6444Swnj 	oc = c;
628*6444Swnj 	if (eight == 0)
629*6444Swnj 		c &= 0177;
630*6444Swnj 	return (ds);
631*6444Swnj }
632*6444Swnj 
633*6444Swnj sig2()
634*6444Swnj {
635*6444Swnj 	signal(SIGINT, SIG_IGN);
636*6444Swnj 	intr = 1;
637*6444Swnj }
638