xref: /freebsd/contrib/ncurses/progs/tset.c (revision aae38d10b4eebf81c0942947e8b83a9bb8651d88)
10e3d5408SPeter Wemm /****************************************************************************
2*aae38d10SBaptiste Daroussin  * Copyright (c) 1998-2016,2017 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>                         *
324a1a9510SRong-En Fan  *     and: Thomas E. Dickey                        1996-on                 *
330e3d5408SPeter Wemm  ****************************************************************************/
340e3d5408SPeter Wemm 
350e3d5408SPeter Wemm /*
3606bfebdeSXin LI  * Notes:
3706bfebdeSXin LI  * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686
3806bfebdeSXin LI  * lines from that version, and made changes/additions for 150 lines.  There
3906bfebdeSXin LI  * was no reformatting, so with/without ignoring whitespace, the amount of
4006bfebdeSXin LI  * change is the same.
4106bfebdeSXin LI  *
4206bfebdeSXin LI  * Comparing with current (2009) source, excluding this comment:
4306bfebdeSXin LI  * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines
4406bfebdeSXin LI  *    changed/added.
4506bfebdeSXin LI  * a) Ignoring whitespace, the current version still uses 516 lines from the
4606bfebdeSXin LI  *    4.4BSD Lite sources, with 402 lines changed/added.
4706bfebdeSXin LI  *
4806bfebdeSXin LI  * Raymond's original comment on this follows...
4906bfebdeSXin LI  */
5006bfebdeSXin LI 
5106bfebdeSXin LI /*
520e3d5408SPeter Wemm  * tset.c - terminal initialization utility
530e3d5408SPeter Wemm  *
540e3d5408SPeter Wemm  * This code was mostly swiped from 4.4BSD tset, with some obsolescent
550e3d5408SPeter Wemm  * cruft removed and substantial portions rewritten.  A Regents of the
560e3d5408SPeter Wemm  * University of California copyright applies to some portions of the
570e3d5408SPeter Wemm  * code, and is reproduced below:
580e3d5408SPeter Wemm  */
590e3d5408SPeter Wemm /*-
600e3d5408SPeter Wemm  * Copyright (c) 1980, 1991, 1993
610e3d5408SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
620e3d5408SPeter Wemm  *
630e3d5408SPeter Wemm  * Redistribution and use in source and binary forms, with or without
640e3d5408SPeter Wemm  * modification, are permitted provided that the following conditions
650e3d5408SPeter Wemm  * are met:
660e3d5408SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
670e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
680e3d5408SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
690e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
700e3d5408SPeter Wemm  *    documentation and/or other materials provided with the distribution.
7106bfebdeSXin LI  * 3. Neither the name of the University nor the names of its contributors
720e3d5408SPeter Wemm  *    may be used to endorse or promote products derived from this software
730e3d5408SPeter Wemm  *    without specific prior written permission.
740e3d5408SPeter Wemm  *
750e3d5408SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
760e3d5408SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
770e3d5408SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
780e3d5408SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
790e3d5408SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
800e3d5408SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
810e3d5408SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
820e3d5408SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
830e3d5408SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
840e3d5408SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
850e3d5408SPeter Wemm  * SUCH DAMAGE.
860e3d5408SPeter Wemm  */
870e3d5408SPeter Wemm 
88*aae38d10SBaptiste Daroussin #include <reset_cmd.h>
890e3d5408SPeter Wemm #include <termcap.h>
90*aae38d10SBaptiste Daroussin #include <transform.h>
91*aae38d10SBaptiste Daroussin #include <tty_settings.h>
920e3d5408SPeter Wemm 
930e3d5408SPeter Wemm #if HAVE_GETTTYNAM && HAVE_TTYENT_H
940e3d5408SPeter Wemm #include <ttyent.h>
950e3d5408SPeter Wemm #endif
960e3d5408SPeter Wemm #ifdef NeXT
970e3d5408SPeter Wemm char *ttyname(int fd);
980e3d5408SPeter Wemm #endif
990e3d5408SPeter Wemm 
100*aae38d10SBaptiste Daroussin MODULE_ID("$Id: tset.c,v 1.120 2017/10/08 00:01:29 tom Exp $")
1010e3d5408SPeter Wemm 
10206bfebdeSXin LI #ifndef environ
1030e3d5408SPeter Wemm extern char **environ;
10406bfebdeSXin LI #endif
1050e3d5408SPeter Wemm 
1060e3d5408SPeter Wemm const char *_nc_progname = "tset";
1070e3d5408SPeter Wemm 
10839f2269fSPeter Wemm #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
1090e3d5408SPeter Wemm 
110*aae38d10SBaptiste Daroussin static void exit_error(void) GCC_NORETURN;
111*aae38d10SBaptiste Daroussin 
1120e3d5408SPeter Wemm static int
11315589c42SPeter Wemm CaselessCmp(const char *a, const char *b)
11415589c42SPeter Wemm {				/* strcasecmp isn't portable */
1150e3d5408SPeter Wemm     while (*a && *b) {
1160e3d5408SPeter Wemm 	int cmp = LOWERCASE(*a) - LOWERCASE(*b);
1170e3d5408SPeter Wemm 	if (cmp != 0)
1180e3d5408SPeter Wemm 	    break;
1190e3d5408SPeter Wemm 	a++, b++;
1200e3d5408SPeter Wemm     }
1210e3d5408SPeter Wemm     return LOWERCASE(*a) - LOWERCASE(*b);
1220e3d5408SPeter Wemm }
1230e3d5408SPeter Wemm 
1240e3d5408SPeter Wemm static void
12539f2269fSPeter Wemm exit_error(void)
12639f2269fSPeter Wemm {
127*aae38d10SBaptiste Daroussin     restore_tty_settings();
12839f2269fSPeter Wemm     (void) fprintf(stderr, "\n");
12939f2269fSPeter Wemm     fflush(stderr);
1304a1a9510SRong-En Fan     ExitProgram(EXIT_FAILURE);
13139f2269fSPeter Wemm     /* NOTREACHED */
13239f2269fSPeter Wemm }
13339f2269fSPeter Wemm 
13439f2269fSPeter Wemm static void
1350e3d5408SPeter Wemm err(const char *fmt,...)
1360e3d5408SPeter Wemm {
1370e3d5408SPeter Wemm     va_list ap;
1380e3d5408SPeter Wemm     va_start(ap, fmt);
1394a1a9510SRong-En Fan     (void) fprintf(stderr, "%s: ", _nc_progname);
1400e3d5408SPeter Wemm     (void) vfprintf(stderr, fmt, ap);
1410e3d5408SPeter Wemm     va_end(ap);
14239f2269fSPeter Wemm     exit_error();
1430e3d5408SPeter Wemm     /* NOTREACHED */
1440e3d5408SPeter Wemm }
1450e3d5408SPeter Wemm 
1460e3d5408SPeter Wemm static void
1470e3d5408SPeter Wemm failed(const char *msg)
1480e3d5408SPeter Wemm {
1490e3d5408SPeter Wemm     char temp[BUFSIZ];
15073f0a83dSXin LI     size_t len = strlen(_nc_progname) + 2;
1514a1a9510SRong-En Fan 
1525d08fb1fSRong-En Fan     if ((int) len < (int) sizeof(temp) - 12) {
15373f0a83dSXin LI 	_nc_STRCPY(temp, _nc_progname, sizeof(temp));
15473f0a83dSXin LI 	_nc_STRCAT(temp, ": ", sizeof(temp));
1554a1a9510SRong-En Fan     } else {
15673f0a83dSXin LI 	_nc_STRCPY(temp, "tset: ", sizeof(temp));
1574a1a9510SRong-En Fan     }
158*aae38d10SBaptiste Daroussin     _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2);
159*aae38d10SBaptiste Daroussin     perror(temp);
16039f2269fSPeter Wemm     exit_error();
1610e3d5408SPeter Wemm     /* NOTREACHED */
1620e3d5408SPeter Wemm }
1630e3d5408SPeter Wemm 
1640e3d5408SPeter Wemm /* Prompt the user for a terminal type. */
1650e3d5408SPeter Wemm static const char *
1660e3d5408SPeter Wemm askuser(const char *dflt)
1670e3d5408SPeter Wemm {
1680e3d5408SPeter Wemm     static char answer[256];
1690e3d5408SPeter Wemm     char *p;
1700e3d5408SPeter Wemm 
1710e3d5408SPeter Wemm     /* We can get recalled; if so, don't continue uselessly. */
1724a1a9510SRong-En Fan     clearerr(stdin);
1730e3d5408SPeter Wemm     if (feof(stdin) || ferror(stdin)) {
1740e3d5408SPeter Wemm 	(void) fprintf(stderr, "\n");
17539f2269fSPeter Wemm 	exit_error();
17639f2269fSPeter Wemm 	/* NOTREACHED */
1770e3d5408SPeter Wemm     }
1780e3d5408SPeter Wemm     for (;;) {
1790e3d5408SPeter Wemm 	if (dflt)
1800e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
1810e3d5408SPeter Wemm 	else
1820e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? ");
1830e3d5408SPeter Wemm 	(void) fflush(stderr);
1840e3d5408SPeter Wemm 
1850e3d5408SPeter Wemm 	if (fgets(answer, sizeof(answer), stdin) == 0) {
1860e3d5408SPeter Wemm 	    if (dflt == 0) {
18739f2269fSPeter Wemm 		exit_error();
18839f2269fSPeter Wemm 		/* NOTREACHED */
1890e3d5408SPeter Wemm 	    }
1900e3d5408SPeter Wemm 	    return (dflt);
1910e3d5408SPeter Wemm 	}
1920e3d5408SPeter Wemm 
1930e3d5408SPeter Wemm 	if ((p = strchr(answer, '\n')) != 0)
1940e3d5408SPeter Wemm 	    *p = '\0';
1950e3d5408SPeter Wemm 	if (answer[0])
1960e3d5408SPeter Wemm 	    return (answer);
1970e3d5408SPeter Wemm 	if (dflt != 0)
1980e3d5408SPeter Wemm 	    return (dflt);
1990e3d5408SPeter Wemm     }
2000e3d5408SPeter Wemm }
2010e3d5408SPeter Wemm 
2020e3d5408SPeter Wemm /**************************************************************************
2030e3d5408SPeter Wemm  *
2040e3d5408SPeter Wemm  * Mapping logic begins here
2050e3d5408SPeter Wemm  *
2060e3d5408SPeter Wemm  **************************************************************************/
2070e3d5408SPeter Wemm 
2080e3d5408SPeter Wemm /* Baud rate conditionals for mapping. */
2090e3d5408SPeter Wemm #define	GT		0x01
2100e3d5408SPeter Wemm #define	EQ		0x02
2110e3d5408SPeter Wemm #define	LT		0x04
2120e3d5408SPeter Wemm #define	NOT		0x08
2130e3d5408SPeter Wemm #define	GE		(GT | EQ)
2140e3d5408SPeter Wemm #define	LE		(LT | EQ)
2150e3d5408SPeter Wemm 
2160e3d5408SPeter Wemm typedef struct map {
2170e3d5408SPeter Wemm     struct map *next;		/* Linked list of maps. */
2180e3d5408SPeter Wemm     const char *porttype;	/* Port type, or "" for any. */
2190e3d5408SPeter Wemm     const char *type;		/* Terminal type to select. */
2200e3d5408SPeter Wemm     int conditional;		/* Baud rate conditionals bitmask. */
22118259542SPeter Wemm     int speed;			/* Baud rate to compare against. */
2220e3d5408SPeter Wemm } MAP;
2230e3d5408SPeter Wemm 
2240e3d5408SPeter Wemm static MAP *cur, *maplist;
2250e3d5408SPeter Wemm 
226*aae38d10SBaptiste Daroussin #define DATA(name,value) { { name }, value }
227*aae38d10SBaptiste Daroussin 
2280e3d5408SPeter Wemm typedef struct speeds {
229*aae38d10SBaptiste Daroussin     const char string[7];
2300e3d5408SPeter Wemm     int speed;
2310e3d5408SPeter Wemm } SPEEDS;
2320e3d5408SPeter Wemm 
23315589c42SPeter Wemm static const SPEEDS speeds[] =
23415589c42SPeter Wemm {
235*aae38d10SBaptiste Daroussin     DATA("0", B0),
236*aae38d10SBaptiste Daroussin     DATA("50", B50),
237*aae38d10SBaptiste Daroussin     DATA("75", B75),
238*aae38d10SBaptiste Daroussin     DATA("110", B110),
239*aae38d10SBaptiste Daroussin     DATA("134", B134),
240*aae38d10SBaptiste Daroussin     DATA("134.5", B134),
241*aae38d10SBaptiste Daroussin     DATA("150", B150),
242*aae38d10SBaptiste Daroussin     DATA("200", B200),
243*aae38d10SBaptiste Daroussin     DATA("300", B300),
244*aae38d10SBaptiste Daroussin     DATA("600", B600),
245*aae38d10SBaptiste Daroussin     DATA("1200", B1200),
246*aae38d10SBaptiste Daroussin     DATA("1800", B1800),
247*aae38d10SBaptiste Daroussin     DATA("2400", B2400),
248*aae38d10SBaptiste Daroussin     DATA("4800", B4800),
249*aae38d10SBaptiste Daroussin     DATA("9600", B9600),
25018259542SPeter Wemm     /* sgttyb may define up to this point */
25118259542SPeter Wemm #ifdef B19200
252*aae38d10SBaptiste Daroussin     DATA("19200", B19200),
25318259542SPeter Wemm #endif
25418259542SPeter Wemm #ifdef B38400
255*aae38d10SBaptiste Daroussin     DATA("38400", B38400),
25618259542SPeter Wemm #endif
25718259542SPeter Wemm #ifdef B19200
258*aae38d10SBaptiste Daroussin     DATA("19200", B19200),
25918259542SPeter Wemm #endif
26018259542SPeter Wemm #ifdef B38400
261*aae38d10SBaptiste Daroussin     DATA("38400", B38400),
26218259542SPeter Wemm #endif
2630e3d5408SPeter Wemm #ifdef B19200
264*aae38d10SBaptiste Daroussin     DATA("19200", B19200),
2650e3d5408SPeter Wemm #else
2660e3d5408SPeter Wemm #ifdef EXTA
267*aae38d10SBaptiste Daroussin     DATA("19200", EXTA),
2680e3d5408SPeter Wemm #endif
2690e3d5408SPeter Wemm #endif
2700e3d5408SPeter Wemm #ifdef B38400
271*aae38d10SBaptiste Daroussin     DATA("38400", B38400),
2720e3d5408SPeter Wemm #else
2730e3d5408SPeter Wemm #ifdef EXTB
274*aae38d10SBaptiste Daroussin     DATA("38400", EXTB),
2750e3d5408SPeter Wemm #endif
2760e3d5408SPeter Wemm #endif
2770e3d5408SPeter Wemm #ifdef B57600
278*aae38d10SBaptiste Daroussin     DATA("57600", B57600),
279*aae38d10SBaptiste Daroussin #endif
280*aae38d10SBaptiste Daroussin #ifdef B76800
281*aae38d10SBaptiste Daroussin     DATA("76800", B57600),
2820e3d5408SPeter Wemm #endif
2830e3d5408SPeter Wemm #ifdef B115200
284*aae38d10SBaptiste Daroussin     DATA("115200", B115200),
285*aae38d10SBaptiste Daroussin #endif
286*aae38d10SBaptiste Daroussin #ifdef B153600
287*aae38d10SBaptiste Daroussin     DATA("153600", B153600),
2880e3d5408SPeter Wemm #endif
2890e3d5408SPeter Wemm #ifdef B230400
290*aae38d10SBaptiste Daroussin     DATA("230400", B230400),
291*aae38d10SBaptiste Daroussin #endif
292*aae38d10SBaptiste Daroussin #ifdef B307200
293*aae38d10SBaptiste Daroussin     DATA("307200", B307200),
2940e3d5408SPeter Wemm #endif
2950e3d5408SPeter Wemm #ifdef B460800
296*aae38d10SBaptiste Daroussin     DATA("460800", B460800),
2970e3d5408SPeter Wemm #endif
298*aae38d10SBaptiste Daroussin #ifdef B500000
299*aae38d10SBaptiste Daroussin     DATA("500000", B500000),
300*aae38d10SBaptiste Daroussin #endif
301*aae38d10SBaptiste Daroussin #ifdef B576000
302*aae38d10SBaptiste Daroussin     DATA("576000", B576000),
303*aae38d10SBaptiste Daroussin #endif
304*aae38d10SBaptiste Daroussin #ifdef B921600
305*aae38d10SBaptiste Daroussin     DATA("921600", B921600),
306*aae38d10SBaptiste Daroussin #endif
307*aae38d10SBaptiste Daroussin #ifdef B1000000
308*aae38d10SBaptiste Daroussin     DATA("1000000", B1000000),
309*aae38d10SBaptiste Daroussin #endif
310*aae38d10SBaptiste Daroussin #ifdef B1152000
311*aae38d10SBaptiste Daroussin     DATA("1152000", B1152000),
312*aae38d10SBaptiste Daroussin #endif
313*aae38d10SBaptiste Daroussin #ifdef B1500000
314*aae38d10SBaptiste Daroussin     DATA("1500000", B1500000),
315*aae38d10SBaptiste Daroussin #endif
316*aae38d10SBaptiste Daroussin #ifdef B2000000
317*aae38d10SBaptiste Daroussin     DATA("2000000", B2000000),
318*aae38d10SBaptiste Daroussin #endif
319*aae38d10SBaptiste Daroussin #ifdef B2500000
320*aae38d10SBaptiste Daroussin     DATA("2500000", B2500000),
321*aae38d10SBaptiste Daroussin #endif
322*aae38d10SBaptiste Daroussin #ifdef B3000000
323*aae38d10SBaptiste Daroussin     DATA("3000000", B3000000),
324*aae38d10SBaptiste Daroussin #endif
325*aae38d10SBaptiste Daroussin #ifdef B3500000
326*aae38d10SBaptiste Daroussin     DATA("3500000", B3500000),
327*aae38d10SBaptiste Daroussin #endif
328*aae38d10SBaptiste Daroussin #ifdef B4000000
329*aae38d10SBaptiste Daroussin     DATA("4000000", B4000000),
330*aae38d10SBaptiste Daroussin #endif
3310e3d5408SPeter Wemm };
332*aae38d10SBaptiste Daroussin #undef DATA
3330e3d5408SPeter Wemm 
3340e3d5408SPeter Wemm static int
3350e3d5408SPeter Wemm tbaudrate(char *rate)
3360e3d5408SPeter Wemm {
337*aae38d10SBaptiste Daroussin     const SPEEDS *sp = 0;
338*aae38d10SBaptiste Daroussin     size_t n;
3390e3d5408SPeter Wemm 
3400e3d5408SPeter Wemm     /* The baudrate number can be preceded by a 'B', which is ignored. */
3410e3d5408SPeter Wemm     if (*rate == 'B')
3420e3d5408SPeter Wemm 	++rate;
3430e3d5408SPeter Wemm 
344*aae38d10SBaptiste Daroussin     for (n = 0; n < SIZEOF(speeds); ++n) {
345*aae38d10SBaptiste Daroussin 	if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
346*aae38d10SBaptiste Daroussin 	    /* if the speeds are not increasing, likely a numeric overflow */
347*aae38d10SBaptiste Daroussin 	    break;
348*aae38d10SBaptiste Daroussin 	}
349*aae38d10SBaptiste Daroussin 	if (!CaselessCmp(rate, speeds[n].string)) {
350*aae38d10SBaptiste Daroussin 	    sp = speeds + n;
3510e3d5408SPeter Wemm 	    break;
3520e3d5408SPeter Wemm 	}
3530e3d5408SPeter Wemm     }
354*aae38d10SBaptiste Daroussin     if (sp == 0)
3550e3d5408SPeter Wemm 	err("unknown baud rate %s", rate);
3560e3d5408SPeter Wemm     return (sp->speed);
3570e3d5408SPeter Wemm }
3580e3d5408SPeter Wemm 
3590e3d5408SPeter Wemm /*
3600e3d5408SPeter Wemm  * Syntax for -m:
3610e3d5408SPeter Wemm  * [port-type][test baudrate]:terminal-type
3620e3d5408SPeter Wemm  * The baud rate tests are: >, <, @, =, !
3630e3d5408SPeter Wemm  */
3640e3d5408SPeter Wemm static void
3650e3d5408SPeter Wemm add_mapping(const char *port, char *arg)
3660e3d5408SPeter Wemm {
3670e3d5408SPeter Wemm     MAP *mapp;
3680e3d5408SPeter Wemm     char *copy, *p;
3690e3d5408SPeter Wemm     const char *termp;
3700e3d5408SPeter Wemm     char *base = 0;
3710e3d5408SPeter Wemm 
3720e3d5408SPeter Wemm     copy = strdup(arg);
37306bfebdeSXin LI     mapp = typeMalloc(MAP, 1);
3740e3d5408SPeter Wemm     if (copy == 0 || mapp == 0)
3750e3d5408SPeter Wemm 	failed("malloc");
37606bfebdeSXin LI 
37706bfebdeSXin LI     assert(copy != 0);
37806bfebdeSXin LI     assert(mapp != 0);
37906bfebdeSXin LI 
3800e3d5408SPeter Wemm     mapp->next = 0;
3810e3d5408SPeter Wemm     if (maplist == 0)
3820e3d5408SPeter Wemm 	cur = maplist = mapp;
3830e3d5408SPeter Wemm     else {
3840e3d5408SPeter Wemm 	cur->next = mapp;
3850e3d5408SPeter Wemm 	cur = mapp;
3860e3d5408SPeter Wemm     }
3870e3d5408SPeter Wemm 
3880e3d5408SPeter Wemm     mapp->porttype = arg;
3890e3d5408SPeter Wemm     mapp->conditional = 0;
3900e3d5408SPeter Wemm 
3910e3d5408SPeter Wemm     arg = strpbrk(arg, "><@=!:");
3920e3d5408SPeter Wemm 
3930e3d5408SPeter Wemm     if (arg == 0) {		/* [?]term */
3940e3d5408SPeter Wemm 	mapp->type = mapp->porttype;
3950e3d5408SPeter Wemm 	mapp->porttype = 0;
3960e3d5408SPeter Wemm 	goto done;
3970e3d5408SPeter Wemm     }
3980e3d5408SPeter Wemm 
3990e3d5408SPeter Wemm     if (arg == mapp->porttype)	/* [><@=! baud]:term */
4000e3d5408SPeter Wemm 	termp = mapp->porttype = 0;
4010e3d5408SPeter Wemm     else
4020e3d5408SPeter Wemm 	termp = base = arg;
4030e3d5408SPeter Wemm 
40415589c42SPeter Wemm     for (;; ++arg) {		/* Optional conditionals. */
4050e3d5408SPeter Wemm 	switch (*arg) {
4060e3d5408SPeter Wemm 	case '<':
4070e3d5408SPeter Wemm 	    if (mapp->conditional & GT)
4080e3d5408SPeter Wemm 		goto badmopt;
4090e3d5408SPeter Wemm 	    mapp->conditional |= LT;
4100e3d5408SPeter Wemm 	    break;
4110e3d5408SPeter Wemm 	case '>':
4120e3d5408SPeter Wemm 	    if (mapp->conditional & LT)
4130e3d5408SPeter Wemm 		goto badmopt;
4140e3d5408SPeter Wemm 	    mapp->conditional |= GT;
4150e3d5408SPeter Wemm 	    break;
4160e3d5408SPeter Wemm 	case '@':
4170e3d5408SPeter Wemm 	case '=':		/* Not documented. */
4180e3d5408SPeter Wemm 	    mapp->conditional |= EQ;
4190e3d5408SPeter Wemm 	    break;
4200e3d5408SPeter Wemm 	case '!':
4210e3d5408SPeter Wemm 	    mapp->conditional |= NOT;
4220e3d5408SPeter Wemm 	    break;
4230e3d5408SPeter Wemm 	default:
4240e3d5408SPeter Wemm 	    goto next;
4250e3d5408SPeter Wemm 	}
42615589c42SPeter Wemm     }
4270e3d5408SPeter Wemm 
42815589c42SPeter Wemm   next:
42915589c42SPeter Wemm     if (*arg == ':') {
4300e3d5408SPeter Wemm 	if (mapp->conditional)
4310e3d5408SPeter Wemm 	    goto badmopt;
4320e3d5408SPeter Wemm 	++arg;
4330e3d5408SPeter Wemm     } else {			/* Optional baudrate. */
4340e3d5408SPeter Wemm 	arg = strchr(p = arg, ':');
4350e3d5408SPeter Wemm 	if (arg == 0)
4360e3d5408SPeter Wemm 	    goto badmopt;
4370e3d5408SPeter Wemm 	*arg++ = '\0';
4380e3d5408SPeter Wemm 	mapp->speed = tbaudrate(p);
4390e3d5408SPeter Wemm     }
4400e3d5408SPeter Wemm 
4410e3d5408SPeter Wemm     mapp->type = arg;
4420e3d5408SPeter Wemm 
4430e3d5408SPeter Wemm     /* Terminate porttype, if specified. */
4440e3d5408SPeter Wemm     if (termp != 0)
4450e3d5408SPeter Wemm 	*base = '\0';
4460e3d5408SPeter Wemm 
4470e3d5408SPeter Wemm     /* If a NOT conditional, reverse the test. */
4480e3d5408SPeter Wemm     if (mapp->conditional & NOT)
4490e3d5408SPeter Wemm 	mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
4500e3d5408SPeter Wemm 
4510e3d5408SPeter Wemm     /* If user specified a port with an option flag, set it. */
4525d08fb1fSRong-En Fan   done:
4535d08fb1fSRong-En Fan     if (port) {
4545d08fb1fSRong-En Fan 	if (mapp->porttype) {
4555d08fb1fSRong-En Fan 	  badmopt:
4565d08fb1fSRong-En Fan 	    err("illegal -m option format: %s", copy);
4575d08fb1fSRong-En Fan 	}
4580e3d5408SPeter Wemm 	mapp->porttype = port;
4590e3d5408SPeter Wemm     }
4605d08fb1fSRong-En Fan     free(copy);
4610e3d5408SPeter Wemm #ifdef MAPDEBUG
4620e3d5408SPeter Wemm     (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
4630e3d5408SPeter Wemm     (void) printf("type: %s\n", mapp->type);
4640e3d5408SPeter Wemm     (void) printf("conditional: ");
4650e3d5408SPeter Wemm     p = "";
4660e3d5408SPeter Wemm     if (mapp->conditional & GT) {
4670e3d5408SPeter Wemm 	(void) printf("GT");
4680e3d5408SPeter Wemm 	p = "/";
4690e3d5408SPeter Wemm     }
4700e3d5408SPeter Wemm     if (mapp->conditional & EQ) {
4710e3d5408SPeter Wemm 	(void) printf("%sEQ", p);
4720e3d5408SPeter Wemm 	p = "/";
4730e3d5408SPeter Wemm     }
4740e3d5408SPeter Wemm     if (mapp->conditional & LT)
4750e3d5408SPeter Wemm 	(void) printf("%sLT", p);
4760e3d5408SPeter Wemm     (void) printf("\nspeed: %d\n", mapp->speed);
4770e3d5408SPeter Wemm #endif
4780e3d5408SPeter Wemm }
4790e3d5408SPeter Wemm 
4800e3d5408SPeter Wemm /*
4810e3d5408SPeter Wemm  * Return the type of terminal to use for a port of type 'type', as specified
4820e3d5408SPeter Wemm  * by the first applicable mapping in 'map'.  If no mappings apply, return
4830e3d5408SPeter Wemm  * 'type'.
4840e3d5408SPeter Wemm  */
4850e3d5408SPeter Wemm static const char *
4860e3d5408SPeter Wemm mapped(const char *type)
4870e3d5408SPeter Wemm {
4880e3d5408SPeter Wemm     MAP *mapp;
4890e3d5408SPeter Wemm     int match;
4900e3d5408SPeter Wemm 
4910e3d5408SPeter Wemm     for (mapp = maplist; mapp; mapp = mapp->next)
4920e3d5408SPeter Wemm 	if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
4930e3d5408SPeter Wemm 	    switch (mapp->conditional) {
4940e3d5408SPeter Wemm 	    case 0:		/* No test specified. */
4950e3d5408SPeter Wemm 		match = TRUE;
4960e3d5408SPeter Wemm 		break;
4970e3d5408SPeter Wemm 	    case EQ:
49873f0a83dSXin LI 		match = ((int) ospeed == mapp->speed);
4990e3d5408SPeter Wemm 		break;
5000e3d5408SPeter Wemm 	    case GE:
50173f0a83dSXin LI 		match = ((int) ospeed >= mapp->speed);
5020e3d5408SPeter Wemm 		break;
5030e3d5408SPeter Wemm 	    case GT:
50473f0a83dSXin LI 		match = ((int) ospeed > mapp->speed);
5050e3d5408SPeter Wemm 		break;
5060e3d5408SPeter Wemm 	    case LE:
50773f0a83dSXin LI 		match = ((int) ospeed <= mapp->speed);
5080e3d5408SPeter Wemm 		break;
5090e3d5408SPeter Wemm 	    case LT:
51073f0a83dSXin LI 		match = ((int) ospeed < mapp->speed);
5110e3d5408SPeter Wemm 		break;
5120e3d5408SPeter Wemm 	    default:
5130e3d5408SPeter Wemm 		match = FALSE;
5140e3d5408SPeter Wemm 	    }
5150e3d5408SPeter Wemm 	    if (match)
5160e3d5408SPeter Wemm 		return (mapp->type);
5170e3d5408SPeter Wemm 	}
5180e3d5408SPeter Wemm     /* No match found; return given type. */
5190e3d5408SPeter Wemm     return (type);
5200e3d5408SPeter Wemm }
5210e3d5408SPeter Wemm 
5220e3d5408SPeter Wemm /**************************************************************************
5230e3d5408SPeter Wemm  *
5240e3d5408SPeter Wemm  * Entry fetching
5250e3d5408SPeter Wemm  *
5260e3d5408SPeter Wemm  **************************************************************************/
5270e3d5408SPeter Wemm 
5280e3d5408SPeter Wemm /*
5290e3d5408SPeter Wemm  * Figure out what kind of terminal we're dealing with, and then read in
5300e3d5408SPeter Wemm  * its termcap entry.
5310e3d5408SPeter Wemm  */
5320e3d5408SPeter Wemm static const char *
533*aae38d10SBaptiste Daroussin get_termcap_entry(int fd, char *userarg)
5340e3d5408SPeter Wemm {
5357a69bbfbSPeter Wemm     int errret;
5360e3d5408SPeter Wemm     char *p;
5370e3d5408SPeter Wemm     const char *ttype;
5380e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5390e3d5408SPeter Wemm     struct ttyent *t;
5400e3d5408SPeter Wemm #else
5410e3d5408SPeter Wemm     FILE *fp;
5420e3d5408SPeter Wemm #endif
5430e3d5408SPeter Wemm     char *ttypath;
5440e3d5408SPeter Wemm 
545*aae38d10SBaptiste Daroussin     (void) fd;
546*aae38d10SBaptiste Daroussin 
5470e3d5408SPeter Wemm     if (userarg) {
5480e3d5408SPeter Wemm 	ttype = userarg;
5490e3d5408SPeter Wemm 	goto found;
5500e3d5408SPeter Wemm     }
5510e3d5408SPeter Wemm 
5520e3d5408SPeter Wemm     /* Try the environment. */
5530e3d5408SPeter Wemm     if ((ttype = getenv("TERM")) != 0)
5540e3d5408SPeter Wemm 	goto map;
5550e3d5408SPeter Wemm 
556*aae38d10SBaptiste Daroussin     if ((ttypath = ttyname(fd)) != 0) {
55718259542SPeter Wemm 	p = _nc_basename(ttypath);
5580e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5590e3d5408SPeter Wemm 	/*
5600e3d5408SPeter Wemm 	 * We have the 4.3BSD library call getttynam(3); that means
5610e3d5408SPeter Wemm 	 * there's an /etc/ttys to look up device-to-type mappings in.
5620e3d5408SPeter Wemm 	 * Try ttyname(3); check for dialup or other mapping.
5630e3d5408SPeter Wemm 	 */
5640e3d5408SPeter Wemm 	if ((t = getttynam(p))) {
5650e3d5408SPeter Wemm 	    ttype = t->ty_type;
5660e3d5408SPeter Wemm 	    goto map;
5670e3d5408SPeter Wemm 	}
5680e3d5408SPeter Wemm #else
5690e3d5408SPeter Wemm 	if ((fp = fopen("/etc/ttytype", "r")) != 0
5700e3d5408SPeter Wemm 	    || (fp = fopen("/etc/ttys", "r")) != 0) {
5710e3d5408SPeter Wemm 	    char buffer[BUFSIZ];
5720e3d5408SPeter Wemm 	    char *s, *t, *d;
5730e3d5408SPeter Wemm 
5740e3d5408SPeter Wemm 	    while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
5750e3d5408SPeter Wemm 		for (s = buffer, t = d = 0; *s; s++) {
57639f2269fSPeter Wemm 		    if (isspace(UChar(*s)))
5770e3d5408SPeter Wemm 			*s = '\0';
5780e3d5408SPeter Wemm 		    else if (t == 0)
5790e3d5408SPeter Wemm 			t = s;
5800e3d5408SPeter Wemm 		    else if (d == 0 && s != buffer && s[-1] == '\0')
5810e3d5408SPeter Wemm 			d = s;
5820e3d5408SPeter Wemm 		}
5830e3d5408SPeter Wemm 		if (t != 0 && d != 0 && !strcmp(d, p)) {
5840e3d5408SPeter Wemm 		    ttype = strdup(t);
5850e3d5408SPeter Wemm 		    fclose(fp);
5860e3d5408SPeter Wemm 		    goto map;
5870e3d5408SPeter Wemm 		}
5880e3d5408SPeter Wemm 	    }
5890e3d5408SPeter Wemm 	    fclose(fp);
5900e3d5408SPeter Wemm 	}
5910e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */
5920e3d5408SPeter Wemm     }
5930e3d5408SPeter Wemm 
5940e3d5408SPeter Wemm     /* If still undefined, use "unknown". */
5950e3d5408SPeter Wemm     ttype = "unknown";
5960e3d5408SPeter Wemm 
5970e3d5408SPeter Wemm   map:ttype = mapped(ttype);
5980e3d5408SPeter Wemm 
5990e3d5408SPeter Wemm     /*
6000e3d5408SPeter Wemm      * If not a path, remove TERMCAP from the environment so we get a
6010e3d5408SPeter Wemm      * real entry from /etc/termcap.  This prevents us from being fooled
6020e3d5408SPeter Wemm      * by out of date stuff in the environment.
6030e3d5408SPeter Wemm      */
60473f0a83dSXin LI   found:
60573f0a83dSXin LI     if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
6060e3d5408SPeter Wemm 	/* 'unsetenv("TERMCAP")' is not portable.
6070e3d5408SPeter Wemm 	 * The 'environ' array is better.
6080e3d5408SPeter Wemm 	 */
6090e3d5408SPeter Wemm 	int n;
6100e3d5408SPeter Wemm 	for (n = 0; environ[n] != 0; n++) {
61173f0a83dSXin LI 	    if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
6120e3d5408SPeter Wemm 		while ((environ[n] = environ[n + 1]) != 0) {
6130e3d5408SPeter Wemm 		    n++;
6140e3d5408SPeter Wemm 		}
6150e3d5408SPeter Wemm 		break;
6160e3d5408SPeter Wemm 	    }
6170e3d5408SPeter Wemm 	}
6180e3d5408SPeter Wemm     }
6190e3d5408SPeter Wemm 
6200e3d5408SPeter Wemm     /*
6210e3d5408SPeter Wemm      * ttype now contains a pointer to the type of the terminal.
6220e3d5408SPeter Wemm      * If the first character is '?', ask the user.
6230e3d5408SPeter Wemm      */
6240e3d5408SPeter Wemm     if (ttype[0] == '?') {
6250e3d5408SPeter Wemm 	if (ttype[1] != '\0')
6260e3d5408SPeter Wemm 	    ttype = askuser(ttype + 1);
6270e3d5408SPeter Wemm 	else
6280e3d5408SPeter Wemm 	    ttype = askuser(0);
6290e3d5408SPeter Wemm     }
6300e3d5408SPeter Wemm     /* Find the terminfo entry.  If it doesn't exist, ask the user. */
631*aae38d10SBaptiste Daroussin     while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
6327a69bbfbSPeter Wemm 	   != OK) {
6330e3d5408SPeter Wemm 	if (errret == 0) {
6344a1a9510SRong-En Fan 	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
6354a1a9510SRong-En Fan 			   _nc_progname, ttype);
6360e3d5408SPeter Wemm 	    ttype = 0;
63715589c42SPeter Wemm 	} else {
63815589c42SPeter Wemm 	    (void) fprintf(stderr,
6394a1a9510SRong-En Fan 			   "%s: can't initialize terminal type %s (error %d)\n",
6404a1a9510SRong-En Fan 			   _nc_progname, ttype, errret);
6410e3d5408SPeter Wemm 	    ttype = 0;
6420e3d5408SPeter Wemm 	}
6430e3d5408SPeter Wemm 	ttype = askuser(ttype);
6440e3d5408SPeter Wemm     }
6450e3d5408SPeter Wemm #if BROKEN_LINKER
6460e3d5408SPeter Wemm     tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */
6470e3d5408SPeter Wemm #endif
6480e3d5408SPeter Wemm     return (ttype);
6490e3d5408SPeter Wemm }
6500e3d5408SPeter Wemm 
6510e3d5408SPeter Wemm /**************************************************************************
6520e3d5408SPeter Wemm  *
6530e3d5408SPeter Wemm  * Main sequence
6540e3d5408SPeter Wemm  *
6550e3d5408SPeter Wemm  **************************************************************************/
6560e3d5408SPeter Wemm 
6570e3d5408SPeter Wemm /*
6580e3d5408SPeter Wemm  * Convert the obsolete argument forms into something that getopt can handle.
6590e3d5408SPeter Wemm  * This means that -e, -i and -k get default arguments supplied for them.
6600e3d5408SPeter Wemm  */
6610e3d5408SPeter Wemm static void
6620e3d5408SPeter Wemm obsolete(char **argv)
6630e3d5408SPeter Wemm {
6640e3d5408SPeter Wemm     for (; *argv; ++argv) {
6650e3d5408SPeter Wemm 	char *parm = argv[0];
6660e3d5408SPeter Wemm 
66715589c42SPeter Wemm 	if (parm[0] == '-' && parm[1] == '\0') {
6680e3d5408SPeter Wemm 	    argv[0] = strdup("-q");
6690e3d5408SPeter Wemm 	    continue;
6700e3d5408SPeter Wemm 	}
6710e3d5408SPeter Wemm 
6720e3d5408SPeter Wemm 	if ((parm[0] != '-')
6730e3d5408SPeter Wemm 	    || (argv[1] && argv[1][0] != '-')
6740e3d5408SPeter Wemm 	    || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
6750e3d5408SPeter Wemm 	    || (parm[2] != '\0'))
6760e3d5408SPeter Wemm 	    continue;
6770e3d5408SPeter Wemm 	switch (argv[0][1]) {
6780e3d5408SPeter Wemm 	case 'e':
6790e3d5408SPeter Wemm 	    argv[0] = strdup("-e^H");
6800e3d5408SPeter Wemm 	    break;
6810e3d5408SPeter Wemm 	case 'i':
6820e3d5408SPeter Wemm 	    argv[0] = strdup("-i^C");
6830e3d5408SPeter Wemm 	    break;
6840e3d5408SPeter Wemm 	case 'k':
6850e3d5408SPeter Wemm 	    argv[0] = strdup("-k^U");
6860e3d5408SPeter Wemm 	    break;
6870e3d5408SPeter Wemm 	}
6880e3d5408SPeter Wemm     }
6890e3d5408SPeter Wemm }
6900e3d5408SPeter Wemm 
6910e3d5408SPeter Wemm static void
692*aae38d10SBaptiste Daroussin print_shell_commands(const char *ttype)
693*aae38d10SBaptiste Daroussin {
694*aae38d10SBaptiste Daroussin     const char *p;
695*aae38d10SBaptiste Daroussin     int len;
696*aae38d10SBaptiste Daroussin     char *var;
697*aae38d10SBaptiste Daroussin     char *leaf;
698*aae38d10SBaptiste Daroussin     /*
699*aae38d10SBaptiste Daroussin      * Figure out what shell we're using.  A hack, we look for an
700*aae38d10SBaptiste Daroussin      * environmental variable SHELL ending in "csh".
701*aae38d10SBaptiste Daroussin      */
702*aae38d10SBaptiste Daroussin     if ((var = getenv("SHELL")) != 0
703*aae38d10SBaptiste Daroussin 	&& ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
704*aae38d10SBaptiste Daroussin 	&& !strcmp(leaf + len - 3, "csh"))
705*aae38d10SBaptiste Daroussin 	p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
706*aae38d10SBaptiste Daroussin     else
707*aae38d10SBaptiste Daroussin 	p = "TERM=%s;\n";
708*aae38d10SBaptiste Daroussin     (void) printf(p, ttype);
709*aae38d10SBaptiste Daroussin }
710*aae38d10SBaptiste Daroussin 
711*aae38d10SBaptiste Daroussin static void
7124a1a9510SRong-En Fan usage(void)
7130e3d5408SPeter Wemm {
714*aae38d10SBaptiste Daroussin #define SKIP(s)			/* nothing */
715*aae38d10SBaptiste Daroussin #define KEEP(s) s "\n"
716*aae38d10SBaptiste Daroussin     static const char msg[] =
7174a1a9510SRong-En Fan     {
718*aae38d10SBaptiste Daroussin 	KEEP("")
719*aae38d10SBaptiste Daroussin 	KEEP("Options:")
720*aae38d10SBaptiste Daroussin 	SKIP("  -a arpanet  (obsolete)")
721*aae38d10SBaptiste Daroussin 	KEEP("  -c          set control characters")
722*aae38d10SBaptiste Daroussin 	SKIP("  -d dialup   (obsolete)")
723*aae38d10SBaptiste Daroussin 	KEEP("  -e ch       erase character")
724*aae38d10SBaptiste Daroussin 	KEEP("  -I          no initialization strings")
725*aae38d10SBaptiste Daroussin 	KEEP("  -i ch       interrupt character")
726*aae38d10SBaptiste Daroussin 	KEEP("  -k ch       kill character")
727*aae38d10SBaptiste Daroussin 	KEEP("  -m mapping  map identifier to type")
728*aae38d10SBaptiste Daroussin 	SKIP("  -p plugboard (obsolete)")
729*aae38d10SBaptiste Daroussin 	KEEP("  -Q          do not output control key settings")
730*aae38d10SBaptiste Daroussin 	KEEP("  -q          display term only, do no changes")
731*aae38d10SBaptiste Daroussin 	KEEP("  -r          display term on stderr")
732*aae38d10SBaptiste Daroussin 	SKIP("  -S          (obsolete)")
733*aae38d10SBaptiste Daroussin 	KEEP("  -s          output TERM set command")
734*aae38d10SBaptiste Daroussin 	KEEP("  -V          print curses-version")
735*aae38d10SBaptiste Daroussin 	KEEP("  -w          set window-size")
736*aae38d10SBaptiste Daroussin 	KEEP("")
737*aae38d10SBaptiste Daroussin 	KEEP("If neither -c/-w are given, both are assumed.")
7384a1a9510SRong-En Fan     };
739*aae38d10SBaptiste Daroussin #undef KEEP
740*aae38d10SBaptiste Daroussin #undef SKIP
7414a1a9510SRong-En Fan     (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
742*aae38d10SBaptiste Daroussin     fputs(msg, stderr);
743*aae38d10SBaptiste Daroussin     ExitProgram(EXIT_FAILURE);
74439f2269fSPeter Wemm     /* NOTREACHED */
7450e3d5408SPeter Wemm }
7460e3d5408SPeter Wemm 
74715589c42SPeter Wemm static char
74815589c42SPeter Wemm arg_to_char(void)
7490e3d5408SPeter Wemm {
7505d08fb1fSRong-En Fan     return (char) ((optarg[0] == '^' && optarg[1] != '\0')
7510e3d5408SPeter Wemm 		   ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
7525d08fb1fSRong-En Fan 		   : optarg[0]);
7530e3d5408SPeter Wemm }
7540e3d5408SPeter Wemm 
7550e3d5408SPeter Wemm int
7560e3d5408SPeter Wemm main(int argc, char **argv)
7570e3d5408SPeter Wemm {
7580e3d5408SPeter Wemm     int ch, noinit, noset, quiet, Sflag, sflag, showterm;
7590e3d5408SPeter Wemm     const char *ttype;
760*aae38d10SBaptiste Daroussin     int terasechar = -1;	/* new erase character */
761*aae38d10SBaptiste Daroussin     int intrchar = -1;		/* new interrupt character */
762*aae38d10SBaptiste Daroussin     int tkillchar = -1;		/* new kill character */
763*aae38d10SBaptiste Daroussin     int my_fd;
764*aae38d10SBaptiste Daroussin     bool opt_c = FALSE;		/* set control-chars */
765*aae38d10SBaptiste Daroussin     bool opt_w = FALSE;		/* set window-size */
766*aae38d10SBaptiste Daroussin     TTY mode, oldmode;
7670e3d5408SPeter Wemm 
768*aae38d10SBaptiste Daroussin     my_fd = STDERR_FILENO;
7690e3d5408SPeter Wemm     obsolete(argv);
7700e3d5408SPeter Wemm     noinit = noset = quiet = Sflag = sflag = showterm = 0;
771*aae38d10SBaptiste Daroussin     while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
7720e3d5408SPeter Wemm 	switch (ch) {
7734a1a9510SRong-En Fan 	case 'c':		/* set control-chars */
7744a1a9510SRong-En Fan 	    opt_c = TRUE;
7750e3d5408SPeter Wemm 	    break;
7760e3d5408SPeter Wemm 	case 'a':		/* OBSOLETE: map identifier to type */
7770e3d5408SPeter Wemm 	    add_mapping("arpanet", optarg);
7780e3d5408SPeter Wemm 	    break;
7790e3d5408SPeter Wemm 	case 'd':		/* OBSOLETE: map identifier to type */
7800e3d5408SPeter Wemm 	    add_mapping("dialup", optarg);
7810e3d5408SPeter Wemm 	    break;
7820e3d5408SPeter Wemm 	case 'e':		/* erase character */
7830e3d5408SPeter Wemm 	    terasechar = arg_to_char();
7840e3d5408SPeter Wemm 	    break;
7850e3d5408SPeter Wemm 	case 'I':		/* no initialization strings */
7860e3d5408SPeter Wemm 	    noinit = 1;
7870e3d5408SPeter Wemm 	    break;
7880e3d5408SPeter Wemm 	case 'i':		/* interrupt character */
7890e3d5408SPeter Wemm 	    intrchar = arg_to_char();
7900e3d5408SPeter Wemm 	    break;
7910e3d5408SPeter Wemm 	case 'k':		/* kill character */
7920e3d5408SPeter Wemm 	    tkillchar = arg_to_char();
7930e3d5408SPeter Wemm 	    break;
7940e3d5408SPeter Wemm 	case 'm':		/* map identifier to type */
7950e3d5408SPeter Wemm 	    add_mapping(0, optarg);
7960e3d5408SPeter Wemm 	    break;
7970e3d5408SPeter Wemm 	case 'p':		/* OBSOLETE: map identifier to type */
7980e3d5408SPeter Wemm 	    add_mapping("plugboard", optarg);
7990e3d5408SPeter Wemm 	    break;
8000e3d5408SPeter Wemm 	case 'Q':		/* don't output control key settings */
8010e3d5408SPeter Wemm 	    quiet = 1;
8020e3d5408SPeter Wemm 	    break;
8034a1a9510SRong-En Fan 	case 'q':		/* display term only */
8044a1a9510SRong-En Fan 	    noset = 1;
8050e3d5408SPeter Wemm 	    break;
8060e3d5408SPeter Wemm 	case 'r':		/* display term on stderr */
8070e3d5408SPeter Wemm 	    showterm = 1;
8080e3d5408SPeter Wemm 	    break;
8094a1a9510SRong-En Fan 	case 'S':		/* OBSOLETE: output TERM & TERMCAP */
8104a1a9510SRong-En Fan 	    Sflag = 1;
8114a1a9510SRong-En Fan 	    break;
8120e3d5408SPeter Wemm 	case 's':		/* output TERM set command */
8130e3d5408SPeter Wemm 	    sflag = 1;
8140e3d5408SPeter Wemm 	    break;
8154a1a9510SRong-En Fan 	case 'V':		/* print curses-version */
81618259542SPeter Wemm 	    puts(curses_version());
8174a1a9510SRong-En Fan 	    ExitProgram(EXIT_SUCCESS);
8184a1a9510SRong-En Fan 	case 'w':		/* set window-size */
8194a1a9510SRong-En Fan 	    opt_w = TRUE;
8204a1a9510SRong-En Fan 	    break;
8210e3d5408SPeter Wemm 	case '?':
8220e3d5408SPeter Wemm 	default:
8234a1a9510SRong-En Fan 	    usage();
8240e3d5408SPeter Wemm 	}
8250e3d5408SPeter Wemm     }
8264a1a9510SRong-En Fan 
8274a1a9510SRong-En Fan     _nc_progname = _nc_rootname(*argv);
8280e3d5408SPeter Wemm     argc -= optind;
8290e3d5408SPeter Wemm     argv += optind;
8300e3d5408SPeter Wemm 
8310e3d5408SPeter Wemm     if (argc > 1)
8324a1a9510SRong-En Fan 	usage();
8334a1a9510SRong-En Fan 
8344a1a9510SRong-En Fan     if (!opt_c && !opt_w)
8354a1a9510SRong-En Fan 	opt_c = opt_w = TRUE;
8364a1a9510SRong-En Fan 
837*aae38d10SBaptiste Daroussin     my_fd = save_tty_settings(&mode, TRUE);
838*aae38d10SBaptiste Daroussin     oldmode = mode;
8394a1a9510SRong-En Fan #ifdef TERMIOS
8405d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
8414a1a9510SRong-En Fan #else
8425d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
8434a1a9510SRong-En Fan #endif
8444a1a9510SRong-En Fan 
84506bfebdeSXin LI     if (same_program(_nc_progname, PROG_RESET)) {
846*aae38d10SBaptiste Daroussin 	reset_start(stderr, TRUE, FALSE);
847*aae38d10SBaptiste Daroussin 	reset_tty_settings(my_fd, &mode);
848*aae38d10SBaptiste Daroussin     } else {
849*aae38d10SBaptiste Daroussin 	reset_start(stderr, FALSE, TRUE);
8504a1a9510SRong-En Fan     }
8510e3d5408SPeter Wemm 
852*aae38d10SBaptiste Daroussin     ttype = get_termcap_entry(my_fd, *argv);
8530e3d5408SPeter Wemm 
8540e3d5408SPeter Wemm     if (!noset) {
85573f0a83dSXin LI #if HAVE_SIZECHANGE
8564a1a9510SRong-En Fan 	if (opt_w) {
857*aae38d10SBaptiste Daroussin 	    set_window_size(my_fd, &lines, &columns);
8584a1a9510SRong-En Fan 	}
8590e3d5408SPeter Wemm #endif
8604a1a9510SRong-En Fan 	if (opt_c) {
861*aae38d10SBaptiste Daroussin 	    set_control_chars(&mode, terasechar, intrchar, tkillchar);
862*aae38d10SBaptiste Daroussin 	    set_conversions(&mode);
8630e3d5408SPeter Wemm 
864*aae38d10SBaptiste Daroussin 	    if (!noinit) {
865*aae38d10SBaptiste Daroussin 		if (send_init_strings(my_fd, &oldmode)) {
866*aae38d10SBaptiste Daroussin 		    (void) putc('\r', stderr);
867*aae38d10SBaptiste Daroussin 		    (void) fflush(stderr);
868*aae38d10SBaptiste Daroussin 		    (void) napms(1000);		/* Settle the terminal. */
8690e3d5408SPeter Wemm 		}
87015589c42SPeter Wemm 	    }
871*aae38d10SBaptiste Daroussin 
872*aae38d10SBaptiste Daroussin 	    update_tty_settings(&oldmode, &mode);
873*aae38d10SBaptiste Daroussin 	}
8744a1a9510SRong-En Fan     }
8750e3d5408SPeter Wemm 
876*aae38d10SBaptiste Daroussin     if (noset) {
8770e3d5408SPeter Wemm 	(void) printf("%s\n", ttype);
878*aae38d10SBaptiste Daroussin     } else {
8790e3d5408SPeter Wemm 	if (showterm)
8800e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
8810e3d5408SPeter Wemm 	/*
8820e3d5408SPeter Wemm 	 * If erase, kill and interrupt characters could have been
8830e3d5408SPeter Wemm 	 * modified and not -Q, display the changes.
8840e3d5408SPeter Wemm 	 */
8850e3d5408SPeter Wemm 	if (!quiet) {
886*aae38d10SBaptiste Daroussin 	    print_tty_chars(&oldmode, &mode);
8870e3d5408SPeter Wemm 	}
8880e3d5408SPeter Wemm     }
8890e3d5408SPeter Wemm 
8900e3d5408SPeter Wemm     if (Sflag)
8910e3d5408SPeter Wemm 	err("The -S option is not supported under terminfo.");
8920e3d5408SPeter Wemm 
8930e3d5408SPeter Wemm     if (sflag) {
894*aae38d10SBaptiste Daroussin 	print_shell_commands(ttype);
8950e3d5408SPeter Wemm     }
8960e3d5408SPeter Wemm 
8974a1a9510SRong-En Fan     ExitProgram(EXIT_SUCCESS);
8980e3d5408SPeter Wemm }
899