xref: /csrg-svn/libexec/telnetd/telnetd.c (revision 42673)
1 /*
2  * Copyright (c) 1989 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1989 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)telnetd.c	5.43 (Berkeley) 06/01/90";
16 #endif /* not lint */
17 
18 #include "telnetd.h"
19 
20 /*
21  * I/O data buffers,
22  * pointers, and counters.
23  */
24 char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;
25 char	ptyibuf2[BUFSIZ];
26 
27 #ifdef	CRAY
28 int	hostinfo = 1;			/* do we print login banner? */
29 #endif
30 
31 #ifdef	CRAY
32 extern int      newmap; /* nonzero if \n maps to ^M^J */
33 int	lowpty = 0, highpty;	/* low, high pty numbers */
34 #endif /* CRAY */
35 
36 int debug = 0;
37 char *progname;
38 
39 #if	defined(IP_TOS) && defined(NEED_GETTOS)
40 struct tosent {
41 	char	*t_name;	/* name */
42 	char	**t_aliases;	/* alias list */
43 	char	*t_proto;	/* protocol */
44 	int	t_tos;		/* Type Of Service bits */
45 };
46 
47 struct tosent *
48 gettosbyname(name, proto)
49 char *name, *proto;
50 {
51 	static struct tosent te;
52 	static char *aliasp = 0;
53 
54 	te.t_name = name;
55 	te.t_aliases = &aliasp;
56 	te.t_proto = proto;
57 	te.t_tos = 020;	/* Low Delay bit */
58 	return(&te);
59 }
60 #endif
61 
62 main(argc, argv)
63 	char *argv[];
64 {
65 	struct sockaddr_in from;
66 	int on = 1, fromlen;
67 #ifdef IP_TOS
68 	struct tosent *tp;
69 #endif /* IP_TOS */
70 
71 	pfrontp = pbackp = ptyobuf;
72 	netip = netibuf;
73 	nfrontp = nbackp = netobuf;
74 
75 	progname = *argv;
76 
77 #ifdef CRAY
78 	/*
79 	 * Get number of pty's before trying to process options,
80 	 * which may include changing pty range.
81 	 */
82 	highpty = getnpty();
83 #endif /* CRAY */
84 
85 top:
86 	argc--, argv++;
87 
88 	if (argc > 0 && strcmp(*argv, "-debug") == 0) {
89 		debug++;
90 		goto top;
91 	}
92 
93 #ifdef	LINEMODE
94 	if (argc > 0 && !strcmp(*argv, "-l")) {
95 		alwayslinemode = 1;
96 		goto top;
97 	}
98 #endif	/* LINEMODE */
99 
100 #ifdef CRAY
101 	if (argc > 0 && !strcmp(*argv, "-h")) {
102 		hostinfo = 0;
103 		goto top;
104 	}
105 
106 	if (argc > 0 && !strncmp(*argv, "-r", 2)) {
107 		char *strchr();
108 		char *c;
109 
110 		/*
111 		 * Allow the specification of alterations to the pty search
112 		 * range.  It is legal to specify only one, and not change the
113 		 * other from its default.
114 		 */
115 		*argv += 2;
116 		if (**argv == '\0' && argc)
117 			argv++, argc--;
118 		c = strchr(*argv, '-');
119 		if (c) {
120 			*c++ = '\0';
121 			highpty = atoi(c);
122 		}
123 		if (**argv != '\0')
124 			lowpty = atoi(*argv);
125 		if ((lowpty > highpty) || (lowpty < 0) || (highpty > 32767)) {
126 	usage:
127 			fprintf(stderr, "Usage: telnetd [-debug] [-h] ");
128 # ifdef	NEWINIT
129 			fprintf(stderr, "[-Iinitid] ");
130 # endif	/* NEWINIT */
131 			fprintf(stderr, "[-l] [-r[lowpty]-[highpty]] [port]\n");
132 			exit(1);
133 		}
134 		goto top;
135 	}
136 # ifdef	NEWINIT
137 	if (argc > 0 && !strncmp(*argv, "-I", 2)) {
138 		extern char *gen_id;
139 
140 		*argv += 2;
141 		if (**argv == '\0') {
142 			if (argc < 2)
143 				goto usage;
144 			argv++, argc--;
145 			if (**argv == '\0')
146 				goto usage;
147 		}
148 		gen_id = *argv;
149 		goto top;
150 	}
151 # endif	/* NEWINIT */
152 #endif	/* CRAY */
153 
154 	if (debug) {
155 	    int s, ns, foo;
156 	    struct servent *sp;
157 	    static struct sockaddr_in sin = { AF_INET };
158 
159 	    if (argc > 0) {
160 		    if (sp = getservbyname(*argv, "tcp")) {
161 			sin.sin_port = sp->s_port;
162 		    } else {
163 			sin.sin_port = atoi(*argv);
164 			if ((int)sin.sin_port <= 0) {
165 			    fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
166 			    exit(1);
167 			}
168 			sin.sin_port = htons((u_short)sin.sin_port);
169 		   }
170 	    } else {
171 		sp = getservbyname("telnet", "tcp");
172 		if (sp == 0) {
173 			fprintf(stderr,
174 				"telnetd: tcp/telnet: unknown service\n");
175 		    exit(1);
176 		}
177 		sin.sin_port = sp->s_port;
178 	    }
179 
180 	    s = socket(AF_INET, SOCK_STREAM, 0);
181 	    if (s < 0) {
182 		    perror("telnetd: socket");;
183 		    exit(1);
184 	    }
185 	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
186 	    if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
187 		perror("bind");
188 		exit(1);
189 	    }
190 	    if (listen(s, 1) < 0) {
191 		perror("listen");
192 		exit(1);
193 	    }
194 	    foo = sizeof sin;
195 	    ns = accept(s, (struct sockaddr *)&sin, &foo);
196 	    if (ns < 0) {
197 		perror("accept");
198 		exit(1);
199 	    }
200 	    (void) dup2(ns, 0);
201 	    (void) close(ns);
202 	    (void) close(s);
203 	}
204 
205 	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
206 	fromlen = sizeof (from);
207 	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
208 		fprintf(stderr, "%s: ", progname);
209 		perror("getpeername");
210 		_exit(1);
211 	}
212 	if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
213 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
214 	}
215 
216 #ifdef IP_TOS
217 	if ((tp = gettosbyname("telnet", "tcp")) &&
218 	    (setsockopt(0, IPPROTO_IP, IP_TOS, &tp->t_tos, sizeof(int)) < 0))
219 		syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
220 #endif /* IP_TOS */
221 	net = 0;
222 	doit(&from);
223 	/* NOTREACHED */
224 }  /* end of main */
225 
226 void	cleanup();
227 
228 /*
229  * getterminaltype
230  *
231  *	Ask the other end to send along its terminal type and speed.
232  * Output is the variable terminaltype filled in.
233  */
234 static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE };
235 void
236 getterminaltype()
237 {
238     void ttloop();
239 
240     settimer(baseline);
241     send_do(TELOPT_TTYPE, 1);
242     send_do(TELOPT_TSPEED, 1);
243     while ((hiswants[TELOPT_TTYPE] != hisopts[TELOPT_TTYPE]) ||
244 	   (hiswants[TELOPT_TSPEED] != hisopts[TELOPT_TSPEED])) {
245 	ttloop();
246     }
247     if (hisopts[TELOPT_TSPEED] == OPT_YES) {
248 	static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
249 
250 	bcopy(sbbuf, nfrontp, sizeof sbbuf);
251 	nfrontp += sizeof sbbuf;
252     }
253     if (hisopts[TELOPT_TTYPE] == OPT_YES) {
254 
255 	bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
256 	nfrontp += sizeof ttytype_sbbuf;
257     }
258     if (hisopts[TELOPT_TSPEED] == OPT_YES) {
259 	while (sequenceIs(tspeedsubopt, baseline))
260 	    ttloop();
261     }
262     if (hisopts[TELOPT_TTYPE] == OPT_YES) {
263 	char first[256], last[256];
264 
265 	while (sequenceIs(ttypesubopt, baseline))
266 	    ttloop();
267 
268 	if (!terminaltypeok(&terminaltype[5])) {
269 	    (void) strncpy(first, terminaltype, sizeof(first));
270 	    for(;;) {
271 		/*
272 		 * Save the unknown name, and request the next name.
273 		 */
274 		(void) strncpy(last, terminaltype, sizeof(last));
275 		_gettermname();
276 		if (terminaltypeok(&terminaltype[5]))
277 		    break;
278 		if (strncmp(last, terminaltype, sizeof(last)) == 0) {
279 		    /*
280 		     * We've hit the end.  If this is the same as
281 		     * the first name, just go with it.
282 		     */
283 		    if (strncmp(first, terminaltype, sizeof(first) == 0))
284 			break;
285 		    /*
286 		     * Get the terminal name one more type, so that
287 		     * RFC1091 compliant telnets will cycle back to
288 		     * the start of the list.
289 		     */
290 		    _gettermname();
291 		    if (strncmp(first, terminaltype, sizeof(first) != 0))
292 			(void) strncpy(terminaltype, first, sizeof(first));
293 		    break;
294 		}
295 	    }
296 	}
297     }
298 }  /* end of getterminaltype */
299 
300 _gettermname()
301 {
302     settimer(baseline);
303     bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
304     nfrontp += sizeof ttytype_sbbuf;
305     while (sequenceIs(ttypesubopt, baseline))
306 	ttloop();
307 }
308 
309 terminaltypeok(s)
310 char *s;
311 {
312     char buf[1024];
313 
314     if (terminaltype == NULL)
315 	return(1);
316 
317     /*
318      * tgetent() will return 1 if the type is known, and
319      * 0 if it is not known.  If it returns -1, it couldn't
320      * open the database.  But if we can't open the database,
321      * it won't help to say we failed, because we won't be
322      * able to verify anything else.  So, we treat -1 like 1.
323      */
324     if (tgetent(buf, s) == 0)
325 	return(0);
326     return(1);
327 }
328 
329 /*
330  * Get a pty, scan input lines.
331  */
332 doit(who)
333 	struct sockaddr_in *who;
334 {
335 	char *host, *inet_ntoa();
336 	int t;
337 	struct hostent *hp;
338 
339 	/*
340 	 * Find an available pty to use.
341 	 */
342 	pty = getpty();
343 	if (pty < 0)
344 		fatal(net, "All network ports in use");
345 
346 	t = getptyslave();
347 
348 	/* get name of connected client */
349 	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
350 		who->sin_family);
351 	if (hp)
352 		host = hp->h_name;
353 	else
354 		host = inet_ntoa(who->sin_addr);
355 
356 	/*
357 	 * get terminal type.
358 	 */
359 	getterminaltype();
360 	if (terminaltype == NULL)
361 		terminaltype = "TERM=network";
362 
363 	/*
364 	 * Start up the login process on the slave side of the terminal
365 	 */
366 	startslave(t, host);
367 
368 	telnet(net, pty);  /* begin server processing */
369 	/*NOTREACHED*/
370 }  /* end of doit */
371 
372 #ifndef	MAXHOSTNAMELEN
373 #define	MAXHOSTNAMELEN 64
374 #endif	MAXHOSTNAMELEN
375 /*
376  * Main loop.  Select from pty and network, and
377  * hand data to telnet receiver finite state machine.
378  */
379 telnet(f, p)
380 int f, p;
381 {
382 	int on = 1;
383 	char hostname[MAXHOSTNAMELEN];
384 #if	defined(CRAY2) && defined(UNICOS5)
385 	int termstat();
386 	int interrupt(), sendbrk();
387 #endif
388 #define	TABBUFSIZ	512
389 	char	defent[TABBUFSIZ];
390 	char	defstrs[TABBUFSIZ];
391 #undef	TABBUFSIZ
392 	char *HE;
393 	char *HN;
394 	char *IM;
395 	void netflush();
396 
397 	/*
398 	 * Initialize the slc mapping table.
399 	 */
400 	get_slc_defaults();
401 
402 	/*
403 	 * Do some tests where it is desireable to wait for a response.
404 	 * Rather than doing them slowly, one at a time, do them all
405 	 * at once.
406 	 */
407 	if (!myopts[TELOPT_SGA])
408 		send_will(TELOPT_SGA, 1);
409 	/*
410 	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
411 	 * because 4.2 clients are unable to deal with TCP urgent data.
412 	 *
413 	 * To find out, we send out a "DO ECHO".  If the remote system
414 	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
415 	 * that fact ("WILL ECHO" ==> that the client will echo what
416 	 * WE, the server, sends it; it does NOT mean that the client will
417 	 * echo the terminal input).
418 	 */
419 	send_do(TELOPT_ECHO, 1);
420 
421 #ifdef	LINEMODE
422 	if (hisopts[TELOPT_LINEMODE] == OPT_NO) {
423 		/* Query the peer for linemode support by trying to negotiate
424 		 * the linemode option.
425 		 */
426 		linemode = 1;
427 		editmode = 0;
428 		send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
429 	}
430 #endif	/* LINEMODE */
431 
432 	/*
433 	 * Send along a couple of other options that we wish to negotiate.
434 	 */
435 	send_do(TELOPT_NAWS, 1);
436 	send_will(TELOPT_STATUS, 1);
437 	flowmode = 1;  /* default flow control state */
438 	send_do(TELOPT_LFLOW, 1);
439 
440 	/*
441 	 * Spin, waiting for a response from the DO ECHO.  However,
442 	 * some REALLY DUMB telnets out there might not respond
443 	 * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
444 	 * telnets so far seem to respond with WONT for a DO that
445 	 * they don't understand...) because by the time we get the
446 	 * response, it will already have processed the DO ECHO.
447 	 * Kludge upon kludge.
448 	 */
449 	while (hiswants[TELOPT_NAWS] != hisopts[TELOPT_NAWS])
450 		ttloop();
451 
452 	/*
453 	 * On the off chance that the telnet client is broken and does not
454 	 * respond to the DO ECHO we sent, (after all, we did send the
455 	 * DO NAWS negotiation after the DO ECHO, and we won't get here
456 	 * until a response to the DO NAWS comes back) simulate the
457 	 * receipt of a will echo.  This will also send a WONT ECHO
458 	 * to the client, since we assume that the client failed to
459 	 * respond because it believes that it is already in DO ECHO
460 	 * mode, which we do not want.
461 	 */
462 	if (hiswants[TELOPT_ECHO] == OPT_YES) {
463 		willoption(TELOPT_ECHO);
464 	}
465 
466 	/*
467 	 * Finally, to clean things up, we turn on our echo.  This
468 	 * will break stupid 4.2 telnets out of local terminal echo.
469 	 */
470 
471 	if (!myopts[TELOPT_ECHO])
472 		send_will(TELOPT_ECHO, 1);
473 
474 	/*
475 	 * Turn on packet mode, and default to line at at time mode.
476 	 */
477 	(void) ioctl(p, TIOCPKT, (char *)&on);
478 #ifdef	LINEMODE
479 	tty_setlinemode(1);
480 
481 # ifdef	KLUDGELINEMODE
482 	/*
483 	 * Continuing line mode support.  If client does not support
484 	 * real linemode, attempt to negotiate kludge linemode by sending
485 	 * the do timing mark sequence.
486 	 */
487 	if (lmodetype < REAL_LINEMODE)
488 		send_do(TELOPT_TM, 1);
489 # endif	/* KLUDGELINEMODE */
490 #endif	/* LINEMODE */
491 
492 	/*
493 	 * Call telrcv() once to pick up anything received during
494 	 * terminal type negotiation, 4.2/4.3 determination, and
495 	 * linemode negotiation.
496 	 */
497 	telrcv();
498 
499 	(void) ioctl(f, FIONBIO, (char *)&on);
500 	(void) ioctl(p, FIONBIO, (char *)&on);
501 #if	defined(CRAY2) && defined(UNICOS5)
502 	init_termdriver(f, p, interrupt, sendbrk);
503 #endif
504 
505 #if	defined(SO_OOBINLINE)
506 	(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
507 #endif	/* defined(SO_OOBINLINE) */
508 
509 #ifdef	SIGTSTP
510 	(void) signal(SIGTSTP, SIG_IGN);
511 #endif
512 #ifdef	SIGTTOU
513 	/*
514 	 * Ignoring SIGTTOU keeps the kernel from blocking us
515 	 * in ttioct() in /sys/tty.c.
516 	 */
517 	(void) signal(SIGTTOU, SIG_IGN);
518 #endif
519 
520 	(void) signal(SIGCHLD, cleanup);
521 
522 #if	defined(CRAY2) && defined(UNICOS5)
523 	/*
524 	 * Cray-2 will send a signal when pty modes are changed by slave
525 	 * side.  Set up signal handler now.
526 	 */
527 	if ((int)signal(SIGUSR1, termstat) < 0)
528 		perror("signal");
529 	else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
530 		perror("ioctl:TCSIGME");
531 	/*
532 	 * Make processing loop check terminal characteristics early on.
533 	 */
534 	termstat();
535 #endif
536 
537 	(void) setpgrp(0, 0);
538 #ifdef	TCSETCTTY
539 	ioctl(p, TCSETCTTY, 0);
540 #endif
541 
542 	/*
543 	 * Show banner that getty never gave.
544 	 *
545 	 * We put the banner in the pty input buffer.  This way, it
546 	 * gets carriage return null processing, etc., just like all
547 	 * other pty --> client data.
548 	 */
549 
550 	(void) gethostname(hostname, sizeof (hostname));
551 
552 	if (getent(defent, "default") == 1) {
553 		char *getstr();
554 		char *cp=defstrs;
555 
556 		HE = getstr("he", &cp);
557 		HN = getstr("hn", &cp);
558 		IM = getstr("im", &cp);
559 		if (HN && *HN)
560 			(void) strcpy(hostname, HN);
561 		if (IM == 0)
562 			IM = "";
563 	} else {
564 #ifdef	CRAY
565 		if (hostinfo == 0)
566 			IM = 0;
567 		else
568 #endif
569 			IM = DEFAULT_IM;
570 		HE = 0;
571 	}
572 	edithost(HE, hostname);
573 	if (IM && *IM)
574 		putf(IM, ptyibuf2);
575 
576 	if (pcc)
577 		(void) strncat(ptyibuf2, ptyip, pcc+1);
578 	ptyip = ptyibuf2;
579 	pcc = strlen(ptyip);
580 #ifdef	LINEMODE
581 	/*
582 	 * Last check to make sure all our states are correct.
583 	 */
584 	init_termbuf();
585 	localstat();
586 #endif	/* LINEMODE */
587 
588 	for (;;) {
589 		fd_set ibits, obits, xbits;
590 		register int c;
591 
592 		if (ncc < 0 && pcc < 0)
593 			break;
594 
595 #if	defined(CRAY2) && defined(UNICOS5)
596 		if (needtermstat)
597 			_termstat();
598 #endif	/* defined(CRAY2) && defined(UNICOS5) */
599 		FD_ZERO(&ibits);
600 		FD_ZERO(&obits);
601 		FD_ZERO(&xbits);
602 		/*
603 		 * Never look for input if there's still
604 		 * stuff in the corresponding output buffer
605 		 */
606 		if (nfrontp - nbackp || pcc > 0) {
607 			FD_SET(f, &obits);
608 		} else {
609 			FD_SET(p, &ibits);
610 		}
611 		if (pfrontp - pbackp || ncc > 0) {
612 			FD_SET(p, &obits);
613 		} else {
614 			FD_SET(f, &ibits);
615 		}
616 		if (!SYNCHing) {
617 			FD_SET(f, &xbits);
618 		}
619 		if ((c = select(16, &ibits, &obits, &xbits,
620 						(struct timeval *)0)) < 1) {
621 			if (c == -1) {
622 				if (errno == EINTR) {
623 					continue;
624 				}
625 			}
626 			sleep(5);
627 			continue;
628 		}
629 
630 		/*
631 		 * Any urgent data?
632 		 */
633 		if (FD_ISSET(net, &xbits)) {
634 		    SYNCHing = 1;
635 		}
636 
637 		/*
638 		 * Something to read from the network...
639 		 */
640 		if (FD_ISSET(net, &ibits)) {
641 #if	!defined(SO_OOBINLINE)
642 			/*
643 			 * In 4.2 (and 4.3 beta) systems, the
644 			 * OOB indication and data handling in the kernel
645 			 * is such that if two separate TCP Urgent requests
646 			 * come in, one byte of TCP data will be overlaid.
647 			 * This is fatal for Telnet, but we try to live
648 			 * with it.
649 			 *
650 			 * In addition, in 4.2 (and...), a special protocol
651 			 * is needed to pick up the TCP Urgent data in
652 			 * the correct sequence.
653 			 *
654 			 * What we do is:  if we think we are in urgent
655 			 * mode, we look to see if we are "at the mark".
656 			 * If we are, we do an OOB receive.  If we run
657 			 * this twice, we will do the OOB receive twice,
658 			 * but the second will fail, since the second
659 			 * time we were "at the mark", but there wasn't
660 			 * any data there (the kernel doesn't reset
661 			 * "at the mark" until we do a normal read).
662 			 * Once we've read the OOB data, we go ahead
663 			 * and do normal reads.
664 			 *
665 			 * There is also another problem, which is that
666 			 * since the OOB byte we read doesn't put us
667 			 * out of OOB state, and since that byte is most
668 			 * likely the TELNET DM (data mark), we would
669 			 * stay in the TELNET SYNCH (SYNCHing) state.
670 			 * So, clocks to the rescue.  If we've "just"
671 			 * received a DM, then we test for the
672 			 * presence of OOB data when the receive OOB
673 			 * fails (and AFTER we did the normal mode read
674 			 * to clear "at the mark").
675 			 */
676 		    if (SYNCHing) {
677 			int atmark;
678 
679 			(void) ioctl(net, SIOCATMARK, (char *)&atmark);
680 			if (atmark) {
681 			    ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
682 			    if ((ncc == -1) && (errno == EINVAL)) {
683 				ncc = read(net, netibuf, sizeof (netibuf));
684 				if (sequenceIs(didnetreceive, gotDM)) {
685 				    SYNCHing = stilloob(net);
686 				}
687 			    }
688 			} else {
689 			    ncc = read(net, netibuf, sizeof (netibuf));
690 			}
691 		    } else {
692 			ncc = read(net, netibuf, sizeof (netibuf));
693 		    }
694 		    settimer(didnetreceive);
695 #else	/* !defined(SO_OOBINLINE)) */
696 		    ncc = read(net, netibuf, sizeof (netibuf));
697 #endif	/* !defined(SO_OOBINLINE)) */
698 		    if (ncc < 0 && errno == EWOULDBLOCK)
699 			ncc = 0;
700 		    else {
701 			if (ncc <= 0) {
702 			    break;
703 			}
704 			netip = netibuf;
705 		    }
706 		}
707 
708 		/*
709 		 * Something to read from the pty...
710 		 */
711 		if (FD_ISSET(p, &ibits)) {
712 			pcc = read(p, ptyibuf, BUFSIZ);
713 			if (pcc < 0 && errno == EWOULDBLOCK)
714 				pcc = 0;
715 			else {
716 				if (pcc <= 0)
717 					break;
718 #if	!defined(CRAY2) || !defined(UNICOS5)
719 #ifdef	LINEMODE
720 				/*
721 				 * If ioctl from pty, pass it through net
722 				 */
723 				if (ptyibuf[0] & TIOCPKT_IOCTL) {
724 					copy_termbuf(ptyibuf+1, pcc-1);
725 					localstat();
726 					pcc = 1;
727 				}
728 #endif	LINEMODE
729 				if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
730 					netclear();	/* clear buffer back */
731 #ifdef	notdef
732 					/*
733 					 * We really should have this in, but
734 					 * there are client telnets on some
735 					 * operating systems get screwed up
736 					 * royally if we send them urgent
737 					 * mode data.  So, for now, we'll not
738 					 * do this...
739 					 */
740 					*nfrontp++ = IAC;
741 					*nfrontp++ = DM;
742 					neturg = nfrontp-1; /* off by one XXX */
743 #endif
744 				}
745 				if (hisopts[TELOPT_LFLOW] &&
746 				    (ptyibuf[0] &
747 				     (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
748 					(void) sprintf(nfrontp, "%c%c%c%c%c%c",
749 					    IAC, SB, TELOPT_LFLOW,
750 					    ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0,
751 					    IAC, SE);
752 					nfrontp += 6;
753 				}
754 				pcc--;
755 				ptyip = ptyibuf+1;
756 #else	/* defined(CRAY2) && defined(UNICOS5) */
757 				if (!uselinemode) {
758 					unpcc = pcc;
759 					unptyip = ptyibuf;
760 					pcc = term_output(&unptyip, ptyibuf2,
761 								&unpcc, BUFSIZ);
762 					ptyip = ptyibuf2;
763 				} else
764 					ptyip = ptyibuf;
765 #endif	/* defined(CRAY2) && defined(UNICOS5) */
766 			}
767 		}
768 
769 		while (pcc > 0) {
770 			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
771 				break;
772 			c = *ptyip++ & 0377, pcc--;
773 			if (c == IAC)
774 				*nfrontp++ = c;
775 #if	defined(CRAY2) && defined(UNICOS5)
776 			else if (c == '\n' &&
777 				     myopts[TELOPT_BINARY] == OPT_NO && newmap)
778 				*nfrontp++ = '\r';
779 #endif	/* defined(CRAY2) && defined(UNICOS5) */
780 			*nfrontp++ = c;
781 			if ((c == '\r') && (myopts[TELOPT_BINARY] == OPT_NO)) {
782 				if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
783 					*nfrontp++ = *ptyip++ & 0377;
784 					pcc--;
785 				} else
786 					*nfrontp++ = '\0';
787 			}
788 		}
789 #if	defined(CRAY2) && defined(UNICOS5)
790 		/*
791 		 * If chars were left over from the terminal driver,
792 		 * note their existence.
793 		 */
794 		 if (!uselinemode && unpcc) {
795 			pcc = unpcc;
796 			unpcc = 0;
797 			ptyip = unptyip;
798 		}
799 #endif	/* defined(CRAY2) && defined(UNICOS5) */
800 
801 		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
802 			netflush();
803 		if (ncc > 0)
804 			telrcv();
805 		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
806 			ptyflush();
807 	}
808 	cleanup();
809 }  /* end of telnet */
810 
811 #ifndef	TCSIG
812 # ifdef	TIOCSIG
813 #  define TCSIG TIOCSIG
814 # endif
815 #endif
816 
817 /*
818  * Send interrupt to process on other side of pty.
819  * If it is in raw mode, just write NULL;
820  * otherwise, write intr char.
821  */
822 interrupt()
823 {
824 	ptyflush();	/* half-hearted */
825 
826 #ifdef	TCSIG
827 	(void) ioctl(pty, TCSIG, (char *)SIGINT);
828 #else	/* TCSIG */
829 	init_termbuf();
830 	*pfrontp++ = slctab[SLC_IP].sptr ?
831 			(unsigned char)*slctab[SLC_IP].sptr : '\177';
832 #endif	/* TCSIG */
833 }
834 
835 /*
836  * Send quit to process on other side of pty.
837  * If it is in raw mode, just write NULL;
838  * otherwise, write quit char.
839  */
840 sendbrk()
841 {
842 	ptyflush();	/* half-hearted */
843 #ifdef	TCSIG
844 	(void) ioctl(pty, TCSIG, (char *)SIGQUIT);
845 #else	/* TCSIG */
846 	init_termbuf();
847 	*pfrontp++ = slctab[SLC_ABORT].sptr ?
848 			(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
849 #endif	/* TCSIG */
850 }
851 
852 sendsusp()
853 {
854 #ifdef	SIGTSTP
855 	ptyflush();	/* half-hearted */
856 # ifdef	TCSIG
857 	(void) ioctl(pty, TCSIG, (char *)SIGTSTP);
858 # else	/* TCSIG */
859 	*pfrontp++ = slctab[SLC_SUSP].sptr ?
860 			(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
861 # endif	/* TCSIG */
862 #endif	/* SIGTSTP */
863 }
864 
865 doeof()
866 {
867 #if	defined(USE_TERMIO) && defined(SYSV_TERMIO)
868 	extern char oldeofc;
869 #endif
870 	init_termbuf();
871 
872 #if	defined(USE_TERMIO) && defined(SYSV_TERMIO)
873 	if (!tty_isediting()) {
874 		*pfrontp++ = oldeofc;
875 		return;
876 	}
877 #endif
878 	*pfrontp++ = slctab[SLC_EOF].sptr ?
879 			(unsigned char)*slctab[SLC_EOF].sptr : '\004';
880 }
881