xref: /freebsd/contrib/ncurses/progs/tset.c (revision e18651243efbc1fe285af34e4937fd697612f1c7)
10e3d5408SPeter Wemm /****************************************************************************
2*e1865124SBaptiste Daroussin  * Copyright 2020 Thomas E. Dickey                                          *
3*e1865124SBaptiste Daroussin  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
40e3d5408SPeter Wemm  *                                                                          *
50e3d5408SPeter Wemm  * Permission is hereby granted, free of charge, to any person obtaining a  *
60e3d5408SPeter Wemm  * copy of this software and associated documentation files (the            *
70e3d5408SPeter Wemm  * "Software"), to deal in the Software without restriction, including      *
80e3d5408SPeter Wemm  * without limitation the rights to use, copy, modify, merge, publish,      *
90e3d5408SPeter Wemm  * distribute, distribute with modifications, sublicense, and/or sell       *
100e3d5408SPeter Wemm  * copies of the Software, and to permit persons to whom the Software is    *
110e3d5408SPeter Wemm  * furnished to do so, subject to the following conditions:                 *
120e3d5408SPeter Wemm  *                                                                          *
130e3d5408SPeter Wemm  * The above copyright notice and this permission notice shall be included  *
140e3d5408SPeter Wemm  * in all copies or substantial portions of the Software.                   *
150e3d5408SPeter Wemm  *                                                                          *
160e3d5408SPeter Wemm  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
170e3d5408SPeter Wemm  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
180e3d5408SPeter Wemm  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
190e3d5408SPeter Wemm  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
200e3d5408SPeter Wemm  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
210e3d5408SPeter Wemm  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
220e3d5408SPeter Wemm  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
230e3d5408SPeter Wemm  *                                                                          *
240e3d5408SPeter Wemm  * Except as contained in this notice, the name(s) of the above copyright   *
250e3d5408SPeter Wemm  * holders shall not be used in advertising or otherwise to promote the     *
260e3d5408SPeter Wemm  * sale, use or other dealings in this Software without prior written       *
270e3d5408SPeter Wemm  * authorization.                                                           *
280e3d5408SPeter Wemm  ****************************************************************************/
290e3d5408SPeter Wemm 
300e3d5408SPeter Wemm /****************************************************************************
310e3d5408SPeter Wemm  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
320e3d5408SPeter Wemm  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
334a1a9510SRong-En Fan  *     and: Thomas E. Dickey                        1996-on                 *
340e3d5408SPeter Wemm  ****************************************************************************/
350e3d5408SPeter Wemm 
360e3d5408SPeter Wemm /*
3706bfebdeSXin LI  * Notes:
3806bfebdeSXin LI  * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686
3906bfebdeSXin LI  * lines from that version, and made changes/additions for 150 lines.  There
4006bfebdeSXin LI  * was no reformatting, so with/without ignoring whitespace, the amount of
4106bfebdeSXin LI  * change is the same.
4206bfebdeSXin LI  *
4306bfebdeSXin LI  * Comparing with current (2009) source, excluding this comment:
4406bfebdeSXin LI  * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines
4506bfebdeSXin LI  *    changed/added.
4606bfebdeSXin LI  * a) Ignoring whitespace, the current version still uses 516 lines from the
4706bfebdeSXin LI  *    4.4BSD Lite sources, with 402 lines changed/added.
4806bfebdeSXin LI  *
4906bfebdeSXin LI  * Raymond's original comment on this follows...
5006bfebdeSXin LI  */
5106bfebdeSXin LI 
5206bfebdeSXin LI /*
530e3d5408SPeter Wemm  * tset.c - terminal initialization utility
540e3d5408SPeter Wemm  *
550e3d5408SPeter Wemm  * This code was mostly swiped from 4.4BSD tset, with some obsolescent
560e3d5408SPeter Wemm  * cruft removed and substantial portions rewritten.  A Regents of the
570e3d5408SPeter Wemm  * University of California copyright applies to some portions of the
580e3d5408SPeter Wemm  * code, and is reproduced below:
590e3d5408SPeter Wemm  */
600e3d5408SPeter Wemm /*-
610e3d5408SPeter Wemm  * Copyright (c) 1980, 1991, 1993
620e3d5408SPeter Wemm  *	The Regents of the University of California.  All rights reserved.
630e3d5408SPeter Wemm  *
640e3d5408SPeter Wemm  * Redistribution and use in source and binary forms, with or without
650e3d5408SPeter Wemm  * modification, are permitted provided that the following conditions
660e3d5408SPeter Wemm  * are met:
670e3d5408SPeter Wemm  * 1. Redistributions of source code must retain the above copyright
680e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer.
690e3d5408SPeter Wemm  * 2. Redistributions in binary form must reproduce the above copyright
700e3d5408SPeter Wemm  *    notice, this list of conditions and the following disclaimer in the
710e3d5408SPeter Wemm  *    documentation and/or other materials provided with the distribution.
7206bfebdeSXin LI  * 3. Neither the name of the University nor the names of its contributors
730e3d5408SPeter Wemm  *    may be used to endorse or promote products derived from this software
740e3d5408SPeter Wemm  *    without specific prior written permission.
750e3d5408SPeter Wemm  *
760e3d5408SPeter Wemm  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
770e3d5408SPeter Wemm  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
780e3d5408SPeter Wemm  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
790e3d5408SPeter Wemm  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
800e3d5408SPeter Wemm  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
810e3d5408SPeter Wemm  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
820e3d5408SPeter Wemm  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
830e3d5408SPeter Wemm  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
840e3d5408SPeter Wemm  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
850e3d5408SPeter Wemm  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
860e3d5408SPeter Wemm  * SUCH DAMAGE.
870e3d5408SPeter Wemm  */
880e3d5408SPeter Wemm 
89aae38d10SBaptiste Daroussin #include <reset_cmd.h>
900e3d5408SPeter Wemm #include <termcap.h>
91aae38d10SBaptiste Daroussin #include <transform.h>
92aae38d10SBaptiste Daroussin #include <tty_settings.h>
930e3d5408SPeter Wemm 
940e3d5408SPeter Wemm #if HAVE_GETTTYNAM && HAVE_TTYENT_H
950e3d5408SPeter Wemm #include <ttyent.h>
960e3d5408SPeter Wemm #endif
970e3d5408SPeter Wemm #ifdef NeXT
980e3d5408SPeter Wemm char *ttyname(int fd);
990e3d5408SPeter Wemm #endif
1000e3d5408SPeter Wemm 
101*e1865124SBaptiste Daroussin MODULE_ID("$Id: tset.c,v 1.121 2020/02/02 23:34:34 tom Exp $")
1020e3d5408SPeter Wemm 
10306bfebdeSXin LI #ifndef environ
1040e3d5408SPeter Wemm extern char **environ;
10506bfebdeSXin LI #endif
1060e3d5408SPeter Wemm 
1070e3d5408SPeter Wemm const char *_nc_progname = "tset";
1080e3d5408SPeter Wemm 
10939f2269fSPeter Wemm #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))
1100e3d5408SPeter Wemm 
111aae38d10SBaptiste Daroussin static void exit_error(void) GCC_NORETURN;
112aae38d10SBaptiste Daroussin 
1130e3d5408SPeter Wemm static int
11415589c42SPeter Wemm CaselessCmp(const char *a, const char *b)
11515589c42SPeter Wemm {				/* strcasecmp isn't portable */
1160e3d5408SPeter Wemm     while (*a && *b) {
1170e3d5408SPeter Wemm 	int cmp = LOWERCASE(*a) - LOWERCASE(*b);
1180e3d5408SPeter Wemm 	if (cmp != 0)
1190e3d5408SPeter Wemm 	    break;
1200e3d5408SPeter Wemm 	a++, b++;
1210e3d5408SPeter Wemm     }
1220e3d5408SPeter Wemm     return LOWERCASE(*a) - LOWERCASE(*b);
1230e3d5408SPeter Wemm }
1240e3d5408SPeter Wemm 
1250e3d5408SPeter Wemm static void
12639f2269fSPeter Wemm exit_error(void)
12739f2269fSPeter Wemm {
128aae38d10SBaptiste Daroussin     restore_tty_settings();
12939f2269fSPeter Wemm     (void) fprintf(stderr, "\n");
13039f2269fSPeter Wemm     fflush(stderr);
1314a1a9510SRong-En Fan     ExitProgram(EXIT_FAILURE);
13239f2269fSPeter Wemm     /* NOTREACHED */
13339f2269fSPeter Wemm }
13439f2269fSPeter Wemm 
13539f2269fSPeter Wemm static void
1360e3d5408SPeter Wemm err(const char *fmt,...)
1370e3d5408SPeter Wemm {
1380e3d5408SPeter Wemm     va_list ap;
1390e3d5408SPeter Wemm     va_start(ap, fmt);
1404a1a9510SRong-En Fan     (void) fprintf(stderr, "%s: ", _nc_progname);
1410e3d5408SPeter Wemm     (void) vfprintf(stderr, fmt, ap);
1420e3d5408SPeter Wemm     va_end(ap);
14339f2269fSPeter Wemm     exit_error();
1440e3d5408SPeter Wemm     /* NOTREACHED */
1450e3d5408SPeter Wemm }
1460e3d5408SPeter Wemm 
1470e3d5408SPeter Wemm static void
1480e3d5408SPeter Wemm failed(const char *msg)
1490e3d5408SPeter Wemm {
1500e3d5408SPeter Wemm     char temp[BUFSIZ];
15173f0a83dSXin LI     size_t len = strlen(_nc_progname) + 2;
1524a1a9510SRong-En Fan 
1535d08fb1fSRong-En Fan     if ((int) len < (int) sizeof(temp) - 12) {
15473f0a83dSXin LI 	_nc_STRCPY(temp, _nc_progname, sizeof(temp));
15573f0a83dSXin LI 	_nc_STRCAT(temp, ": ", sizeof(temp));
1564a1a9510SRong-En Fan     } else {
15773f0a83dSXin LI 	_nc_STRCPY(temp, "tset: ", sizeof(temp));
1584a1a9510SRong-En Fan     }
159aae38d10SBaptiste Daroussin     _nc_STRNCAT(temp, msg, sizeof(temp), sizeof(temp) - strlen(temp) - 2);
160aae38d10SBaptiste Daroussin     perror(temp);
16139f2269fSPeter Wemm     exit_error();
1620e3d5408SPeter Wemm     /* NOTREACHED */
1630e3d5408SPeter Wemm }
1640e3d5408SPeter Wemm 
1650e3d5408SPeter Wemm /* Prompt the user for a terminal type. */
1660e3d5408SPeter Wemm static const char *
1670e3d5408SPeter Wemm askuser(const char *dflt)
1680e3d5408SPeter Wemm {
1690e3d5408SPeter Wemm     static char answer[256];
1700e3d5408SPeter Wemm     char *p;
1710e3d5408SPeter Wemm 
1720e3d5408SPeter Wemm     /* We can get recalled; if so, don't continue uselessly. */
1734a1a9510SRong-En Fan     clearerr(stdin);
1740e3d5408SPeter Wemm     if (feof(stdin) || ferror(stdin)) {
1750e3d5408SPeter Wemm 	(void) fprintf(stderr, "\n");
17639f2269fSPeter Wemm 	exit_error();
17739f2269fSPeter Wemm 	/* NOTREACHED */
1780e3d5408SPeter Wemm     }
1790e3d5408SPeter Wemm     for (;;) {
1800e3d5408SPeter Wemm 	if (dflt)
1810e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
1820e3d5408SPeter Wemm 	else
1830e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? ");
1840e3d5408SPeter Wemm 	(void) fflush(stderr);
1850e3d5408SPeter Wemm 
1860e3d5408SPeter Wemm 	if (fgets(answer, sizeof(answer), stdin) == 0) {
1870e3d5408SPeter Wemm 	    if (dflt == 0) {
18839f2269fSPeter Wemm 		exit_error();
18939f2269fSPeter Wemm 		/* NOTREACHED */
1900e3d5408SPeter Wemm 	    }
1910e3d5408SPeter Wemm 	    return (dflt);
1920e3d5408SPeter Wemm 	}
1930e3d5408SPeter Wemm 
1940e3d5408SPeter Wemm 	if ((p = strchr(answer, '\n')) != 0)
1950e3d5408SPeter Wemm 	    *p = '\0';
1960e3d5408SPeter Wemm 	if (answer[0])
1970e3d5408SPeter Wemm 	    return (answer);
1980e3d5408SPeter Wemm 	if (dflt != 0)
1990e3d5408SPeter Wemm 	    return (dflt);
2000e3d5408SPeter Wemm     }
2010e3d5408SPeter Wemm }
2020e3d5408SPeter Wemm 
2030e3d5408SPeter Wemm /**************************************************************************
2040e3d5408SPeter Wemm  *
2050e3d5408SPeter Wemm  * Mapping logic begins here
2060e3d5408SPeter Wemm  *
2070e3d5408SPeter Wemm  **************************************************************************/
2080e3d5408SPeter Wemm 
2090e3d5408SPeter Wemm /* Baud rate conditionals for mapping. */
2100e3d5408SPeter Wemm #define	GT		0x01
2110e3d5408SPeter Wemm #define	EQ		0x02
2120e3d5408SPeter Wemm #define	LT		0x04
2130e3d5408SPeter Wemm #define	NOT		0x08
2140e3d5408SPeter Wemm #define	GE		(GT | EQ)
2150e3d5408SPeter Wemm #define	LE		(LT | EQ)
2160e3d5408SPeter Wemm 
2170e3d5408SPeter Wemm typedef struct map {
2180e3d5408SPeter Wemm     struct map *next;		/* Linked list of maps. */
2190e3d5408SPeter Wemm     const char *porttype;	/* Port type, or "" for any. */
2200e3d5408SPeter Wemm     const char *type;		/* Terminal type to select. */
2210e3d5408SPeter Wemm     int conditional;		/* Baud rate conditionals bitmask. */
22218259542SPeter Wemm     int speed;			/* Baud rate to compare against. */
2230e3d5408SPeter Wemm } MAP;
2240e3d5408SPeter Wemm 
2250e3d5408SPeter Wemm static MAP *cur, *maplist;
2260e3d5408SPeter Wemm 
227aae38d10SBaptiste Daroussin #define DATA(name,value) { { name }, value }
228aae38d10SBaptiste Daroussin 
2290e3d5408SPeter Wemm typedef struct speeds {
230aae38d10SBaptiste Daroussin     const char string[7];
2310e3d5408SPeter Wemm     int speed;
2320e3d5408SPeter Wemm } SPEEDS;
2330e3d5408SPeter Wemm 
23415589c42SPeter Wemm static const SPEEDS speeds[] =
23515589c42SPeter Wemm {
236aae38d10SBaptiste Daroussin     DATA("0", B0),
237aae38d10SBaptiste Daroussin     DATA("50", B50),
238aae38d10SBaptiste Daroussin     DATA("75", B75),
239aae38d10SBaptiste Daroussin     DATA("110", B110),
240aae38d10SBaptiste Daroussin     DATA("134", B134),
241aae38d10SBaptiste Daroussin     DATA("134.5", B134),
242aae38d10SBaptiste Daroussin     DATA("150", B150),
243aae38d10SBaptiste Daroussin     DATA("200", B200),
244aae38d10SBaptiste Daroussin     DATA("300", B300),
245aae38d10SBaptiste Daroussin     DATA("600", B600),
246aae38d10SBaptiste Daroussin     DATA("1200", B1200),
247aae38d10SBaptiste Daroussin     DATA("1800", B1800),
248aae38d10SBaptiste Daroussin     DATA("2400", B2400),
249aae38d10SBaptiste Daroussin     DATA("4800", B4800),
250aae38d10SBaptiste Daroussin     DATA("9600", B9600),
25118259542SPeter Wemm     /* sgttyb may define up to this point */
25218259542SPeter Wemm #ifdef B19200
253aae38d10SBaptiste Daroussin     DATA("19200", B19200),
25418259542SPeter Wemm #endif
25518259542SPeter Wemm #ifdef B38400
256aae38d10SBaptiste Daroussin     DATA("38400", B38400),
25718259542SPeter Wemm #endif
25818259542SPeter Wemm #ifdef B19200
259aae38d10SBaptiste Daroussin     DATA("19200", B19200),
26018259542SPeter Wemm #endif
26118259542SPeter Wemm #ifdef B38400
262aae38d10SBaptiste Daroussin     DATA("38400", B38400),
26318259542SPeter Wemm #endif
2640e3d5408SPeter Wemm #ifdef B19200
265aae38d10SBaptiste Daroussin     DATA("19200", B19200),
2660e3d5408SPeter Wemm #else
2670e3d5408SPeter Wemm #ifdef EXTA
268aae38d10SBaptiste Daroussin     DATA("19200", EXTA),
2690e3d5408SPeter Wemm #endif
2700e3d5408SPeter Wemm #endif
2710e3d5408SPeter Wemm #ifdef B38400
272aae38d10SBaptiste Daroussin     DATA("38400", B38400),
2730e3d5408SPeter Wemm #else
2740e3d5408SPeter Wemm #ifdef EXTB
275aae38d10SBaptiste Daroussin     DATA("38400", EXTB),
2760e3d5408SPeter Wemm #endif
2770e3d5408SPeter Wemm #endif
2780e3d5408SPeter Wemm #ifdef B57600
279aae38d10SBaptiste Daroussin     DATA("57600", B57600),
280aae38d10SBaptiste Daroussin #endif
281aae38d10SBaptiste Daroussin #ifdef B76800
282aae38d10SBaptiste Daroussin     DATA("76800", B57600),
2830e3d5408SPeter Wemm #endif
2840e3d5408SPeter Wemm #ifdef B115200
285aae38d10SBaptiste Daroussin     DATA("115200", B115200),
286aae38d10SBaptiste Daroussin #endif
287aae38d10SBaptiste Daroussin #ifdef B153600
288aae38d10SBaptiste Daroussin     DATA("153600", B153600),
2890e3d5408SPeter Wemm #endif
2900e3d5408SPeter Wemm #ifdef B230400
291aae38d10SBaptiste Daroussin     DATA("230400", B230400),
292aae38d10SBaptiste Daroussin #endif
293aae38d10SBaptiste Daroussin #ifdef B307200
294aae38d10SBaptiste Daroussin     DATA("307200", B307200),
2950e3d5408SPeter Wemm #endif
2960e3d5408SPeter Wemm #ifdef B460800
297aae38d10SBaptiste Daroussin     DATA("460800", B460800),
2980e3d5408SPeter Wemm #endif
299aae38d10SBaptiste Daroussin #ifdef B500000
300aae38d10SBaptiste Daroussin     DATA("500000", B500000),
301aae38d10SBaptiste Daroussin #endif
302aae38d10SBaptiste Daroussin #ifdef B576000
303aae38d10SBaptiste Daroussin     DATA("576000", B576000),
304aae38d10SBaptiste Daroussin #endif
305aae38d10SBaptiste Daroussin #ifdef B921600
306aae38d10SBaptiste Daroussin     DATA("921600", B921600),
307aae38d10SBaptiste Daroussin #endif
308aae38d10SBaptiste Daroussin #ifdef B1000000
309aae38d10SBaptiste Daroussin     DATA("1000000", B1000000),
310aae38d10SBaptiste Daroussin #endif
311aae38d10SBaptiste Daroussin #ifdef B1152000
312aae38d10SBaptiste Daroussin     DATA("1152000", B1152000),
313aae38d10SBaptiste Daroussin #endif
314aae38d10SBaptiste Daroussin #ifdef B1500000
315aae38d10SBaptiste Daroussin     DATA("1500000", B1500000),
316aae38d10SBaptiste Daroussin #endif
317aae38d10SBaptiste Daroussin #ifdef B2000000
318aae38d10SBaptiste Daroussin     DATA("2000000", B2000000),
319aae38d10SBaptiste Daroussin #endif
320aae38d10SBaptiste Daroussin #ifdef B2500000
321aae38d10SBaptiste Daroussin     DATA("2500000", B2500000),
322aae38d10SBaptiste Daroussin #endif
323aae38d10SBaptiste Daroussin #ifdef B3000000
324aae38d10SBaptiste Daroussin     DATA("3000000", B3000000),
325aae38d10SBaptiste Daroussin #endif
326aae38d10SBaptiste Daroussin #ifdef B3500000
327aae38d10SBaptiste Daroussin     DATA("3500000", B3500000),
328aae38d10SBaptiste Daroussin #endif
329aae38d10SBaptiste Daroussin #ifdef B4000000
330aae38d10SBaptiste Daroussin     DATA("4000000", B4000000),
331aae38d10SBaptiste Daroussin #endif
3320e3d5408SPeter Wemm };
333aae38d10SBaptiste Daroussin #undef DATA
3340e3d5408SPeter Wemm 
3350e3d5408SPeter Wemm static int
3360e3d5408SPeter Wemm tbaudrate(char *rate)
3370e3d5408SPeter Wemm {
338aae38d10SBaptiste Daroussin     const SPEEDS *sp = 0;
339aae38d10SBaptiste Daroussin     size_t n;
3400e3d5408SPeter Wemm 
3410e3d5408SPeter Wemm     /* The baudrate number can be preceded by a 'B', which is ignored. */
3420e3d5408SPeter Wemm     if (*rate == 'B')
3430e3d5408SPeter Wemm 	++rate;
3440e3d5408SPeter Wemm 
345aae38d10SBaptiste Daroussin     for (n = 0; n < SIZEOF(speeds); ++n) {
346aae38d10SBaptiste Daroussin 	if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
347aae38d10SBaptiste Daroussin 	    /* if the speeds are not increasing, likely a numeric overflow */
348aae38d10SBaptiste Daroussin 	    break;
349aae38d10SBaptiste Daroussin 	}
350aae38d10SBaptiste Daroussin 	if (!CaselessCmp(rate, speeds[n].string)) {
351aae38d10SBaptiste Daroussin 	    sp = speeds + n;
3520e3d5408SPeter Wemm 	    break;
3530e3d5408SPeter Wemm 	}
3540e3d5408SPeter Wemm     }
355aae38d10SBaptiste Daroussin     if (sp == 0)
3560e3d5408SPeter Wemm 	err("unknown baud rate %s", rate);
3570e3d5408SPeter Wemm     return (sp->speed);
3580e3d5408SPeter Wemm }
3590e3d5408SPeter Wemm 
3600e3d5408SPeter Wemm /*
3610e3d5408SPeter Wemm  * Syntax for -m:
3620e3d5408SPeter Wemm  * [port-type][test baudrate]:terminal-type
3630e3d5408SPeter Wemm  * The baud rate tests are: >, <, @, =, !
3640e3d5408SPeter Wemm  */
3650e3d5408SPeter Wemm static void
3660e3d5408SPeter Wemm add_mapping(const char *port, char *arg)
3670e3d5408SPeter Wemm {
3680e3d5408SPeter Wemm     MAP *mapp;
3690e3d5408SPeter Wemm     char *copy, *p;
3700e3d5408SPeter Wemm     const char *termp;
3710e3d5408SPeter Wemm     char *base = 0;
3720e3d5408SPeter Wemm 
3730e3d5408SPeter Wemm     copy = strdup(arg);
37406bfebdeSXin LI     mapp = typeMalloc(MAP, 1);
3750e3d5408SPeter Wemm     if (copy == 0 || mapp == 0)
3760e3d5408SPeter Wemm 	failed("malloc");
37706bfebdeSXin LI 
37806bfebdeSXin LI     assert(copy != 0);
37906bfebdeSXin LI     assert(mapp != 0);
38006bfebdeSXin LI 
3810e3d5408SPeter Wemm     mapp->next = 0;
3820e3d5408SPeter Wemm     if (maplist == 0)
3830e3d5408SPeter Wemm 	cur = maplist = mapp;
3840e3d5408SPeter Wemm     else {
3850e3d5408SPeter Wemm 	cur->next = mapp;
3860e3d5408SPeter Wemm 	cur = mapp;
3870e3d5408SPeter Wemm     }
3880e3d5408SPeter Wemm 
3890e3d5408SPeter Wemm     mapp->porttype = arg;
3900e3d5408SPeter Wemm     mapp->conditional = 0;
3910e3d5408SPeter Wemm 
3920e3d5408SPeter Wemm     arg = strpbrk(arg, "><@=!:");
3930e3d5408SPeter Wemm 
3940e3d5408SPeter Wemm     if (arg == 0) {		/* [?]term */
3950e3d5408SPeter Wemm 	mapp->type = mapp->porttype;
3960e3d5408SPeter Wemm 	mapp->porttype = 0;
3970e3d5408SPeter Wemm 	goto done;
3980e3d5408SPeter Wemm     }
3990e3d5408SPeter Wemm 
4000e3d5408SPeter Wemm     if (arg == mapp->porttype)	/* [><@=! baud]:term */
4010e3d5408SPeter Wemm 	termp = mapp->porttype = 0;
4020e3d5408SPeter Wemm     else
4030e3d5408SPeter Wemm 	termp = base = arg;
4040e3d5408SPeter Wemm 
40515589c42SPeter Wemm     for (;; ++arg) {		/* Optional conditionals. */
4060e3d5408SPeter Wemm 	switch (*arg) {
4070e3d5408SPeter Wemm 	case '<':
4080e3d5408SPeter Wemm 	    if (mapp->conditional & GT)
4090e3d5408SPeter Wemm 		goto badmopt;
4100e3d5408SPeter Wemm 	    mapp->conditional |= LT;
4110e3d5408SPeter Wemm 	    break;
4120e3d5408SPeter Wemm 	case '>':
4130e3d5408SPeter Wemm 	    if (mapp->conditional & LT)
4140e3d5408SPeter Wemm 		goto badmopt;
4150e3d5408SPeter Wemm 	    mapp->conditional |= GT;
4160e3d5408SPeter Wemm 	    break;
4170e3d5408SPeter Wemm 	case '@':
4180e3d5408SPeter Wemm 	case '=':		/* Not documented. */
4190e3d5408SPeter Wemm 	    mapp->conditional |= EQ;
4200e3d5408SPeter Wemm 	    break;
4210e3d5408SPeter Wemm 	case '!':
4220e3d5408SPeter Wemm 	    mapp->conditional |= NOT;
4230e3d5408SPeter Wemm 	    break;
4240e3d5408SPeter Wemm 	default:
4250e3d5408SPeter Wemm 	    goto next;
4260e3d5408SPeter Wemm 	}
42715589c42SPeter Wemm     }
4280e3d5408SPeter Wemm 
42915589c42SPeter Wemm   next:
43015589c42SPeter Wemm     if (*arg == ':') {
4310e3d5408SPeter Wemm 	if (mapp->conditional)
4320e3d5408SPeter Wemm 	    goto badmopt;
4330e3d5408SPeter Wemm 	++arg;
4340e3d5408SPeter Wemm     } else {			/* Optional baudrate. */
4350e3d5408SPeter Wemm 	arg = strchr(p = arg, ':');
4360e3d5408SPeter Wemm 	if (arg == 0)
4370e3d5408SPeter Wemm 	    goto badmopt;
4380e3d5408SPeter Wemm 	*arg++ = '\0';
4390e3d5408SPeter Wemm 	mapp->speed = tbaudrate(p);
4400e3d5408SPeter Wemm     }
4410e3d5408SPeter Wemm 
4420e3d5408SPeter Wemm     mapp->type = arg;
4430e3d5408SPeter Wemm 
4440e3d5408SPeter Wemm     /* Terminate porttype, if specified. */
4450e3d5408SPeter Wemm     if (termp != 0)
4460e3d5408SPeter Wemm 	*base = '\0';
4470e3d5408SPeter Wemm 
4480e3d5408SPeter Wemm     /* If a NOT conditional, reverse the test. */
4490e3d5408SPeter Wemm     if (mapp->conditional & NOT)
4500e3d5408SPeter Wemm 	mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
4510e3d5408SPeter Wemm 
4520e3d5408SPeter Wemm     /* If user specified a port with an option flag, set it. */
4535d08fb1fSRong-En Fan   done:
4545d08fb1fSRong-En Fan     if (port) {
4555d08fb1fSRong-En Fan 	if (mapp->porttype) {
4565d08fb1fSRong-En Fan 	  badmopt:
4575d08fb1fSRong-En Fan 	    err("illegal -m option format: %s", copy);
4585d08fb1fSRong-En Fan 	}
4590e3d5408SPeter Wemm 	mapp->porttype = port;
4600e3d5408SPeter Wemm     }
4615d08fb1fSRong-En Fan     free(copy);
4620e3d5408SPeter Wemm #ifdef MAPDEBUG
4630e3d5408SPeter Wemm     (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
4640e3d5408SPeter Wemm     (void) printf("type: %s\n", mapp->type);
4650e3d5408SPeter Wemm     (void) printf("conditional: ");
4660e3d5408SPeter Wemm     p = "";
4670e3d5408SPeter Wemm     if (mapp->conditional & GT) {
4680e3d5408SPeter Wemm 	(void) printf("GT");
4690e3d5408SPeter Wemm 	p = "/";
4700e3d5408SPeter Wemm     }
4710e3d5408SPeter Wemm     if (mapp->conditional & EQ) {
4720e3d5408SPeter Wemm 	(void) printf("%sEQ", p);
4730e3d5408SPeter Wemm 	p = "/";
4740e3d5408SPeter Wemm     }
4750e3d5408SPeter Wemm     if (mapp->conditional & LT)
4760e3d5408SPeter Wemm 	(void) printf("%sLT", p);
4770e3d5408SPeter Wemm     (void) printf("\nspeed: %d\n", mapp->speed);
4780e3d5408SPeter Wemm #endif
4790e3d5408SPeter Wemm }
4800e3d5408SPeter Wemm 
4810e3d5408SPeter Wemm /*
4820e3d5408SPeter Wemm  * Return the type of terminal to use for a port of type 'type', as specified
4830e3d5408SPeter Wemm  * by the first applicable mapping in 'map'.  If no mappings apply, return
4840e3d5408SPeter Wemm  * 'type'.
4850e3d5408SPeter Wemm  */
4860e3d5408SPeter Wemm static const char *
4870e3d5408SPeter Wemm mapped(const char *type)
4880e3d5408SPeter Wemm {
4890e3d5408SPeter Wemm     MAP *mapp;
4900e3d5408SPeter Wemm     int match;
4910e3d5408SPeter Wemm 
4920e3d5408SPeter Wemm     for (mapp = maplist; mapp; mapp = mapp->next)
4930e3d5408SPeter Wemm 	if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
4940e3d5408SPeter Wemm 	    switch (mapp->conditional) {
4950e3d5408SPeter Wemm 	    case 0:		/* No test specified. */
4960e3d5408SPeter Wemm 		match = TRUE;
4970e3d5408SPeter Wemm 		break;
4980e3d5408SPeter Wemm 	    case EQ:
49973f0a83dSXin LI 		match = ((int) ospeed == mapp->speed);
5000e3d5408SPeter Wemm 		break;
5010e3d5408SPeter Wemm 	    case GE:
50273f0a83dSXin LI 		match = ((int) ospeed >= mapp->speed);
5030e3d5408SPeter Wemm 		break;
5040e3d5408SPeter Wemm 	    case GT:
50573f0a83dSXin LI 		match = ((int) ospeed > mapp->speed);
5060e3d5408SPeter Wemm 		break;
5070e3d5408SPeter Wemm 	    case LE:
50873f0a83dSXin LI 		match = ((int) ospeed <= mapp->speed);
5090e3d5408SPeter Wemm 		break;
5100e3d5408SPeter Wemm 	    case LT:
51173f0a83dSXin LI 		match = ((int) ospeed < mapp->speed);
5120e3d5408SPeter Wemm 		break;
5130e3d5408SPeter Wemm 	    default:
5140e3d5408SPeter Wemm 		match = FALSE;
5150e3d5408SPeter Wemm 	    }
5160e3d5408SPeter Wemm 	    if (match)
5170e3d5408SPeter Wemm 		return (mapp->type);
5180e3d5408SPeter Wemm 	}
5190e3d5408SPeter Wemm     /* No match found; return given type. */
5200e3d5408SPeter Wemm     return (type);
5210e3d5408SPeter Wemm }
5220e3d5408SPeter Wemm 
5230e3d5408SPeter Wemm /**************************************************************************
5240e3d5408SPeter Wemm  *
5250e3d5408SPeter Wemm  * Entry fetching
5260e3d5408SPeter Wemm  *
5270e3d5408SPeter Wemm  **************************************************************************/
5280e3d5408SPeter Wemm 
5290e3d5408SPeter Wemm /*
5300e3d5408SPeter Wemm  * Figure out what kind of terminal we're dealing with, and then read in
5310e3d5408SPeter Wemm  * its termcap entry.
5320e3d5408SPeter Wemm  */
5330e3d5408SPeter Wemm static const char *
534aae38d10SBaptiste Daroussin get_termcap_entry(int fd, char *userarg)
5350e3d5408SPeter Wemm {
5367a69bbfbSPeter Wemm     int errret;
5370e3d5408SPeter Wemm     char *p;
5380e3d5408SPeter Wemm     const char *ttype;
5390e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5400e3d5408SPeter Wemm     struct ttyent *t;
5410e3d5408SPeter Wemm #else
5420e3d5408SPeter Wemm     FILE *fp;
5430e3d5408SPeter Wemm #endif
5440e3d5408SPeter Wemm     char *ttypath;
5450e3d5408SPeter Wemm 
546aae38d10SBaptiste Daroussin     (void) fd;
547aae38d10SBaptiste Daroussin 
5480e3d5408SPeter Wemm     if (userarg) {
5490e3d5408SPeter Wemm 	ttype = userarg;
5500e3d5408SPeter Wemm 	goto found;
5510e3d5408SPeter Wemm     }
5520e3d5408SPeter Wemm 
5530e3d5408SPeter Wemm     /* Try the environment. */
5540e3d5408SPeter Wemm     if ((ttype = getenv("TERM")) != 0)
5550e3d5408SPeter Wemm 	goto map;
5560e3d5408SPeter Wemm 
557aae38d10SBaptiste Daroussin     if ((ttypath = ttyname(fd)) != 0) {
55818259542SPeter Wemm 	p = _nc_basename(ttypath);
5590e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5600e3d5408SPeter Wemm 	/*
5610e3d5408SPeter Wemm 	 * We have the 4.3BSD library call getttynam(3); that means
5620e3d5408SPeter Wemm 	 * there's an /etc/ttys to look up device-to-type mappings in.
5630e3d5408SPeter Wemm 	 * Try ttyname(3); check for dialup or other mapping.
5640e3d5408SPeter Wemm 	 */
5650e3d5408SPeter Wemm 	if ((t = getttynam(p))) {
5660e3d5408SPeter Wemm 	    ttype = t->ty_type;
5670e3d5408SPeter Wemm 	    goto map;
5680e3d5408SPeter Wemm 	}
5690e3d5408SPeter Wemm #else
5700e3d5408SPeter Wemm 	if ((fp = fopen("/etc/ttytype", "r")) != 0
5710e3d5408SPeter Wemm 	    || (fp = fopen("/etc/ttys", "r")) != 0) {
5720e3d5408SPeter Wemm 	    char buffer[BUFSIZ];
5730e3d5408SPeter Wemm 	    char *s, *t, *d;
5740e3d5408SPeter Wemm 
5750e3d5408SPeter Wemm 	    while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
5760e3d5408SPeter Wemm 		for (s = buffer, t = d = 0; *s; s++) {
57739f2269fSPeter Wemm 		    if (isspace(UChar(*s)))
5780e3d5408SPeter Wemm 			*s = '\0';
5790e3d5408SPeter Wemm 		    else if (t == 0)
5800e3d5408SPeter Wemm 			t = s;
5810e3d5408SPeter Wemm 		    else if (d == 0 && s != buffer && s[-1] == '\0')
5820e3d5408SPeter Wemm 			d = s;
5830e3d5408SPeter Wemm 		}
5840e3d5408SPeter Wemm 		if (t != 0 && d != 0 && !strcmp(d, p)) {
5850e3d5408SPeter Wemm 		    ttype = strdup(t);
5860e3d5408SPeter Wemm 		    fclose(fp);
5870e3d5408SPeter Wemm 		    goto map;
5880e3d5408SPeter Wemm 		}
5890e3d5408SPeter Wemm 	    }
5900e3d5408SPeter Wemm 	    fclose(fp);
5910e3d5408SPeter Wemm 	}
5920e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */
5930e3d5408SPeter Wemm     }
5940e3d5408SPeter Wemm 
5950e3d5408SPeter Wemm     /* If still undefined, use "unknown". */
5960e3d5408SPeter Wemm     ttype = "unknown";
5970e3d5408SPeter Wemm 
5980e3d5408SPeter Wemm   map:ttype = mapped(ttype);
5990e3d5408SPeter Wemm 
6000e3d5408SPeter Wemm     /*
6010e3d5408SPeter Wemm      * If not a path, remove TERMCAP from the environment so we get a
6020e3d5408SPeter Wemm      * real entry from /etc/termcap.  This prevents us from being fooled
6030e3d5408SPeter Wemm      * by out of date stuff in the environment.
6040e3d5408SPeter Wemm      */
60573f0a83dSXin LI   found:
60673f0a83dSXin LI     if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
6070e3d5408SPeter Wemm 	/* 'unsetenv("TERMCAP")' is not portable.
6080e3d5408SPeter Wemm 	 * The 'environ' array is better.
6090e3d5408SPeter Wemm 	 */
6100e3d5408SPeter Wemm 	int n;
6110e3d5408SPeter Wemm 	for (n = 0; environ[n] != 0; n++) {
61273f0a83dSXin LI 	    if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
6130e3d5408SPeter Wemm 		while ((environ[n] = environ[n + 1]) != 0) {
6140e3d5408SPeter Wemm 		    n++;
6150e3d5408SPeter Wemm 		}
6160e3d5408SPeter Wemm 		break;
6170e3d5408SPeter Wemm 	    }
6180e3d5408SPeter Wemm 	}
6190e3d5408SPeter Wemm     }
6200e3d5408SPeter Wemm 
6210e3d5408SPeter Wemm     /*
6220e3d5408SPeter Wemm      * ttype now contains a pointer to the type of the terminal.
6230e3d5408SPeter Wemm      * If the first character is '?', ask the user.
6240e3d5408SPeter Wemm      */
6250e3d5408SPeter Wemm     if (ttype[0] == '?') {
6260e3d5408SPeter Wemm 	if (ttype[1] != '\0')
6270e3d5408SPeter Wemm 	    ttype = askuser(ttype + 1);
6280e3d5408SPeter Wemm 	else
6290e3d5408SPeter Wemm 	    ttype = askuser(0);
6300e3d5408SPeter Wemm     }
6310e3d5408SPeter Wemm     /* Find the terminfo entry.  If it doesn't exist, ask the user. */
632aae38d10SBaptiste Daroussin     while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
6337a69bbfbSPeter Wemm 	   != OK) {
6340e3d5408SPeter Wemm 	if (errret == 0) {
6354a1a9510SRong-En Fan 	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
6364a1a9510SRong-En Fan 			   _nc_progname, ttype);
6370e3d5408SPeter Wemm 	    ttype = 0;
63815589c42SPeter Wemm 	} else {
63915589c42SPeter Wemm 	    (void) fprintf(stderr,
6404a1a9510SRong-En Fan 			   "%s: can't initialize terminal type %s (error %d)\n",
6414a1a9510SRong-En Fan 			   _nc_progname, ttype, errret);
6420e3d5408SPeter Wemm 	    ttype = 0;
6430e3d5408SPeter Wemm 	}
6440e3d5408SPeter Wemm 	ttype = askuser(ttype);
6450e3d5408SPeter Wemm     }
6460e3d5408SPeter Wemm #if BROKEN_LINKER
6470e3d5408SPeter Wemm     tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */
6480e3d5408SPeter Wemm #endif
6490e3d5408SPeter Wemm     return (ttype);
6500e3d5408SPeter Wemm }
6510e3d5408SPeter Wemm 
6520e3d5408SPeter Wemm /**************************************************************************
6530e3d5408SPeter Wemm  *
6540e3d5408SPeter Wemm  * Main sequence
6550e3d5408SPeter Wemm  *
6560e3d5408SPeter Wemm  **************************************************************************/
6570e3d5408SPeter Wemm 
6580e3d5408SPeter Wemm /*
6590e3d5408SPeter Wemm  * Convert the obsolete argument forms into something that getopt can handle.
6600e3d5408SPeter Wemm  * This means that -e, -i and -k get default arguments supplied for them.
6610e3d5408SPeter Wemm  */
6620e3d5408SPeter Wemm static void
6630e3d5408SPeter Wemm obsolete(char **argv)
6640e3d5408SPeter Wemm {
6650e3d5408SPeter Wemm     for (; *argv; ++argv) {
6660e3d5408SPeter Wemm 	char *parm = argv[0];
6670e3d5408SPeter Wemm 
66815589c42SPeter Wemm 	if (parm[0] == '-' && parm[1] == '\0') {
6690e3d5408SPeter Wemm 	    argv[0] = strdup("-q");
6700e3d5408SPeter Wemm 	    continue;
6710e3d5408SPeter Wemm 	}
6720e3d5408SPeter Wemm 
6730e3d5408SPeter Wemm 	if ((parm[0] != '-')
6740e3d5408SPeter Wemm 	    || (argv[1] && argv[1][0] != '-')
6750e3d5408SPeter Wemm 	    || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
6760e3d5408SPeter Wemm 	    || (parm[2] != '\0'))
6770e3d5408SPeter Wemm 	    continue;
6780e3d5408SPeter Wemm 	switch (argv[0][1]) {
6790e3d5408SPeter Wemm 	case 'e':
6800e3d5408SPeter Wemm 	    argv[0] = strdup("-e^H");
6810e3d5408SPeter Wemm 	    break;
6820e3d5408SPeter Wemm 	case 'i':
6830e3d5408SPeter Wemm 	    argv[0] = strdup("-i^C");
6840e3d5408SPeter Wemm 	    break;
6850e3d5408SPeter Wemm 	case 'k':
6860e3d5408SPeter Wemm 	    argv[0] = strdup("-k^U");
6870e3d5408SPeter Wemm 	    break;
6880e3d5408SPeter Wemm 	}
6890e3d5408SPeter Wemm     }
6900e3d5408SPeter Wemm }
6910e3d5408SPeter Wemm 
6920e3d5408SPeter Wemm static void
693aae38d10SBaptiste Daroussin print_shell_commands(const char *ttype)
694aae38d10SBaptiste Daroussin {
695aae38d10SBaptiste Daroussin     const char *p;
696aae38d10SBaptiste Daroussin     int len;
697aae38d10SBaptiste Daroussin     char *var;
698aae38d10SBaptiste Daroussin     char *leaf;
699aae38d10SBaptiste Daroussin     /*
700aae38d10SBaptiste Daroussin      * Figure out what shell we're using.  A hack, we look for an
701aae38d10SBaptiste Daroussin      * environmental variable SHELL ending in "csh".
702aae38d10SBaptiste Daroussin      */
703aae38d10SBaptiste Daroussin     if ((var = getenv("SHELL")) != 0
704aae38d10SBaptiste Daroussin 	&& ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
705aae38d10SBaptiste Daroussin 	&& !strcmp(leaf + len - 3, "csh"))
706aae38d10SBaptiste Daroussin 	p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
707aae38d10SBaptiste Daroussin     else
708aae38d10SBaptiste Daroussin 	p = "TERM=%s;\n";
709aae38d10SBaptiste Daroussin     (void) printf(p, ttype);
710aae38d10SBaptiste Daroussin }
711aae38d10SBaptiste Daroussin 
712aae38d10SBaptiste Daroussin static void
7134a1a9510SRong-En Fan usage(void)
7140e3d5408SPeter Wemm {
715aae38d10SBaptiste Daroussin #define SKIP(s)			/* nothing */
716aae38d10SBaptiste Daroussin #define KEEP(s) s "\n"
717aae38d10SBaptiste Daroussin     static const char msg[] =
7184a1a9510SRong-En Fan     {
719aae38d10SBaptiste Daroussin 	KEEP("")
720aae38d10SBaptiste Daroussin 	KEEP("Options:")
721aae38d10SBaptiste Daroussin 	SKIP("  -a arpanet  (obsolete)")
722aae38d10SBaptiste Daroussin 	KEEP("  -c          set control characters")
723aae38d10SBaptiste Daroussin 	SKIP("  -d dialup   (obsolete)")
724aae38d10SBaptiste Daroussin 	KEEP("  -e ch       erase character")
725aae38d10SBaptiste Daroussin 	KEEP("  -I          no initialization strings")
726aae38d10SBaptiste Daroussin 	KEEP("  -i ch       interrupt character")
727aae38d10SBaptiste Daroussin 	KEEP("  -k ch       kill character")
728aae38d10SBaptiste Daroussin 	KEEP("  -m mapping  map identifier to type")
729aae38d10SBaptiste Daroussin 	SKIP("  -p plugboard (obsolete)")
730aae38d10SBaptiste Daroussin 	KEEP("  -Q          do not output control key settings")
731aae38d10SBaptiste Daroussin 	KEEP("  -q          display term only, do no changes")
732aae38d10SBaptiste Daroussin 	KEEP("  -r          display term on stderr")
733aae38d10SBaptiste Daroussin 	SKIP("  -S          (obsolete)")
734aae38d10SBaptiste Daroussin 	KEEP("  -s          output TERM set command")
735aae38d10SBaptiste Daroussin 	KEEP("  -V          print curses-version")
736aae38d10SBaptiste Daroussin 	KEEP("  -w          set window-size")
737aae38d10SBaptiste Daroussin 	KEEP("")
738aae38d10SBaptiste Daroussin 	KEEP("If neither -c/-w are given, both are assumed.")
7394a1a9510SRong-En Fan     };
740aae38d10SBaptiste Daroussin #undef KEEP
741aae38d10SBaptiste Daroussin #undef SKIP
7424a1a9510SRong-En Fan     (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
743aae38d10SBaptiste Daroussin     fputs(msg, stderr);
744aae38d10SBaptiste Daroussin     ExitProgram(EXIT_FAILURE);
74539f2269fSPeter Wemm     /* NOTREACHED */
7460e3d5408SPeter Wemm }
7470e3d5408SPeter Wemm 
74815589c42SPeter Wemm static char
74915589c42SPeter Wemm arg_to_char(void)
7500e3d5408SPeter Wemm {
7515d08fb1fSRong-En Fan     return (char) ((optarg[0] == '^' && optarg[1] != '\0')
7520e3d5408SPeter Wemm 		   ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
7535d08fb1fSRong-En Fan 		   : optarg[0]);
7540e3d5408SPeter Wemm }
7550e3d5408SPeter Wemm 
7560e3d5408SPeter Wemm int
7570e3d5408SPeter Wemm main(int argc, char **argv)
7580e3d5408SPeter Wemm {
7590e3d5408SPeter Wemm     int ch, noinit, noset, quiet, Sflag, sflag, showterm;
7600e3d5408SPeter Wemm     const char *ttype;
761aae38d10SBaptiste Daroussin     int terasechar = -1;	/* new erase character */
762aae38d10SBaptiste Daroussin     int intrchar = -1;		/* new interrupt character */
763aae38d10SBaptiste Daroussin     int tkillchar = -1;		/* new kill character */
764aae38d10SBaptiste Daroussin     int my_fd;
765aae38d10SBaptiste Daroussin     bool opt_c = FALSE;		/* set control-chars */
766aae38d10SBaptiste Daroussin     bool opt_w = FALSE;		/* set window-size */
767aae38d10SBaptiste Daroussin     TTY mode, oldmode;
7680e3d5408SPeter Wemm 
769aae38d10SBaptiste Daroussin     my_fd = STDERR_FILENO;
7700e3d5408SPeter Wemm     obsolete(argv);
7710e3d5408SPeter Wemm     noinit = noset = quiet = Sflag = sflag = showterm = 0;
772aae38d10SBaptiste Daroussin     while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
7730e3d5408SPeter Wemm 	switch (ch) {
7744a1a9510SRong-En Fan 	case 'c':		/* set control-chars */
7754a1a9510SRong-En Fan 	    opt_c = TRUE;
7760e3d5408SPeter Wemm 	    break;
7770e3d5408SPeter Wemm 	case 'a':		/* OBSOLETE: map identifier to type */
7780e3d5408SPeter Wemm 	    add_mapping("arpanet", optarg);
7790e3d5408SPeter Wemm 	    break;
7800e3d5408SPeter Wemm 	case 'd':		/* OBSOLETE: map identifier to type */
7810e3d5408SPeter Wemm 	    add_mapping("dialup", optarg);
7820e3d5408SPeter Wemm 	    break;
7830e3d5408SPeter Wemm 	case 'e':		/* erase character */
7840e3d5408SPeter Wemm 	    terasechar = arg_to_char();
7850e3d5408SPeter Wemm 	    break;
7860e3d5408SPeter Wemm 	case 'I':		/* no initialization strings */
7870e3d5408SPeter Wemm 	    noinit = 1;
7880e3d5408SPeter Wemm 	    break;
7890e3d5408SPeter Wemm 	case 'i':		/* interrupt character */
7900e3d5408SPeter Wemm 	    intrchar = arg_to_char();
7910e3d5408SPeter Wemm 	    break;
7920e3d5408SPeter Wemm 	case 'k':		/* kill character */
7930e3d5408SPeter Wemm 	    tkillchar = arg_to_char();
7940e3d5408SPeter Wemm 	    break;
7950e3d5408SPeter Wemm 	case 'm':		/* map identifier to type */
7960e3d5408SPeter Wemm 	    add_mapping(0, optarg);
7970e3d5408SPeter Wemm 	    break;
7980e3d5408SPeter Wemm 	case 'p':		/* OBSOLETE: map identifier to type */
7990e3d5408SPeter Wemm 	    add_mapping("plugboard", optarg);
8000e3d5408SPeter Wemm 	    break;
8010e3d5408SPeter Wemm 	case 'Q':		/* don't output control key settings */
8020e3d5408SPeter Wemm 	    quiet = 1;
8030e3d5408SPeter Wemm 	    break;
8044a1a9510SRong-En Fan 	case 'q':		/* display term only */
8054a1a9510SRong-En Fan 	    noset = 1;
8060e3d5408SPeter Wemm 	    break;
8070e3d5408SPeter Wemm 	case 'r':		/* display term on stderr */
8080e3d5408SPeter Wemm 	    showterm = 1;
8090e3d5408SPeter Wemm 	    break;
8104a1a9510SRong-En Fan 	case 'S':		/* OBSOLETE: output TERM & TERMCAP */
8114a1a9510SRong-En Fan 	    Sflag = 1;
8124a1a9510SRong-En Fan 	    break;
8130e3d5408SPeter Wemm 	case 's':		/* output TERM set command */
8140e3d5408SPeter Wemm 	    sflag = 1;
8150e3d5408SPeter Wemm 	    break;
8164a1a9510SRong-En Fan 	case 'V':		/* print curses-version */
81718259542SPeter Wemm 	    puts(curses_version());
8184a1a9510SRong-En Fan 	    ExitProgram(EXIT_SUCCESS);
8194a1a9510SRong-En Fan 	case 'w':		/* set window-size */
8204a1a9510SRong-En Fan 	    opt_w = TRUE;
8214a1a9510SRong-En Fan 	    break;
8220e3d5408SPeter Wemm 	case '?':
8230e3d5408SPeter Wemm 	default:
8244a1a9510SRong-En Fan 	    usage();
8250e3d5408SPeter Wemm 	}
8260e3d5408SPeter Wemm     }
8274a1a9510SRong-En Fan 
8284a1a9510SRong-En Fan     _nc_progname = _nc_rootname(*argv);
8290e3d5408SPeter Wemm     argc -= optind;
8300e3d5408SPeter Wemm     argv += optind;
8310e3d5408SPeter Wemm 
8320e3d5408SPeter Wemm     if (argc > 1)
8334a1a9510SRong-En Fan 	usage();
8344a1a9510SRong-En Fan 
8354a1a9510SRong-En Fan     if (!opt_c && !opt_w)
8364a1a9510SRong-En Fan 	opt_c = opt_w = TRUE;
8374a1a9510SRong-En Fan 
838aae38d10SBaptiste Daroussin     my_fd = save_tty_settings(&mode, TRUE);
839aae38d10SBaptiste Daroussin     oldmode = mode;
8404a1a9510SRong-En Fan #ifdef TERMIOS
8415d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
8424a1a9510SRong-En Fan #else
8435d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
8444a1a9510SRong-En Fan #endif
8454a1a9510SRong-En Fan 
84606bfebdeSXin LI     if (same_program(_nc_progname, PROG_RESET)) {
847aae38d10SBaptiste Daroussin 	reset_start(stderr, TRUE, FALSE);
848aae38d10SBaptiste Daroussin 	reset_tty_settings(my_fd, &mode);
849aae38d10SBaptiste Daroussin     } else {
850aae38d10SBaptiste Daroussin 	reset_start(stderr, FALSE, TRUE);
8514a1a9510SRong-En Fan     }
8520e3d5408SPeter Wemm 
853aae38d10SBaptiste Daroussin     ttype = get_termcap_entry(my_fd, *argv);
8540e3d5408SPeter Wemm 
8550e3d5408SPeter Wemm     if (!noset) {
85673f0a83dSXin LI #if HAVE_SIZECHANGE
8574a1a9510SRong-En Fan 	if (opt_w) {
858aae38d10SBaptiste Daroussin 	    set_window_size(my_fd, &lines, &columns);
8594a1a9510SRong-En Fan 	}
8600e3d5408SPeter Wemm #endif
8614a1a9510SRong-En Fan 	if (opt_c) {
862aae38d10SBaptiste Daroussin 	    set_control_chars(&mode, terasechar, intrchar, tkillchar);
863aae38d10SBaptiste Daroussin 	    set_conversions(&mode);
8640e3d5408SPeter Wemm 
865aae38d10SBaptiste Daroussin 	    if (!noinit) {
866aae38d10SBaptiste Daroussin 		if (send_init_strings(my_fd, &oldmode)) {
867aae38d10SBaptiste Daroussin 		    (void) putc('\r', stderr);
868aae38d10SBaptiste Daroussin 		    (void) fflush(stderr);
869aae38d10SBaptiste Daroussin 		    (void) napms(1000);		/* Settle the terminal. */
8700e3d5408SPeter Wemm 		}
87115589c42SPeter Wemm 	    }
872aae38d10SBaptiste Daroussin 
873aae38d10SBaptiste Daroussin 	    update_tty_settings(&oldmode, &mode);
874aae38d10SBaptiste Daroussin 	}
8754a1a9510SRong-En Fan     }
8760e3d5408SPeter Wemm 
877aae38d10SBaptiste Daroussin     if (noset) {
8780e3d5408SPeter Wemm 	(void) printf("%s\n", ttype);
879aae38d10SBaptiste Daroussin     } else {
8800e3d5408SPeter Wemm 	if (showterm)
8810e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
8820e3d5408SPeter Wemm 	/*
8830e3d5408SPeter Wemm 	 * If erase, kill and interrupt characters could have been
8840e3d5408SPeter Wemm 	 * modified and not -Q, display the changes.
8850e3d5408SPeter Wemm 	 */
8860e3d5408SPeter Wemm 	if (!quiet) {
887aae38d10SBaptiste Daroussin 	    print_tty_chars(&oldmode, &mode);
8880e3d5408SPeter Wemm 	}
8890e3d5408SPeter Wemm     }
8900e3d5408SPeter Wemm 
8910e3d5408SPeter Wemm     if (Sflag)
8920e3d5408SPeter Wemm 	err("The -S option is not supported under terminfo.");
8930e3d5408SPeter Wemm 
8940e3d5408SPeter Wemm     if (sflag) {
895aae38d10SBaptiste Daroussin 	print_shell_commands(ttype);
8960e3d5408SPeter Wemm     }
8970e3d5408SPeter Wemm 
8984a1a9510SRong-En Fan     ExitProgram(EXIT_SUCCESS);
8990e3d5408SPeter Wemm }
900