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 
56 extern	bool	_use_env;	/* in curses.c */
57 
58 chtype	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 
70 char	*Def_term = "unknown",	/* default terminal type */
71 	term_parm_err[32], ttytype[BUFSIZ], _frst_tblstr[1400];
72 
73 TERMINAL		_first_term, *cur_term = &_first_term;
74 struct	_bool_struct	_frst_bools, *cur_bools = &_frst_bools;
75 struct	_num_struct	_frst_nums, *cur_nums = &_frst_nums;
76 struct	_str_struct	_frst_strs, *cur_strs = &_frst_strs;
77 
78 /* _called_before is used/cleared by delterm.c and restart.c */
79 char	_called_before = 0;
80 short	term_errno = -1;
81 
82 #ifdef SYSV
83 int	prog_istermios = -1;
84 int	shell_istermios = -1;
85 #endif
86 
87 #ifdef	DUMPTI
88 extern	char	*boolfnames[], *boolnames[], *boolcodes[],
89 		*numfnames[], *numnames[], *numcodes[],
90 		*strfnames[], *strnames[], *strcodes[];
91 
92 main(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  */
192 static 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  */
228 int
229 setupterm(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) {
291 cant_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) {
317 corrupt:
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) {
388 freenums:
389 			free((char *)cur_nums);
390 freebools:
391 			free((char *)cur_bools);
392 freeterminal:
393 			free((char *)cur_term);
394 badmalloc:
395 			term_errno = TERM_BAD_MALLOC;
396 #ifdef	DEBUG
397 			strcpy(term_parm_err, "setupterm");
398 #endif	/* DEBUG */
399 out_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) {
668 next:
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 
764 void
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 
777 int
778 reset_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 
817 int
818 def_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