xref: /original-bsd/libexec/telnetd/telnetd.c (revision cb015375)
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.49 (Berkeley) 12/18/92";
16 #endif /* not lint */
17 
18 #include "telnetd.h"
19 #include "pathnames.h"
20 
21 #if	defined(_SC_CRAY_SECURE_SYS)
22 #include <sys/sysv.h>
23 #include <sys/secdev.h>
24 int	secflag;
25 char	tty_dev[16];
26 struct	secdev dv;
27 struct	sysv sysv;
28 struct	socket_security ss;
29 #endif	/* _SC_CRAY_SECURE_SYS */
30 
31 #if	defined(AUTHENTICATION)
32 #include <libtelnet/auth.h>
33 int	auth_level = 0;
34 #endif
35 #if	defined(SecurID)
36 int	require_SecurID = 0;
37 #endif
38 
39 extern	int utmp_len;
40 int	registerd_host_only = 0;
41 
42 #ifdef	STREAMSPTY
43 # include <stropts.h>
44 # include <termio.h>
45 /* make sure we don't get the bsd version */
46 # include "/usr/include/sys/tty.h"
47 # include <sys/ptyvar.h>
48 
49 /*
50  * Because of the way ptyibuf is used with streams messages, we need
51  * ptyibuf+1 to be on a full-word boundary.  The following wierdness
52  * is simply to make that happen.
53  */
54 char	ptyibufbuf[BUFSIZ+4];
55 char	*ptyibuf = ptyibufbuf+3;
56 char	*ptyip = ptyibufbuf+3;
57 char	ptyibuf2[BUFSIZ];
58 unsigned char ctlbuf[BUFSIZ];
59 struct	strbuf strbufc, strbufd;
60 
61 int readstream();
62 
63 #else	/* ! STREAMPTY */
64 
65 /*
66  * I/O data buffers,
67  * pointers, and counters.
68  */
69 char	ptyibuf[BUFSIZ], *ptyip = ptyibuf;
70 char	ptyibuf2[BUFSIZ];
71 
72 #endif /* ! STREAMPTY */
73 
74 int	hostinfo = 1;			/* do we print login banner? */
75 
76 #ifdef	CRAY
77 extern int      newmap; /* nonzero if \n maps to ^M^J */
78 int	lowpty = 0, highpty;	/* low, high pty numbers */
79 #endif /* CRAY */
80 
81 int debug = 0;
82 int keepalive = 1;
83 char *progname;
84 
85 extern void usage P((void));
86 
87 main(argc, argv)
88 	char *argv[];
89 {
90 	struct sockaddr_in from;
91 	int on = 1, fromlen;
92 	register int ch;
93 	extern char *optarg;
94 	extern int optind;
95 #if	defined(IPPROTO_IP) && defined(IP_TOS)
96 	int tos = -1;
97 #endif
98 
99 	pfrontp = pbackp = ptyobuf;
100 	netip = netibuf;
101 	nfrontp = nbackp = netobuf;
102 #if	defined(ENCRYPTION)
103 	nclearto = 0;
104 #endif
105 
106 	progname = *argv;
107 
108 #ifdef CRAY
109 	/*
110 	 * Get number of pty's before trying to process options,
111 	 * which may include changing pty range.
112 	 */
113 	highpty = getnpty();
114 #endif /* CRAY */
115 
116 	while ((ch = getopt(argc, argv, "d:a:e:klhnr:u:UI:D:B:sS:a:X:")) != EOF) {
117 		switch(ch) {
118 
119 #ifdef	AUTHENTICATION
120 		case 'a':
121 			/*
122 			 * Check for required authentication level
123 			 */
124 			if (strcmp(optarg, "debug") == 0) {
125 				extern int auth_debug_mode;
126 				auth_debug_mode = 1;
127 			} else if (strcasecmp(optarg, "none") == 0) {
128 				auth_level = 0;
129 			} else if (strcasecmp(optarg, "other") == 0) {
130 				auth_level = AUTH_OTHER;
131 			} else if (strcasecmp(optarg, "user") == 0) {
132 				auth_level = AUTH_USER;
133 			} else if (strcasecmp(optarg, "valid") == 0) {
134 				auth_level = AUTH_VALID;
135 			} else if (strcasecmp(optarg, "off") == 0) {
136 				/*
137 				 * This hack turns off authentication
138 				 */
139 				auth_level = -1;
140 			} else {
141 				fprintf(stderr,
142 			    "telnetd: unknown authorization level for -a\n");
143 			}
144 			break;
145 #endif	/* AUTHENTICATION */
146 
147 #ifdef BFTPDAEMON
148 		case 'B':
149 			bftpd++;
150 			break;
151 #endif /* BFTPDAEMON */
152 
153 		case 'd':
154 			if (strcmp(optarg, "ebug") == 0) {
155 				debug++;
156 				break;
157 			}
158 			usage();
159 			/* NOTREACHED */
160 			break;
161 
162 #ifdef DIAGNOSTICS
163 		case 'D':
164 			/*
165 			 * Check for desired diagnostics capabilities.
166 			 */
167 			if (!strcmp(optarg, "report")) {
168 				diagnostic |= TD_REPORT|TD_OPTIONS;
169 			} else if (!strcmp(optarg, "exercise")) {
170 				diagnostic |= TD_EXERCISE;
171 			} else if (!strcmp(optarg, "netdata")) {
172 				diagnostic |= TD_NETDATA;
173 			} else if (!strcmp(optarg, "ptydata")) {
174 				diagnostic |= TD_PTYDATA;
175 			} else if (!strcmp(optarg, "options")) {
176 				diagnostic |= TD_OPTIONS;
177 			} else {
178 				usage();
179 				/* NOT REACHED */
180 			}
181 			break;
182 #endif /* DIAGNOSTICS */
183 
184 #ifdef	ENCRYPTION
185 		case 'e':
186 			if (strcmp(optarg, "debug") == 0) {
187 				extern int encrypt_debug_mode;
188 				encrypt_debug_mode = 1;
189 				break;
190 			}
191 			usage();
192 			/* NOTREACHED */
193 			break;
194 #endif	/* ENCRYPTION */
195 
196 		case 'h':
197 			hostinfo = 0;
198 			break;
199 
200 #if	defined(CRAY) && defined(NEWINIT)
201 		case 'I':
202 		    {
203 			extern char *gen_id;
204 			gen_id = optarg;
205 			break;
206 		    }
207 #endif	/* defined(CRAY) && defined(NEWINIT) */
208 
209 #ifdef	LINEMODE
210 		case 'l':
211 			alwayslinemode = 1;
212 			break;
213 #endif	/* LINEMODE */
214 
215 		case 'k':
216 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
217 			lmodetype = NO_AUTOKLUDGE;
218 #else
219 			/* ignore -k option if built without kludge linemode */
220 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
221 			break;
222 
223 		case 'n':
224 			keepalive = 0;
225 			break;
226 
227 #ifdef CRAY
228 		case 'r':
229 		    {
230 			char *strchr();
231 			char *c;
232 
233 			/*
234 			 * Allow the specification of alterations
235 			 * to the pty search range.  It is legal to
236 			 * specify only one, and not change the
237 			 * other from its default.
238 			 */
239 			c = strchr(optarg, '-');
240 			if (c) {
241 				*c++ = '\0';
242 				highpty = atoi(c);
243 			}
244 			if (*optarg != '\0')
245 				lowpty = atoi(optarg);
246 			if ((lowpty > highpty) || (lowpty < 0) ||
247 							(highpty > 32767)) {
248 				usage();
249 				/* NOT REACHED */
250 			}
251 			break;
252 		    }
253 #endif	/* CRAY */
254 
255 #ifdef	SecurID
256 		case 's':
257 			/* SecurID required */
258 			require_SecurID = 1;
259 			break;
260 #endif	/* SecurID */
261 		case 'S':
262 #ifdef	HAS_GETTOS
263 			if ((tos = parsetos(optarg, "tcp")) < 0)
264 				fprintf(stderr, "%s%s%s\n",
265 					"telnetd: Bad TOS argument '", optarg,
266 					"'; will try to use default TOS");
267 #else
268 			fprintf(stderr, "%s%s\n", "TOS option unavailable; ",
269 						"-S flag not supported\n");
270 #endif
271 			break;
272 
273 		case 'u':
274 			utmp_len = atoi(optarg);
275 			break;
276 
277 		case 'U':
278 			registerd_host_only = 1;
279 			break;
280 
281 #ifdef	AUTHENTICATION
282 		case 'X':
283 			/*
284 			 * Check for invalid authentication types
285 			 */
286 			auth_disable_name(optarg);
287 			break;
288 #endif	/* AUTHENTICATION */
289 
290 		default:
291 			fprintf(stderr, "telnetd: %s: unknown option\n", ch);
292 			/* FALLTHROUGH */
293 		case '?':
294 			usage();
295 			/* NOTREACHED */
296 		}
297 	}
298 
299 	argc -= optind;
300 	argv += optind;
301 
302 	if (debug) {
303 	    int s, ns, foo;
304 	    struct servent *sp;
305 	    static struct sockaddr_in sin = { AF_INET };
306 
307 	    if (argc > 1) {
308 		usage();
309 		/* NOT REACHED */
310 	    } else if (argc == 1) {
311 		    if (sp = getservbyname(*argv, "tcp")) {
312 			sin.sin_port = sp->s_port;
313 		    } else {
314 			sin.sin_port = atoi(*argv);
315 			if ((int)sin.sin_port <= 0) {
316 			    fprintf(stderr, "telnetd: %s: bad port #\n", *argv);
317 			    usage();
318 			    /* NOT REACHED */
319 			}
320 			sin.sin_port = htons((u_short)sin.sin_port);
321 		   }
322 	    } else {
323 		sp = getservbyname("telnet", "tcp");
324 		if (sp == 0) {
325 		    fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
326 		    exit(1);
327 		}
328 		sin.sin_port = sp->s_port;
329 	    }
330 
331 	    s = socket(AF_INET, SOCK_STREAM, 0);
332 	    if (s < 0) {
333 		    perror("telnetd: socket");;
334 		    exit(1);
335 	    }
336 	    (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
337 				(char *)&on, sizeof(on));
338 	    if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) {
339 		perror("bind");
340 		exit(1);
341 	    }
342 	    if (listen(s, 1) < 0) {
343 		perror("listen");
344 		exit(1);
345 	    }
346 	    foo = sizeof sin;
347 	    ns = accept(s, (struct sockaddr *)&sin, &foo);
348 	    if (ns < 0) {
349 		perror("accept");
350 		exit(1);
351 	    }
352 	    (void) dup2(ns, 0);
353 	    (void) close(ns);
354 	    (void) close(s);
355 #ifdef convex
356 	} else if (argc == 1) {
357 		; /* VOID*/		/* Just ignore the host/port name */
358 #endif
359 	} else if (argc > 0) {
360 		usage();
361 		/* NOT REACHED */
362 	}
363 
364 #if	defined(_SC_CRAY_SECURE_SYS)
365 	secflag = sysconf(_SC_CRAY_SECURE_SYS);
366 
367 	/*
368 	 *      Get socket's security label
369 	 */
370 	if (secflag)  {
371 		int sz = sizeof(ss);
372 
373 		bzero((char *)&dv, sizeof(dv));
374 
375 		if (getsysv(&sysv, sizeof(struct sysv)) != 0) {
376 			perror("getsysv");
377 			exit(1);
378 		}
379 
380 		/*
381 		 *      Get socket security label and set device values
382 		 *         {security label to be set on ttyp device}
383 		 */
384 		if (getsockopt(0, SOL_SOCKET, SO_SECURITY,
385 				(char *)&ss, &sz) >= 0) {
386 
387 			dv.dv_actlvl = ss.ss_slevel;
388 			dv.dv_actcmp = ss.ss_compart;
389 			dv.dv_minlvl = ss.ss_minlvl;
390 			dv.dv_maxlvl = ss.ss_maxlvl;
391 			dv.dv_valcmp = ss.ss_maxcmp;
392 		}
393 	}
394 #endif	/* _SC_CRAY_SECURE_SYS */
395 
396 	openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
397 	fromlen = sizeof (from);
398 	if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
399 		fprintf(stderr, "%s: ", progname);
400 		perror("getpeername");
401 		_exit(1);
402 	}
403 	if (keepalive &&
404 	    setsockopt(0, SOL_SOCKET, SO_KEEPALIVE,
405 			(char *)&on, sizeof (on)) < 0) {
406 		syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");
407 	}
408 
409 #if	defined(IPPROTO_IP) && defined(IP_TOS)
410 	{
411 # if	defined(HAS_GETTOS)
412 		struct tosent *tp;
413 		if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
414 			tos = tp->t_tos;
415 # endif
416 		if (tos < 0)
417 			tos = 020;	/* Low Delay bit */
418 		if (tos
419 		   && (setsockopt(0, IPPROTO_IP, IP_TOS,
420 				  (char *)&tos, sizeof(tos)) < 0)
421 		   && (errno != ENOPROTOOPT) )
422 			syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
423 	}
424 #endif	/* defined(IPPROTO_IP) && defined(IP_TOS) */
425 	net = 0;
426 	doit(&from);
427 	/* NOTREACHED */
428 }  /* end of main */
429 
430 	void
431 usage()
432 {
433 	fprintf(stderr, "Usage: telnetd");
434 #ifdef	AUTHENTICATION
435 	fprintf(stderr, " [-a (debug|other|user|valid|off)]\n\t");
436 #endif
437 #ifdef BFTPDAEMON
438 	fprintf(stderr, " [-B]");
439 #endif
440 	fprintf(stderr, " [-debug]");
441 #ifdef DIAGNOSTICS
442 	fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
443 #endif
444 #ifdef	AUTHENTICATION
445 	fprintf(stderr, " [-edebug]");
446 #endif
447 	fprintf(stderr, " [-h]");
448 #if	defined(CRAY) && defined(NEWINIT)
449 	fprintf(stderr, " [-Iinitid]");
450 #endif
451 #ifdef LINEMODE
452 	fprintf(stderr, " [-l]");
453 #endif
454 	fprintf(stderr, " [-n]");
455 #ifdef	CRAY
456 	fprintf(stderr, " [-r[lowpty]-[highpty]]");
457 #endif
458 #ifdef	SecurID
459 	fprintf(stderr, " [-s]");
460 #endif
461 #ifdef	AUTHENTICATION
462 	fprintf(stderr, " [-X auth-type]");
463 #endif
464 	fprintf(stderr, " [-u utmp_hostname_length] [-U]");
465 	fprintf(stderr, " [port]\n");
466 	exit(1);
467 }
468 
469 /*
470  * getterminaltype
471  *
472  *	Ask the other end to send along its terminal type and speed.
473  * Output is the variable terminaltype filled in.
474  */
475 static char ttytype_sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE };
476 
477     int
478 getterminaltype(name)
479     char *name;
480 {
481     int retval = -1;
482     void _gettermname();
483 
484     settimer(baseline);
485 #if	defined(AUTHENTICATION)
486     /*
487      * Handle the Authentication option before we do anything else.
488      */
489     send_do(TELOPT_AUTHENTICATION, 1);
490     while (his_will_wont_is_changing(TELOPT_AUTHENTICATION))
491 	ttloop();
492     if (his_state_is_will(TELOPT_AUTHENTICATION)) {
493 	retval = auth_wait(name);
494     }
495 #endif
496 
497 #if	defined(ENCRYPTION)
498     send_will(TELOPT_ENCRYPT, 1);
499 #endif
500     send_do(TELOPT_TTYPE, 1);
501     send_do(TELOPT_TSPEED, 1);
502     send_do(TELOPT_XDISPLOC, 1);
503     send_do(TELOPT_ENVIRON, 1);
504     while (
505 #if	defined(ENCRYPTION)
506 	   his_do_dont_is_changing(TELOPT_ENCRYPT) ||
507 #endif
508 	   his_will_wont_is_changing(TELOPT_TTYPE) ||
509 	   his_will_wont_is_changing(TELOPT_TSPEED) ||
510 	   his_will_wont_is_changing(TELOPT_XDISPLOC) ||
511 	   his_will_wont_is_changing(TELOPT_ENVIRON)) {
512 	ttloop();
513     }
514 #if	defined(ENCRYPTION)
515     /*
516      * Wait for the negotiation of what type of encryption we can
517      * send with.  If autoencrypt is not set, this will just return.
518      */
519     if (his_state_is_will(TELOPT_ENCRYPT)) {
520 	encrypt_wait();
521     }
522 #endif
523     if (his_state_is_will(TELOPT_TSPEED)) {
524 	static char sbbuf[] = { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
525 
526 	bcopy(sbbuf, nfrontp, sizeof sbbuf);
527 	nfrontp += sizeof sbbuf;
528     }
529     if (his_state_is_will(TELOPT_XDISPLOC)) {
530 	static char sbbuf[] = { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE };
531 
532 	bcopy(sbbuf, nfrontp, sizeof sbbuf);
533 	nfrontp += sizeof sbbuf;
534     }
535     if (his_state_is_will(TELOPT_ENVIRON)) {
536 	static char sbbuf[] = { IAC, SB, TELOPT_ENVIRON, TELQUAL_SEND, IAC, SE };
537 
538 	bcopy(sbbuf, nfrontp, sizeof sbbuf);
539 	nfrontp += sizeof sbbuf;
540     }
541     if (his_state_is_will(TELOPT_TTYPE)) {
542 
543 	bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
544 	nfrontp += sizeof ttytype_sbbuf;
545     }
546     if (his_state_is_will(TELOPT_TSPEED)) {
547 	while (sequenceIs(tspeedsubopt, baseline))
548 	    ttloop();
549     }
550     if (his_state_is_will(TELOPT_XDISPLOC)) {
551 	while (sequenceIs(xdisplocsubopt, baseline))
552 	    ttloop();
553     }
554     if (his_state_is_will(TELOPT_ENVIRON)) {
555 	while (sequenceIs(environsubopt, baseline))
556 	    ttloop();
557     }
558     if (his_state_is_will(TELOPT_TTYPE)) {
559 	char first[256], last[256];
560 
561 	while (sequenceIs(ttypesubopt, baseline))
562 	    ttloop();
563 
564 	/*
565 	 * If the other side has already disabled the option, then
566 	 * we have to just go with what we (might) have already gotten.
567 	 */
568 	if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) {
569 	    (void) strncpy(first, terminaltype, sizeof(first));
570 	    for(;;) {
571 		/*
572 		 * Save the unknown name, and request the next name.
573 		 */
574 		(void) strncpy(last, terminaltype, sizeof(last));
575 		_gettermname();
576 		if (terminaltypeok(terminaltype))
577 		    break;
578 		if ((strncmp(last, terminaltype, sizeof(last)) == 0) ||
579 		    his_state_is_wont(TELOPT_TTYPE)) {
580 		    /*
581 		     * We've hit the end.  If this is the same as
582 		     * the first name, just go with it.
583 		     */
584 		    if (strncmp(first, terminaltype, sizeof(first)) == 0)
585 			break;
586 		    /*
587 		     * Get the terminal name one more time, so that
588 		     * RFC1091 compliant telnets will cycle back to
589 		     * the start of the list.
590 		     */
591 		     _gettermname();
592 		    if (strncmp(first, terminaltype, sizeof(first)) != 0)
593 			(void) strncpy(terminaltype, first, sizeof(first));
594 		    break;
595 		}
596 	    }
597 	}
598     }
599     return(retval);
600 }  /* end of getterminaltype */
601 
602     void
603 _gettermname()
604 {
605     /*
606      * If the client turned off the option,
607      * we can't send another request, so we
608      * just return.
609      */
610     if (his_state_is_wont(TELOPT_TTYPE))
611 	return;
612     settimer(baseline);
613     bcopy(ttytype_sbbuf, nfrontp, sizeof ttytype_sbbuf);
614     nfrontp += sizeof ttytype_sbbuf;
615     while (sequenceIs(ttypesubopt, baseline))
616 	ttloop();
617 }
618 
619     int
620 terminaltypeok(s)
621     char *s;
622 {
623     char buf[1024];
624 
625     if (terminaltype == NULL)
626 	return(1);
627 
628     /*
629      * tgetent() will return 1 if the type is known, and
630      * 0 if it is not known.  If it returns -1, it couldn't
631      * open the database.  But if we can't open the database,
632      * it won't help to say we failed, because we won't be
633      * able to verify anything else.  So, we treat -1 like 1.
634      */
635     if (tgetent(buf, s) == 0)
636 	return(0);
637     return(1);
638 }
639 
640 #ifndef	MAXHOSTNAMELEN
641 #define	MAXHOSTNAMELEN 64
642 #endif	/* MAXHOSTNAMELEN */
643 
644 char *hostname;
645 char host_name[MAXHOSTNAMELEN];
646 char remote_host_name[MAXHOSTNAMELEN];
647 
648 #ifndef	convex
649 extern void telnet P((int, int));
650 #else
651 extern void telnet P((int, int, char *));
652 #endif
653 
654 /*
655  * Get a pty, scan input lines.
656  */
657 doit(who)
658 	struct sockaddr_in *who;
659 {
660 	char *host, *inet_ntoa();
661 	int t;
662 	struct hostent *hp;
663 	int level;
664 	char user_name[256];
665 
666 	/*
667 	 * Find an available pty to use.
668 	 */
669 #ifndef	convex
670 	pty = getpty();
671 	if (pty < 0)
672 		fatal(net, "All network ports in use");
673 #else
674 	for (;;) {
675 		char *lp;
676 		extern char *line, *getpty();
677 
678 		if ((lp = getpty()) == NULL)
679 			fatal(net, "Out of ptys");
680 
681 		if ((pty = open(lp, 2)) >= 0) {
682 			strcpy(line,lp);
683 			line[5] = 't';
684 			break;
685 		}
686 	}
687 #endif
688 
689 #if	defined(_SC_CRAY_SECURE_SYS)
690 	/*
691 	 *	set ttyp line security label
692 	 */
693 	if (secflag) {
694 		extern char *myline;
695 		if (setdevs(myline, &dv) < 0)
696 			fatal(net, "cannot set pty security");
697 	}
698 #endif	/* _SC_CRAY_SECURE_SYS */
699 
700 	/* get name of connected client */
701 	hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
702 		who->sin_family);
703 
704 	if (hp &&
705 	    (strlen(hp->h_name) <= ((utmp_len < 0) ? -utmp_len : utmp_len))) {
706 		host = hp->h_name;
707 	} else if (registerd_host_only) {
708 		fatal(net, "Couldn't resolve your address into a host name.\r\n\
709          Please contact your net administrator");
710 	} else {
711 		host = inet_ntoa(who->sin_addr);
712 	}
713 	/*
714 	 * We must make a copy because Kerberos is probably going
715 	 * to also do a gethost* and overwrite the static data...
716 	 */
717 	strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
718 	remote_host_name[sizeof(remote_host_name)-1] = 0;
719 	host = remote_host_name;
720 
721 	(void) gethostname(host_name, sizeof (host_name));
722 	hostname = host_name;
723 
724 #if	defined(AUTHENTICATION) || defined(ENCRYPTION)
725 	auth_encrypt_init(hostname, host, "TELNETD", 1);
726 #endif
727 
728 	init_env();
729 	/*
730 	 * get terminal type.
731 	 */
732 	*user_name = 0;
733 	level = getterminaltype(user_name);
734 	setenv("TERM", terminaltype ? terminaltype : "network", 1);
735 
736 	/*
737 	 * Start up the login process on the slave side of the terminal
738 	 */
739 #ifndef	convex
740 	startslave(host, level, user_name);
741 
742 	telnet(net, pty);  /* begin server processing */
743 #else
744 	telnet(net, pty, host);
745 #endif
746 	/*NOTREACHED*/
747 }  /* end of doit */
748 
749 #if	defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50)
750 	int
751 Xterm_output(ibufp, obuf, icountp, ocount)
752 	char **ibufp, *obuf;
753 	int *icountp, ocount;
754 {
755 	int ret;
756 	ret = term_output(*ibufp, obuf, *icountp, ocount);
757 	*ibufp += *icountp;
758 	*icountp = 0;
759 	return(ret);
760 }
761 #define	term_output	Xterm_output
762 #endif	/* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */
763 
764 /*
765  * Main loop.  Select from pty and network, and
766  * hand data to telnet receiver finite state machine.
767  */
768 	void
769 #ifndef	convex
770 telnet(f, p)
771 #else
772 telnet(f, p, host)
773 #endif
774 	int f, p;
775 #ifdef convex
776 	char *host;
777 #endif
778 {
779 	int on = 1;
780 #define	TABBUFSIZ	512
781 	char	defent[TABBUFSIZ];
782 	char	defstrs[TABBUFSIZ];
783 #undef	TABBUFSIZ
784 	char *HE;
785 	char *HN;
786 	char *IM;
787 	void netflush();
788 
789 	/*
790 	 * Initialize the slc mapping table.
791 	 */
792 	get_slc_defaults();
793 
794 	/*
795 	 * Do some tests where it is desireable to wait for a response.
796 	 * Rather than doing them slowly, one at a time, do them all
797 	 * at once.
798 	 */
799 	if (my_state_is_wont(TELOPT_SGA))
800 		send_will(TELOPT_SGA, 1);
801 	/*
802 	 * Is the client side a 4.2 (NOT 4.3) system?  We need to know this
803 	 * because 4.2 clients are unable to deal with TCP urgent data.
804 	 *
805 	 * To find out, we send out a "DO ECHO".  If the remote system
806 	 * answers "WILL ECHO" it is probably a 4.2 client, and we note
807 	 * that fact ("WILL ECHO" ==> that the client will echo what
808 	 * WE, the server, sends it; it does NOT mean that the client will
809 	 * echo the terminal input).
810 	 */
811 	send_do(TELOPT_ECHO, 1);
812 
813 #ifdef	LINEMODE
814 	if (his_state_is_wont(TELOPT_LINEMODE)) {
815 		/* Query the peer for linemode support by trying to negotiate
816 		 * the linemode option.
817 		 */
818 		linemode = 0;
819 		editmode = 0;
820 		send_do(TELOPT_LINEMODE, 1);  /* send do linemode */
821 	}
822 #endif	/* LINEMODE */
823 
824 	/*
825 	 * Send along a couple of other options that we wish to negotiate.
826 	 */
827 	send_do(TELOPT_NAWS, 1);
828 	send_will(TELOPT_STATUS, 1);
829 	flowmode = 1;  /* default flow control state */
830 	send_do(TELOPT_LFLOW, 1);
831 
832 	/*
833 	 * Spin, waiting for a response from the DO ECHO.  However,
834 	 * some REALLY DUMB telnets out there might not respond
835 	 * to the DO ECHO.  So, we spin looking for NAWS, (most dumb
836 	 * telnets so far seem to respond with WONT for a DO that
837 	 * they don't understand...) because by the time we get the
838 	 * response, it will already have processed the DO ECHO.
839 	 * Kludge upon kludge.
840 	 */
841 	while (his_will_wont_is_changing(TELOPT_NAWS))
842 		ttloop();
843 
844 	/*
845 	 * But...
846 	 * The client might have sent a WILL NAWS as part of its
847 	 * startup code; if so, we'll be here before we get the
848 	 * response to the DO ECHO.  We'll make the assumption
849 	 * that any implementation that understands about NAWS
850 	 * is a modern enough implementation that it will respond
851 	 * to our DO ECHO request; hence we'll do another spin
852 	 * waiting for the ECHO option to settle down, which is
853 	 * what we wanted to do in the first place...
854 	 */
855 	if (his_want_state_is_will(TELOPT_ECHO) &&
856 	    his_state_is_will(TELOPT_NAWS)) {
857 		while (his_will_wont_is_changing(TELOPT_ECHO))
858 			ttloop();
859 	}
860 	/*
861 	 * On the off chance that the telnet client is broken and does not
862 	 * respond to the DO ECHO we sent, (after all, we did send the
863 	 * DO NAWS negotiation after the DO ECHO, and we won't get here
864 	 * until a response to the DO NAWS comes back) simulate the
865 	 * receipt of a will echo.  This will also send a WONT ECHO
866 	 * to the client, since we assume that the client failed to
867 	 * respond because it believes that it is already in DO ECHO
868 	 * mode, which we do not want.
869 	 */
870 	if (his_want_state_is_will(TELOPT_ECHO)) {
871 		DIAG(TD_OPTIONS,
872 			{sprintf(nfrontp, "td: simulating recv\r\n");
873 			 nfrontp += strlen(nfrontp);});
874 		willoption(TELOPT_ECHO);
875 	}
876 
877 	/*
878 	 * Finally, to clean things up, we turn on our echo.  This
879 	 * will break stupid 4.2 telnets out of local terminal echo.
880 	 */
881 
882 	if (my_state_is_wont(TELOPT_ECHO))
883 		send_will(TELOPT_ECHO, 1);
884 
885 #ifndef	STREAMSPTY
886 	/*
887 	 * Turn on packet mode
888 	 */
889 	(void) ioctl(p, TIOCPKT, (char *)&on);
890 #endif
891 
892 #if	defined(LINEMODE) && defined(KLUDGELINEMODE)
893 	/*
894 	 * Continuing line mode support.  If client does not support
895 	 * real linemode, attempt to negotiate kludge linemode by sending
896 	 * the do timing mark sequence.
897 	 */
898 	if (lmodetype < REAL_LINEMODE)
899 		send_do(TELOPT_TM, 1);
900 #endif	/* defined(LINEMODE) && defined(KLUDGELINEMODE) */
901 
902 	/*
903 	 * Call telrcv() once to pick up anything received during
904 	 * terminal type negotiation, 4.2/4.3 determination, and
905 	 * linemode negotiation.
906 	 */
907 	telrcv();
908 
909 	(void) ioctl(f, FIONBIO, (char *)&on);
910 	(void) ioctl(p, FIONBIO, (char *)&on);
911 #if	defined(CRAY2) && defined(UNICOS5)
912 	init_termdriver(f, p, interrupt, sendbrk);
913 #endif
914 
915 #if	defined(SO_OOBINLINE)
916 	(void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE,
917 				(char *)&on, sizeof on);
918 #endif	/* defined(SO_OOBINLINE) */
919 
920 #ifdef	SIGTSTP
921 	(void) signal(SIGTSTP, SIG_IGN);
922 #endif
923 #ifdef	SIGTTOU
924 	/*
925 	 * Ignoring SIGTTOU keeps the kernel from blocking us
926 	 * in ttioct() in /sys/tty.c.
927 	 */
928 	(void) signal(SIGTTOU, SIG_IGN);
929 #endif
930 
931 	(void) signal(SIGCHLD, cleanup);
932 
933 #if	defined(CRAY2) && defined(UNICOS5)
934 	/*
935 	 * Cray-2 will send a signal when pty modes are changed by slave
936 	 * side.  Set up signal handler now.
937 	 */
938 	if ((int)signal(SIGUSR1, termstat) < 0)
939 		perror("signal");
940 	else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0)
941 		perror("ioctl:TCSIGME");
942 	/*
943 	 * Make processing loop check terminal characteristics early on.
944 	 */
945 	termstat();
946 #endif
947 
948 #ifdef  TIOCNOTTY
949 	{
950 		register int t;
951 		t = open(_PATH_TTY, O_RDWR);
952 		if (t >= 0) {
953 			(void) ioctl(t, TIOCNOTTY, (char *)0);
954 			(void) close(t);
955 		}
956 	}
957 #endif
958 
959 #if	defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY)
960 	(void) setsid();
961 	ioctl(p, TIOCSCTTY, 0);
962 #endif
963 
964 	/*
965 	 * Show banner that getty never gave.
966 	 *
967 	 * We put the banner in the pty input buffer.  This way, it
968 	 * gets carriage return null processing, etc., just like all
969 	 * other pty --> client data.
970 	 */
971 
972 #if	!defined(CRAY) || !defined(NEWINIT)
973 	if (getenv("USER"))
974 		hostinfo = 0;
975 #endif
976 
977 	if (getent(defent, "default") == 1) {
978 		char *getstr();
979 		char *cp=defstrs;
980 
981 		HE = getstr("he", &cp);
982 		HN = getstr("hn", &cp);
983 		IM = getstr("im", &cp);
984 		if (HN && *HN)
985 			(void) strcpy(host_name, HN);
986 		if (IM == 0)
987 			IM = "";
988 	} else {
989 		IM = DEFAULT_IM;
990 		HE = 0;
991 	}
992 	edithost(HE, host_name);
993 	if (hostinfo && *IM)
994 		putf(IM, ptyibuf2);
995 
996 	if (pcc)
997 		(void) strncat(ptyibuf2, ptyip, pcc+1);
998 	ptyip = ptyibuf2;
999 	pcc = strlen(ptyip);
1000 #ifdef	LINEMODE
1001 	/*
1002 	 * Last check to make sure all our states are correct.
1003 	 */
1004 	init_termbuf();
1005 	localstat();
1006 #endif	/* LINEMODE */
1007 
1008 	DIAG(TD_REPORT,
1009 		{sprintf(nfrontp, "td: Entering processing loop\r\n");
1010 		 nfrontp += strlen(nfrontp);});
1011 
1012 #ifdef	convex
1013 	startslave(host);
1014 #endif
1015 
1016 	for (;;) {
1017 		fd_set ibits, obits, xbits;
1018 		register int c;
1019 
1020 		if (ncc < 0 && pcc < 0)
1021 			break;
1022 
1023 #if	defined(CRAY2) && defined(UNICOS5)
1024 		if (needtermstat)
1025 			_termstat();
1026 #endif	/* defined(CRAY2) && defined(UNICOS5) */
1027 		FD_ZERO(&ibits);
1028 		FD_ZERO(&obits);
1029 		FD_ZERO(&xbits);
1030 		/*
1031 		 * Never look for input if there's still
1032 		 * stuff in the corresponding output buffer
1033 		 */
1034 		if (nfrontp - nbackp || pcc > 0) {
1035 			FD_SET(f, &obits);
1036 		} else {
1037 			FD_SET(p, &ibits);
1038 		}
1039 		if (pfrontp - pbackp || ncc > 0) {
1040 			FD_SET(p, &obits);
1041 		} else {
1042 			FD_SET(f, &ibits);
1043 		}
1044 		if (!SYNCHing) {
1045 			FD_SET(f, &xbits);
1046 		}
1047 		if ((c = select(16, &ibits, &obits, &xbits,
1048 						(struct timeval *)0)) < 1) {
1049 			if (c == -1) {
1050 				if (errno == EINTR) {
1051 					continue;
1052 				}
1053 			}
1054 			sleep(5);
1055 			continue;
1056 		}
1057 
1058 		/*
1059 		 * Any urgent data?
1060 		 */
1061 		if (FD_ISSET(net, &xbits)) {
1062 		    SYNCHing = 1;
1063 		}
1064 
1065 		/*
1066 		 * Something to read from the network...
1067 		 */
1068 		if (FD_ISSET(net, &ibits)) {
1069 #if	!defined(SO_OOBINLINE)
1070 			/*
1071 			 * In 4.2 (and 4.3 beta) systems, the
1072 			 * OOB indication and data handling in the kernel
1073 			 * is such that if two separate TCP Urgent requests
1074 			 * come in, one byte of TCP data will be overlaid.
1075 			 * This is fatal for Telnet, but we try to live
1076 			 * with it.
1077 			 *
1078 			 * In addition, in 4.2 (and...), a special protocol
1079 			 * is needed to pick up the TCP Urgent data in
1080 			 * the correct sequence.
1081 			 *
1082 			 * What we do is:  if we think we are in urgent
1083 			 * mode, we look to see if we are "at the mark".
1084 			 * If we are, we do an OOB receive.  If we run
1085 			 * this twice, we will do the OOB receive twice,
1086 			 * but the second will fail, since the second
1087 			 * time we were "at the mark", but there wasn't
1088 			 * any data there (the kernel doesn't reset
1089 			 * "at the mark" until we do a normal read).
1090 			 * Once we've read the OOB data, we go ahead
1091 			 * and do normal reads.
1092 			 *
1093 			 * There is also another problem, which is that
1094 			 * since the OOB byte we read doesn't put us
1095 			 * out of OOB state, and since that byte is most
1096 			 * likely the TELNET DM (data mark), we would
1097 			 * stay in the TELNET SYNCH (SYNCHing) state.
1098 			 * So, clocks to the rescue.  If we've "just"
1099 			 * received a DM, then we test for the
1100 			 * presence of OOB data when the receive OOB
1101 			 * fails (and AFTER we did the normal mode read
1102 			 * to clear "at the mark").
1103 			 */
1104 		    if (SYNCHing) {
1105 			int atmark;
1106 
1107 			(void) ioctl(net, SIOCATMARK, (char *)&atmark);
1108 			if (atmark) {
1109 			    ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB);
1110 			    if ((ncc == -1) && (errno == EINVAL)) {
1111 				ncc = read(net, netibuf, sizeof (netibuf));
1112 				if (sequenceIs(didnetreceive, gotDM)) {
1113 				    SYNCHing = stilloob(net);
1114 				}
1115 			    }
1116 			} else {
1117 			    ncc = read(net, netibuf, sizeof (netibuf));
1118 			}
1119 		    } else {
1120 			ncc = read(net, netibuf, sizeof (netibuf));
1121 		    }
1122 		    settimer(didnetreceive);
1123 #else	/* !defined(SO_OOBINLINE)) */
1124 		    ncc = read(net, netibuf, sizeof (netibuf));
1125 #endif	/* !defined(SO_OOBINLINE)) */
1126 		    if (ncc < 0 && errno == EWOULDBLOCK)
1127 			ncc = 0;
1128 		    else {
1129 			if (ncc <= 0) {
1130 			    break;
1131 			}
1132 			netip = netibuf;
1133 		    }
1134 		    DIAG((TD_REPORT | TD_NETDATA),
1135 			    {sprintf(nfrontp, "td: netread %d chars\r\n", ncc);
1136 			     nfrontp += strlen(nfrontp);});
1137 		    DIAG(TD_NETDATA, printdata("nd", netip, ncc));
1138 		}
1139 
1140 		/*
1141 		 * Something to read from the pty...
1142 		 */
1143 		if (FD_ISSET(p, &ibits)) {
1144 #ifndef	STREAMSPTY
1145 			pcc = read(p, ptyibuf, BUFSIZ);
1146 #else
1147 			pcc = readstream(p, ptyibuf, BUFSIZ);
1148 #endif
1149 			/*
1150 			 * On some systems, if we try to read something
1151 			 * off the master side before the slave side is
1152 			 * opened, we get EIO.
1153 			 */
1154 			if (pcc < 0 && (errno == EWOULDBLOCK ||
1155 #ifdef	EAGAIN
1156 					errno == EAGAIN ||
1157 #endif
1158 					errno == EIO)) {
1159 				pcc = 0;
1160 			} else {
1161 				if (pcc <= 0)
1162 					break;
1163 #if	!defined(CRAY2) || !defined(UNICOS5)
1164 #ifdef	LINEMODE
1165 				/*
1166 				 * If ioctl from pty, pass it through net
1167 				 */
1168 				if (ptyibuf[0] & TIOCPKT_IOCTL) {
1169 					copy_termbuf(ptyibuf+1, pcc-1);
1170 					localstat();
1171 					pcc = 1;
1172 				}
1173 #endif	/* LINEMODE */
1174 				if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
1175 					netclear();	/* clear buffer back */
1176 #ifndef	NO_URGENT
1177 					/*
1178 					 * There are client telnets on some
1179 					 * operating systems get screwed up
1180 					 * royally if we send them urgent
1181 					 * mode data.
1182 					 */
1183 					*nfrontp++ = IAC;
1184 					*nfrontp++ = DM;
1185 					neturg = nfrontp-1; /* off by one XXX */
1186 #endif
1187 				}
1188 				if (his_state_is_will(TELOPT_LFLOW) &&
1189 				    (ptyibuf[0] &
1190 				     (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) {
1191 					(void) sprintf(nfrontp, "%c%c%c%c%c%c",
1192 					    IAC, SB, TELOPT_LFLOW,
1193 					    ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0,
1194 					    IAC, SE);
1195 					nfrontp += 6;
1196 				}
1197 				pcc--;
1198 				ptyip = ptyibuf+1;
1199 #else	/* defined(CRAY2) && defined(UNICOS5) */
1200 				if (!uselinemode) {
1201 					unpcc = pcc;
1202 					unptyip = ptyibuf;
1203 					pcc = term_output(&unptyip, ptyibuf2,
1204 								&unpcc, BUFSIZ);
1205 					ptyip = ptyibuf2;
1206 				} else
1207 					ptyip = ptyibuf;
1208 #endif	/* defined(CRAY2) && defined(UNICOS5) */
1209 			}
1210 		}
1211 
1212 		while (pcc > 0) {
1213 			if ((&netobuf[BUFSIZ] - nfrontp) < 2)
1214 				break;
1215 			c = *ptyip++ & 0377, pcc--;
1216 			if (c == IAC)
1217 				*nfrontp++ = c;
1218 #if	defined(CRAY2) && defined(UNICOS5)
1219 			else if (c == '\n' &&
1220 				     my_state_is_wont(TELOPT_BINARY) && newmap)
1221 				*nfrontp++ = '\r';
1222 #endif	/* defined(CRAY2) && defined(UNICOS5) */
1223 			*nfrontp++ = c;
1224 			if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
1225 				if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
1226 					*nfrontp++ = *ptyip++ & 0377;
1227 					pcc--;
1228 				} else
1229 					*nfrontp++ = '\0';
1230 			}
1231 		}
1232 #if	defined(CRAY2) && defined(UNICOS5)
1233 		/*
1234 		 * If chars were left over from the terminal driver,
1235 		 * note their existence.
1236 		 */
1237 		if (!uselinemode && unpcc) {
1238 			pcc = unpcc;
1239 			unpcc = 0;
1240 			ptyip = unptyip;
1241 		}
1242 #endif	/* defined(CRAY2) && defined(UNICOS5) */
1243 
1244 		if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
1245 			netflush();
1246 		if (ncc > 0)
1247 			telrcv();
1248 		if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
1249 			ptyflush();
1250 	}
1251 	cleanup(0);
1252 }  /* end of telnet */
1253 
1254 #ifndef	TCSIG
1255 # ifdef	TIOCSIG
1256 #  define TCSIG TIOCSIG
1257 # endif
1258 #endif
1259 
1260 #ifdef	STREAMSPTY
1261 
1262 int flowison = -1;  /* current state of flow: -1 is unknown */
1263 
1264 int readstream(p, ibuf, bufsize)
1265 	int p;
1266 	char *ibuf;
1267 	int bufsize;
1268 {
1269 	int flags = 0;
1270 	int ret = 0;
1271 	struct termios *tsp;
1272 	struct termio *tp;
1273 	struct iocblk *ip;
1274 	char vstop, vstart;
1275 	int ixon;
1276 	int newflow;
1277 
1278 	strbufc.maxlen = BUFSIZ;
1279 	strbufc.buf = ctlbuf;
1280 	strbufd.maxlen = bufsize-1;
1281 	strbufd.len = 0;
1282 	strbufd.buf = ibuf+1;
1283 	ibuf[0] = 0;
1284 
1285 	ret = getmsg(p, &strbufc, &strbufd, &flags);
1286 	if (ret < 0)  /* error of some sort -- probably EAGAIN */
1287 		return(-1);
1288 
1289 	if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) {
1290 		/* data message */
1291 		if (strbufd.len > 0) {			/* real data */
1292 			return(strbufd.len + 1);	/* count header char */
1293 		} else {
1294 			/* nothing there */
1295 			errno = EAGAIN;
1296 			return(-1);
1297 		}
1298 	}
1299 
1300 	/*
1301 	 * It's a control message.  Return 1, to look at the flag we set
1302 	 */
1303 
1304 	switch (ctlbuf[0]) {
1305 	case M_FLUSH:
1306 		if (ibuf[1] & FLUSHW)
1307 			ibuf[0] = TIOCPKT_FLUSHWRITE;
1308 		return(1);
1309 
1310 	case M_IOCTL:
1311 		ip = (struct iocblk *) (ibuf+1);
1312 
1313 		switch (ip->ioc_cmd) {
1314 		case TCSETS:
1315 		case TCSETSW:
1316 		case TCSETSF:
1317 			tsp = (struct termios *)
1318 					(ibuf+1 + sizeof(struct iocblk));
1319 			vstop = tsp->c_cc[VSTOP];
1320 			vstart = tsp->c_cc[VSTART];
1321 			ixon = tsp->c_iflag & IXON;
1322 			break;
1323 		case TCSETA:
1324 		case TCSETAW:
1325 		case TCSETAF:
1326 			tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk));
1327 			vstop = tp->c_cc[VSTOP];
1328 			vstart = tp->c_cc[VSTART];
1329 			ixon = tp->c_iflag & IXON;
1330 			break;
1331 		default:
1332 			errno = EAGAIN;
1333 			return(-1);
1334 		}
1335 
1336 		newflow =  (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0;
1337 		if (newflow != flowison) {  /* it's a change */
1338 			flowison = newflow;
1339 			ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP;
1340 			return(1);
1341 		}
1342 	}
1343 
1344 	/* nothing worth doing anything about */
1345 	errno = EAGAIN;
1346 	return(-1);
1347 }
1348 #endif /* STREAMSPTY */
1349 
1350 /*
1351  * Send interrupt to process on other side of pty.
1352  * If it is in raw mode, just write NULL;
1353  * otherwise, write intr char.
1354  */
1355 	void
1356 interrupt()
1357 {
1358 	ptyflush();	/* half-hearted */
1359 
1360 #ifdef	TCSIG
1361 	(void) ioctl(pty, TCSIG, (char *)SIGINT);
1362 #else	/* TCSIG */
1363 	init_termbuf();
1364 	*pfrontp++ = slctab[SLC_IP].sptr ?
1365 			(unsigned char)*slctab[SLC_IP].sptr : '\177';
1366 #endif	/* TCSIG */
1367 }
1368 
1369 /*
1370  * Send quit to process on other side of pty.
1371  * If it is in raw mode, just write NULL;
1372  * otherwise, write quit char.
1373  */
1374 	void
1375 sendbrk()
1376 {
1377 	ptyflush();	/* half-hearted */
1378 #ifdef	TCSIG
1379 	(void) ioctl(pty, TCSIG, (char *)SIGQUIT);
1380 #else	/* TCSIG */
1381 	init_termbuf();
1382 	*pfrontp++ = slctab[SLC_ABORT].sptr ?
1383 			(unsigned char)*slctab[SLC_ABORT].sptr : '\034';
1384 #endif	/* TCSIG */
1385 }
1386 
1387 	void
1388 sendsusp()
1389 {
1390 #ifdef	SIGTSTP
1391 	ptyflush();	/* half-hearted */
1392 # ifdef	TCSIG
1393 	(void) ioctl(pty, TCSIG, (char *)SIGTSTP);
1394 # else	/* TCSIG */
1395 	*pfrontp++ = slctab[SLC_SUSP].sptr ?
1396 			(unsigned char)*slctab[SLC_SUSP].sptr : '\032';
1397 # endif	/* TCSIG */
1398 #endif	/* SIGTSTP */
1399 }
1400 
1401 /*
1402  * When we get an AYT, if ^T is enabled, use that.  Otherwise,
1403  * just send back "[Yes]".
1404  */
1405 	void
1406 recv_ayt()
1407 {
1408 #if	defined(SIGINFO) && defined(TCSIG)
1409 	if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
1410 		(void) ioctl(pty, TCSIG, (char *)SIGINFO);
1411 		return;
1412 	}
1413 #endif
1414 	(void) strcpy(nfrontp, "\r\n[Yes]\r\n");
1415 	nfrontp += 9;
1416 }
1417 
1418 	void
1419 doeof()
1420 {
1421 	init_termbuf();
1422 
1423 #if	defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN)
1424 	if (!tty_isediting()) {
1425 		extern char oldeofc;
1426 		*pfrontp++ = oldeofc;
1427 		return;
1428 	}
1429 #endif
1430 	*pfrontp++ = slctab[SLC_EOF].sptr ?
1431 			(unsigned char)*slctab[SLC_EOF].sptr : '\004';
1432 }
1433