1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22/*
23 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27/*	Copyright (c) 1988 AT&T	*/
28/*	  All Rights Reserved	*/
29
30/*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40#pragma ident	"%Z%%M%	%I%	%E% SMI"
41
42/*LINTLIBRARY*/
43
44#include	<stdio.h>
45#include	<sys/types.h>
46#include	<fcntl.h>
47#include	<stdlib.h>
48#include	<string.h>
49#include	<unistd.h>
50#include	<errno.h>
51#include	"curses_inc.h"
52
53#define	TERMPATH	"/usr/share/lib/terminfo/"
54#define	TERMPATHLEN	512
55
56extern	bool	_use_env;	/* in curses.c */
57
58chtype	bit_attributes[NUM_ATTRIBUTES] = {
59	    A_STANDOUT,
60	    A_UNDERLINE,
61	    A_ALTCHARSET,
62	    A_REVERSE,
63	    A_BLINK,
64	    A_DIM,
65	    A_BOLD,
66	    A_INVIS,
67	    A_PROTECT
68	};
69
70char	*Def_term = "unknown",	/* default terminal type */
71	term_parm_err[32], ttytype[BUFSIZ], _frst_tblstr[1400];
72
73TERMINAL		_first_term, *cur_term = &_first_term;
74struct	_bool_struct	_frst_bools, *cur_bools = &_frst_bools;
75struct	_num_struct	_frst_nums, *cur_nums = &_frst_nums;
76struct	_str_struct	_frst_strs, *cur_strs = &_frst_strs;
77
78/* _called_before is used/cleared by delterm.c and restart.c */
79char	_called_before = 0;
80short	term_errno = -1;
81
82#ifdef SYSV
83int	prog_istermios = -1;
84int	shell_istermios = -1;
85#endif
86
87#ifdef	DUMPTI
88extern	char	*boolfnames[], *boolnames[], *boolcodes[],
89		*numfnames[], *numnames[], *numcodes[],
90		*strfnames[], *strnames[], *strcodes[];
91
92main(int argc, char **argv)	/* FOR DEBUG ONLY */
93{
94	if (argc > 1)
95		setupterm(argv[1], 1, (int *)0);
96	else
97		setupterm((char *)0, 1, (int *)0);
98	return (0);
99}
100
101_Pr(int ch)	/* FOR DEBUG ONLY */
102{
103	if (ch >= 0200) {
104		printf("M-");
105		ch -= 0200;
106	}
107	if ((ch < ' ') || (ch == 0177))
108		printf("^%c", ch ^ 0100);
109	else
110		printf("%c", ch);
111}
112
113_Sprint(int n, char *string)	/* FOR DEBUG ONLY */
114{
115	int	ch;
116
117	if (n == -1) {
118		printf(".\n");
119		return;
120	}
121	printf(", string = '");
122	while (ch = *string++)
123		_Pr(ch&0377);
124
125	printf("'.\n");
126}
127
128_Mprint(int n, char *memory)	/* FOR DEBUG ONLY */
129{
130	unsigned	char	ch;
131
132	while (ch = *memory++, n-- > 0)
133		_Pr(ch&0377);
134}
135
136#define	_Vr2getshi()	_Vr2getsh(ip-2)
137
138#if	vax || pdp11
139#define	_Vr2getsh(ip)	(* (short *)(ip))
140#endif	/* vax || pdp11 */
141
142#ifndef	_Vr2getsh
143/*
144 * Here is a more portable version, which does not assume byte ordering
145 * in shorts, sign extension, etc.
146 */
147_Vr2getsh(char *p)
148{
149	int	rv;
150
151	if (*p == (char)0377)
152		return (-1);
153	rv = (unsigned char) *p++;
154	rv += (unsigned char) *p * 256;
155	return (rv);
156}
157#endif	/* _Vr2getsh */
158
159#endif	/* DUMPTI */
160
161#define	_Getshi()	_Getsh(ip); ip += 2
162
163/*
164 * "function" to get a short from a pointer.  The short is in a standard
165 * format: two bytes, the first is the low order byte, the second is
166 * the high order byte (base 256).  The only negative numbers allowed are
167 * -1 and -2, which are represented as 255,255 and 255,254  This format
168 * happens to be the same as the hardware on the pdp-11, vax, and 386,
169 * making it fast and convenient and small to do this on a pdp-11.
170 */
171
172#if	vax || pdp11 || i386
173#define	_Getsh(ip)	(* (short *)ip)
174#endif	/* vax || pdp11 */
175/*
176 * The following macro is partly due to Mike Laman, laman@sdcsvax
177 *	NCR @ Torrey Pines.		- Tony Hansen
178 */
179#if	u3b || u3b15 || u3b2 || m68000
180#define	_Getsh(ip)	((short)(*((unsigned char *)ip) | (*(ip+1) << 8)))
181#endif	/* u3b || u3b15 || u3b2 || m68000 */
182
183#ifndef	_Getsh
184/*
185 * Here is a more portable version, which does not assume byte ordering
186 * in shorts, sign extension, etc.  For the sake of the porters,
187 * two alternative implementations, for the machines that don't have
188 * casting to "unsigned char", are also given, but commented out.
189 * Not ANSI C implementation assumes that the * C preprocessor does
190 * sign-extension the same as on the machine being compiled for.
191 */
192static int
193_Getsh(char *p)
194{
195	int	rv, rv2;
196
197	rv  = (unsigned char) p[0];
198	rv2 = (unsigned char) p[1];
199
200	/* the following stuff is only for porting.  See the comment above */
201
202#ifdef FOR_PORTING
203#if    CHAR_MIN < 0
204	rv = (*p++) & 0377;
205	rv2 = (*p) & 0377;
206#else   /* CHAR_MIN < 0 */
207	rv = *p++;
208	rv2 = *p;
209#endif  /* CHAR_MIN < 0 */
210
211#endif  /* FOR_PORTING  */
212
213	if ((rv2 == 0377) && ((rv == 0377) || (rv == 0376)))
214		return (-1);
215	return (rv + (rv2 * 256));
216}
217#endif	/* _Getsh */
218
219/*
220 * setupterm: low level routine to dig up terminfo from database
221 * and read it in.  Parms are terminal type (0 means use getenv("TERM"),
222 * file descriptor all output will go to (for ioctls), and a pointer
223 * to an int into which the error return code goes (0 means to bomb
224 * out with an error message if there's an error).  Thus,
225 * setupterm((char *)0, 1, (int *)0) is a reasonable way for a simple
226 * program to set up.
227 */
228int
229setupterm(char *term, int filenum, int *errret)
230	/* filenum - This is a UNIX file descriptor, not a stdio ptr. */
231{
232	char	tiebuf[4096];
233	char	fname[TERMPATHLEN];
234	char	*ip;
235	char	*cp;
236	int	n, tfd;
237	char	*lcp, *ccp, **on_sequences, **str_array;
238	int	snames, nbools, nints, nstrs, sstrtab;
239	char	*strtab;
240#ifdef	DUMPTI
241	int		Vr2val;
242#endif	/* DUMPTI */
243
244	(void) mbgetwidth();
245
246	if (term == NULL)
247		term = getenv("TERM");
248
249	if (term == NULL || *term == '\0')
250		term = Def_term;
251
252	tfd = -1;
253	errno = 0; 	/* ehr3 */
254
255	if (errret != 0)
256		*errret = -1;
257
258	if (((cp = getenv("TERMINFO")) != 0) && *cp) {
259		/* $TERMINFO/?/$TERM */
260		if (snprintf(fname, sizeof (fname),
261			"%s/%c/%s", cp, *term, term) >= sizeof (fname)) {
262			term_errno = TERMINFO_TOO_LONG;
263			goto out_err;
264		}
265
266		tfd = open(fname, 0);
267#ifdef	DUMPTI
268		printf("looking in file %s\n", fname);
269#endif	/* DUMPTI */
270		if ((tfd < 0) && (errno == EACCES))
271			goto cant_read;
272	}
273
274	if (tfd < 0) {
275		/* /usr/share/lib/terminfo/?/$TERM */
276		if (snprintf(fname, sizeof (fname),
277			"%s/%c/%s", TERMPATH, *term, term) >= sizeof (fname)) {
278			term_errno = TERMINFO_TOO_LONG;
279			goto out_err;
280		}
281
282		tfd = open(fname, 0);
283#ifdef	DUMPTI
284		printf("looking in file %s\n", fname);
285#endif	/* DUMPTI */
286
287	}
288
289	if (tfd < 0) {
290		if (errno == EACCES) {
291cant_read:
292			term_errno = NOT_READABLE;
293		} else {
294			if (access(TERMPATH, 0) == -1)
295				term_errno = UNACCESSIBLE;
296			else {
297				term_errno = NO_TERMINAL;
298				if (errret != 0)
299					*errret = 0;
300			}
301		}
302		/*
303		 * if the length of the specified terminal name is longer
304		 * than 31, it will be chopped after the 31st byte.
305		 * This should be a rare case.
306		 */
307		(void) strncpy(term_parm_err, term, 31);
308		term_parm_err[31] = '\0';
309		goto out_err;
310	}
311
312	/* LINTED */
313	n = (int)read(tfd, tiebuf, sizeof (tiebuf));
314	(void) close(tfd);
315
316	if (n <= 0) {
317corrupt:
318		term_errno = CORRUPTED;
319		goto out_err;
320	} else
321		if (n == sizeof (tiebuf)) {
322			term_errno = ENTRY_TOO_LONG;
323			goto out_err;
324		}
325	cp = ttytype;
326	ip = tiebuf;
327
328	/* Pick up header */
329	snames = _Getshi();
330#ifdef	DUMPTI
331	Vr2val = _Vr2getshi();
332	printf("Magic number = %d, %#o [%d, %#o].\n", snames,
333	    snames, Vr2val, Vr2val);
334#endif	/* DUMPTI */
335	if (snames != MAGNUM)
336		goto corrupt;
337	snames = _Getshi();
338#ifdef	DUMPTI
339	Vr2val = _Vr2getshi();
340	printf("Size of names = %d, %#o [%d, %#o].\n", snames,
341	    snames, Vr2val, Vr2val);
342#endif	/* DUMPTI */
343
344	nbools = _Getshi();
345#ifdef	DUMPTI
346	Vr2val = _Vr2getshi();
347	printf("Number of bools = %d, %#o [%d, %#o].\n", nbools,
348	    nbools, Vr2val, Vr2val);
349#endif	/* DUMPTI */
350
351	nints = _Getshi();
352#ifdef	DUMPTI
353	Vr2val = _Vr2getshi();
354	printf("Number of ints = %d, %#o [%d, %#o].\n", nints, nints,
355	    Vr2val, Vr2val);
356#endif	/* DUMPTI */
357
358	nstrs = _Getshi();
359#ifdef	DUMPTI
360	Vr2val = _Vr2getshi();
361	printf("Number of strings = %d, %#o [%d, %#o].\n", nstrs, nstrs,
362	    Vr2val, Vr2val);
363#endif	/* DUMPTI */
364
365	sstrtab = _Getshi();
366#ifdef	DUMPTI
367	Vr2val = _Vr2getshi();
368	printf("Size of string table = %d, %#o [%d, %#o].\n", sstrtab,
369	    sstrtab, Vr2val, Vr2val);
370	printf("Names are: %.*s.\n", snames, ip);
371#endif	/* DUMPTI */
372
373	/* allocate all of the space */
374	strtab = NULL;
375	if (_called_before) {
376		/* 2nd or more times through */
377		if ((cur_term = (TERMINAL *)
378		    calloc(sizeof (TERMINAL), 1)) == NULL)
379			goto badmalloc;
380		if ((cur_bools = (struct _bool_struct *)
381		    calloc(sizeof (struct _bool_struct), 1)) == NULL)
382			goto freeterminal;
383		if ((cur_nums = (struct _num_struct *)
384		    calloc(sizeof (struct _num_struct), 1)) == NULL)
385			goto freebools;
386		if ((cur_strs = (struct _str_struct *)
387		    calloc(sizeof (struct _str_struct), 1)) == NULL) {
388freenums:
389			free((char *)cur_nums);
390freebools:
391			free((char *)cur_bools);
392freeterminal:
393			free((char *)cur_term);
394badmalloc:
395			term_errno = TERM_BAD_MALLOC;
396#ifdef	DEBUG
397			strcpy(term_parm_err, "setupterm");
398#endif	/* DEBUG */
399out_err:
400			if (errret == 0) {
401				termerr();
402				exit(-term_errno);
403			} else
404				return (ERR);
405		}
406	} else {
407		/* First time through */
408		_called_before = TRUE;
409		cur_term = &_first_term;
410		cur_bools = &_frst_bools;
411		cur_nums = &_frst_nums;
412		cur_strs = &_frst_strs;
413		if (sstrtab < sizeof (_frst_tblstr))
414			strtab = _frst_tblstr;
415	}
416
417	if (strtab == NULL) {
418		if ((strtab = (char *)malloc((unsigned)sstrtab)) == NULL) {
419			if (cur_strs != &_frst_strs)
420				free((char *)cur_strs);
421			goto freenums;
422		}
423	}
424
425	/* no more catchable errors */
426	if (errret)
427		*errret = 1;
428
429	(void) strncpy(cur_term->_termname, term, 14);
430	/* In case the name is exactly 15 characters */
431	cur_term->_termname[14] = '\0';
432	cur_term->_bools = cur_bools;
433	cur_term->_nums = cur_nums;
434	cur_term->_strs = cur_strs;
435	cur_term->_strtab = strtab;
436	cur_term->sgr_mode = cur_term->sgr_faked = A_NORMAL;
437
438	if (filenum == 1 && !isatty(filenum))
439		filenum = 2;	/* Allow output redirect */
440	/* LINTED */
441	cur_term->Filedes = (short)filenum;
442	_blast_keys(cur_term);
443	cur_term->_iwait = cur_term->fl_typeahdok = cur_term->_chars_on_queue =
444		cur_term->_fl_rawmode = cur_term->_ungotten = 0;
445	cur_term->_cursorstate = 1;
446	cur_term->_delay = cur_term->_inputfd = cur_term->_check_fd = -1;
447	(void) memset((char *)cur_term->_regs, 0, 26 * sizeof (short));
448
449#ifndef	DUMPTI
450	(void) def_shell_mode();
451	/* This is a useful default for PROGTTY, too */
452#ifdef SYSV
453	if (shell_istermios < 0) {
454		int i;
455
456		SHELLTTY.c_lflag = SHELLTTYS.c_lflag;
457		SHELLTTY.c_oflag = SHELLTTYS.c_oflag;
458		SHELLTTY.c_iflag = SHELLTTYS.c_iflag;
459		SHELLTTY.c_cflag = SHELLTTYS.c_cflag;
460		for (i = 0; i < NCC; i++)
461			SHELLTTY.c_cc[i] = SHELLTTYS.c_cc[i];
462		PROGTTY = SHELLTTY;
463		prog_istermios = -1;
464
465		PROGTTYS.c_lflag = PROGTTY.c_lflag;
466		PROGTTYS.c_oflag = PROGTTY.c_oflag;
467		PROGTTYS.c_iflag = PROGTTY.c_iflag;
468		PROGTTYS.c_cflag = PROGTTY.c_cflag;
469		for (i = 0; i < NCC; i++)
470			PROGTTYS.c_cc[i] = PROGTTY.c_cc[i];
471	} else {
472		PROGTTYS = SHELLTTYS;
473		prog_istermios = 0;
474	}
475#else	/* SYSV */
476	PROGTTY = SHELLTTY;
477#endif	/* SYSV */
478#endif	/* DUMPTI */
479
480	/* Skip names of terminals */
481	(void) memcpy((char *)cp, (char *)ip, (snames * sizeof (*cp)));
482	ip += snames;
483
484	/*
485	 * Pull out the booleans.
486	 * The for loop below takes care of a new curses with an old tic
487	 * file and visa-versa.  nbools says how many bools the tic file has.
488	 * So, we only loop for as long as there are bools to read.
489	 * However, if this is an old curses that doesn't have all the
490	 * bools that this new tic has dumped, then the extra if
491	 * "if (cp < fp)" says that if we are going to read into our structure
492	 * passed its size don't do it but we still need to keep bumping
493	 * up the pointer of what we read in from the terminfo file.
494	 */
495	{
496		char	*fp = &cur_bools->Sentinel;
497		char	s;
498#ifdef	DUMPTI
499		int	tempindex = 0;
500#endif	/* DUMPTI */
501		cp = &cur_bools->_auto_left_margin;
502		while (nbools--) {
503			s = *ip++;
504#ifdef	DUMPTI
505			printf("Bool %s [%s] (%s) = %d.\n",
506			    boolfnames[tempindex], boolnames[tempindex],
507			    boolcodes[tempindex], s);
508			tempindex++;
509#endif	/* DUMPTI */
510			if (cp < fp)
511				*cp++ = s & 01;
512		}
513		if (cp < fp)
514			(void) memset(cp, 0, ((fp - cp) * sizeof (bool)));
515	}
516
517	/* Force proper alignment */
518	if (((unsigned long) ip) & 1)
519		ip++;
520
521	/*
522	 * Pull out the numbers.
523	 */
524	{
525		short	*sp = &cur_nums->_columns;
526		short	*fp = &cur_nums->Sentinel;
527		int	s;
528#ifdef	DUMPTI
529		int	tempindex = 0;
530#endif	/* DUMPTI */
531
532		while (nints--) {
533			s = _Getshi();
534#ifdef	DUMPTI
535			Vr2val = _Vr2getshi();
536			printf("Num %s [%s] (%s) = %d [%d].\n",
537			    numfnames[tempindex], numnames[tempindex],
538			    numcodes[tempindex], s, Vr2val);
539			tempindex++;
540#endif	/* DUMPTI */
541			if (sp < fp)
542				if (s < 0)
543					*sp++ = -1;
544				else
545					/* LINTED */
546					*sp++ = (short)s;
547		}
548		if (sp < fp)
549			(void) memset((char *)sp, '\377',
550			    ((fp - sp) * sizeof (short)));
551	}
552
553	if (_use_env) {
554		/*
555		 * This ioctl defines the window size and overrides what
556		 * it says in terminfo.
557		 */
558		{
559			struct	winsize	w;
560
561			if (ioctl(filenum, TIOCGWINSZ, &w) != -1) {
562				if (w.ws_row != 0)
563					cur_nums->_lines = w.ws_row;
564				if (w.ws_col != 0)
565					cur_nums->_columns = w.ws_col;
566#ifdef	DUMPTI
567				printf("ioctl TIOCGWINSZ override: "
568				    "(lines, columns) = (%d, %d)\n",
569				    w.ws_row, w.ws_col);
570#endif	/* DUMPTI */
571			}
572		}
573
574		/*
575		 * Check $LINES and $COLUMNS.
576		 */
577		{
578			int	ilines, icolumns;
579
580			lcp = getenv("LINES");
581			ccp = getenv("COLUMNS");
582			if (lcp)
583				if ((ilines = atoi(lcp)) > 0) {
584					/* LINTED */
585					cur_nums->_lines = (short)ilines;
586#ifdef	DUMPTI
587					printf("$LINES override: lines = %d\n",
588					    ilines);
589#endif	/* DUMPTI */
590				}
591			if (ccp)
592				if ((icolumns = atoi(ccp)) > 0) {
593					/* LINTED */
594					cur_nums->_columns = (short)icolumns;
595#ifdef	DUMPTI
596					printf("$COLUMNS override: columns = "
597					    "%d\n", icolumns);
598#endif	/* DUMPTI */
599				}
600		}
601	}
602
603	/* Pull out the strings. */
604	{
605		char	**pp = &cur_strs->strs._back_tab;
606		char	**fp = &cur_strs->strs4.Sentinel;
607#ifdef	DUMPTI
608		int	tempindex = 0;
609		char	*startstr = ip + sizeof (short) *
610					    nstrs;
611
612		printf("string table = '");
613		_Mprint(sstrtab, startstr);
614		printf("'\n");
615#endif	/* DUMPTI */
616
617		while (nstrs--) {
618			n = _Getshi();
619#ifdef	DUMPTI
620			Vr2val = _Vr2getshi();
621			printf("String %s [%s] (%s) offset = %d [%d]",
622			    strfnames[tempindex], strnames[tempindex],
623			    strcodes[tempindex], n, Vr2val);
624			tempindex++;
625#endif	/* DUMPTI */
626			if (pp < fp) {
627#ifdef	DUMPTI
628				_Sprint(n, startstr+n);
629#endif	/* DUMPTI */
630				if (n < 0)
631					*pp++ = NULL;
632				else
633					*pp++ = strtab + n;
634			}
635#ifdef	DUMPTI
636			else
637				_Sprint(-1, (char *)0);
638#endif	/* DUMPTI */
639		}
640		if (pp < fp)
641		(void) memset((char *)pp, 0, ((fp - pp) * sizeof (charptr)));
642	}
643
644	(void) memcpy(strtab, ip, sstrtab);
645
646#ifndef	DUMPTI
647
648	/*
649	 * If tabs are being expanded in software, turn this off
650	 * so output won't get messed up.  Also, don't use tab
651	 * or backtab, even if the terminal has them, since the
652	 * user might not have hardware tabs set right.
653	 */
654#ifdef	SYSV
655	if ((PROGTTYS.c_oflag & TABDLY) == TAB3) {
656		PROGTTYS.c_oflag &= ~TABDLY;
657		(void) reset_prog_mode();
658		goto next;
659	}
660#else	/* SYSV */
661	if ((PROGTTY.sg_flags & XTABS) == XTABS) {
662		PROGTTY.sg_flags &= ~XTABS;
663		(void) reset_prog_mode();
664		goto next;
665	}
666#endif	/* SYSV */
667	if (dest_tabs_magic_smso) {
668next:
669		cur_strs->strs2._tab = cur_strs->strs._back_tab = NULL;
670	}
671
672#ifdef	LTILDE
673	ioctl(cur_term -> Filedes, TIOCLGET, &n);
674#endif	/* LTILDE */
675#endif	/* DUMPTI */
676
677#ifdef	_VR2_COMPAT_CODE
678	(void) memcpy(&cur_term->_b1, &cur_bools->_auto_left_margin,
679	    (char *)&cur_term->_c1 - (char *)&cur_term->_b1);
680	(void) memcpy((char *)&cur_term->_c1, (char *)&cur_nums->_columns,
681	    (char *)&cur_term->_Vr2_Astrs._s1 - (char *)&cur_term->_c1);
682	(void) memcpy((char *)&cur_term->_Vr2_Astrs._s1,
683	    (char *)&cur_strs->strs._back_tab,
684	    (char *)&cur_term->Filedes - (char *)&cur_term->_Vr2_Astrs._s1);
685#endif	/* _VR2_COMPAT_CODE */
686
687	on_sequences = cur_term->turn_on_seq;
688	str_array = (char **)cur_strs;
689	{
690		static	char	offsets[] = {
691			    35,	/* enter_standout_mode, */
692			    36,	/* enter_underline_mode, */
693			    25,	/* enter_alt_charset_mode, */
694			    34,	/* enter_reverse_mode, */
695			    26,	/* enter_blink_mode, */
696			    30,	/* enter_dim_mode, */
697			    27,	/* enter_bold_mode, */
698			    32,	/* enter_secure_mode, */
699			    33,	/* enter_protected_mode, */
700			};
701
702		for (n = 0; n < NUM_ATTRIBUTES; n++) {
703			if ((on_sequences[n] = str_array[offsets[n]]) != 0)
704				cur_term->bit_vector |= bit_attributes[n];
705		}
706	}
707
708	if (!(set_attributes)) {
709		static	char	faked_attrs[] = { 1, 3, 4, 6 },
710			offsets[] = {
711			    43,	/* exit_standout_mode, */
712			    44,	/* exit_underline_mode, */
713			    38,	/* exit_alt_charset_mode, */
714			};
715		char		**off_sequences = cur_term->turn_off_seq;
716		int		i;
717
718		if ((max_attributes == -1) && (ceol_standout_glitch ||
719		    (magic_cookie_glitch >= 0)))
720			max_attributes = 1;
721
722		/* Figure out what attributes need to be faked. */
723		/* See vidupdate.c */
724
725		for (n = 0; n < sizeof (faked_attrs); n++) {
726			if (on_sequences[0] != NULL) {
727				if ((!on_sequences[i = faked_attrs[n]]) ||
728				    (strcmp(on_sequences[i],
729				    on_sequences[0]) == 0)) {
730					cur_term->sgr_faked |=
731					    bit_attributes[i];
732				}
733			} else {
734				if (!on_sequences[i = faked_attrs[n]]) {
735					cur_term->sgr_faked |=
736					    bit_attributes[i];
737				}
738			}
739		}
740
741		cur_term->check_turn_off = A_STANDOUT | A_UNDERLINE |
742		    A_ALTCHARSET;
743
744		for (n = 0; n < sizeof (offsets); n++) {
745			if ((!(off_sequences[n] = str_array[offsets[n]])) ||
746			    ((n > 0) && off_sequences[0] &&
747			    (strcmp(off_sequences[n], off_sequences[0]) ==
748			    0)) || ((n == 2) && (exit_attribute_mode) &&
749			    (strcmp(exit_attribute_mode, off_sequences[n]) ==
750			    0))) {
751				cur_term->check_turn_off &= ~bit_attributes[n];
752			}
753		}
754	}
755	cur_term->cursor_seq[0] = cursor_invisible;
756	cur_term->cursor_seq[1] = cursor_normal;
757	cur_term->cursor_seq[2] = cursor_visible;
758	cur_term->_pairs_tbl = (_Color_pair *) NULL;
759	cur_term->_color_tbl = (_Color *) NULL;
760
761	return (OK);
762}
763
764void
765_blast_keys(TERMINAL *terminal)
766{
767	terminal->_keys = NULL;
768	terminal->internal_keys = NULL;
769	terminal->_ksz = terminal->_first_macro = 0;
770	terminal->_lastkey_ordered = terminal->_lastmacro_ordered = -1;
771	(void) memset((char *)terminal->funckeystarter, 0, 0400 *
772	    sizeof (bool));
773}
774
775#ifndef	DUMPTI
776
777int
778reset_prog_mode(void)
779{
780#ifdef	SYSV
781	if (_BRS(PROGTTYS)) {
782		if (prog_istermios < 0) {
783			int i;
784
785			PROGTTY.c_lflag = PROGTTYS.c_lflag;
786			PROGTTY.c_oflag = PROGTTYS.c_oflag;
787			PROGTTY.c_iflag = PROGTTYS.c_iflag;
788			PROGTTY.c_cflag = PROGTTYS.c_cflag;
789			for (i = 0; i < NCC; i++)
790				PROGTTY.c_cc[i] = PROGTTYS.c_cc[i];
791			(void) ioctl(cur_term -> Filedes, TCSETAW, &PROGTTY);
792		} else
793			(void) ioctl(cur_term -> Filedes, TCSETSW, &PROGTTYS);
794	}
795#else	/* SYSV */
796	if (_BR(PROGTTY))
797		(void) ioctl(cur_term -> Filedes, TIOCSETN, &PROGTTY);
798#endif	/* SYSV */
799
800#ifdef	LTILDE
801	ioctl(cur_term -> Filedes, TIOCLGET, &cur_term -> oldlmode);
802	cur_term -> newlmode = cur_term -> oldlmode & ~LTILDE;
803	if (cur_term -> newlmode != cur_term -> oldlmode)
804		ioctl(cur_term -> Filedes, TIOCLSET, &cur_term -> newlmode);
805#endif	/* LTILDE */
806#ifdef	DIOCSETT
807	if (cur_term -> old.st_termt == 0)
808		ioctl(cur_term->Filedes, DIOCGETT, &cur_term -> old);
809	cur_term -> new = cur_term -> old;
810	cur_term -> new.st_termt = 0;
811	cur_term -> new.st_flgs |= TM_SET;
812	ioctl(cur_term->Filedes, DIOCSETT, &cur_term -> new);
813#endif	/* DIOCSETT */
814	return (OK);
815}
816
817int
818def_shell_mode(void)
819{
820#ifdef	SYSV
821	if ((shell_istermios =
822	    ioctl(cur_term -> Filedes, TCGETS, &SHELLTTYS)) < 0) {
823		int i;
824
825		(void) ioctl(cur_term -> Filedes, TCGETA, &SHELLTTY);
826		SHELLTTYS.c_lflag = SHELLTTY.c_lflag;
827		SHELLTTYS.c_oflag = SHELLTTY.c_oflag;
828		SHELLTTYS.c_iflag = SHELLTTY.c_iflag;
829		SHELLTTYS.c_cflag = SHELLTTY.c_cflag;
830		for (i = 0; i < NCC; i++)
831			SHELLTTYS.c_cc[i] = SHELLTTY.c_cc[i];
832	}
833#else	/* SYSV */
834	(void) ioctl(cur_term -> Filedes, TIOCGETP, &SHELLTTY);
835#endif	/* SYSV */
836	return (OK);
837}
838
839#endif	/* DUMPTI */
840