xref: /freebsd/contrib/ncurses/progs/tset.c (revision 0e3d540892016a47f6a68ec9ba2879d35ce5f7c2)
10e3d5408SPeter Wemm /****************************************************************************
20e3d5408SPeter Wemm  * Copyright (c) 1998 Free Software Foundation, Inc.                        *
30e3d5408SPeter Wemm  *                                                                          *
40e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
50e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
60e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
70e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
80e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
90e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
100e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
110e3d5408SPeter Wemm  *                                                                          *
120e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
130e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
140e3d5408SPeter Wemm  *                                                                          *
150e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
160e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
170e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
180e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
190e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
200e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
210e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
220e3d5408SPeter Wemm  *                                                                          *
230e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
240e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
250e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
260e3d5408SPeter Wemm  * authorization.                                                           *
270e3d5408SPeter Wemm  ****************************************************************************/
280e3d5408SPeter Wemm 
290e3d5408SPeter Wemm /****************************************************************************
300e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
310e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
320e3d5408SPeter Wemm  ****************************************************************************/
330e3d5408SPeter Wemm 
340e3d5408SPeter Wemm 
350e3d5408SPeter Wemm /*
360e3d5408SPeter Wemm  * tset.c - terminal initialization utility
370e3d5408SPeter Wemm  *
380e3d5408SPeter Wemm  * This code was mostly swiped from 4.4BSD tset, with some obsolescent
390e3d5408SPeter Wemm  * cruft removed and substantial portions rewritten.  A Regents of the
400e3d5408SPeter Wemm  * University of California copyright applies to some portions of the
410e3d5408SPeter Wemm  * code, and is reproduced below:
420e3d5408SPeter Wemm  */
430e3d5408SPeter Wemm /*-
440e3d5408SPeter Wemm  * Copyright (c) 1980, 1991, 1993
450e3d5408SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
460e3d5408SPeter Wemm  *
470e3d5408SPeter Wemm  * Redistribution and use in source and binary forms, with or without
480e3d5408SPeter Wemm  * modification, are permitted provided that the following conditions
490e3d5408SPeter Wemm  * are met:
500e3d5408SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
510e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
520e3d5408SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
530e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
540e3d5408SPeter Wemm  *    documentation and/or other materials provided with the distribution.
550e3d5408SPeter Wemm  * 3. All advertising materials mentioning features or use of this software
560e3d5408SPeter Wemm  *    must display the following acknowledgement:
570e3d5408SPeter Wemm  *	This product includes software developed by the University of
580e3d5408SPeter Wemm  *	California, Berkeley and its contributors.
590e3d5408SPeter Wemm  * 4. Neither the name of the University nor the names of its contributors
600e3d5408SPeter Wemm  *    may be used to endorse or promote products derived from this software
610e3d5408SPeter Wemm  *    without specific prior written permission.
620e3d5408SPeter Wemm  *
630e3d5408SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
640e3d5408SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
650e3d5408SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
660e3d5408SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
670e3d5408SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
680e3d5408SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
690e3d5408SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
700e3d5408SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
710e3d5408SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
720e3d5408SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
730e3d5408SPeter Wemm  * SUCH DAMAGE.
740e3d5408SPeter Wemm  */
750e3d5408SPeter Wemm 
760e3d5408SPeter Wemm #define __INTERNAL_CAPS_VISIBLE	/* we need to see has_hardware_tabs */
770e3d5408SPeter Wemm #include <progs.priv.h>
780e3d5408SPeter Wemm 
790e3d5408SPeter Wemm #include <errno.h>
800e3d5408SPeter Wemm #include <stdio.h>
810e3d5408SPeter Wemm #include <termcap.h>
820e3d5408SPeter Wemm #include <fcntl.h>
830e3d5408SPeter Wemm 
840e3d5408SPeter Wemm #if HAVE_GETTTYNAM && HAVE_TTYENT_H
850e3d5408SPeter Wemm #include <ttyent.h>
860e3d5408SPeter Wemm #endif
870e3d5408SPeter Wemm #ifdef NeXT
880e3d5408SPeter Wemm char *ttyname(int fd);
890e3d5408SPeter Wemm #endif
900e3d5408SPeter Wemm 
910e3d5408SPeter Wemm /* this is just to stifle a missing-prototype warning */
920e3d5408SPeter Wemm #ifdef linux
930e3d5408SPeter Wemm # include <sys/ioctl.h>
940e3d5408SPeter Wemm #endif
950e3d5408SPeter Wemm 
960e3d5408SPeter Wemm #if NEED_PTEM_H
970e3d5408SPeter Wemm /* they neglected to define struct winsize in termios.h -- it's only
980e3d5408SPeter Wemm    in termio.h	*/
990e3d5408SPeter Wemm #include	<sys/stream.h>
1000e3d5408SPeter Wemm #include	<sys/ptem.h>
1010e3d5408SPeter Wemm #endif
1020e3d5408SPeter Wemm 
1030e3d5408SPeter Wemm #include <curses.h>	/* for bool typedef */
1040e3d5408SPeter Wemm #include <dump_entry.h>
1050e3d5408SPeter Wemm 
1060e3d5408SPeter Wemm MODULE_ID("$Id: tset.c,v 0.37 1999/03/14 12:30:02 tom Exp $")
1070e3d5408SPeter Wemm 
1080e3d5408SPeter Wemm extern char **environ;
1090e3d5408SPeter Wemm 
1100e3d5408SPeter Wemm #undef CTRL
1110e3d5408SPeter Wemm #define CTRL(x)	((x) & 0x1f)
1120e3d5408SPeter Wemm 
1130e3d5408SPeter Wemm const char *_nc_progname = "tset";
1140e3d5408SPeter Wemm 
1150e3d5408SPeter Wemm static TTY mode, oldmode;
1160e3d5408SPeter Wemm 
1170e3d5408SPeter Wemm static int	terasechar = -1;	/* new erase character */
1180e3d5408SPeter Wemm static int	intrchar = -1;		/* new interrupt character */
1190e3d5408SPeter Wemm static int	isreset;		/* invoked as reset */
1200e3d5408SPeter Wemm static int	tkillchar = -1;		/* new kill character */
1210e3d5408SPeter Wemm static int	tlines, tcolumns;		/* window size */
1220e3d5408SPeter Wemm 
1230e3d5408SPeter Wemm #define LOWERCASE(c) ((isalpha(c) && isupper(c)) ? tolower(c) : (c))
1240e3d5408SPeter Wemm 
1250e3d5408SPeter Wemm static int
1260e3d5408SPeter Wemm CaselessCmp(const char *a, const char *b) /* strcasecmp isn't portable */
1270e3d5408SPeter Wemm {
1280e3d5408SPeter Wemm 	while (*a && *b) {
1290e3d5408SPeter Wemm 		int cmp = LOWERCASE(*a) - LOWERCASE(*b);
1300e3d5408SPeter Wemm 		if (cmp != 0)
1310e3d5408SPeter Wemm 			break;
1320e3d5408SPeter Wemm 		a++, b++;
1330e3d5408SPeter Wemm 	}
1340e3d5408SPeter Wemm 	return LOWERCASE(*a) - LOWERCASE(*b);
1350e3d5408SPeter Wemm }
1360e3d5408SPeter Wemm 
1370e3d5408SPeter Wemm #if !HAVE_STRDUP
1380e3d5408SPeter Wemm #define strdup _nc_strdup
1390e3d5408SPeter Wemm extern char *_nc_strdup(const char *);
1400e3d5408SPeter Wemm #endif /* not HAVE_STRDUP */
1410e3d5408SPeter Wemm 
1420e3d5408SPeter Wemm static void
1430e3d5408SPeter Wemm err(const char *fmt, ...)
1440e3d5408SPeter Wemm {
1450e3d5408SPeter Wemm 	va_list ap;
1460e3d5408SPeter Wemm 	va_start(ap, fmt);
1470e3d5408SPeter Wemm 	(void)fprintf(stderr, "tset: ");
1480e3d5408SPeter Wemm 	(void)vfprintf(stderr, fmt, ap);
1490e3d5408SPeter Wemm 	va_end(ap);
1500e3d5408SPeter Wemm 	(void)fprintf(stderr, "\n");
1510e3d5408SPeter Wemm 	exit(EXIT_FAILURE);
1520e3d5408SPeter Wemm 	/* NOTREACHED */
1530e3d5408SPeter Wemm }
1540e3d5408SPeter Wemm 
1550e3d5408SPeter Wemm static void
1560e3d5408SPeter Wemm failed(const char *msg)
1570e3d5408SPeter Wemm {
1580e3d5408SPeter Wemm 	char	temp[BUFSIZ];
1590e3d5408SPeter Wemm 	perror(strcat(strcpy(temp, "tset: "), msg));
1600e3d5408SPeter Wemm 	exit(EXIT_FAILURE);
1610e3d5408SPeter Wemm 	/* NOTREACHED */
1620e3d5408SPeter Wemm }
1630e3d5408SPeter Wemm 
1640e3d5408SPeter Wemm static void
1650e3d5408SPeter Wemm cat(char *file)
1660e3d5408SPeter Wemm {
1670e3d5408SPeter Wemm 	register int fd, nr, nw;
1680e3d5408SPeter Wemm 	char buf[BUFSIZ];
1690e3d5408SPeter Wemm 
1700e3d5408SPeter Wemm 	if ((fd = open(file, O_RDONLY, 0)) < 0)
1710e3d5408SPeter Wemm 		failed(file);
1720e3d5408SPeter Wemm 
1730e3d5408SPeter Wemm 	while ((nr = read(fd, buf, sizeof(buf))) > 0)
1740e3d5408SPeter Wemm 		if ((nw = write(STDERR_FILENO, buf, (size_t)nr)) == -1)
1750e3d5408SPeter Wemm 			failed("write to stderr");
1760e3d5408SPeter Wemm 	if (nr != 0)
1770e3d5408SPeter Wemm 		failed(file);
1780e3d5408SPeter Wemm 	(void)close(fd);
1790e3d5408SPeter Wemm }
1800e3d5408SPeter Wemm 
1810e3d5408SPeter Wemm static int
1820e3d5408SPeter Wemm outc(int c)
1830e3d5408SPeter Wemm {
1840e3d5408SPeter Wemm 	return putc(c, stderr);
1850e3d5408SPeter Wemm }
1860e3d5408SPeter Wemm 
1870e3d5408SPeter Wemm /* Prompt the user for a terminal type. */
1880e3d5408SPeter Wemm static const char *
1890e3d5408SPeter Wemm askuser(const char *dflt)
1900e3d5408SPeter Wemm {
1910e3d5408SPeter Wemm 	static char answer[256];
1920e3d5408SPeter Wemm 	char *p;
1930e3d5408SPeter Wemm 
1940e3d5408SPeter Wemm 	/* We can get recalled; if so, don't continue uselessly. */
1950e3d5408SPeter Wemm 	if (feof(stdin) || ferror(stdin)) {
1960e3d5408SPeter Wemm 		(void)fprintf(stderr, "\n");
1970e3d5408SPeter Wemm 		exit(EXIT_FAILURE);
1980e3d5408SPeter Wemm 	}
1990e3d5408SPeter Wemm 	for (;;) {
2000e3d5408SPeter Wemm 		if (dflt)
2010e3d5408SPeter Wemm 			(void)fprintf(stderr, "Terminal type? [%s] ", dflt);
2020e3d5408SPeter Wemm 		else
2030e3d5408SPeter Wemm 			(void)fprintf(stderr, "Terminal type? ");
2040e3d5408SPeter Wemm 		(void)fflush(stderr);
2050e3d5408SPeter Wemm 
2060e3d5408SPeter Wemm 		if (fgets(answer, sizeof(answer), stdin) == 0) {
2070e3d5408SPeter Wemm 			if (dflt == 0) {
2080e3d5408SPeter Wemm 				(void)fprintf(stderr, "\n");
2090e3d5408SPeter Wemm 				exit(EXIT_FAILURE);
2100e3d5408SPeter Wemm 			}
2110e3d5408SPeter Wemm 			return (dflt);
2120e3d5408SPeter Wemm 		}
2130e3d5408SPeter Wemm 
2140e3d5408SPeter Wemm 		if ((p = strchr(answer, '\n')) != 0)
2150e3d5408SPeter Wemm 			*p = '\0';
2160e3d5408SPeter Wemm 		if (answer[0])
2170e3d5408SPeter Wemm 			return (answer);
2180e3d5408SPeter Wemm 		if (dflt != 0)
2190e3d5408SPeter Wemm 			return (dflt);
2200e3d5408SPeter Wemm 	}
2210e3d5408SPeter Wemm }
2220e3d5408SPeter Wemm 
2230e3d5408SPeter Wemm /**************************************************************************
2240e3d5408SPeter Wemm  *
2250e3d5408SPeter Wemm  * Mapping logic begins here
2260e3d5408SPeter Wemm  *
2270e3d5408SPeter Wemm  **************************************************************************/
2280e3d5408SPeter Wemm 
2290e3d5408SPeter Wemm /* Baud rate conditionals for mapping. */
2300e3d5408SPeter Wemm #define	GT		0x01
2310e3d5408SPeter Wemm #define	EQ		0x02
2320e3d5408SPeter Wemm #define	LT		0x04
2330e3d5408SPeter Wemm #define	NOT		0x08
2340e3d5408SPeter Wemm #define	GE		(GT | EQ)
2350e3d5408SPeter Wemm #define	LE		(LT | EQ)
2360e3d5408SPeter Wemm 
2370e3d5408SPeter Wemm typedef struct map {
2380e3d5408SPeter Wemm 	struct map *next;	/* Linked list of maps. */
2390e3d5408SPeter Wemm 	const char *porttype;	/* Port type, or "" for any. */
2400e3d5408SPeter Wemm 	const char *type;	/* Terminal type to select. */
2410e3d5408SPeter Wemm 	int conditional;	/* Baud rate conditionals bitmask. */
2420e3d5408SPeter Wemm 	speed_t speed;		/* Baud rate to compare against. */
2430e3d5408SPeter Wemm } MAP;
2440e3d5408SPeter Wemm 
2450e3d5408SPeter Wemm static MAP *cur, *maplist;
2460e3d5408SPeter Wemm 
2470e3d5408SPeter Wemm typedef struct speeds {
2480e3d5408SPeter Wemm 	const char *string;
2490e3d5408SPeter Wemm 	int	speed;
2500e3d5408SPeter Wemm } SPEEDS;
2510e3d5408SPeter Wemm 
2520e3d5408SPeter Wemm static const SPEEDS speeds[] = {
2530e3d5408SPeter Wemm 	{ "0",		B0 },
2540e3d5408SPeter Wemm 	{ "50",		B50 },
2550e3d5408SPeter Wemm 	{ "75",		B75 },
2560e3d5408SPeter Wemm 	{ "110",	B110 },
2570e3d5408SPeter Wemm 	{ "134",	B134 },
2580e3d5408SPeter Wemm 	{ "134.5",	B134 },
2590e3d5408SPeter Wemm 	{ "150",	B150 },
2600e3d5408SPeter Wemm 	{ "200",	B200 },
2610e3d5408SPeter Wemm 	{ "300",	B300 },
2620e3d5408SPeter Wemm 	{ "600",	B600 },
2630e3d5408SPeter Wemm 	{ "1200",	B1200 },
2640e3d5408SPeter Wemm 	{ "1800",	B1800 },
2650e3d5408SPeter Wemm 	{ "2400",	B2400 },
2660e3d5408SPeter Wemm 	{ "4800",	B4800 },
2670e3d5408SPeter Wemm 	{ "9600",	B9600 },
2680e3d5408SPeter Wemm 	{ "19200",	B19200 },
2690e3d5408SPeter Wemm 	{ "38400",	B38400 },
2700e3d5408SPeter Wemm 	{ "19200",	B19200 },
2710e3d5408SPeter Wemm 	{ "38400",	B38400 },
2720e3d5408SPeter Wemm #ifdef B19200
2730e3d5408SPeter Wemm 	{ "19200",	B19200 },
2740e3d5408SPeter Wemm #else
2750e3d5408SPeter Wemm #ifdef EXTA
2760e3d5408SPeter Wemm 	{ "19200",	EXTA },
2770e3d5408SPeter Wemm #endif
2780e3d5408SPeter Wemm #endif
2790e3d5408SPeter Wemm #ifdef B38400
2800e3d5408SPeter Wemm 	{ "38400",	B38400 },
2810e3d5408SPeter Wemm #else
2820e3d5408SPeter Wemm #ifdef EXTB
2830e3d5408SPeter Wemm 	{ "38400",	EXTB },
2840e3d5408SPeter Wemm #endif
2850e3d5408SPeter Wemm #endif
2860e3d5408SPeter Wemm #ifdef B57600
2870e3d5408SPeter Wemm 	{ "57600",	B57600 },
2880e3d5408SPeter Wemm #endif
2890e3d5408SPeter Wemm #ifdef B115200
2900e3d5408SPeter Wemm 	{ "115200",	B115200 },
2910e3d5408SPeter Wemm #endif
2920e3d5408SPeter Wemm #ifdef B230400
2930e3d5408SPeter Wemm 	{ "230400",	B230400 },
2940e3d5408SPeter Wemm #endif
2950e3d5408SPeter Wemm #ifdef B460800
2960e3d5408SPeter Wemm 	{ "460800",	B460800 },
2970e3d5408SPeter Wemm #endif
2980e3d5408SPeter Wemm 	{ (char *)0,    0 }
2990e3d5408SPeter Wemm };
3000e3d5408SPeter Wemm 
3010e3d5408SPeter Wemm static int
3020e3d5408SPeter Wemm tbaudrate(char *rate)
3030e3d5408SPeter Wemm {
3040e3d5408SPeter Wemm 	const SPEEDS *sp;
3050e3d5408SPeter Wemm 	int found = FALSE;
3060e3d5408SPeter Wemm 
3070e3d5408SPeter Wemm 	/* The baudrate number can be preceded by a 'B', which is ignored. */
3080e3d5408SPeter Wemm 	if (*rate == 'B')
3090e3d5408SPeter Wemm 		++rate;
3100e3d5408SPeter Wemm 
3110e3d5408SPeter Wemm 	for (sp = speeds; sp->string; ++sp) {
3120e3d5408SPeter Wemm 		if (!CaselessCmp(rate, sp->string)) {
3130e3d5408SPeter Wemm 			found = TRUE;
3140e3d5408SPeter Wemm 			break;
3150e3d5408SPeter Wemm 		}
3160e3d5408SPeter Wemm 	}
3170e3d5408SPeter Wemm 	if (!found)
3180e3d5408SPeter Wemm 		err("unknown baud rate %s", rate);
3190e3d5408SPeter Wemm 	return (sp->speed);
3200e3d5408SPeter Wemm }
3210e3d5408SPeter Wemm 
3220e3d5408SPeter Wemm /*
3230e3d5408SPeter Wemm  * Syntax for -m:
3240e3d5408SPeter Wemm  * [port-type][test baudrate]:terminal-type
3250e3d5408SPeter Wemm  * The baud rate tests are: >, <, @, =, !
3260e3d5408SPeter Wemm  */
3270e3d5408SPeter Wemm static void
3280e3d5408SPeter Wemm add_mapping(const char *port, char *arg)
3290e3d5408SPeter Wemm {
3300e3d5408SPeter Wemm 	MAP *mapp;
3310e3d5408SPeter Wemm 	char *copy, *p;
3320e3d5408SPeter Wemm 	const char *termp;
3330e3d5408SPeter Wemm 	char *base = 0;
3340e3d5408SPeter Wemm 
3350e3d5408SPeter Wemm 	copy = strdup(arg);
3360e3d5408SPeter Wemm 	mapp = malloc(sizeof(MAP));
3370e3d5408SPeter Wemm 	if (copy == 0 || mapp == 0)
3380e3d5408SPeter Wemm 		failed("malloc");
3390e3d5408SPeter Wemm 	mapp->next = 0;
3400e3d5408SPeter Wemm 	if (maplist == 0)
3410e3d5408SPeter Wemm 		cur = maplist = mapp;
3420e3d5408SPeter Wemm 	else {
3430e3d5408SPeter Wemm 		cur->next = mapp;
3440e3d5408SPeter Wemm 		cur =  mapp;
3450e3d5408SPeter Wemm 	}
3460e3d5408SPeter Wemm 
3470e3d5408SPeter Wemm 	mapp->porttype = arg;
3480e3d5408SPeter Wemm 	mapp->conditional = 0;
3490e3d5408SPeter Wemm 
3500e3d5408SPeter Wemm 	arg = strpbrk(arg, "><@=!:");
3510e3d5408SPeter Wemm 
3520e3d5408SPeter Wemm 	if (arg == 0) {			/* [?]term */
3530e3d5408SPeter Wemm 		mapp->type = mapp->porttype;
3540e3d5408SPeter Wemm 		mapp->porttype = 0;
3550e3d5408SPeter Wemm 		goto done;
3560e3d5408SPeter Wemm 	}
3570e3d5408SPeter Wemm 
3580e3d5408SPeter Wemm 	if (arg == mapp->porttype)		/* [><@=! baud]:term */
3590e3d5408SPeter Wemm 		termp = mapp->porttype = 0;
3600e3d5408SPeter Wemm 	else
3610e3d5408SPeter Wemm 		termp = base = arg;
3620e3d5408SPeter Wemm 
3630e3d5408SPeter Wemm 	for (;; ++arg)				/* Optional conditionals. */
3640e3d5408SPeter Wemm 		switch(*arg) {
3650e3d5408SPeter Wemm 		case '<':
3660e3d5408SPeter Wemm 			if (mapp->conditional & GT)
3670e3d5408SPeter Wemm 				goto badmopt;
3680e3d5408SPeter Wemm 			mapp->conditional |= LT;
3690e3d5408SPeter Wemm 			break;
3700e3d5408SPeter Wemm 		case '>':
3710e3d5408SPeter Wemm 			if (mapp->conditional & LT)
3720e3d5408SPeter Wemm 				goto badmopt;
3730e3d5408SPeter Wemm 			mapp->conditional |= GT;
3740e3d5408SPeter Wemm 			break;
3750e3d5408SPeter Wemm 		case '@':
3760e3d5408SPeter Wemm 		case '=':			/* Not documented. */
3770e3d5408SPeter Wemm 			mapp->conditional |= EQ;
3780e3d5408SPeter Wemm 			break;
3790e3d5408SPeter Wemm 		case '!':
3800e3d5408SPeter Wemm 			mapp->conditional |= NOT;
3810e3d5408SPeter Wemm 			break;
3820e3d5408SPeter Wemm 		default:
3830e3d5408SPeter Wemm 			goto next;
3840e3d5408SPeter Wemm 		}
3850e3d5408SPeter Wemm 
3860e3d5408SPeter Wemm next:	if (*arg == ':') {
3870e3d5408SPeter Wemm 		if (mapp->conditional)
3880e3d5408SPeter Wemm 			goto badmopt;
3890e3d5408SPeter Wemm 		++arg;
3900e3d5408SPeter Wemm 	} else {				/* Optional baudrate. */
3910e3d5408SPeter Wemm 		arg = strchr(p = arg, ':');
3920e3d5408SPeter Wemm 		if (arg == 0)
3930e3d5408SPeter Wemm 			goto badmopt;
3940e3d5408SPeter Wemm 		*arg++ = '\0';
3950e3d5408SPeter Wemm 		mapp->speed = tbaudrate(p);
3960e3d5408SPeter Wemm 	}
3970e3d5408SPeter Wemm 
3980e3d5408SPeter Wemm 	if (arg == (char *)0)		/* Non-optional type. */
3990e3d5408SPeter Wemm 		goto badmopt;
4000e3d5408SPeter Wemm 
4010e3d5408SPeter Wemm 	mapp->type = arg;
4020e3d5408SPeter Wemm 
4030e3d5408SPeter Wemm 	/* Terminate porttype, if specified. */
4040e3d5408SPeter Wemm 	if (termp != 0)
4050e3d5408SPeter Wemm 		*base = '\0';
4060e3d5408SPeter Wemm 
4070e3d5408SPeter Wemm 	/* If a NOT conditional, reverse the test. */
4080e3d5408SPeter Wemm 	if (mapp->conditional & NOT)
4090e3d5408SPeter Wemm 		mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
4100e3d5408SPeter Wemm 
4110e3d5408SPeter Wemm 	/* If user specified a port with an option flag, set it. */
4120e3d5408SPeter Wemm done:	if (port) {
4130e3d5408SPeter Wemm 		if (mapp->porttype)
4140e3d5408SPeter Wemm badmopt:		err("illegal -m option format: %s", copy);
4150e3d5408SPeter Wemm 		mapp->porttype = port;
4160e3d5408SPeter Wemm 	}
4170e3d5408SPeter Wemm 
4180e3d5408SPeter Wemm #ifdef MAPDEBUG
4190e3d5408SPeter Wemm 	(void)printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
4200e3d5408SPeter Wemm 	(void)printf("type: %s\n", mapp->type);
4210e3d5408SPeter Wemm 	(void)printf("conditional: ");
4220e3d5408SPeter Wemm 	p = "";
4230e3d5408SPeter Wemm 	if (mapp->conditional & GT) {
4240e3d5408SPeter Wemm 		(void)printf("GT");
4250e3d5408SPeter Wemm 		p = "/";
4260e3d5408SPeter Wemm 	}
4270e3d5408SPeter Wemm 	if (mapp->conditional & EQ) {
4280e3d5408SPeter Wemm 		(void)printf("%sEQ", p);
4290e3d5408SPeter Wemm 		p = "/";
4300e3d5408SPeter Wemm 	}
4310e3d5408SPeter Wemm 	if (mapp->conditional & LT)
4320e3d5408SPeter Wemm 		(void)printf("%sLT", p);
4330e3d5408SPeter Wemm 	(void)printf("\nspeed: %d\n", mapp->speed);
4340e3d5408SPeter Wemm #endif
4350e3d5408SPeter Wemm }
4360e3d5408SPeter Wemm 
4370e3d5408SPeter Wemm /*
4380e3d5408SPeter Wemm  * Return the type of terminal to use for a port of type 'type', as specified
4390e3d5408SPeter Wemm  * by the first applicable mapping in 'map'.  If no mappings apply, return
4400e3d5408SPeter Wemm  * 'type'.
4410e3d5408SPeter Wemm  */
4420e3d5408SPeter Wemm static const char *
4430e3d5408SPeter Wemm mapped(const char *type)
4440e3d5408SPeter Wemm {
4450e3d5408SPeter Wemm 	MAP *mapp;
4460e3d5408SPeter Wemm 	int match;
4470e3d5408SPeter Wemm 
4480e3d5408SPeter Wemm 	for (mapp = maplist; mapp; mapp = mapp->next)
4490e3d5408SPeter Wemm 		if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
4500e3d5408SPeter Wemm 			switch (mapp->conditional) {
4510e3d5408SPeter Wemm 			case 0:			/* No test specified. */
4520e3d5408SPeter Wemm 				match = TRUE;
4530e3d5408SPeter Wemm 				break;
4540e3d5408SPeter Wemm 			case EQ:
4550e3d5408SPeter Wemm 				match = (ospeed == mapp->speed);
4560e3d5408SPeter Wemm 				break;
4570e3d5408SPeter Wemm 			case GE:
4580e3d5408SPeter Wemm 				match = (ospeed >= mapp->speed);
4590e3d5408SPeter Wemm 				break;
4600e3d5408SPeter Wemm 			case GT:
4610e3d5408SPeter Wemm 				match = (ospeed > mapp->speed);
4620e3d5408SPeter Wemm 				break;
4630e3d5408SPeter Wemm 			case LE:
4640e3d5408SPeter Wemm 				match = (ospeed <= mapp->speed);
4650e3d5408SPeter Wemm 				break;
4660e3d5408SPeter Wemm 			case LT:
4670e3d5408SPeter Wemm 				match = (ospeed < mapp->speed);
4680e3d5408SPeter Wemm 				break;
4690e3d5408SPeter Wemm 			default:
4700e3d5408SPeter Wemm 				match = FALSE;
4710e3d5408SPeter Wemm 			}
4720e3d5408SPeter Wemm 			if (match)
4730e3d5408SPeter Wemm 				return (mapp->type);
4740e3d5408SPeter Wemm 		}
4750e3d5408SPeter Wemm 	/* No match found; return given type. */
4760e3d5408SPeter Wemm 	return (type);
4770e3d5408SPeter Wemm }
4780e3d5408SPeter Wemm 
4790e3d5408SPeter Wemm /**************************************************************************
4800e3d5408SPeter Wemm  *
4810e3d5408SPeter Wemm  * Entry fetching
4820e3d5408SPeter Wemm  *
4830e3d5408SPeter Wemm  **************************************************************************/
4840e3d5408SPeter Wemm 
4850e3d5408SPeter Wemm /*
4860e3d5408SPeter Wemm  * Figure out what kind of terminal we're dealing with, and then read in
4870e3d5408SPeter Wemm  * its termcap entry.
4880e3d5408SPeter Wemm  */
4890e3d5408SPeter Wemm static const char *
4900e3d5408SPeter Wemm get_termcap_entry(char *userarg)
4910e3d5408SPeter Wemm {
4920e3d5408SPeter Wemm 	int rval, errret;
4930e3d5408SPeter Wemm 	char *p;
4940e3d5408SPeter Wemm 	const char *ttype;
4950e3d5408SPeter Wemm #if HAVE_GETTTYNAM
4960e3d5408SPeter Wemm 	struct ttyent *t;
4970e3d5408SPeter Wemm #else
4980e3d5408SPeter Wemm 	FILE *fp;
4990e3d5408SPeter Wemm #endif
5000e3d5408SPeter Wemm 	char *ttypath;
5010e3d5408SPeter Wemm 
5020e3d5408SPeter Wemm 	if (userarg) {
5030e3d5408SPeter Wemm 		ttype = userarg;
5040e3d5408SPeter Wemm 		goto found;
5050e3d5408SPeter Wemm 	}
5060e3d5408SPeter Wemm 
5070e3d5408SPeter Wemm 	/* Try the environment. */
5080e3d5408SPeter Wemm 	if ((ttype = getenv("TERM")) != 0)
5090e3d5408SPeter Wemm 		goto map;
5100e3d5408SPeter Wemm 
5110e3d5408SPeter Wemm 	if ((ttypath = ttyname(STDERR_FILENO)) != 0) {
5120e3d5408SPeter Wemm 		if ((p = strrchr(ttypath, '/')) != 0)
5130e3d5408SPeter Wemm 			++p;
5140e3d5408SPeter Wemm 		else
5150e3d5408SPeter Wemm 			p = ttypath;
5160e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5170e3d5408SPeter Wemm 		/*
5180e3d5408SPeter Wemm 		 * We have the 4.3BSD library call getttynam(3); that means
5190e3d5408SPeter Wemm 		 * there's an /etc/ttys to look up device-to-type mappings in.
5200e3d5408SPeter Wemm 		 * Try ttyname(3); check for dialup or other mapping.
5210e3d5408SPeter Wemm 		 */
5220e3d5408SPeter Wemm 		if ((t = getttynam(p))) {
5230e3d5408SPeter Wemm 			ttype = t->ty_type;
5240e3d5408SPeter Wemm 			goto map;
5250e3d5408SPeter Wemm 		}
5260e3d5408SPeter Wemm #else
5270e3d5408SPeter Wemm 		if ((fp = fopen("/etc/ttytype", "r")) != 0
5280e3d5408SPeter Wemm 		 || (fp = fopen("/etc/ttys", "r")) != 0) {
5290e3d5408SPeter Wemm 			char buffer[BUFSIZ];
5300e3d5408SPeter Wemm 			char *s, *t, *d;
5310e3d5408SPeter Wemm 
5320e3d5408SPeter Wemm 			while (fgets(buffer, sizeof(buffer)-1, fp) != 0) {
5330e3d5408SPeter Wemm 				for (s = buffer, t = d = 0; *s; s++) {
5340e3d5408SPeter Wemm 					if (isspace(*s))
5350e3d5408SPeter Wemm 						*s = '\0';
5360e3d5408SPeter Wemm 					else if (t == 0)
5370e3d5408SPeter Wemm 						t = s;
5380e3d5408SPeter Wemm 					else if (d == 0 && s != buffer && s[-1] == '\0')
5390e3d5408SPeter Wemm 						d = s;
5400e3d5408SPeter Wemm 				}
5410e3d5408SPeter Wemm 				if (t != 0 && d != 0 && !strcmp(d,p)) {
5420e3d5408SPeter Wemm 					ttype = strdup(t);
5430e3d5408SPeter Wemm 					fclose(fp);
5440e3d5408SPeter Wemm 					goto map;
5450e3d5408SPeter Wemm 				}
5460e3d5408SPeter Wemm 			}
5470e3d5408SPeter Wemm 			fclose(fp);
5480e3d5408SPeter Wemm 		}
5490e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */
5500e3d5408SPeter Wemm 	}
5510e3d5408SPeter Wemm 
5520e3d5408SPeter Wemm 	/* If still undefined, use "unknown". */
5530e3d5408SPeter Wemm 	ttype = "unknown";
5540e3d5408SPeter Wemm 
5550e3d5408SPeter Wemm map:	ttype = mapped(ttype);
5560e3d5408SPeter Wemm 
5570e3d5408SPeter Wemm 	/*
5580e3d5408SPeter Wemm 	 * If not a path, remove TERMCAP from the environment so we get a
5590e3d5408SPeter Wemm 	 * real entry from /etc/termcap.  This prevents us from being fooled
5600e3d5408SPeter Wemm 	 * by out of date stuff in the environment.
5610e3d5408SPeter Wemm 	 */
5620e3d5408SPeter Wemm found:	if ((p = getenv("TERMCAP")) != 0 && *p != '/') {
5630e3d5408SPeter Wemm 		/* 'unsetenv("TERMCAP")' is not portable.
5640e3d5408SPeter Wemm 		 * The 'environ' array is better.
5650e3d5408SPeter Wemm 		 */
5660e3d5408SPeter Wemm 		int n;
5670e3d5408SPeter Wemm 		for (n = 0; environ[n] != 0; n++) {
5680e3d5408SPeter Wemm 			if (!strncmp("TERMCAP=", environ[n], 8)) {
5690e3d5408SPeter Wemm 				while ((environ[n] = environ[n+1]) != 0) {
5700e3d5408SPeter Wemm 					n++;
5710e3d5408SPeter Wemm 				}
5720e3d5408SPeter Wemm 				break;
5730e3d5408SPeter Wemm 			}
5740e3d5408SPeter Wemm 		}
5750e3d5408SPeter Wemm 	}
5760e3d5408SPeter Wemm 
5770e3d5408SPeter Wemm 	/*
5780e3d5408SPeter Wemm 	 * ttype now contains a pointer to the type of the terminal.
5790e3d5408SPeter Wemm 	 * If the first character is '?', ask the user.
5800e3d5408SPeter Wemm 	 */
5810e3d5408SPeter Wemm 	if (ttype[0] == '?') {
5820e3d5408SPeter Wemm 		if (ttype[1] != '\0')
5830e3d5408SPeter Wemm 			ttype = askuser(ttype + 1);
5840e3d5408SPeter Wemm 		else
5850e3d5408SPeter Wemm 			ttype = askuser(0);
5860e3d5408SPeter Wemm 	}
5870e3d5408SPeter Wemm 	/* Find the terminfo entry.  If it doesn't exist, ask the user. */
5880e3d5408SPeter Wemm 	while ((rval = setupterm((NCURSES_CONST char *)ttype, STDOUT_FILENO, &errret)) != OK) {
5890e3d5408SPeter Wemm 		if (errret == 0) {
5900e3d5408SPeter Wemm 			(void)fprintf(stderr, "tset: unknown terminal type %s\n",
5910e3d5408SPeter Wemm 			    ttype);
5920e3d5408SPeter Wemm 			ttype = 0;
5930e3d5408SPeter Wemm 		}
5940e3d5408SPeter Wemm 		else {
5950e3d5408SPeter Wemm 			(void)fprintf(stderr, "tset: can't initialize terminal type %s (error %d)\n", ttype, errret);
5960e3d5408SPeter Wemm 			ttype = 0;
5970e3d5408SPeter Wemm 		}
5980e3d5408SPeter Wemm 		ttype = askuser(ttype);
5990e3d5408SPeter Wemm 	}
6000e3d5408SPeter Wemm #if BROKEN_LINKER
6010e3d5408SPeter Wemm 	tgetflag("am");	/* force lib_termcap.o to be linked for 'ospeed' */
6020e3d5408SPeter Wemm #endif
6030e3d5408SPeter Wemm 	return (ttype);
6040e3d5408SPeter Wemm }
6050e3d5408SPeter Wemm 
6060e3d5408SPeter Wemm /**************************************************************************
6070e3d5408SPeter Wemm  *
6080e3d5408SPeter Wemm  * Mode-setting logic
6090e3d5408SPeter Wemm  *
6100e3d5408SPeter Wemm  **************************************************************************/
6110e3d5408SPeter Wemm 
6120e3d5408SPeter Wemm /* some BSD systems have these built in, some systems are missing
6130e3d5408SPeter Wemm  * one or more definitions. The safest solution is to override.
6140e3d5408SPeter Wemm  */
6150e3d5408SPeter Wemm #undef CEOF
6160e3d5408SPeter Wemm #undef CERASE
6170e3d5408SPeter Wemm #undef CINTR
6180e3d5408SPeter Wemm #undef CKILL
6190e3d5408SPeter Wemm #undef CLNEXT
6200e3d5408SPeter Wemm #undef CRPRNT
6210e3d5408SPeter Wemm #undef CQUIT
6220e3d5408SPeter Wemm #undef CSTART
6230e3d5408SPeter Wemm #undef CSTOP
6240e3d5408SPeter Wemm #undef CSUSP
6250e3d5408SPeter Wemm 
6260e3d5408SPeter Wemm /* control-character defaults */
6270e3d5408SPeter Wemm #define CEOF	CTRL('D')
6280e3d5408SPeter Wemm #define CERASE	CTRL('H')
6290e3d5408SPeter Wemm #define CINTR	127		/* ^? */
6300e3d5408SPeter Wemm #define CKILL	CTRL('U')
6310e3d5408SPeter Wemm #define CLNEXT  CTRL('v')
6320e3d5408SPeter Wemm #define CRPRNT  CTRL('r')
6330e3d5408SPeter Wemm #define CQUIT	CTRL('\\')
6340e3d5408SPeter Wemm #define CSTART	CTRL('Q')
6350e3d5408SPeter Wemm #define CSTOP	CTRL('S')
6360e3d5408SPeter Wemm #define CSUSP	CTRL('Z')
6370e3d5408SPeter Wemm 
6380e3d5408SPeter Wemm #define	CHK(val, dft)	((int)val <= 0 ? dft : val)
6390e3d5408SPeter Wemm 
6400e3d5408SPeter Wemm static bool	set_tabs (void);
6410e3d5408SPeter Wemm 
6420e3d5408SPeter Wemm /*
6430e3d5408SPeter Wemm  * Reset the terminal mode bits to a sensible state.  Very useful after
6440e3d5408SPeter Wemm  * a child program dies in raw mode.
6450e3d5408SPeter Wemm  */
6460e3d5408SPeter Wemm static void
6470e3d5408SPeter Wemm reset_mode(void)
6480e3d5408SPeter Wemm {
6490e3d5408SPeter Wemm #ifdef TERMIOS
6500e3d5408SPeter Wemm 	tcgetattr(STDERR_FILENO, &mode);
6510e3d5408SPeter Wemm #else
6520e3d5408SPeter Wemm 	stty(STDERR_FILENO,&mode);
6530e3d5408SPeter Wemm #endif
6540e3d5408SPeter Wemm 
6550e3d5408SPeter Wemm #ifdef TERMIOS
6560e3d5408SPeter Wemm #if defined(VDISCARD) && defined(CDISCARD)
6570e3d5408SPeter Wemm 	mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD);
6580e3d5408SPeter Wemm #endif
6590e3d5408SPeter Wemm 	mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF);
6600e3d5408SPeter Wemm 	mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE);
6610e3d5408SPeter Wemm #if defined(VFLUSH) && defined(CFLUSH)
6620e3d5408SPeter Wemm 	mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH);
6630e3d5408SPeter Wemm #endif
6640e3d5408SPeter Wemm 	mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR);
6650e3d5408SPeter Wemm 	mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL);
6660e3d5408SPeter Wemm #if defined(VLNEXT) && defined(CLNEXT)
6670e3d5408SPeter Wemm 	mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT);
6680e3d5408SPeter Wemm #endif
6690e3d5408SPeter Wemm 	mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT);
6700e3d5408SPeter Wemm #if defined(VREPRINT) && defined(CRPRNT)
6710e3d5408SPeter Wemm 	mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT);
6720e3d5408SPeter Wemm #endif
6730e3d5408SPeter Wemm #if defined(VSTART) && defined(CSTART)
6740e3d5408SPeter Wemm 	mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART);
6750e3d5408SPeter Wemm #endif
6760e3d5408SPeter Wemm #if defined(VSTOP) && defined(CSTOP)
6770e3d5408SPeter Wemm 	mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP);
6780e3d5408SPeter Wemm #endif
6790e3d5408SPeter Wemm #if defined(VSUSP) && defined(CSUSP)
6800e3d5408SPeter Wemm 	mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP);
6810e3d5408SPeter Wemm #endif
6820e3d5408SPeter Wemm #if defined(VWERASE) && defined(CWERASE)
6830e3d5408SPeter Wemm 	mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE);
6840e3d5408SPeter Wemm #endif
6850e3d5408SPeter Wemm 
6860e3d5408SPeter Wemm 	mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR
6870e3d5408SPeter Wemm #ifdef IUCLC
6880e3d5408SPeter Wemm 			  | IUCLC
6890e3d5408SPeter Wemm #endif
6900e3d5408SPeter Wemm #ifdef IXANY
6910e3d5408SPeter Wemm 			  | IXANY
6920e3d5408SPeter Wemm #endif
6930e3d5408SPeter Wemm 			  | IXOFF);
6940e3d5408SPeter Wemm 
6950e3d5408SPeter Wemm 	mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON
6960e3d5408SPeter Wemm #ifdef IMAXBEL
6970e3d5408SPeter Wemm 			 | IMAXBEL
6980e3d5408SPeter Wemm #endif
6990e3d5408SPeter Wemm 			 );
7000e3d5408SPeter Wemm 
7010e3d5408SPeter Wemm 	mode.c_oflag &= ~(0
7020e3d5408SPeter Wemm #ifdef OLCUC
7030e3d5408SPeter Wemm 			  | OLCUC
7040e3d5408SPeter Wemm #endif
7050e3d5408SPeter Wemm #ifdef OCRNL
7060e3d5408SPeter Wemm 			  | OCRNL
7070e3d5408SPeter Wemm #endif
7080e3d5408SPeter Wemm #ifdef ONOCR
7090e3d5408SPeter Wemm 			  | ONOCR
7100e3d5408SPeter Wemm #endif
7110e3d5408SPeter Wemm #ifdef ONLRET
7120e3d5408SPeter Wemm 			  | ONLRET
7130e3d5408SPeter Wemm #endif
7140e3d5408SPeter Wemm #ifdef OFILL
7150e3d5408SPeter Wemm 			  | OFILL
7160e3d5408SPeter Wemm #endif
7170e3d5408SPeter Wemm #ifdef OFDEL
7180e3d5408SPeter Wemm 			  | OFDEL
7190e3d5408SPeter Wemm #endif
7200e3d5408SPeter Wemm #ifdef NLDLY
7210e3d5408SPeter Wemm 			  | NLDLY | CRDLY | TABDLY | BSDLY | VTDLY | FFDLY
7220e3d5408SPeter Wemm #endif
7230e3d5408SPeter Wemm 			  );
7240e3d5408SPeter Wemm 
7250e3d5408SPeter Wemm 	mode.c_oflag |= (OPOST
7260e3d5408SPeter Wemm #ifdef ONLCR
7270e3d5408SPeter Wemm 			 | ONLCR
7280e3d5408SPeter Wemm #endif
7290e3d5408SPeter Wemm 			 );
7300e3d5408SPeter Wemm 
7310e3d5408SPeter Wemm 	mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL);
7320e3d5408SPeter Wemm 	mode.c_cflag |= (CS8 | CREAD);
7330e3d5408SPeter Wemm 	mode.c_lflag &= ~(ECHONL | NOFLSH
7340e3d5408SPeter Wemm #ifdef TOSTOP
7350e3d5408SPeter Wemm 			  | TOSTOP
7360e3d5408SPeter Wemm #endif
7370e3d5408SPeter Wemm #ifdef ECHOPTR
7380e3d5408SPeter Wemm 			  | ECHOPRT
7390e3d5408SPeter Wemm #endif
7400e3d5408SPeter Wemm #ifdef XCASE
7410e3d5408SPeter Wemm 			  | XCASE
7420e3d5408SPeter Wemm #endif
7430e3d5408SPeter Wemm 			  );
7440e3d5408SPeter Wemm 
7450e3d5408SPeter Wemm 	mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK
7460e3d5408SPeter Wemm #ifdef ECHOCTL
7470e3d5408SPeter Wemm 			 | ECHOCTL
7480e3d5408SPeter Wemm #endif
7490e3d5408SPeter Wemm #ifdef ECHOKE
7500e3d5408SPeter Wemm 			 | ECHOKE
7510e3d5408SPeter Wemm #endif
7520e3d5408SPeter Wemm  			 );
7530e3d5408SPeter Wemm #endif
7540e3d5408SPeter Wemm 
7550e3d5408SPeter Wemm #ifdef TERMIOS
7560e3d5408SPeter Wemm 	tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
7570e3d5408SPeter Wemm #else
7580e3d5408SPeter Wemm 	stty(STDERR_FILENO, &mode);
7590e3d5408SPeter Wemm #endif
7600e3d5408SPeter Wemm }
7610e3d5408SPeter Wemm 
7620e3d5408SPeter Wemm /*
7630e3d5408SPeter Wemm  * Returns a "good" value for the erase character.  This is loosely based on
7640e3d5408SPeter Wemm  * the BSD4.4 logic.
7650e3d5408SPeter Wemm  */
7660e3d5408SPeter Wemm static int
7670e3d5408SPeter Wemm default_erase(void)
7680e3d5408SPeter Wemm {
7690e3d5408SPeter Wemm 	int result;
7700e3d5408SPeter Wemm 
7710e3d5408SPeter Wemm 	if (over_strike
7720e3d5408SPeter Wemm 	 && key_backspace != 0
7730e3d5408SPeter Wemm 	 && strlen(key_backspace) == 1)
7740e3d5408SPeter Wemm 		result = key_backspace[0];
7750e3d5408SPeter Wemm 	else
7760e3d5408SPeter Wemm 		result = CERASE;
7770e3d5408SPeter Wemm 
7780e3d5408SPeter Wemm 	return result;
7790e3d5408SPeter Wemm }
7800e3d5408SPeter Wemm 
7810e3d5408SPeter Wemm /*
7820e3d5408SPeter Wemm  * Update the values of the erase, interrupt, and kill characters in 'mode'.
7830e3d5408SPeter Wemm  *
7840e3d5408SPeter Wemm  * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase
7850e3d5408SPeter Wemm  * characters if they're unset, or if we specify them as options.  This differs
7860e3d5408SPeter Wemm  * from BSD 4.4 tset, which always sets erase.
7870e3d5408SPeter Wemm  */
7880e3d5408SPeter Wemm static void
7890e3d5408SPeter Wemm set_control_chars(void)
7900e3d5408SPeter Wemm {
7910e3d5408SPeter Wemm #ifdef TERMIOS
7920e3d5408SPeter Wemm 	if (mode.c_cc[VERASE] == 0 || terasechar >= 0)
7930e3d5408SPeter Wemm 		mode.c_cc[VERASE] = terasechar >= 0 ? terasechar : default_erase();
7940e3d5408SPeter Wemm 
7950e3d5408SPeter Wemm 	if (mode.c_cc[VINTR] == 0 || intrchar >= 0)
7960e3d5408SPeter Wemm 		 mode.c_cc[VINTR] = intrchar >= 0 ? intrchar : CINTR;
7970e3d5408SPeter Wemm 
7980e3d5408SPeter Wemm 	if (mode.c_cc[VKILL] == 0 || tkillchar >= 0)
7990e3d5408SPeter Wemm 		mode.c_cc[VKILL] = tkillchar >= 0 ? tkillchar : CKILL;
8000e3d5408SPeter Wemm #endif
8010e3d5408SPeter Wemm }
8020e3d5408SPeter Wemm 
8030e3d5408SPeter Wemm /*
8040e3d5408SPeter Wemm  * Set up various conversions in 'mode', including parity, tabs, returns,
8050e3d5408SPeter Wemm  * echo, and case, according to the termcap entry.  If the program we're
8060e3d5408SPeter Wemm  * running was named with a leading upper-case character, map external
8070e3d5408SPeter Wemm  * uppercase to internal lowercase.
8080e3d5408SPeter Wemm  */
8090e3d5408SPeter Wemm static void
8100e3d5408SPeter Wemm set_conversions(void)
8110e3d5408SPeter Wemm {
8120e3d5408SPeter Wemm #ifdef __OBSOLETE__
8130e3d5408SPeter Wemm 	/*
8140e3d5408SPeter Wemm 	 * Conversion logic for some *really* ancient terminal glitches,
8150e3d5408SPeter Wemm 	 * not supported in terminfo.  Left here for succeeding generations
8160e3d5408SPeter Wemm 	 * to marvel at.
8170e3d5408SPeter Wemm 	 */
8180e3d5408SPeter Wemm 	if (tgetflag("UC")) {
8190e3d5408SPeter Wemm #ifdef IUCLC
8200e3d5408SPeter Wemm 		mode.c_iflag |= IUCLC;
8210e3d5408SPeter Wemm 		mode.c_oflag |= OLCUC;
8220e3d5408SPeter Wemm #endif
8230e3d5408SPeter Wemm 	} else if (tgetflag("LC")) {
8240e3d5408SPeter Wemm #ifdef IUCLC
8250e3d5408SPeter Wemm 		mode.c_iflag &= ~IUCLC;
8260e3d5408SPeter Wemm 		mode.c_oflag &= ~OLCUC;
8270e3d5408SPeter Wemm #endif
8280e3d5408SPeter Wemm 	}
8290e3d5408SPeter Wemm 	mode.c_iflag &= ~(PARMRK | INPCK);
8300e3d5408SPeter Wemm 	mode.c_lflag |= ICANON;
8310e3d5408SPeter Wemm 	if (tgetflag("EP")) {
8320e3d5408SPeter Wemm 		mode.c_cflag |= PARENB;
8330e3d5408SPeter Wemm 		mode.c_cflag &= ~PARODD;
8340e3d5408SPeter Wemm 	}
8350e3d5408SPeter Wemm 	if (tgetflag("OP")) {
8360e3d5408SPeter Wemm 		mode.c_cflag |= PARENB;
8370e3d5408SPeter Wemm 		mode.c_cflag |= PARODD;
8380e3d5408SPeter Wemm 	}
8390e3d5408SPeter Wemm #endif /* __OBSOLETE__ */
8400e3d5408SPeter Wemm 
8410e3d5408SPeter Wemm #ifdef TERMIOS
8420e3d5408SPeter Wemm #ifdef ONLCR
8430e3d5408SPeter Wemm 	mode.c_oflag |= ONLCR;
8440e3d5408SPeter Wemm #endif
8450e3d5408SPeter Wemm 	mode.c_iflag |= ICRNL;
8460e3d5408SPeter Wemm 	mode.c_lflag |= ECHO;
8470e3d5408SPeter Wemm #ifdef OXTABS
8480e3d5408SPeter Wemm 	mode.c_oflag |= OXTABS;
8490e3d5408SPeter Wemm #endif /* OXTABS */
8500e3d5408SPeter Wemm 
8510e3d5408SPeter Wemm 	/* test used to be tgetflag("NL") */
8520e3d5408SPeter Wemm 	if (newline != (char *)0 && newline[0] == '\n' && !newline[1]) {
8530e3d5408SPeter Wemm 		/* Newline, not linefeed. */
8540e3d5408SPeter Wemm #ifdef ONLCR
8550e3d5408SPeter Wemm 		mode.c_oflag &= ~ONLCR;
8560e3d5408SPeter Wemm #endif
8570e3d5408SPeter Wemm 		mode.c_iflag &= ~ICRNL;
8580e3d5408SPeter Wemm 	}
8590e3d5408SPeter Wemm #ifdef __OBSOLETE__
8600e3d5408SPeter Wemm 	if (tgetflag("HD"))			/* Half duplex. */
8610e3d5408SPeter Wemm 		mode.c_lflag &= ~ECHO;
8620e3d5408SPeter Wemm #endif /* __OBSOLETE__ */
8630e3d5408SPeter Wemm #ifdef OXTABS
8640e3d5408SPeter Wemm 	/* test used to be tgetflag("pt") */
8650e3d5408SPeter Wemm 	if (has_hardware_tabs)			/* Print tabs. */
8660e3d5408SPeter Wemm 		mode.c_oflag &= ~OXTABS;
8670e3d5408SPeter Wemm #endif /* OXTABS */
8680e3d5408SPeter Wemm 	mode.c_lflag |= (ECHOE | ECHOK);
8690e3d5408SPeter Wemm #endif
8700e3d5408SPeter Wemm }
8710e3d5408SPeter Wemm 
8720e3d5408SPeter Wemm /* Output startup string. */
8730e3d5408SPeter Wemm static void
8740e3d5408SPeter Wemm set_init(void)
8750e3d5408SPeter Wemm {
8760e3d5408SPeter Wemm 	char	*p;
8770e3d5408SPeter Wemm 	bool settle;
8780e3d5408SPeter Wemm 
8790e3d5408SPeter Wemm #ifdef __OBSOLETE__
8800e3d5408SPeter Wemm 	if (pad_char != (char *)0)		/* Get/set pad character. */
8810e3d5408SPeter Wemm 		PC = pad_char[0];
8820e3d5408SPeter Wemm #endif /* OBSOLETE */
8830e3d5408SPeter Wemm 
8840e3d5408SPeter Wemm #ifdef TAB3
8850e3d5408SPeter Wemm 	if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) {
8860e3d5408SPeter Wemm 		oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET);
8870e3d5408SPeter Wemm 		tcsetattr(STDERR_FILENO, TCSADRAIN, &oldmode);
8880e3d5408SPeter Wemm 	}
8890e3d5408SPeter Wemm #endif
8900e3d5408SPeter Wemm 	settle = set_tabs();
8910e3d5408SPeter Wemm 
8920e3d5408SPeter Wemm 	if (isreset) {
8930e3d5408SPeter Wemm 		if ((p = reset_1string) != 0) {
8940e3d5408SPeter Wemm 			tputs(p, 0, outc);
8950e3d5408SPeter Wemm 			settle = TRUE;
8960e3d5408SPeter Wemm 		}
8970e3d5408SPeter Wemm 		if ((p = reset_2string) != 0) {
8980e3d5408SPeter Wemm 			tputs(p, 0, outc);
8990e3d5408SPeter Wemm 			settle = TRUE;
9000e3d5408SPeter Wemm 		}
9010e3d5408SPeter Wemm 		/* What about rf, rs3, as per terminfo man page? */
9020e3d5408SPeter Wemm 		/* also might be nice to send rmacs, rmul, rmm */
9030e3d5408SPeter Wemm 		if ((p = reset_file) != 0
9040e3d5408SPeter Wemm 		 || (p = init_file) != 0) {
9050e3d5408SPeter Wemm 			cat(p);
9060e3d5408SPeter Wemm 			settle = TRUE;
9070e3d5408SPeter Wemm 		}
9080e3d5408SPeter Wemm 	}
9090e3d5408SPeter Wemm 
9100e3d5408SPeter Wemm 	if (settle) {
9110e3d5408SPeter Wemm 		(void)putc('\r', stderr);
9120e3d5408SPeter Wemm 		(void)fflush(stderr);
9130e3d5408SPeter Wemm 		(void)napms(1000);	/* Settle the terminal. */
9140e3d5408SPeter Wemm 	}
9150e3d5408SPeter Wemm }
9160e3d5408SPeter Wemm 
9170e3d5408SPeter Wemm /*
9180e3d5408SPeter Wemm  * Set the hardware tabs on the terminal, using the ct (clear all tabs),
9190e3d5408SPeter Wemm  * st (set one tab) and ch (horizontal cursor addressing) capabilities.
9200e3d5408SPeter Wemm  * This is done before if and is, so they can patch in case we blow this.
9210e3d5408SPeter Wemm  * Return TRUE if we set any tab stops, FALSE if not.
9220e3d5408SPeter Wemm  */
9230e3d5408SPeter Wemm static bool
9240e3d5408SPeter Wemm set_tabs()
9250e3d5408SPeter Wemm {
9260e3d5408SPeter Wemm 	if (set_tab && clear_all_tabs) {
9270e3d5408SPeter Wemm 		int c;
9280e3d5408SPeter Wemm 
9290e3d5408SPeter Wemm 		(void)putc('\r', stderr);	/* Force to left margin. */
9300e3d5408SPeter Wemm 		tputs(clear_all_tabs, 0, outc);
9310e3d5408SPeter Wemm 
9320e3d5408SPeter Wemm 		for (c = 8; c < tcolumns; c += 8) {
9330e3d5408SPeter Wemm 			/* Get to the right column.  In BSD tset, this
9340e3d5408SPeter Wemm 			 * used to try a bunch of half-clever things
9350e3d5408SPeter Wemm 			 * with cup and hpa, for an average saving of
9360e3d5408SPeter Wemm 			 * somewhat less than two character times per
9370e3d5408SPeter Wemm 			 * tab stop, less that .01 sec at 2400cps. We
9380e3d5408SPeter Wemm 			 * lost all this cruft because it seemed to be
9390e3d5408SPeter Wemm 			 * introducing some odd bugs.
9400e3d5408SPeter Wemm 			 * ----------12345678----------- */
9410e3d5408SPeter Wemm 			(void)fputs("        ", stderr);
9420e3d5408SPeter Wemm 			tputs(set_tab, 0, outc);
9430e3d5408SPeter Wemm 		}
9440e3d5408SPeter Wemm 		putc('\r', stderr);
9450e3d5408SPeter Wemm 		return (TRUE);
9460e3d5408SPeter Wemm 	}
9470e3d5408SPeter Wemm 	return (FALSE);
9480e3d5408SPeter Wemm }
9490e3d5408SPeter Wemm 
9500e3d5408SPeter Wemm /**************************************************************************
9510e3d5408SPeter Wemm  *
9520e3d5408SPeter Wemm  * Main sequence
9530e3d5408SPeter Wemm  *
9540e3d5408SPeter Wemm  **************************************************************************/
9550e3d5408SPeter Wemm 
9560e3d5408SPeter Wemm /*
9570e3d5408SPeter Wemm  * Tell the user if a control key has been changed from the default value.
9580e3d5408SPeter Wemm  */
9590e3d5408SPeter Wemm static void
9600e3d5408SPeter Wemm report(const char *name, int which, unsigned def)
9610e3d5408SPeter Wemm {
9620e3d5408SPeter Wemm #ifdef TERMIOS
9630e3d5408SPeter Wemm 	unsigned older, newer;
9640e3d5408SPeter Wemm 	char *p;
9650e3d5408SPeter Wemm 
9660e3d5408SPeter Wemm 	newer = mode.c_cc[which];
9670e3d5408SPeter Wemm 	older = oldmode.c_cc[which];
9680e3d5408SPeter Wemm 
9690e3d5408SPeter Wemm 	if (older == newer && older == def)
9700e3d5408SPeter Wemm 		return;
9710e3d5408SPeter Wemm 
9720e3d5408SPeter Wemm 	(void)fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to");
9730e3d5408SPeter Wemm 
9740e3d5408SPeter Wemm 	/*
9750e3d5408SPeter Wemm 	 * Check 'delete' before 'backspace', since the key_backspace value
9760e3d5408SPeter Wemm 	 * is ambiguous.
9770e3d5408SPeter Wemm 	 */
9780e3d5408SPeter Wemm 	if (newer == 0177)
9790e3d5408SPeter Wemm 		(void)fprintf(stderr, "delete.\n");
9800e3d5408SPeter Wemm 	else if ((p = key_backspace) != 0
9810e3d5408SPeter Wemm 	 && newer == (unsigned char)p[0]
9820e3d5408SPeter Wemm 	 && p[1] == '\0')
9830e3d5408SPeter Wemm 		(void)fprintf(stderr, "backspace.\n");
9840e3d5408SPeter Wemm 	else if (newer < 040) {
9850e3d5408SPeter Wemm 		newer ^= 0100;
9860e3d5408SPeter Wemm 		(void)fprintf(stderr, "control-%c (^%c).\n", newer, newer);
9870e3d5408SPeter Wemm 	} else
9880e3d5408SPeter Wemm 		(void)fprintf(stderr, "%c.\n", newer);
9890e3d5408SPeter Wemm #endif
9900e3d5408SPeter Wemm }
9910e3d5408SPeter Wemm 
9920e3d5408SPeter Wemm /*
9930e3d5408SPeter Wemm  * Convert the obsolete argument forms into something that getopt can handle.
9940e3d5408SPeter Wemm  * This means that -e, -i and -k get default arguments supplied for them.
9950e3d5408SPeter Wemm  */
9960e3d5408SPeter Wemm static void
9970e3d5408SPeter Wemm obsolete(char **argv)
9980e3d5408SPeter Wemm {
9990e3d5408SPeter Wemm 	for (; *argv; ++argv) {
10000e3d5408SPeter Wemm 		char *parm = argv[0];
10010e3d5408SPeter Wemm 
10020e3d5408SPeter Wemm 		if (parm[0] == '-' && parm[1] == '\0')
10030e3d5408SPeter Wemm 		{
10040e3d5408SPeter Wemm 		    argv[0] = strdup("-q");
10050e3d5408SPeter Wemm 		    continue;
10060e3d5408SPeter Wemm 		}
10070e3d5408SPeter Wemm 
10080e3d5408SPeter Wemm 		if ((parm[0] != '-')
10090e3d5408SPeter Wemm 		 || (argv[1] && argv[1][0] != '-')
10100e3d5408SPeter Wemm 		 || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
10110e3d5408SPeter Wemm 		 || (parm[2] != '\0'))
10120e3d5408SPeter Wemm 			continue;
10130e3d5408SPeter Wemm 		switch(argv[0][1]) {
10140e3d5408SPeter Wemm 		case 'e':
10150e3d5408SPeter Wemm 			argv[0] = strdup("-e^H");
10160e3d5408SPeter Wemm 			break;
10170e3d5408SPeter Wemm 		case 'i':
10180e3d5408SPeter Wemm 			argv[0] = strdup("-i^C");
10190e3d5408SPeter Wemm 			break;
10200e3d5408SPeter Wemm 		case 'k':
10210e3d5408SPeter Wemm 			argv[0] = strdup("-k^U");
10220e3d5408SPeter Wemm 			break;
10230e3d5408SPeter Wemm 		}
10240e3d5408SPeter Wemm 	}
10250e3d5408SPeter Wemm }
10260e3d5408SPeter Wemm 
10270e3d5408SPeter Wemm static void
10280e3d5408SPeter Wemm usage(const char* pname)
10290e3d5408SPeter Wemm {
10300e3d5408SPeter Wemm 	(void)fprintf(stderr,
10310e3d5408SPeter Wemm "usage: %s [-IQrs] [-] [-e ch] [-i ch] [-k ch] [-m mapping] [terminal]\n", pname);
10320e3d5408SPeter Wemm 	exit(EXIT_FAILURE);
10330e3d5408SPeter Wemm }
10340e3d5408SPeter Wemm 
10350e3d5408SPeter Wemm static char arg_to_char(void)
10360e3d5408SPeter Wemm {
10370e3d5408SPeter Wemm 	return (optarg[0] == '^' && optarg[1] != '\0')
10380e3d5408SPeter Wemm 		? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
10390e3d5408SPeter Wemm 		: optarg[0];
10400e3d5408SPeter Wemm }
10410e3d5408SPeter Wemm 
10420e3d5408SPeter Wemm int
10430e3d5408SPeter Wemm main(int argc, char **argv)
10440e3d5408SPeter Wemm {
10450e3d5408SPeter Wemm #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
10460e3d5408SPeter Wemm 	struct winsize win;
10470e3d5408SPeter Wemm #endif
10480e3d5408SPeter Wemm 	int ch, noinit, noset, quiet, Sflag, sflag, showterm;
10490e3d5408SPeter Wemm 	const char *p;
10500e3d5408SPeter Wemm 	const char *ttype;
10510e3d5408SPeter Wemm 
10520e3d5408SPeter Wemm #ifdef TERMIOS
10530e3d5408SPeter Wemm 	if (tcgetattr(STDERR_FILENO, &mode) < 0)
10540e3d5408SPeter Wemm 		failed("standard error");
10550e3d5408SPeter Wemm 
10560e3d5408SPeter Wemm 	oldmode = mode;
10570e3d5408SPeter Wemm 	ospeed = cfgetospeed(&mode);
10580e3d5408SPeter Wemm #else
10590e3d5408SPeter Wemm 	if (gtty(STDERR_FILENO, &mode) < 0)
10600e3d5408SPeter Wemm 		failed("standard error");
10610e3d5408SPeter Wemm 
10620e3d5408SPeter Wemm 	oldmode = mode;
10630e3d5408SPeter Wemm 	ospeed = mode.sg_ospeed;
10640e3d5408SPeter Wemm #endif
10650e3d5408SPeter Wemm 
10660e3d5408SPeter Wemm 	if ((p = strrchr(*argv, '/')) != 0)
10670e3d5408SPeter Wemm 		++p;
10680e3d5408SPeter Wemm 	else
10690e3d5408SPeter Wemm 		p = *argv;
10700e3d5408SPeter Wemm 	if (!CaselessCmp(p, "reset")) {
10710e3d5408SPeter Wemm 		isreset = 1;
10720e3d5408SPeter Wemm 		reset_mode();
10730e3d5408SPeter Wemm 	}
10740e3d5408SPeter Wemm 
10750e3d5408SPeter Wemm 	obsolete(argv);
10760e3d5408SPeter Wemm 	noinit = noset = quiet = Sflag = sflag = showterm = 0;
10770e3d5408SPeter Wemm 	while ((ch = getopt(argc, argv, "a:d:e:Ii:k:m:np:qQSrs")) != EOF) {
10780e3d5408SPeter Wemm 		switch (ch) {
10790e3d5408SPeter Wemm 		case 'q':		/* display term only */
10800e3d5408SPeter Wemm 			noset = 1;
10810e3d5408SPeter Wemm 			break;
10820e3d5408SPeter Wemm 		case 'a':		/* OBSOLETE: map identifier to type */
10830e3d5408SPeter Wemm 			add_mapping("arpanet", optarg);
10840e3d5408SPeter Wemm 			break;
10850e3d5408SPeter Wemm 		case 'd':		/* OBSOLETE: map identifier to type */
10860e3d5408SPeter Wemm 			add_mapping("dialup", optarg);
10870e3d5408SPeter Wemm 			break;
10880e3d5408SPeter Wemm 		case 'e':		/* erase character */
10890e3d5408SPeter Wemm 			terasechar = arg_to_char();
10900e3d5408SPeter Wemm 			break;
10910e3d5408SPeter Wemm 		case 'I':		/* no initialization strings */
10920e3d5408SPeter Wemm 			noinit = 1;
10930e3d5408SPeter Wemm 			break;
10940e3d5408SPeter Wemm 		case 'i':		/* interrupt character */
10950e3d5408SPeter Wemm 			intrchar = arg_to_char();
10960e3d5408SPeter Wemm 			break;
10970e3d5408SPeter Wemm 		case 'k':		/* kill character */
10980e3d5408SPeter Wemm 			tkillchar = arg_to_char();
10990e3d5408SPeter Wemm 			break;
11000e3d5408SPeter Wemm 		case 'm':		/* map identifier to type */
11010e3d5408SPeter Wemm 			add_mapping(0, optarg);
11020e3d5408SPeter Wemm 			break;
11030e3d5408SPeter Wemm 		case 'n':		/* OBSOLETE: set new tty driver */
11040e3d5408SPeter Wemm 			break;
11050e3d5408SPeter Wemm 		case 'p':		/* OBSOLETE: map identifier to type */
11060e3d5408SPeter Wemm 			add_mapping("plugboard", optarg);
11070e3d5408SPeter Wemm 			break;
11080e3d5408SPeter Wemm 		case 'Q':		/* don't output control key settings */
11090e3d5408SPeter Wemm 			quiet = 1;
11100e3d5408SPeter Wemm 			break;
11110e3d5408SPeter Wemm 		case 'S':		/* OBSOLETE: output TERM & TERMCAP */
11120e3d5408SPeter Wemm 			Sflag = 1;
11130e3d5408SPeter Wemm 			break;
11140e3d5408SPeter Wemm 		case 'r':		/* display term on stderr */
11150e3d5408SPeter Wemm 			showterm = 1;
11160e3d5408SPeter Wemm 			break;
11170e3d5408SPeter Wemm 		case 's':		/* output TERM set command */
11180e3d5408SPeter Wemm 			sflag = 1;
11190e3d5408SPeter Wemm 			break;
11200e3d5408SPeter Wemm 		case '?':
11210e3d5408SPeter Wemm 		default:
11220e3d5408SPeter Wemm 			usage(*argv);
11230e3d5408SPeter Wemm 		}
11240e3d5408SPeter Wemm 	}
11250e3d5408SPeter Wemm 	argc -= optind;
11260e3d5408SPeter Wemm 	argv += optind;
11270e3d5408SPeter Wemm 
11280e3d5408SPeter Wemm 	if (argc > 1)
11290e3d5408SPeter Wemm 		usage(*argv);
11300e3d5408SPeter Wemm 
11310e3d5408SPeter Wemm 	ttype = get_termcap_entry(*argv);
11320e3d5408SPeter Wemm 
11330e3d5408SPeter Wemm 	if (!noset) {
11340e3d5408SPeter Wemm 		tcolumns = columns;
11350e3d5408SPeter Wemm 		tlines = lines;
11360e3d5408SPeter Wemm 
11370e3d5408SPeter Wemm #if defined(TIOCGWINSZ) && defined(TIOCSWINSZ)
11380e3d5408SPeter Wemm 		/* Set window size */
11390e3d5408SPeter Wemm 		(void)ioctl(STDERR_FILENO, TIOCGWINSZ, &win);
11400e3d5408SPeter Wemm 		if (win.ws_row == 0 && win.ws_col == 0 &&
11410e3d5408SPeter Wemm 		    tlines > 0 && tcolumns > 0) {
11420e3d5408SPeter Wemm 			win.ws_row = tlines;
11430e3d5408SPeter Wemm 			win.ws_col = tcolumns;
11440e3d5408SPeter Wemm 			(void)ioctl(STDERR_FILENO, TIOCSWINSZ, &win);
11450e3d5408SPeter Wemm 		}
11460e3d5408SPeter Wemm #endif
11470e3d5408SPeter Wemm 		set_control_chars();
11480e3d5408SPeter Wemm 		set_conversions();
11490e3d5408SPeter Wemm 
11500e3d5408SPeter Wemm 		if (!noinit)
11510e3d5408SPeter Wemm 			set_init();
11520e3d5408SPeter Wemm 
11530e3d5408SPeter Wemm 		/* Set the modes if they've changed. */
11540e3d5408SPeter Wemm 		if (memcmp(&mode, &oldmode, sizeof(mode)))
11550e3d5408SPeter Wemm #ifdef TERMIOS
11560e3d5408SPeter Wemm 			tcsetattr(STDERR_FILENO, TCSADRAIN, &mode);
11570e3d5408SPeter Wemm #else
11580e3d5408SPeter Wemm 			stty(STDERR_FILENO, &mode);
11590e3d5408SPeter Wemm #endif
11600e3d5408SPeter Wemm 	}
11610e3d5408SPeter Wemm 
11620e3d5408SPeter Wemm 	/* Get the terminal name from the entry. */
11630e3d5408SPeter Wemm 	ttype = _nc_first_name(cur_term->type.term_names);
11640e3d5408SPeter Wemm 
11650e3d5408SPeter Wemm 	if (noset)
11660e3d5408SPeter Wemm 		(void)printf("%s\n", ttype);
11670e3d5408SPeter Wemm 	else {
11680e3d5408SPeter Wemm 		if (showterm)
11690e3d5408SPeter Wemm 			(void)fprintf(stderr, "Terminal type is %s.\n", ttype);
11700e3d5408SPeter Wemm 		/*
11710e3d5408SPeter Wemm 		 * If erase, kill and interrupt characters could have been
11720e3d5408SPeter Wemm 		 * modified and not -Q, display the changes.
11730e3d5408SPeter Wemm 		 */
11740e3d5408SPeter Wemm 		if (!quiet) {
11750e3d5408SPeter Wemm 			report("Erase", VERASE, CERASE);
11760e3d5408SPeter Wemm 			report("Kill", VKILL, CINTR);
11770e3d5408SPeter Wemm 			report("Interrupt", VINTR, CKILL);
11780e3d5408SPeter Wemm 		}
11790e3d5408SPeter Wemm 	}
11800e3d5408SPeter Wemm 
11810e3d5408SPeter Wemm 	if (Sflag)
11820e3d5408SPeter Wemm 		err("The -S option is not supported under terminfo.");
11830e3d5408SPeter Wemm 
11840e3d5408SPeter Wemm 	if (sflag) {
11850e3d5408SPeter Wemm 		/*
11860e3d5408SPeter Wemm 		 * Figure out what shell we're using.  A hack, we look for an
11870e3d5408SPeter Wemm 		 * environmental variable SHELL ending in "csh".
11880e3d5408SPeter Wemm 		 */
11890e3d5408SPeter Wemm 		if ((p = getenv("SHELL")) != 0
11900e3d5408SPeter Wemm 		 && !strcmp(p + strlen(p) - 3, "csh"))
11910e3d5408SPeter Wemm 			p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
11920e3d5408SPeter Wemm 		else
11930e3d5408SPeter Wemm 			p = "TERM=%s;\n";
11940e3d5408SPeter Wemm 		(void) printf(p, ttype);
11950e3d5408SPeter Wemm 	}
11960e3d5408SPeter Wemm 
11970e3d5408SPeter Wemm 	return EXIT_SUCCESS;
11980e3d5408SPeter Wemm }
11990e3d5408SPeter Wemm 
12000e3d5408SPeter Wemm /* tset.c ends here */
1201