17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright (c) 1995, by Sun Microsystems, Inc.
247c478bd9Sstevel@tonic-gate  * All rights reserved.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate /*
287c478bd9Sstevel@tonic-gate  * setupterm.c
297c478bd9Sstevel@tonic-gate  *
307c478bd9Sstevel@tonic-gate  * XCurses Library
317c478bd9Sstevel@tonic-gate  *
327c478bd9Sstevel@tonic-gate  * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
337c478bd9Sstevel@tonic-gate  *
347c478bd9Sstevel@tonic-gate  */
357c478bd9Sstevel@tonic-gate 
367c478bd9Sstevel@tonic-gate #ifdef M_RCSID
377c478bd9Sstevel@tonic-gate #ifndef lint
387c478bd9Sstevel@tonic-gate static char const rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/setup.c 1.9 1995/10/02 20:22:57 ant Exp $";
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include <private.h>
437c478bd9Sstevel@tonic-gate #include <sys/types.h>
447c478bd9Sstevel@tonic-gate #include <sys/stat.h>
457c478bd9Sstevel@tonic-gate #ifdef M_USE_IOCTL_H
467c478bd9Sstevel@tonic-gate #include <sys/ioctl.h>
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate #include <ctype.h>
497c478bd9Sstevel@tonic-gate #include <fcntl.h>
507c478bd9Sstevel@tonic-gate #include <limits.h>
517c478bd9Sstevel@tonic-gate #include <stdlib.h>
527c478bd9Sstevel@tonic-gate #include <string.h>
537c478bd9Sstevel@tonic-gate #include <unistd.h>
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate TERMINAL *cur_term;
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate  * Any version number should be placed in this file, since setupterm()
597c478bd9Sstevel@tonic-gate  * must be called in order to initialize Curses or Terminfo.
607c478bd9Sstevel@tonic-gate  */
617c478bd9Sstevel@tonic-gate char __m_curses_version[] = M_CURSES_VERSION;
627c478bd9Sstevel@tonic-gate 
63*1da57d55SToomas Soome /* True if __m_setupterm() should use either the window settings from
647c478bd9Sstevel@tonic-gate  * ioctl(), or the environment variables LINES and COLUMNS to override
65*1da57d55SToomas Soome  * the terminfo database entries for 'lines' and 'columns'.
667c478bd9Sstevel@tonic-gate  *
677c478bd9Sstevel@tonic-gate  * Call use_env(flag) before either setupterm(), newterm(), or initscr().
687c478bd9Sstevel@tonic-gate  */
69*1da57d55SToomas Soome static bool use_environment = TRUE;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate static char const e_terminal[] = "No memory for TERMINAL structure.\n";
727c478bd9Sstevel@tonic-gate static char const e_unknown[] = "\"%s\": Unknown terminal type.\n";
737c478bd9Sstevel@tonic-gate static char const e_pathmax[] = "\"%s\": terminfo database path too long.\n";
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static char def_cr[] = "\r";
767c478bd9Sstevel@tonic-gate static char def_nl[] = "\n";
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate  * Take the real command character out of the CC environment variable
807c478bd9Sstevel@tonic-gate  * and substitute it in for the prototype given in 'command_character'.
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate static void
do_prototype()837c478bd9Sstevel@tonic-gate do_prototype()
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate     	int i, j;
867c478bd9Sstevel@tonic-gate 	char CC, proto;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	CC = *__m_getenv("CC");
897c478bd9Sstevel@tonic-gate 	proto = *command_character;
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	for (i=0; i < __COUNT_STR; i++)
927c478bd9Sstevel@tonic-gate 		for(j = 0; cur_term->_str[i][j]; ++j)
937c478bd9Sstevel@tonic-gate 			if (cur_term->_str[i][j] == proto)
947c478bd9Sstevel@tonic-gate 				cur_term->_str[i][j] = CC;
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate #define min(a, b)		((a) < (b) ? (a) : (b))
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate /*
1007c478bd9Sstevel@tonic-gate  * Return a number from a terminfo file.  Numbers in a terminfo
1017c478bd9Sstevel@tonic-gate  * file are stored as two bytes with low-high ordering.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate static short
getnum(fd)1047c478bd9Sstevel@tonic-gate getnum(fd)
1057c478bd9Sstevel@tonic-gate int fd;
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate         unsigned char bytes[2];
108*1da57d55SToomas Soome 
1097c478bd9Sstevel@tonic-gate         if (read(fd, bytes, 2) != 2)
1107c478bd9Sstevel@tonic-gate                 return SHRT_MIN;
111*1da57d55SToomas Soome 
1127c478bd9Sstevel@tonic-gate         return (short) (bytes[0] + bytes[1] * 256);
1137c478bd9Sstevel@tonic-gate }
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /*f
1167c478bd9Sstevel@tonic-gate  * Read the compiled terminfo entry in the given file into the
1177c478bd9Sstevel@tonic-gate  * structure pointed to by ptr, allocating space for the string
1187c478bd9Sstevel@tonic-gate  * table and placing its address in ptr->str_table.
1197c478bd9Sstevel@tonic-gate  */
1207c478bd9Sstevel@tonic-gate int
__m_read_terminfo(filename,tp)1217c478bd9Sstevel@tonic-gate __m_read_terminfo(filename, tp)
1227c478bd9Sstevel@tonic-gate const char *filename;
1237c478bd9Sstevel@tonic-gate TERMINAL *tp;
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate 	int fd;
1267c478bd9Sstevel@tonic-gate 	short offset;
1277c478bd9Sstevel@tonic-gate 	size_t i, len;
1287c478bd9Sstevel@tonic-gate 	struct stat statbuf;
1297c478bd9Sstevel@tonic-gate 	terminfo_header_t header;
1307c478bd9Sstevel@tonic-gate 	unsigned char ch, bytebuf[2];
1317c478bd9Sstevel@tonic-gate 
1327c478bd9Sstevel@tonic-gate 	/* Get compiled terminfo file header. */
1337c478bd9Sstevel@tonic-gate 	if ((fd = open(filename, 0)) < 0)
1347c478bd9Sstevel@tonic-gate 		goto error_1;
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	if ((header.magic = getnum(fd)) != __TERMINFO_MAGIC
1377c478bd9Sstevel@tonic-gate 	|| (header.name_size = getnum(fd)) < 0
1387c478bd9Sstevel@tonic-gate 	|| (header.bool_count = getnum(fd)) < 0
1397c478bd9Sstevel@tonic-gate 	|| (header.num_count = getnum(fd)) < 0
1407c478bd9Sstevel@tonic-gate 	|| (header.str_count = getnum(fd)) < 0
1417c478bd9Sstevel@tonic-gate 	|| (header.str_size = getnum(fd)) < 0)
1427c478bd9Sstevel@tonic-gate 		goto error_2;
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/* Allocate and fetch terminal names. */
1457c478bd9Sstevel@tonic-gate 	len = min(127, header.name_size);
1467c478bd9Sstevel@tonic-gate 	if ((tp->_names = (char *) malloc(len + 1)) == (char *) 0)
1477c478bd9Sstevel@tonic-gate 		goto error_2;
1487c478bd9Sstevel@tonic-gate 	if (read(fd, tp->_names, len) != len)
1497c478bd9Sstevel@tonic-gate 		goto error_3;
1507c478bd9Sstevel@tonic-gate 	tp->_names[len] = '\0';
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate 	if (127 < header.name_size)
1537c478bd9Sstevel@tonic-gate 		(void) lseek(fd, (off_t) (header.name_size - 127), SEEK_CUR);
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	/* Fetch booleans. */
1567c478bd9Sstevel@tonic-gate 	len = min(__COUNT_BOOL, header.bool_count);
1577c478bd9Sstevel@tonic-gate 	if (read(fd, tp->_bool, len) != len)
1587c478bd9Sstevel@tonic-gate 		goto error_3;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 	if (__COUNT_BOOL < header.bool_count) {
1617c478bd9Sstevel@tonic-gate 		(void) lseek(
162*1da57d55SToomas Soome 			fd, (off_t) (header.bool_count - __COUNT_BOOL),
1637c478bd9Sstevel@tonic-gate 			SEEK_CUR
1647c478bd9Sstevel@tonic-gate 		);
1657c478bd9Sstevel@tonic-gate 	} else {
1667c478bd9Sstevel@tonic-gate 		for (len = header.bool_count; len < __COUNT_BOOL; ++len)
1677c478bd9Sstevel@tonic-gate 			tp->_bool[len] = 0;
1687c478bd9Sstevel@tonic-gate 	}
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	/* Eat padding byte. */
1717c478bd9Sstevel@tonic-gate 	if ((header.name_size + header.bool_count) % 2 != 0)
1727c478bd9Sstevel@tonic-gate 		(void) read(fd, &ch, sizeof ch);
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 	/* Fetch numbers. */
1757c478bd9Sstevel@tonic-gate 	len = min(__COUNT_NUM, header.num_count);
1767c478bd9Sstevel@tonic-gate 	for (i = 0; i < len; ++i)
1777c478bd9Sstevel@tonic-gate 		tp->_num[i] = getnum(fd);
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	if (__COUNT_NUM < header.num_count) {
1807c478bd9Sstevel@tonic-gate 		(void) lseek(
181*1da57d55SToomas Soome 			fd, (off_t) (2 * (header.num_count - __COUNT_NUM)),
1827c478bd9Sstevel@tonic-gate 			SEEK_CUR
1837c478bd9Sstevel@tonic-gate 		);
1847c478bd9Sstevel@tonic-gate 	} else {
1857c478bd9Sstevel@tonic-gate 		for (len = header.num_count; len < __COUNT_NUM; ++len)
1867c478bd9Sstevel@tonic-gate 			tp->_num[len] = -1;
1877c478bd9Sstevel@tonic-gate 	}
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/* Allocate and fetch strings. */
1907c478bd9Sstevel@tonic-gate 	if ((tp->_str_table = (char *) malloc(header.str_size)) == (char *) 0)
1917c478bd9Sstevel@tonic-gate 		goto error_3;
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate         /* Read in string offset section setting pointers to strings. */
1947c478bd9Sstevel@tonic-gate 	len = min(__COUNT_STR, header.str_count);
1957c478bd9Sstevel@tonic-gate         for (i = 0; i < len; ++i) {
1967c478bd9Sstevel@tonic-gate                 if ((offset = getnum(fd)) == SHRT_MIN)
1977c478bd9Sstevel@tonic-gate                         goto error_4;
198*1da57d55SToomas Soome 
1997c478bd9Sstevel@tonic-gate                 if (offset < 0)
2007c478bd9Sstevel@tonic-gate                         tp->_str[i] = (char *) 0;
2017c478bd9Sstevel@tonic-gate                 else
2027c478bd9Sstevel@tonic-gate                         tp->_str[i] = tp->_str_table + offset;
2037c478bd9Sstevel@tonic-gate         }
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate 	if (__COUNT_STR < header.str_count) {
2067c478bd9Sstevel@tonic-gate 		(void) lseek(
207*1da57d55SToomas Soome 			fd, (off_t) (2 * (header.str_count - __COUNT_STR)),
2087c478bd9Sstevel@tonic-gate 			SEEK_CUR
2097c478bd9Sstevel@tonic-gate 		);
2107c478bd9Sstevel@tonic-gate 	} else {
2117c478bd9Sstevel@tonic-gate 		for (; i < __COUNT_STR; ++i)
2127c478bd9Sstevel@tonic-gate 			tp->_str[i] = (char *) 0;
2137c478bd9Sstevel@tonic-gate 	}
2147c478bd9Sstevel@tonic-gate 
2157c478bd9Sstevel@tonic-gate 	if (read(fd, tp->_str_table, header.str_size) != header.str_size)
2167c478bd9Sstevel@tonic-gate 		goto error_4;
2177c478bd9Sstevel@tonic-gate 	(void) close(fd);
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	return 0;
2207c478bd9Sstevel@tonic-gate error_4:
2217c478bd9Sstevel@tonic-gate 	free(tp->_str_table);
2227c478bd9Sstevel@tonic-gate error_3:
2237c478bd9Sstevel@tonic-gate 	free(tp->_names);
2247c478bd9Sstevel@tonic-gate error_2:
2257c478bd9Sstevel@tonic-gate 	(void) close(fd);
2267c478bd9Sstevel@tonic-gate error_1:
2277c478bd9Sstevel@tonic-gate 	return -1;
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate 
2307c478bd9Sstevel@tonic-gate void
use_env(bool bf)2317c478bd9Sstevel@tonic-gate use_env(bool bf)
2327c478bd9Sstevel@tonic-gate {
2337c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
2347c478bd9Sstevel@tonic-gate 	__m_trace("use_env(%d)", bf);
2357c478bd9Sstevel@tonic-gate #endif
2367c478bd9Sstevel@tonic-gate 	use_environment = bf;
2377c478bd9Sstevel@tonic-gate 	__m_return_void("use_env");
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate /*f
2417c478bd9Sstevel@tonic-gate  * Set up terminal.
2427c478bd9Sstevel@tonic-gate  *
2437c478bd9Sstevel@tonic-gate  * Reads in the terminfo database pointed to by $TERMINFO env. var.
244*1da57d55SToomas Soome  * for the given terminal, but does not set up the output virtualization
245*1da57d55SToomas Soome  * structues used by CURSES.  If the terminal name pointer is NULL,
246*1da57d55SToomas Soome  * the $TERM env. var. is used for the terminal.  All output is to
247*1da57d55SToomas Soome  * the given file descriptor which is initialized for output.
2487c478bd9Sstevel@tonic-gate  *
249*1da57d55SToomas Soome  * On error, if errret != NULL then setupterm() returns OK
250*1da57d55SToomas Soome  * or ERR and stores a status value in the integer pointed to by
251*1da57d55SToomas Soome  * errret.  A status of 1 is normal, 0 means the terminal could
252*1da57d55SToomas Soome  * not be found, and -1 means the terminfo database could not be
253*1da57d55SToomas Soome  * found.  If errret == NULL then setupterm() prints an error
2547c478bd9Sstevel@tonic-gate  * message upon and exit().
2557c478bd9Sstevel@tonic-gate  *
2567c478bd9Sstevel@tonic-gate  * On success, cur_term set to a terminfo structure and OK returned.
2577c478bd9Sstevel@tonic-gate  */
2587c478bd9Sstevel@tonic-gate int
__m_setupterm(termname,ifd,ofd,err_return)2597c478bd9Sstevel@tonic-gate __m_setupterm(termname, ifd, ofd, err_return)
2607c478bd9Sstevel@tonic-gate const char *termname;
2617c478bd9Sstevel@tonic-gate int ifd, ofd;
2627c478bd9Sstevel@tonic-gate int *err_return;
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate 	int err_code = 1;
2657c478bd9Sstevel@tonic-gate 	TERMINAL *old_term;
2667c478bd9Sstevel@tonic-gate 	char const *err_msg;
2677c478bd9Sstevel@tonic-gate 
268*1da57d55SToomas Soome 	/* It is possible to call setupterm() for multiple terminals,
269*1da57d55SToomas Soome 	 * in which case we have to be able to restore cur_term in
2707c478bd9Sstevel@tonic-gate 	 * case of error.
2717c478bd9Sstevel@tonic-gate 	 */
2727c478bd9Sstevel@tonic-gate 	old_term = cur_term;
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	cur_term = (TERMINAL *) calloc(1, sizeof *cur_term);
2757c478bd9Sstevel@tonic-gate 	if (cur_term == (TERMINAL *) 0) {
2767c478bd9Sstevel@tonic-gate 		err_code = -1;
2777c478bd9Sstevel@tonic-gate 		goto error;
2787c478bd9Sstevel@tonic-gate 	}
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 	if (isatty(cur_term->_ifd = ifd))
2817c478bd9Sstevel@tonic-gate 		cur_term->_flags |= __TERM_ISATTY_IN;
2827c478bd9Sstevel@tonic-gate 	if (isatty(cur_term->_ifd = ofd))
2837c478bd9Sstevel@tonic-gate 		cur_term->_flags |= __TERM_ISATTY_OUT;
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	(void) def_shell_mode();
2867c478bd9Sstevel@tonic-gate 	(void) def_prog_mode();
2877c478bd9Sstevel@tonic-gate 
2887c478bd9Sstevel@tonic-gate #ifdef ONLCR
2897c478bd9Sstevel@tonic-gate 	if ((cur_term->_prog.c_oflag & (OPOST | ONLCR)) == (OPOST | ONLCR))
2907c478bd9Sstevel@tonic-gate #else
2917c478bd9Sstevel@tonic-gate 	if (cur_term->_prog.c_oflag & OPOST)
2927c478bd9Sstevel@tonic-gate #endif
2937c478bd9Sstevel@tonic-gate 		cur_term->_flags |= __TERM_NL_IS_CRLF;
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 	(void) restartterm(termname, ofd, &err_code);
2967c478bd9Sstevel@tonic-gate error:
2977c478bd9Sstevel@tonic-gate 	switch (err_code) {
2987c478bd9Sstevel@tonic-gate 	case -1:
2997c478bd9Sstevel@tonic-gate 		err_msg = e_terminal;
3007c478bd9Sstevel@tonic-gate 		break;
3017c478bd9Sstevel@tonic-gate 	case 0:
3027c478bd9Sstevel@tonic-gate 		err_msg = e_unknown;
3037c478bd9Sstevel@tonic-gate 		break;
3047c478bd9Sstevel@tonic-gate 	case 1:
3057c478bd9Sstevel@tonic-gate 		break;
3067c478bd9Sstevel@tonic-gate 	case 2:
3077c478bd9Sstevel@tonic-gate 		err_msg = e_pathmax;
3087c478bd9Sstevel@tonic-gate 		err_code = -1;
3097c478bd9Sstevel@tonic-gate 		break;
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	if (err_return != (int *) 0) {
3137c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
3147c478bd9Sstevel@tonic-gate 		__m_trace(
315*1da57d55SToomas Soome 			"__m_setupterm error code passed back in %p = %d.",
3167c478bd9Sstevel@tonic-gate 			err_return, err_code
3177c478bd9Sstevel@tonic-gate 		);
3187c478bd9Sstevel@tonic-gate #endif
3197c478bd9Sstevel@tonic-gate 		*err_return = err_code;
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 		if (err_code == 1) {
3227c478bd9Sstevel@tonic-gate 			err_code = OK;
3237c478bd9Sstevel@tonic-gate 		} else {
3247c478bd9Sstevel@tonic-gate 			err_code = ERR;
3257c478bd9Sstevel@tonic-gate 			free(cur_term);
3267c478bd9Sstevel@tonic-gate 			cur_term = old_term;
327*1da57d55SToomas Soome 		}
3287c478bd9Sstevel@tonic-gate 	} else if (err_code != 1) {
3297c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
3307c478bd9Sstevel@tonic-gate 		__m_trace("__m_setupterm() failed with:");
3317c478bd9Sstevel@tonic-gate 		__m_trace(err_msg, termname);
3327c478bd9Sstevel@tonic-gate #endif
3337c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_msg, termname);
3347c478bd9Sstevel@tonic-gate 		exit(1);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	return __m_return_code("__m_setupterm", err_code);
3387c478bd9Sstevel@tonic-gate }
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate int
setupterm(term,out,err)3417c478bd9Sstevel@tonic-gate setupterm(term, out, err)
3427c478bd9Sstevel@tonic-gate const char *term;
3437c478bd9Sstevel@tonic-gate int out, *err;
3447c478bd9Sstevel@tonic-gate {
3457c478bd9Sstevel@tonic-gate 	int code;
3467c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
3477c478bd9Sstevel@tonic-gate 	__m_trace("setupterm(%p, %d, %p)", term, out, err);
3487c478bd9Sstevel@tonic-gate #endif
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	code = __m_setupterm(term, STDIN_FILENO, out, err);
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	return __m_return_code("setupterm", code);
3537c478bd9Sstevel@tonic-gate }
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate int
del_curterm(tp)3567c478bd9Sstevel@tonic-gate del_curterm(tp)
3577c478bd9Sstevel@tonic-gate TERMINAL *tp;
3587c478bd9Sstevel@tonic-gate {
3597c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
3607c478bd9Sstevel@tonic-gate 	__m_trace("del_curterm(%p)", tp);
3617c478bd9Sstevel@tonic-gate #endif
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	if (tp != (TERMINAL *) 0) {
3647c478bd9Sstevel@tonic-gate 		if (cur_term == tp)
3657c478bd9Sstevel@tonic-gate 			cur_term = (TERMINAL *) 0;
3667c478bd9Sstevel@tonic-gate 		if (tp->_str_table != (char *) 0)
3677c478bd9Sstevel@tonic-gate 			free(tp->_str_table);
3687c478bd9Sstevel@tonic-gate 		if (tp->_names != (char *) 0)
3697c478bd9Sstevel@tonic-gate 			free(tp->_names);
3707c478bd9Sstevel@tonic-gate 		if (tp->_term != (char *) 0)
3717c478bd9Sstevel@tonic-gate 			free(tp->_term);
3727c478bd9Sstevel@tonic-gate 		if (tp->_pair != (short (*)[2]) 0)
3737c478bd9Sstevel@tonic-gate 			free(tp->_pair);
3747c478bd9Sstevel@tonic-gate 		if (tp->_color != (short (*)[3]) 0)
3757c478bd9Sstevel@tonic-gate 			free(tp->_color);
3767c478bd9Sstevel@tonic-gate 		free(tp);
3777c478bd9Sstevel@tonic-gate 	}
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate 	return __m_return_code("del_curterm", OK);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate TERMINAL *
set_curterm(tp)3837c478bd9Sstevel@tonic-gate set_curterm(tp)
3847c478bd9Sstevel@tonic-gate TERMINAL *tp;
3857c478bd9Sstevel@tonic-gate {
3867c478bd9Sstevel@tonic-gate 	TERMINAL *old;
3877c478bd9Sstevel@tonic-gate 
3887c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
3897c478bd9Sstevel@tonic-gate 	__m_trace("set_curterm(%p)", tp);
3907c478bd9Sstevel@tonic-gate #endif
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	old = cur_term;
3937c478bd9Sstevel@tonic-gate 	cur_term = tp;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	return __m_return_pointer("set_curterm", old);
3967c478bd9Sstevel@tonic-gate }
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate int
restartterm(tm,fd,err_return)3997c478bd9Sstevel@tonic-gate restartterm(tm, fd, err_return)
4007c478bd9Sstevel@tonic-gate const char *tm;
4017c478bd9Sstevel@tonic-gate int fd, *err_return;
4027c478bd9Sstevel@tonic-gate {
4037c478bd9Sstevel@tonic-gate 	size_t len;
4047c478bd9Sstevel@tonic-gate 	int path_max, err_code;
4057c478bd9Sstevel@tonic-gate 	char const *err_msg, *terminfo;
4067c478bd9Sstevel@tonic-gate 	char *old_names, *old_strings, *old_term, *filename;
4077c478bd9Sstevel@tonic-gate 	static char const def_termname[] = M_TERM_NAME;
4087c478bd9Sstevel@tonic-gate 	static char const def_terminfo[] = M_TERMINFO_DIR;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
4117c478bd9Sstevel@tonic-gate 	__m_trace("restartterm(%s, %d, %p)", tm ? tm : "NULL", fd, err_return);
4127c478bd9Sstevel@tonic-gate #endif
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	err_code = 1;
4157c478bd9Sstevel@tonic-gate 	filename = (char *) 0;
4167c478bd9Sstevel@tonic-gate 	old_term = cur_term->_term;
4177c478bd9Sstevel@tonic-gate 	old_names = cur_term->_names;
4187c478bd9Sstevel@tonic-gate 	old_strings = cur_term->_str_table;
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	terminfo = __m_getenv("TERMINFO");
4217c478bd9Sstevel@tonic-gate 	if (terminfo == (char *) 0 || terminfo[0] == '\0') {
422*1da57d55SToomas Soome 		terminfo = def_terminfo;
4237c478bd9Sstevel@tonic-gate 	} else {
4247c478bd9Sstevel@tonic-gate 		terminfo = (const char *) strdup((char *) terminfo);
4257c478bd9Sstevel@tonic-gate 		if (terminfo == (char *) 0) {
4267c478bd9Sstevel@tonic-gate 			/* Not really true... */
427*1da57d55SToomas Soome 			err_msg = e_terminal;
4287c478bd9Sstevel@tonic-gate 			err_code = 2;
4297c478bd9Sstevel@tonic-gate 			goto error;
4307c478bd9Sstevel@tonic-gate 		}
4317c478bd9Sstevel@tonic-gate 	}
432*1da57d55SToomas Soome 
4337c478bd9Sstevel@tonic-gate 	if (tm == (char *) 0 && (tm = getenv("TERM")) == (char *) 0)
4347c478bd9Sstevel@tonic-gate 		tm = def_termname;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	/* Remember the terminal name being loaded. */
4377c478bd9Sstevel@tonic-gate 	cur_term->_term = m_strdup(tm);
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 	/* Length of path we're going to construct. */
4407c478bd9Sstevel@tonic-gate 	len = strlen(terminfo) + 3 + strlen(tm);
4417c478bd9Sstevel@tonic-gate 
4427c478bd9Sstevel@tonic-gate 	if ((path_max = m_pathmax(terminfo)) == -1 || path_max < len
4437c478bd9Sstevel@tonic-gate 	|| (filename = (char *) malloc(path_max+1)) == (char *) 0) {
4447c478bd9Sstevel@tonic-gate 		err_msg = e_pathmax;
4457c478bd9Sstevel@tonic-gate 		err_code = 2;
4467c478bd9Sstevel@tonic-gate 		goto error;
4477c478bd9Sstevel@tonic-gate 	}
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate 	/* Construct terminfo filename. */
4507c478bd9Sstevel@tonic-gate 	(void) sprintf(filename, "%s/%c/%s", terminfo, tolower(tm[0]), tm);
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/* Go looking for compiled terminal definition. */
4537c478bd9Sstevel@tonic-gate 	if (__m_read_terminfo(filename, cur_term) < 0) {
4547c478bd9Sstevel@tonic-gate 		/* Length of default terminfo path. */
4557c478bd9Sstevel@tonic-gate 		len = strlen(def_terminfo) + 3 + strlen(tm);
4567c478bd9Sstevel@tonic-gate 
4577c478bd9Sstevel@tonic-gate 		if (path_max < len) {
4587c478bd9Sstevel@tonic-gate 			err_msg = e_pathmax;
4597c478bd9Sstevel@tonic-gate 			err_code = 2;
4607c478bd9Sstevel@tonic-gate 			goto error;
4617c478bd9Sstevel@tonic-gate 		}
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 		(void) sprintf(filename, "%s/%c/%s", def_terminfo, tm[0], tm);
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		if (__m_read_terminfo(filename, cur_term) < 0) {
4667c478bd9Sstevel@tonic-gate 			err_msg = e_unknown;
4677c478bd9Sstevel@tonic-gate 			err_code = 0;
4687c478bd9Sstevel@tonic-gate 			goto error;
4697c478bd9Sstevel@tonic-gate 		}
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	if (use_environment) {
4737c478bd9Sstevel@tonic-gate 		char *env;
4747c478bd9Sstevel@tonic-gate #ifdef TIOCGWINSZ
4757c478bd9Sstevel@tonic-gate 		/*l
4767c478bd9Sstevel@tonic-gate 		 * Use ioctl(TIOCGWINSZ) to get row and column values.  These
4777c478bd9Sstevel@tonic-gate 		 * values may override the default terminfo settings.
4787c478bd9Sstevel@tonic-gate 		 */
4797c478bd9Sstevel@tonic-gate 		{
4807c478bd9Sstevel@tonic-gate 			struct winsize wininfo;
4817c478bd9Sstevel@tonic-gate 			if (ioctl(fd, TIOCGWINSZ, &wininfo) != -1) {
4827c478bd9Sstevel@tonic-gate 				if (0 < wininfo.ws_col)
4837c478bd9Sstevel@tonic-gate 					columns = wininfo.ws_col;
4847c478bd9Sstevel@tonic-gate 				if (0 < wininfo.ws_row)
4857c478bd9Sstevel@tonic-gate 					lines = wininfo.ws_row;
486*1da57d55SToomas Soome 			}
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate #endif /* TIOCGWINSZ */
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 		/* Check to see is the user wants a particular size terminal. */
4917c478bd9Sstevel@tonic-gate 		if ((env = __m_getenv("LINES")) != (char *) 0) {
4927c478bd9Sstevel@tonic-gate 			int nlines = strtol(env, (char **) 0, 10);
4937c478bd9Sstevel@tonic-gate 			if (0 < nlines)
4947c478bd9Sstevel@tonic-gate 				lines = nlines;
4957c478bd9Sstevel@tonic-gate 		}
4967c478bd9Sstevel@tonic-gate 		if ((env = __m_getenv("COLUMNS")) != (char *) 0) {
4977c478bd9Sstevel@tonic-gate 			int ncolumns = strtol(env, (char **) 0, 10);
4987c478bd9Sstevel@tonic-gate 			if (0 < ncolumns)
4997c478bd9Sstevel@tonic-gate 				columns = ncolumns;
5007c478bd9Sstevel@tonic-gate 		}
5017c478bd9Sstevel@tonic-gate 	}
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	if (command_character != (char *) 0 && __m_getenv("CC") != (char *) 0)
5047c478bd9Sstevel@tonic-gate 		do_prototype();
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 	/* If no_color_video is disabled, then assign it a value that
5077c478bd9Sstevel@tonic-gate 	 * permits all attributes in combination with colour.
5087c478bd9Sstevel@tonic-gate 	 */
5097c478bd9Sstevel@tonic-gate 	if (no_color_video == -1)
5107c478bd9Sstevel@tonic-gate 		no_color_video = 0;
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	__m_mvcur_cost();
5137c478bd9Sstevel@tonic-gate error:
5147c478bd9Sstevel@tonic-gate 	if (filename != (char *) 0)
5157c478bd9Sstevel@tonic-gate 		free(filename);
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	if (terminfo != def_terminfo)
5187c478bd9Sstevel@tonic-gate 		free((void *) terminfo);
5197c478bd9Sstevel@tonic-gate 
5207c478bd9Sstevel@tonic-gate 	if (err_return != NULL) {
5217c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
5227c478bd9Sstevel@tonic-gate 		__m_trace(
523*1da57d55SToomas Soome 			"restartterm() error code passed back in %p = %d.",
5247c478bd9Sstevel@tonic-gate 			err_return, err_code
5257c478bd9Sstevel@tonic-gate 		);
5267c478bd9Sstevel@tonic-gate #endif
5277c478bd9Sstevel@tonic-gate 		*err_return = err_code;
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 		if (err_code == 1) {
5307c478bd9Sstevel@tonic-gate 			err_code = OK;
5317c478bd9Sstevel@tonic-gate 		} else {
5327c478bd9Sstevel@tonic-gate 			err_code = ERR;
5337c478bd9Sstevel@tonic-gate 			cur_term->_term = old_term;
5347c478bd9Sstevel@tonic-gate 			cur_term->_names = old_names;
5357c478bd9Sstevel@tonic-gate 			cur_term->_str_table = old_strings;
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 	} else if (err_code != 1) {
5387c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
5397c478bd9Sstevel@tonic-gate 		__m_trace("restartterm() failed with:");
5407c478bd9Sstevel@tonic-gate 		__m_trace(err_msg, tm);
5417c478bd9Sstevel@tonic-gate #endif
5427c478bd9Sstevel@tonic-gate 		fprintf(stderr, err_msg, tm);
5437c478bd9Sstevel@tonic-gate 		exit(1);
544*1da57d55SToomas Soome 	}
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 	if (err_code == OK) {
5477c478bd9Sstevel@tonic-gate 		if (old_names != (char *) 0)
5487c478bd9Sstevel@tonic-gate 			free(old_names);
5497c478bd9Sstevel@tonic-gate 		if (old_strings != (char *) 0)
5507c478bd9Sstevel@tonic-gate 			free(old_strings);
5517c478bd9Sstevel@tonic-gate 		if (old_term != (char *) 0)
5527c478bd9Sstevel@tonic-gate 			free(old_term);
5537c478bd9Sstevel@tonic-gate 	}
5547c478bd9Sstevel@tonic-gate 
5557c478bd9Sstevel@tonic-gate 	return __m_return_code("restartterm", err_code);
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate /*
5597c478bd9Sstevel@tonic-gate  * Get the termios setting for the terminal.  Check the input
5607c478bd9Sstevel@tonic-gate  * file descriptor first, else the output file descriptor.  If
561*1da57d55SToomas Soome  * both input and output are both terminals, it is assumed that
5627c478bd9Sstevel@tonic-gate  * they refer to the same terminal.
5637c478bd9Sstevel@tonic-gate  */
5647c478bd9Sstevel@tonic-gate int
__m_tty_get(tp)5657c478bd9Sstevel@tonic-gate __m_tty_get(tp)
5667c478bd9Sstevel@tonic-gate struct termios *tp;
5677c478bd9Sstevel@tonic-gate {
5687c478bd9Sstevel@tonic-gate 	if (tcgetattr(cur_term->_ifd, tp) != 0) {
569*1da57d55SToomas Soome 		/* Input was not a terminal, possibly redirected.
5707c478bd9Sstevel@tonic-gate 		 * Check output instead.
5717c478bd9Sstevel@tonic-gate 		 */
5727c478bd9Sstevel@tonic-gate 		if (tcgetattr(cur_term->_ofd, tp) != 0)
5737c478bd9Sstevel@tonic-gate 			return ERR;
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate 	return OK;
5777c478bd9Sstevel@tonic-gate }
5787c478bd9Sstevel@tonic-gate 
5797c478bd9Sstevel@tonic-gate /*
5807c478bd9Sstevel@tonic-gate  * Restore the termios settings.
5817c478bd9Sstevel@tonic-gate  */
5827c478bd9Sstevel@tonic-gate int
__m_tty_set(tp)5837c478bd9Sstevel@tonic-gate __m_tty_set(tp)
5847c478bd9Sstevel@tonic-gate struct termios *tp;
5857c478bd9Sstevel@tonic-gate {
5867c478bd9Sstevel@tonic-gate 	int fd;
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 	if (cur_term->_flags & __TERM_ISATTY_IN)
5897c478bd9Sstevel@tonic-gate 		fd = cur_term->_ifd;
5907c478bd9Sstevel@tonic-gate 	else if (cur_term->_flags & __TERM_ISATTY_OUT)
5917c478bd9Sstevel@tonic-gate 		fd = cur_term->_ofd;
5927c478bd9Sstevel@tonic-gate 	else
5937c478bd9Sstevel@tonic-gate 		return OK;
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate #ifdef NOT_NOW
5967c478bd9Sstevel@tonic-gate 	return tcsetattr(fd, TCSADRAIN, tp) == 0 ? OK : ERR;
5977c478bd9Sstevel@tonic-gate #else
5987c478bd9Sstevel@tonic-gate /* VSU testing bug does not read the master side properly so in order
5997c478bd9Sstevel@tonic-gate  * to drain the buffer.  Must use TCSANOW.
6007c478bd9Sstevel@tonic-gate  */
6017c478bd9Sstevel@tonic-gate 	return tcsetattr(fd, TCSANOW, tp) == 0 ? OK : ERR;
6027c478bd9Sstevel@tonic-gate #endif
6037c478bd9Sstevel@tonic-gate }
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate int
def_shell_mode()6067c478bd9Sstevel@tonic-gate def_shell_mode()
6077c478bd9Sstevel@tonic-gate {
6087c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
6097c478bd9Sstevel@tonic-gate 	__m_trace("def_shell_mode(void)");
6107c478bd9Sstevel@tonic-gate #endif
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	return __m_return_code(
6137c478bd9Sstevel@tonic-gate 		"def_shell_mode", __m_tty_get(&cur_term->_shell)
6147c478bd9Sstevel@tonic-gate 	);
6157c478bd9Sstevel@tonic-gate }
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate int
def_prog_mode()6187c478bd9Sstevel@tonic-gate def_prog_mode()
6197c478bd9Sstevel@tonic-gate {
6207c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
6217c478bd9Sstevel@tonic-gate 	__m_trace("def_prog_mode(void)");
6227c478bd9Sstevel@tonic-gate #endif
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	return __m_return_code("def_prog_mode", __m_tty_get(&cur_term->_prog));
6257c478bd9Sstevel@tonic-gate }
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate int
reset_shell_mode()6287c478bd9Sstevel@tonic-gate reset_shell_mode()
6297c478bd9Sstevel@tonic-gate {
6307c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
6317c478bd9Sstevel@tonic-gate 	__m_trace("reset_shell_mode(void)");
6327c478bd9Sstevel@tonic-gate #endif
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	return __m_return_code(
6357c478bd9Sstevel@tonic-gate 		"reset_shell_mode", __m_tty_set(&cur_term->_shell)
6367c478bd9Sstevel@tonic-gate 	);
6377c478bd9Sstevel@tonic-gate }
6387c478bd9Sstevel@tonic-gate 
6397c478bd9Sstevel@tonic-gate int
reset_prog_mode()6407c478bd9Sstevel@tonic-gate reset_prog_mode()
6417c478bd9Sstevel@tonic-gate {
6427c478bd9Sstevel@tonic-gate #ifdef M_CURSES_TRACE
6437c478bd9Sstevel@tonic-gate 	__m_trace("reset_prog_mode(void)");
6447c478bd9Sstevel@tonic-gate #endif
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 	return __m_return_code(
6477c478bd9Sstevel@tonic-gate 		"reset_prog_mode", __m_tty_set(&cur_term->_prog)
6487c478bd9Sstevel@tonic-gate 	);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate 
651