xref: /freebsd/contrib/ncurses/progs/tset.c (revision 7a65641922f404b84e9a249d48593de84d8e8d17)
10e3d5408SPeter Wemm /****************************************************************************
2e1865124SBaptiste Daroussin  * Copyright 2020 Thomas E. Dickey                                          *
3e1865124SBaptiste 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*7a656419SBaptiste Daroussin MODULE_ID("$Id: tset.c,v 1.125 2020/09/05 22:54:47 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 {
230*7a656419SBaptiste Daroussin     const char string[8];
2310e3d5408SPeter Wemm     int speed;
2320e3d5408SPeter Wemm } SPEEDS;
2330e3d5408SPeter Wemm 
234*7a656419SBaptiste Daroussin #if defined(EXP_WIN32_DRIVER)
235*7a656419SBaptiste Daroussin static const SPEEDS speeds[] =
236*7a656419SBaptiste Daroussin {
237*7a656419SBaptiste Daroussin     {"0", 0}
238*7a656419SBaptiste Daroussin };
239*7a656419SBaptiste Daroussin #else
24015589c42SPeter Wemm static const SPEEDS speeds[] =
24115589c42SPeter Wemm {
242aae38d10SBaptiste Daroussin     DATA("0", B0),
243aae38d10SBaptiste Daroussin     DATA("50", B50),
244aae38d10SBaptiste Daroussin     DATA("75", B75),
245aae38d10SBaptiste Daroussin     DATA("110", B110),
246aae38d10SBaptiste Daroussin     DATA("134", B134),
247aae38d10SBaptiste Daroussin     DATA("134.5", B134),
248aae38d10SBaptiste Daroussin     DATA("150", B150),
249aae38d10SBaptiste Daroussin     DATA("200", B200),
250aae38d10SBaptiste Daroussin     DATA("300", B300),
251aae38d10SBaptiste Daroussin     DATA("600", B600),
252aae38d10SBaptiste Daroussin     DATA("1200", B1200),
253aae38d10SBaptiste Daroussin     DATA("1800", B1800),
254aae38d10SBaptiste Daroussin     DATA("2400", B2400),
255aae38d10SBaptiste Daroussin     DATA("4800", B4800),
256aae38d10SBaptiste Daroussin     DATA("9600", B9600),
25718259542SPeter Wemm     /* sgttyb may define up to this point */
25818259542SPeter Wemm #ifdef B19200
259aae38d10SBaptiste Daroussin     DATA("19200", B19200),
26018259542SPeter Wemm #endif
26118259542SPeter Wemm #ifdef B38400
262aae38d10SBaptiste Daroussin     DATA("38400", B38400),
26318259542SPeter Wemm #endif
26418259542SPeter Wemm #ifdef B19200
265aae38d10SBaptiste Daroussin     DATA("19200", B19200),
26618259542SPeter Wemm #endif
26718259542SPeter Wemm #ifdef B38400
268aae38d10SBaptiste Daroussin     DATA("38400", B38400),
26918259542SPeter Wemm #endif
2700e3d5408SPeter Wemm #ifdef B19200
271aae38d10SBaptiste Daroussin     DATA("19200", B19200),
2720e3d5408SPeter Wemm #else
2730e3d5408SPeter Wemm #ifdef EXTA
274aae38d10SBaptiste Daroussin     DATA("19200", EXTA),
2750e3d5408SPeter Wemm #endif
2760e3d5408SPeter Wemm #endif
2770e3d5408SPeter Wemm #ifdef B38400
278aae38d10SBaptiste Daroussin     DATA("38400", B38400),
2790e3d5408SPeter Wemm #else
2800e3d5408SPeter Wemm #ifdef EXTB
281aae38d10SBaptiste Daroussin     DATA("38400", EXTB),
2820e3d5408SPeter Wemm #endif
2830e3d5408SPeter Wemm #endif
2840e3d5408SPeter Wemm #ifdef B57600
285aae38d10SBaptiste Daroussin     DATA("57600", B57600),
286aae38d10SBaptiste Daroussin #endif
287aae38d10SBaptiste Daroussin #ifdef B76800
288aae38d10SBaptiste Daroussin     DATA("76800", B57600),
2890e3d5408SPeter Wemm #endif
2900e3d5408SPeter Wemm #ifdef B115200
291aae38d10SBaptiste Daroussin     DATA("115200", B115200),
292aae38d10SBaptiste Daroussin #endif
293aae38d10SBaptiste Daroussin #ifdef B153600
294aae38d10SBaptiste Daroussin     DATA("153600", B153600),
2950e3d5408SPeter Wemm #endif
2960e3d5408SPeter Wemm #ifdef B230400
297aae38d10SBaptiste Daroussin     DATA("230400", B230400),
298aae38d10SBaptiste Daroussin #endif
299aae38d10SBaptiste Daroussin #ifdef B307200
300aae38d10SBaptiste Daroussin     DATA("307200", B307200),
3010e3d5408SPeter Wemm #endif
3020e3d5408SPeter Wemm #ifdef B460800
303aae38d10SBaptiste Daroussin     DATA("460800", B460800),
3040e3d5408SPeter Wemm #endif
305aae38d10SBaptiste Daroussin #ifdef B500000
306aae38d10SBaptiste Daroussin     DATA("500000", B500000),
307aae38d10SBaptiste Daroussin #endif
308aae38d10SBaptiste Daroussin #ifdef B576000
309aae38d10SBaptiste Daroussin     DATA("576000", B576000),
310aae38d10SBaptiste Daroussin #endif
311aae38d10SBaptiste Daroussin #ifdef B921600
312aae38d10SBaptiste Daroussin     DATA("921600", B921600),
313aae38d10SBaptiste Daroussin #endif
314aae38d10SBaptiste Daroussin #ifdef B1000000
315aae38d10SBaptiste Daroussin     DATA("1000000", B1000000),
316aae38d10SBaptiste Daroussin #endif
317aae38d10SBaptiste Daroussin #ifdef B1152000
318aae38d10SBaptiste Daroussin     DATA("1152000", B1152000),
319aae38d10SBaptiste Daroussin #endif
320aae38d10SBaptiste Daroussin #ifdef B1500000
321aae38d10SBaptiste Daroussin     DATA("1500000", B1500000),
322aae38d10SBaptiste Daroussin #endif
323aae38d10SBaptiste Daroussin #ifdef B2000000
324aae38d10SBaptiste Daroussin     DATA("2000000", B2000000),
325aae38d10SBaptiste Daroussin #endif
326aae38d10SBaptiste Daroussin #ifdef B2500000
327aae38d10SBaptiste Daroussin     DATA("2500000", B2500000),
328aae38d10SBaptiste Daroussin #endif
329aae38d10SBaptiste Daroussin #ifdef B3000000
330aae38d10SBaptiste Daroussin     DATA("3000000", B3000000),
331aae38d10SBaptiste Daroussin #endif
332aae38d10SBaptiste Daroussin #ifdef B3500000
333aae38d10SBaptiste Daroussin     DATA("3500000", B3500000),
334aae38d10SBaptiste Daroussin #endif
335aae38d10SBaptiste Daroussin #ifdef B4000000
336aae38d10SBaptiste Daroussin     DATA("4000000", B4000000),
337aae38d10SBaptiste Daroussin #endif
3380e3d5408SPeter Wemm };
339aae38d10SBaptiste Daroussin #undef DATA
340*7a656419SBaptiste Daroussin #endif
3410e3d5408SPeter Wemm 
3420e3d5408SPeter Wemm static int
3430e3d5408SPeter Wemm tbaudrate(char *rate)
3440e3d5408SPeter Wemm {
345aae38d10SBaptiste Daroussin     const SPEEDS *sp = 0;
346aae38d10SBaptiste Daroussin     size_t n;
3470e3d5408SPeter Wemm 
3480e3d5408SPeter Wemm     /* The baudrate number can be preceded by a 'B', which is ignored. */
3490e3d5408SPeter Wemm     if (*rate == 'B')
3500e3d5408SPeter Wemm 	++rate;
3510e3d5408SPeter Wemm 
352aae38d10SBaptiste Daroussin     for (n = 0; n < SIZEOF(speeds); ++n) {
353aae38d10SBaptiste Daroussin 	if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
354aae38d10SBaptiste Daroussin 	    /* if the speeds are not increasing, likely a numeric overflow */
355aae38d10SBaptiste Daroussin 	    break;
356aae38d10SBaptiste Daroussin 	}
357aae38d10SBaptiste Daroussin 	if (!CaselessCmp(rate, speeds[n].string)) {
358aae38d10SBaptiste Daroussin 	    sp = speeds + n;
3590e3d5408SPeter Wemm 	    break;
3600e3d5408SPeter Wemm 	}
3610e3d5408SPeter Wemm     }
362aae38d10SBaptiste Daroussin     if (sp == 0)
3630e3d5408SPeter Wemm 	err("unknown baud rate %s", rate);
3640e3d5408SPeter Wemm     return (sp->speed);
3650e3d5408SPeter Wemm }
3660e3d5408SPeter Wemm 
3670e3d5408SPeter Wemm /*
3680e3d5408SPeter Wemm  * Syntax for -m:
3690e3d5408SPeter Wemm  * [port-type][test baudrate]:terminal-type
3700e3d5408SPeter Wemm  * The baud rate tests are: >, <, @, =, !
3710e3d5408SPeter Wemm  */
3720e3d5408SPeter Wemm static void
3730e3d5408SPeter Wemm add_mapping(const char *port, char *arg)
3740e3d5408SPeter Wemm {
3750e3d5408SPeter Wemm     MAP *mapp;
3760e3d5408SPeter Wemm     char *copy, *p;
3770e3d5408SPeter Wemm     const char *termp;
3780e3d5408SPeter Wemm     char *base = 0;
3790e3d5408SPeter Wemm 
3800e3d5408SPeter Wemm     copy = strdup(arg);
38106bfebdeSXin LI     mapp = typeMalloc(MAP, 1);
3820e3d5408SPeter Wemm     if (copy == 0 || mapp == 0)
3830e3d5408SPeter Wemm 	failed("malloc");
38406bfebdeSXin LI 
38506bfebdeSXin LI     assert(copy != 0);
38606bfebdeSXin LI     assert(mapp != 0);
38706bfebdeSXin LI 
3880e3d5408SPeter Wemm     mapp->next = 0;
3890e3d5408SPeter Wemm     if (maplist == 0)
3900e3d5408SPeter Wemm 	cur = maplist = mapp;
3910e3d5408SPeter Wemm     else {
3920e3d5408SPeter Wemm 	cur->next = mapp;
3930e3d5408SPeter Wemm 	cur = mapp;
3940e3d5408SPeter Wemm     }
3950e3d5408SPeter Wemm 
3960e3d5408SPeter Wemm     mapp->porttype = arg;
3970e3d5408SPeter Wemm     mapp->conditional = 0;
3980e3d5408SPeter Wemm 
3990e3d5408SPeter Wemm     arg = strpbrk(arg, "><@=!:");
4000e3d5408SPeter Wemm 
4010e3d5408SPeter Wemm     if (arg == 0) {		/* [?]term */
4020e3d5408SPeter Wemm 	mapp->type = mapp->porttype;
4030e3d5408SPeter Wemm 	mapp->porttype = 0;
4040e3d5408SPeter Wemm 	goto done;
4050e3d5408SPeter Wemm     }
4060e3d5408SPeter Wemm 
4070e3d5408SPeter Wemm     if (arg == mapp->porttype)	/* [><@=! baud]:term */
4080e3d5408SPeter Wemm 	termp = mapp->porttype = 0;
4090e3d5408SPeter Wemm     else
4100e3d5408SPeter Wemm 	termp = base = arg;
4110e3d5408SPeter Wemm 
41215589c42SPeter Wemm     for (;; ++arg) {		/* Optional conditionals. */
4130e3d5408SPeter Wemm 	switch (*arg) {
4140e3d5408SPeter Wemm 	case '<':
4150e3d5408SPeter Wemm 	    if (mapp->conditional & GT)
4160e3d5408SPeter Wemm 		goto badmopt;
4170e3d5408SPeter Wemm 	    mapp->conditional |= LT;
4180e3d5408SPeter Wemm 	    break;
4190e3d5408SPeter Wemm 	case '>':
4200e3d5408SPeter Wemm 	    if (mapp->conditional & LT)
4210e3d5408SPeter Wemm 		goto badmopt;
4220e3d5408SPeter Wemm 	    mapp->conditional |= GT;
4230e3d5408SPeter Wemm 	    break;
4240e3d5408SPeter Wemm 	case '@':
4250e3d5408SPeter Wemm 	case '=':		/* Not documented. */
4260e3d5408SPeter Wemm 	    mapp->conditional |= EQ;
4270e3d5408SPeter Wemm 	    break;
4280e3d5408SPeter Wemm 	case '!':
4290e3d5408SPeter Wemm 	    mapp->conditional |= NOT;
4300e3d5408SPeter Wemm 	    break;
4310e3d5408SPeter Wemm 	default:
4320e3d5408SPeter Wemm 	    goto next;
4330e3d5408SPeter Wemm 	}
43415589c42SPeter Wemm     }
4350e3d5408SPeter Wemm 
43615589c42SPeter Wemm   next:
43715589c42SPeter Wemm     if (*arg == ':') {
4380e3d5408SPeter Wemm 	if (mapp->conditional)
4390e3d5408SPeter Wemm 	    goto badmopt;
4400e3d5408SPeter Wemm 	++arg;
4410e3d5408SPeter Wemm     } else {			/* Optional baudrate. */
4420e3d5408SPeter Wemm 	arg = strchr(p = arg, ':');
4430e3d5408SPeter Wemm 	if (arg == 0)
4440e3d5408SPeter Wemm 	    goto badmopt;
4450e3d5408SPeter Wemm 	*arg++ = '\0';
4460e3d5408SPeter Wemm 	mapp->speed = tbaudrate(p);
4470e3d5408SPeter Wemm     }
4480e3d5408SPeter Wemm 
4490e3d5408SPeter Wemm     mapp->type = arg;
4500e3d5408SPeter Wemm 
4510e3d5408SPeter Wemm     /* Terminate porttype, if specified. */
4520e3d5408SPeter Wemm     if (termp != 0)
4530e3d5408SPeter Wemm 	*base = '\0';
4540e3d5408SPeter Wemm 
4550e3d5408SPeter Wemm     /* If a NOT conditional, reverse the test. */
4560e3d5408SPeter Wemm     if (mapp->conditional & NOT)
4570e3d5408SPeter Wemm 	mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
4580e3d5408SPeter Wemm 
4590e3d5408SPeter Wemm     /* If user specified a port with an option flag, set it. */
4605d08fb1fSRong-En Fan   done:
4615d08fb1fSRong-En Fan     if (port) {
4625d08fb1fSRong-En Fan 	if (mapp->porttype) {
4635d08fb1fSRong-En Fan 	  badmopt:
4645d08fb1fSRong-En Fan 	    err("illegal -m option format: %s", copy);
4655d08fb1fSRong-En Fan 	}
4660e3d5408SPeter Wemm 	mapp->porttype = port;
4670e3d5408SPeter Wemm     }
4685d08fb1fSRong-En Fan     free(copy);
4690e3d5408SPeter Wemm #ifdef MAPDEBUG
4700e3d5408SPeter Wemm     (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
4710e3d5408SPeter Wemm     (void) printf("type: %s\n", mapp->type);
4720e3d5408SPeter Wemm     (void) printf("conditional: ");
4730e3d5408SPeter Wemm     p = "";
4740e3d5408SPeter Wemm     if (mapp->conditional & GT) {
4750e3d5408SPeter Wemm 	(void) printf("GT");
4760e3d5408SPeter Wemm 	p = "/";
4770e3d5408SPeter Wemm     }
4780e3d5408SPeter Wemm     if (mapp->conditional & EQ) {
4790e3d5408SPeter Wemm 	(void) printf("%sEQ", p);
4800e3d5408SPeter Wemm 	p = "/";
4810e3d5408SPeter Wemm     }
4820e3d5408SPeter Wemm     if (mapp->conditional & LT)
4830e3d5408SPeter Wemm 	(void) printf("%sLT", p);
4840e3d5408SPeter Wemm     (void) printf("\nspeed: %d\n", mapp->speed);
4850e3d5408SPeter Wemm #endif
4860e3d5408SPeter Wemm }
4870e3d5408SPeter Wemm 
4880e3d5408SPeter Wemm /*
4890e3d5408SPeter Wemm  * Return the type of terminal to use for a port of type 'type', as specified
4900e3d5408SPeter Wemm  * by the first applicable mapping in 'map'.  If no mappings apply, return
4910e3d5408SPeter Wemm  * 'type'.
4920e3d5408SPeter Wemm  */
4930e3d5408SPeter Wemm static const char *
4940e3d5408SPeter Wemm mapped(const char *type)
4950e3d5408SPeter Wemm {
4960e3d5408SPeter Wemm     MAP *mapp;
4970e3d5408SPeter Wemm     int match;
4980e3d5408SPeter Wemm 
4990e3d5408SPeter Wemm     for (mapp = maplist; mapp; mapp = mapp->next)
5000e3d5408SPeter Wemm 	if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
5010e3d5408SPeter Wemm 	    switch (mapp->conditional) {
5020e3d5408SPeter Wemm 	    case 0:		/* No test specified. */
5030e3d5408SPeter Wemm 		match = TRUE;
5040e3d5408SPeter Wemm 		break;
5050e3d5408SPeter Wemm 	    case EQ:
50673f0a83dSXin LI 		match = ((int) ospeed == mapp->speed);
5070e3d5408SPeter Wemm 		break;
5080e3d5408SPeter Wemm 	    case GE:
50973f0a83dSXin LI 		match = ((int) ospeed >= mapp->speed);
5100e3d5408SPeter Wemm 		break;
5110e3d5408SPeter Wemm 	    case GT:
51273f0a83dSXin LI 		match = ((int) ospeed > mapp->speed);
5130e3d5408SPeter Wemm 		break;
5140e3d5408SPeter Wemm 	    case LE:
51573f0a83dSXin LI 		match = ((int) ospeed <= mapp->speed);
5160e3d5408SPeter Wemm 		break;
5170e3d5408SPeter Wemm 	    case LT:
51873f0a83dSXin LI 		match = ((int) ospeed < mapp->speed);
5190e3d5408SPeter Wemm 		break;
5200e3d5408SPeter Wemm 	    default:
5210e3d5408SPeter Wemm 		match = FALSE;
5220e3d5408SPeter Wemm 	    }
5230e3d5408SPeter Wemm 	    if (match)
5240e3d5408SPeter Wemm 		return (mapp->type);
5250e3d5408SPeter Wemm 	}
5260e3d5408SPeter Wemm     /* No match found; return given type. */
5270e3d5408SPeter Wemm     return (type);
5280e3d5408SPeter Wemm }
5290e3d5408SPeter Wemm 
5300e3d5408SPeter Wemm /**************************************************************************
5310e3d5408SPeter Wemm  *
5320e3d5408SPeter Wemm  * Entry fetching
5330e3d5408SPeter Wemm  *
5340e3d5408SPeter Wemm  **************************************************************************/
5350e3d5408SPeter Wemm 
5360e3d5408SPeter Wemm /*
5370e3d5408SPeter Wemm  * Figure out what kind of terminal we're dealing with, and then read in
5380e3d5408SPeter Wemm  * its termcap entry.
5390e3d5408SPeter Wemm  */
5400e3d5408SPeter Wemm static const char *
541aae38d10SBaptiste Daroussin get_termcap_entry(int fd, char *userarg)
5420e3d5408SPeter Wemm {
5437a69bbfbSPeter Wemm     int errret;
5440e3d5408SPeter Wemm     char *p;
5450e3d5408SPeter Wemm     const char *ttype;
5460e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5470e3d5408SPeter Wemm     struct ttyent *t;
5480e3d5408SPeter Wemm #else
5490e3d5408SPeter Wemm     FILE *fp;
5500e3d5408SPeter Wemm #endif
5510e3d5408SPeter Wemm     char *ttypath;
5520e3d5408SPeter Wemm 
553aae38d10SBaptiste Daroussin     (void) fd;
554aae38d10SBaptiste Daroussin 
5550e3d5408SPeter Wemm     if (userarg) {
5560e3d5408SPeter Wemm 	ttype = userarg;
5570e3d5408SPeter Wemm 	goto found;
5580e3d5408SPeter Wemm     }
5590e3d5408SPeter Wemm 
5600e3d5408SPeter Wemm     /* Try the environment. */
5610e3d5408SPeter Wemm     if ((ttype = getenv("TERM")) != 0)
5620e3d5408SPeter Wemm 	goto map;
5630e3d5408SPeter Wemm 
564aae38d10SBaptiste Daroussin     if ((ttypath = ttyname(fd)) != 0) {
56518259542SPeter Wemm 	p = _nc_basename(ttypath);
5660e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5670e3d5408SPeter Wemm 	/*
5680e3d5408SPeter Wemm 	 * We have the 4.3BSD library call getttynam(3); that means
5690e3d5408SPeter Wemm 	 * there's an /etc/ttys to look up device-to-type mappings in.
5700e3d5408SPeter Wemm 	 * Try ttyname(3); check for dialup or other mapping.
5710e3d5408SPeter Wemm 	 */
5720e3d5408SPeter Wemm 	if ((t = getttynam(p))) {
5730e3d5408SPeter Wemm 	    ttype = t->ty_type;
5740e3d5408SPeter Wemm 	    goto map;
5750e3d5408SPeter Wemm 	}
5760e3d5408SPeter Wemm #else
5770e3d5408SPeter Wemm 	if ((fp = fopen("/etc/ttytype", "r")) != 0
5780e3d5408SPeter Wemm 	    || (fp = fopen("/etc/ttys", "r")) != 0) {
5790e3d5408SPeter Wemm 	    char buffer[BUFSIZ];
5800e3d5408SPeter Wemm 	    char *s, *t, *d;
5810e3d5408SPeter Wemm 
5820e3d5408SPeter Wemm 	    while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
5830e3d5408SPeter Wemm 		for (s = buffer, t = d = 0; *s; s++) {
58439f2269fSPeter Wemm 		    if (isspace(UChar(*s)))
5850e3d5408SPeter Wemm 			*s = '\0';
5860e3d5408SPeter Wemm 		    else if (t == 0)
5870e3d5408SPeter Wemm 			t = s;
5880e3d5408SPeter Wemm 		    else if (d == 0 && s != buffer && s[-1] == '\0')
5890e3d5408SPeter Wemm 			d = s;
5900e3d5408SPeter Wemm 		}
5910e3d5408SPeter Wemm 		if (t != 0 && d != 0 && !strcmp(d, p)) {
5920e3d5408SPeter Wemm 		    ttype = strdup(t);
5930e3d5408SPeter Wemm 		    fclose(fp);
5940e3d5408SPeter Wemm 		    goto map;
5950e3d5408SPeter Wemm 		}
5960e3d5408SPeter Wemm 	    }
5970e3d5408SPeter Wemm 	    fclose(fp);
5980e3d5408SPeter Wemm 	}
5990e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */
6000e3d5408SPeter Wemm     }
6010e3d5408SPeter Wemm 
6020e3d5408SPeter Wemm     /* If still undefined, use "unknown". */
6030e3d5408SPeter Wemm     ttype = "unknown";
6040e3d5408SPeter Wemm 
6050e3d5408SPeter Wemm   map:ttype = mapped(ttype);
6060e3d5408SPeter Wemm 
6070e3d5408SPeter Wemm     /*
6080e3d5408SPeter Wemm      * If not a path, remove TERMCAP from the environment so we get a
6090e3d5408SPeter Wemm      * real entry from /etc/termcap.  This prevents us from being fooled
6100e3d5408SPeter Wemm      * by out of date stuff in the environment.
6110e3d5408SPeter Wemm      */
61273f0a83dSXin LI   found:
61373f0a83dSXin LI     if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
6140e3d5408SPeter Wemm 	/* 'unsetenv("TERMCAP")' is not portable.
6150e3d5408SPeter Wemm 	 * The 'environ' array is better.
6160e3d5408SPeter Wemm 	 */
6170e3d5408SPeter Wemm 	int n;
6180e3d5408SPeter Wemm 	for (n = 0; environ[n] != 0; n++) {
61973f0a83dSXin LI 	    if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
6200e3d5408SPeter Wemm 		while ((environ[n] = environ[n + 1]) != 0) {
6210e3d5408SPeter Wemm 		    n++;
6220e3d5408SPeter Wemm 		}
6230e3d5408SPeter Wemm 		break;
6240e3d5408SPeter Wemm 	    }
6250e3d5408SPeter Wemm 	}
6260e3d5408SPeter Wemm     }
6270e3d5408SPeter Wemm 
6280e3d5408SPeter Wemm     /*
6290e3d5408SPeter Wemm      * ttype now contains a pointer to the type of the terminal.
6300e3d5408SPeter Wemm      * If the first character is '?', ask the user.
6310e3d5408SPeter Wemm      */
6320e3d5408SPeter Wemm     if (ttype[0] == '?') {
6330e3d5408SPeter Wemm 	if (ttype[1] != '\0')
6340e3d5408SPeter Wemm 	    ttype = askuser(ttype + 1);
6350e3d5408SPeter Wemm 	else
6360e3d5408SPeter Wemm 	    ttype = askuser(0);
6370e3d5408SPeter Wemm     }
6380e3d5408SPeter Wemm     /* Find the terminfo entry.  If it doesn't exist, ask the user. */
639aae38d10SBaptiste Daroussin     while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
6407a69bbfbSPeter Wemm 	   != OK) {
6410e3d5408SPeter Wemm 	if (errret == 0) {
6424a1a9510SRong-En Fan 	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
6434a1a9510SRong-En Fan 			   _nc_progname, ttype);
6440e3d5408SPeter Wemm 	    ttype = 0;
64515589c42SPeter Wemm 	} else {
64615589c42SPeter Wemm 	    (void) fprintf(stderr,
6474a1a9510SRong-En Fan 			   "%s: can't initialize terminal type %s (error %d)\n",
6484a1a9510SRong-En Fan 			   _nc_progname, ttype, errret);
6490e3d5408SPeter Wemm 	    ttype = 0;
6500e3d5408SPeter Wemm 	}
6510e3d5408SPeter Wemm 	ttype = askuser(ttype);
6520e3d5408SPeter Wemm     }
6530e3d5408SPeter Wemm #if BROKEN_LINKER
6540e3d5408SPeter Wemm     tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */
6550e3d5408SPeter Wemm #endif
6560e3d5408SPeter Wemm     return (ttype);
6570e3d5408SPeter Wemm }
6580e3d5408SPeter Wemm 
6590e3d5408SPeter Wemm /**************************************************************************
6600e3d5408SPeter Wemm  *
6610e3d5408SPeter Wemm  * Main sequence
6620e3d5408SPeter Wemm  *
6630e3d5408SPeter Wemm  **************************************************************************/
6640e3d5408SPeter Wemm 
6650e3d5408SPeter Wemm /*
6660e3d5408SPeter Wemm  * Convert the obsolete argument forms into something that getopt can handle.
6670e3d5408SPeter Wemm  * This means that -e, -i and -k get default arguments supplied for them.
6680e3d5408SPeter Wemm  */
6690e3d5408SPeter Wemm static void
6700e3d5408SPeter Wemm obsolete(char **argv)
6710e3d5408SPeter Wemm {
6720e3d5408SPeter Wemm     for (; *argv; ++argv) {
6730e3d5408SPeter Wemm 	char *parm = argv[0];
6740e3d5408SPeter Wemm 
67515589c42SPeter Wemm 	if (parm[0] == '-' && parm[1] == '\0') {
6760e3d5408SPeter Wemm 	    argv[0] = strdup("-q");
6770e3d5408SPeter Wemm 	    continue;
6780e3d5408SPeter Wemm 	}
6790e3d5408SPeter Wemm 
6800e3d5408SPeter Wemm 	if ((parm[0] != '-')
6810e3d5408SPeter Wemm 	    || (argv[1] && argv[1][0] != '-')
6820e3d5408SPeter Wemm 	    || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
6830e3d5408SPeter Wemm 	    || (parm[2] != '\0'))
6840e3d5408SPeter Wemm 	    continue;
6850e3d5408SPeter Wemm 	switch (argv[0][1]) {
6860e3d5408SPeter Wemm 	case 'e':
6870e3d5408SPeter Wemm 	    argv[0] = strdup("-e^H");
6880e3d5408SPeter Wemm 	    break;
6890e3d5408SPeter Wemm 	case 'i':
6900e3d5408SPeter Wemm 	    argv[0] = strdup("-i^C");
6910e3d5408SPeter Wemm 	    break;
6920e3d5408SPeter Wemm 	case 'k':
6930e3d5408SPeter Wemm 	    argv[0] = strdup("-k^U");
6940e3d5408SPeter Wemm 	    break;
6950e3d5408SPeter Wemm 	}
6960e3d5408SPeter Wemm     }
6970e3d5408SPeter Wemm }
6980e3d5408SPeter Wemm 
6990e3d5408SPeter Wemm static void
700aae38d10SBaptiste Daroussin print_shell_commands(const char *ttype)
701aae38d10SBaptiste Daroussin {
702aae38d10SBaptiste Daroussin     const char *p;
703aae38d10SBaptiste Daroussin     int len;
704aae38d10SBaptiste Daroussin     char *var;
705aae38d10SBaptiste Daroussin     char *leaf;
706aae38d10SBaptiste Daroussin     /*
707aae38d10SBaptiste Daroussin      * Figure out what shell we're using.  A hack, we look for an
708aae38d10SBaptiste Daroussin      * environmental variable SHELL ending in "csh".
709aae38d10SBaptiste Daroussin      */
710aae38d10SBaptiste Daroussin     if ((var = getenv("SHELL")) != 0
711aae38d10SBaptiste Daroussin 	&& ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
712aae38d10SBaptiste Daroussin 	&& !strcmp(leaf + len - 3, "csh"))
713aae38d10SBaptiste Daroussin 	p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
714aae38d10SBaptiste Daroussin     else
715aae38d10SBaptiste Daroussin 	p = "TERM=%s;\n";
716aae38d10SBaptiste Daroussin     (void) printf(p, ttype);
717aae38d10SBaptiste Daroussin }
718aae38d10SBaptiste Daroussin 
719aae38d10SBaptiste Daroussin static void
7204a1a9510SRong-En Fan usage(void)
7210e3d5408SPeter Wemm {
722aae38d10SBaptiste Daroussin #define SKIP(s)			/* nothing */
723aae38d10SBaptiste Daroussin #define KEEP(s) s "\n"
724aae38d10SBaptiste Daroussin     static const char msg[] =
7254a1a9510SRong-En Fan     {
726aae38d10SBaptiste Daroussin 	KEEP("")
727aae38d10SBaptiste Daroussin 	KEEP("Options:")
728aae38d10SBaptiste Daroussin 	SKIP("  -a arpanet  (obsolete)")
729aae38d10SBaptiste Daroussin 	KEEP("  -c          set control characters")
730aae38d10SBaptiste Daroussin 	SKIP("  -d dialup   (obsolete)")
731aae38d10SBaptiste Daroussin 	KEEP("  -e ch       erase character")
732aae38d10SBaptiste Daroussin 	KEEP("  -I          no initialization strings")
733aae38d10SBaptiste Daroussin 	KEEP("  -i ch       interrupt character")
734aae38d10SBaptiste Daroussin 	KEEP("  -k ch       kill character")
735aae38d10SBaptiste Daroussin 	KEEP("  -m mapping  map identifier to type")
736aae38d10SBaptiste Daroussin 	SKIP("  -p plugboard (obsolete)")
737aae38d10SBaptiste Daroussin 	KEEP("  -Q          do not output control key settings")
738aae38d10SBaptiste Daroussin 	KEEP("  -q          display term only, do no changes")
739aae38d10SBaptiste Daroussin 	KEEP("  -r          display term on stderr")
740aae38d10SBaptiste Daroussin 	SKIP("  -S          (obsolete)")
741aae38d10SBaptiste Daroussin 	KEEP("  -s          output TERM set command")
742aae38d10SBaptiste Daroussin 	KEEP("  -V          print curses-version")
743aae38d10SBaptiste Daroussin 	KEEP("  -w          set window-size")
744aae38d10SBaptiste Daroussin 	KEEP("")
745aae38d10SBaptiste Daroussin 	KEEP("If neither -c/-w are given, both are assumed.")
7464a1a9510SRong-En Fan     };
747aae38d10SBaptiste Daroussin #undef KEEP
748aae38d10SBaptiste Daroussin #undef SKIP
7494a1a9510SRong-En Fan     (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
750aae38d10SBaptiste Daroussin     fputs(msg, stderr);
751aae38d10SBaptiste Daroussin     ExitProgram(EXIT_FAILURE);
75239f2269fSPeter Wemm     /* NOTREACHED */
7530e3d5408SPeter Wemm }
7540e3d5408SPeter Wemm 
75515589c42SPeter Wemm static char
75615589c42SPeter Wemm arg_to_char(void)
7570e3d5408SPeter Wemm {
7585d08fb1fSRong-En Fan     return (char) ((optarg[0] == '^' && optarg[1] != '\0')
7590e3d5408SPeter Wemm 		   ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
7605d08fb1fSRong-En Fan 		   : optarg[0]);
7610e3d5408SPeter Wemm }
7620e3d5408SPeter Wemm 
7630e3d5408SPeter Wemm int
7640e3d5408SPeter Wemm main(int argc, char **argv)
7650e3d5408SPeter Wemm {
7660e3d5408SPeter Wemm     int ch, noinit, noset, quiet, Sflag, sflag, showterm;
7670e3d5408SPeter Wemm     const char *ttype;
768aae38d10SBaptiste Daroussin     int terasechar = -1;	/* new erase character */
769aae38d10SBaptiste Daroussin     int intrchar = -1;		/* new interrupt character */
770aae38d10SBaptiste Daroussin     int tkillchar = -1;		/* new kill character */
771aae38d10SBaptiste Daroussin     int my_fd;
772aae38d10SBaptiste Daroussin     bool opt_c = FALSE;		/* set control-chars */
773aae38d10SBaptiste Daroussin     bool opt_w = FALSE;		/* set window-size */
774aae38d10SBaptiste Daroussin     TTY mode, oldmode;
7750e3d5408SPeter Wemm 
776aae38d10SBaptiste Daroussin     my_fd = STDERR_FILENO;
7770e3d5408SPeter Wemm     obsolete(argv);
7780e3d5408SPeter Wemm     noinit = noset = quiet = Sflag = sflag = showterm = 0;
779aae38d10SBaptiste Daroussin     while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
7800e3d5408SPeter Wemm 	switch (ch) {
7814a1a9510SRong-En Fan 	case 'c':		/* set control-chars */
7824a1a9510SRong-En Fan 	    opt_c = TRUE;
7830e3d5408SPeter Wemm 	    break;
7840e3d5408SPeter Wemm 	case 'a':		/* OBSOLETE: map identifier to type */
7850e3d5408SPeter Wemm 	    add_mapping("arpanet", optarg);
7860e3d5408SPeter Wemm 	    break;
7870e3d5408SPeter Wemm 	case 'd':		/* OBSOLETE: map identifier to type */
7880e3d5408SPeter Wemm 	    add_mapping("dialup", optarg);
7890e3d5408SPeter Wemm 	    break;
7900e3d5408SPeter Wemm 	case 'e':		/* erase character */
7910e3d5408SPeter Wemm 	    terasechar = arg_to_char();
7920e3d5408SPeter Wemm 	    break;
7930e3d5408SPeter Wemm 	case 'I':		/* no initialization strings */
7940e3d5408SPeter Wemm 	    noinit = 1;
7950e3d5408SPeter Wemm 	    break;
7960e3d5408SPeter Wemm 	case 'i':		/* interrupt character */
7970e3d5408SPeter Wemm 	    intrchar = arg_to_char();
7980e3d5408SPeter Wemm 	    break;
7990e3d5408SPeter Wemm 	case 'k':		/* kill character */
8000e3d5408SPeter Wemm 	    tkillchar = arg_to_char();
8010e3d5408SPeter Wemm 	    break;
8020e3d5408SPeter Wemm 	case 'm':		/* map identifier to type */
8030e3d5408SPeter Wemm 	    add_mapping(0, optarg);
8040e3d5408SPeter Wemm 	    break;
8050e3d5408SPeter Wemm 	case 'p':		/* OBSOLETE: map identifier to type */
8060e3d5408SPeter Wemm 	    add_mapping("plugboard", optarg);
8070e3d5408SPeter Wemm 	    break;
8080e3d5408SPeter Wemm 	case 'Q':		/* don't output control key settings */
8090e3d5408SPeter Wemm 	    quiet = 1;
8100e3d5408SPeter Wemm 	    break;
8114a1a9510SRong-En Fan 	case 'q':		/* display term only */
8124a1a9510SRong-En Fan 	    noset = 1;
8130e3d5408SPeter Wemm 	    break;
8140e3d5408SPeter Wemm 	case 'r':		/* display term on stderr */
8150e3d5408SPeter Wemm 	    showterm = 1;
8160e3d5408SPeter Wemm 	    break;
8174a1a9510SRong-En Fan 	case 'S':		/* OBSOLETE: output TERM & TERMCAP */
8184a1a9510SRong-En Fan 	    Sflag = 1;
8194a1a9510SRong-En Fan 	    break;
8200e3d5408SPeter Wemm 	case 's':		/* output TERM set command */
8210e3d5408SPeter Wemm 	    sflag = 1;
8220e3d5408SPeter Wemm 	    break;
8234a1a9510SRong-En Fan 	case 'V':		/* print curses-version */
82418259542SPeter Wemm 	    puts(curses_version());
8254a1a9510SRong-En Fan 	    ExitProgram(EXIT_SUCCESS);
8264a1a9510SRong-En Fan 	case 'w':		/* set window-size */
8274a1a9510SRong-En Fan 	    opt_w = TRUE;
8284a1a9510SRong-En Fan 	    break;
8290e3d5408SPeter Wemm 	case '?':
8300e3d5408SPeter Wemm 	default:
8314a1a9510SRong-En Fan 	    usage();
8320e3d5408SPeter Wemm 	}
8330e3d5408SPeter Wemm     }
8344a1a9510SRong-En Fan 
8354a1a9510SRong-En Fan     _nc_progname = _nc_rootname(*argv);
8360e3d5408SPeter Wemm     argc -= optind;
8370e3d5408SPeter Wemm     argv += optind;
8380e3d5408SPeter Wemm 
8390e3d5408SPeter Wemm     if (argc > 1)
8404a1a9510SRong-En Fan 	usage();
8414a1a9510SRong-En Fan 
8424a1a9510SRong-En Fan     if (!opt_c && !opt_w)
8434a1a9510SRong-En Fan 	opt_c = opt_w = TRUE;
8444a1a9510SRong-En Fan 
845aae38d10SBaptiste Daroussin     my_fd = save_tty_settings(&mode, TRUE);
846aae38d10SBaptiste Daroussin     oldmode = mode;
8474a1a9510SRong-En Fan #ifdef TERMIOS
8485d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
849*7a656419SBaptiste Daroussin #elif defined(EXP_WIN32_DRIVER)
850*7a656419SBaptiste Daroussin     ospeed = 0;
8514a1a9510SRong-En Fan #else
8525d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
8534a1a9510SRong-En Fan #endif
8544a1a9510SRong-En Fan 
85506bfebdeSXin LI     if (same_program(_nc_progname, PROG_RESET)) {
856aae38d10SBaptiste Daroussin 	reset_start(stderr, TRUE, FALSE);
857aae38d10SBaptiste Daroussin 	reset_tty_settings(my_fd, &mode);
858aae38d10SBaptiste Daroussin     } else {
859aae38d10SBaptiste Daroussin 	reset_start(stderr, FALSE, TRUE);
8604a1a9510SRong-En Fan     }
8610e3d5408SPeter Wemm 
862aae38d10SBaptiste Daroussin     ttype = get_termcap_entry(my_fd, *argv);
8630e3d5408SPeter Wemm 
8640e3d5408SPeter Wemm     if (!noset) {
86573f0a83dSXin LI #if HAVE_SIZECHANGE
8664a1a9510SRong-En Fan 	if (opt_w) {
867aae38d10SBaptiste Daroussin 	    set_window_size(my_fd, &lines, &columns);
8684a1a9510SRong-En Fan 	}
8690e3d5408SPeter Wemm #endif
8704a1a9510SRong-En Fan 	if (opt_c) {
871aae38d10SBaptiste Daroussin 	    set_control_chars(&mode, terasechar, intrchar, tkillchar);
872aae38d10SBaptiste Daroussin 	    set_conversions(&mode);
8730e3d5408SPeter Wemm 
874aae38d10SBaptiste Daroussin 	    if (!noinit) {
875aae38d10SBaptiste Daroussin 		if (send_init_strings(my_fd, &oldmode)) {
876aae38d10SBaptiste Daroussin 		    (void) putc('\r', stderr);
877aae38d10SBaptiste Daroussin 		    (void) fflush(stderr);
878aae38d10SBaptiste Daroussin 		    (void) napms(1000);		/* Settle the terminal. */
8790e3d5408SPeter Wemm 		}
88015589c42SPeter Wemm 	    }
881aae38d10SBaptiste Daroussin 
882aae38d10SBaptiste Daroussin 	    update_tty_settings(&oldmode, &mode);
883aae38d10SBaptiste Daroussin 	}
8844a1a9510SRong-En Fan     }
8850e3d5408SPeter Wemm 
886aae38d10SBaptiste Daroussin     if (noset) {
8870e3d5408SPeter Wemm 	(void) printf("%s\n", ttype);
888aae38d10SBaptiste Daroussin     } else {
8890e3d5408SPeter Wemm 	if (showterm)
8900e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
8910e3d5408SPeter Wemm 	/*
8920e3d5408SPeter Wemm 	 * If erase, kill and interrupt characters could have been
8930e3d5408SPeter Wemm 	 * modified and not -Q, display the changes.
8940e3d5408SPeter Wemm 	 */
8950e3d5408SPeter Wemm 	if (!quiet) {
896aae38d10SBaptiste Daroussin 	    print_tty_chars(&oldmode, &mode);
8970e3d5408SPeter Wemm 	}
8980e3d5408SPeter Wemm     }
8990e3d5408SPeter Wemm 
9000e3d5408SPeter Wemm     if (Sflag)
9010e3d5408SPeter Wemm 	err("The -S option is not supported under terminfo.");
9020e3d5408SPeter Wemm 
9030e3d5408SPeter Wemm     if (sflag) {
904aae38d10SBaptiste Daroussin 	print_shell_commands(ttype);
9050e3d5408SPeter Wemm     }
9060e3d5408SPeter Wemm 
9074a1a9510SRong-En Fan     ExitProgram(EXIT_SUCCESS);
9080e3d5408SPeter Wemm }
909