xref: /freebsd/contrib/ncurses/progs/tset.c (revision 21817992b3314c908ab50f0bb88d2ee750b9c4ac)
10e3d5408SPeter Wemm /****************************************************************************
2*21817992SBaptiste Daroussin  * Copyright 2020-2021,2024 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 
94*21817992SBaptiste Daroussin #if HAVE_GETTTYNAM
950e3d5408SPeter Wemm #include <ttyent.h>
960e3d5408SPeter Wemm #endif
970e3d5408SPeter Wemm #ifdef NeXT
980e3d5408SPeter Wemm char *ttyname(int fd);
990e3d5408SPeter Wemm #endif
1000e3d5408SPeter Wemm 
101*21817992SBaptiste Daroussin MODULE_ID("$Id: tset.c,v 1.135 2024/04/20 22:20:41 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 
111*21817992SBaptiste Daroussin static GCC_NORETURN void exit_error(void);
112aae38d10SBaptiste Daroussin 
1130e3d5408SPeter Wemm static int
CaselessCmp(const char * a,const char * b)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 
125*21817992SBaptiste Daroussin static GCC_NORETURN void
exit_error(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 
135*21817992SBaptiste Daroussin static GCC_NORETURN void
err(const char * fmt,...)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 
147*21817992SBaptiste Daroussin static GCC_NORETURN void
failed(const char * msg)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 *
askuser(const char * dflt)1670e3d5408SPeter Wemm askuser(const char *dflt)
1680e3d5408SPeter Wemm {
1690e3d5408SPeter Wemm     static char answer[256];
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     }
178*21817992SBaptiste Daroussin 
1790e3d5408SPeter Wemm     for (;;) {
180*21817992SBaptiste Daroussin 	char *p;
181*21817992SBaptiste Daroussin 
1820e3d5408SPeter Wemm 	if (dflt)
1830e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? [%s] ", dflt);
1840e3d5408SPeter Wemm 	else
1850e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type? ");
1860e3d5408SPeter Wemm 	(void) fflush(stderr);
1870e3d5408SPeter Wemm 
1880e3d5408SPeter Wemm 	if (fgets(answer, sizeof(answer), stdin) == 0) {
1890e3d5408SPeter Wemm 	    if (dflt == 0) {
19039f2269fSPeter Wemm 		exit_error();
19139f2269fSPeter Wemm 		/* NOTREACHED */
1920e3d5408SPeter Wemm 	    }
1930e3d5408SPeter Wemm 	    return (dflt);
1940e3d5408SPeter Wemm 	}
1950e3d5408SPeter Wemm 
1960e3d5408SPeter Wemm 	if ((p = strchr(answer, '\n')) != 0)
1970e3d5408SPeter Wemm 	    *p = '\0';
1980e3d5408SPeter Wemm 	if (answer[0])
1990e3d5408SPeter Wemm 	    return (answer);
2000e3d5408SPeter Wemm 	if (dflt != 0)
2010e3d5408SPeter Wemm 	    return (dflt);
2020e3d5408SPeter Wemm     }
2030e3d5408SPeter Wemm }
2040e3d5408SPeter Wemm 
2050e3d5408SPeter Wemm /**************************************************************************
2060e3d5408SPeter Wemm  *
2070e3d5408SPeter Wemm  * Mapping logic begins here
2080e3d5408SPeter Wemm  *
2090e3d5408SPeter Wemm  **************************************************************************/
2100e3d5408SPeter Wemm 
2110e3d5408SPeter Wemm /* Baud rate conditionals for mapping. */
2120e3d5408SPeter Wemm #define	GT		0x01
2130e3d5408SPeter Wemm #define	EQ		0x02
2140e3d5408SPeter Wemm #define	LT		0x04
2150e3d5408SPeter Wemm #define	NOT		0x08
2160e3d5408SPeter Wemm #define	GE		(GT | EQ)
2170e3d5408SPeter Wemm #define	LE		(LT | EQ)
2180e3d5408SPeter Wemm 
2190e3d5408SPeter Wemm typedef struct map {
2200e3d5408SPeter Wemm     struct map *next;		/* Linked list of maps. */
2210e3d5408SPeter Wemm     const char *porttype;	/* Port type, or "" for any. */
2220e3d5408SPeter Wemm     const char *type;		/* Terminal type to select. */
2230e3d5408SPeter Wemm     int conditional;		/* Baud rate conditionals bitmask. */
22418259542SPeter Wemm     int speed;			/* Baud rate to compare against. */
2250e3d5408SPeter Wemm } MAP;
2260e3d5408SPeter Wemm 
2270e3d5408SPeter Wemm static MAP *cur, *maplist;
2280e3d5408SPeter Wemm 
229aae38d10SBaptiste Daroussin #define DATA(name,value) { { name }, value }
230aae38d10SBaptiste Daroussin 
2310e3d5408SPeter Wemm typedef struct speeds {
2327a656419SBaptiste Daroussin     const char string[8];
2330e3d5408SPeter Wemm     int speed;
2340e3d5408SPeter Wemm } SPEEDS;
2350e3d5408SPeter Wemm 
2367a656419SBaptiste Daroussin #if defined(EXP_WIN32_DRIVER)
2377a656419SBaptiste Daroussin static const SPEEDS speeds[] =
2387a656419SBaptiste Daroussin {
2397a656419SBaptiste Daroussin     {"0", 0}
2407a656419SBaptiste Daroussin };
2417a656419SBaptiste Daroussin #else
24215589c42SPeter Wemm static const SPEEDS speeds[] =
24315589c42SPeter Wemm {
244aae38d10SBaptiste Daroussin     DATA("0", B0),
245aae38d10SBaptiste Daroussin     DATA("50", B50),
246aae38d10SBaptiste Daroussin     DATA("75", B75),
247aae38d10SBaptiste Daroussin     DATA("110", B110),
248aae38d10SBaptiste Daroussin     DATA("134", B134),
249aae38d10SBaptiste Daroussin     DATA("134.5", B134),
250aae38d10SBaptiste Daroussin     DATA("150", B150),
251aae38d10SBaptiste Daroussin     DATA("200", B200),
252aae38d10SBaptiste Daroussin     DATA("300", B300),
253aae38d10SBaptiste Daroussin     DATA("600", B600),
254aae38d10SBaptiste Daroussin     DATA("1200", B1200),
255aae38d10SBaptiste Daroussin     DATA("1800", B1800),
256aae38d10SBaptiste Daroussin     DATA("2400", B2400),
257aae38d10SBaptiste Daroussin     DATA("4800", B4800),
258aae38d10SBaptiste Daroussin     DATA("9600", B9600),
25918259542SPeter Wemm     /* sgttyb may define up to this point */
26018259542SPeter Wemm #ifdef B19200
261aae38d10SBaptiste Daroussin     DATA("19200", B19200),
26218259542SPeter Wemm #endif
26318259542SPeter Wemm #ifdef B38400
264aae38d10SBaptiste Daroussin     DATA("38400", B38400),
26518259542SPeter Wemm #endif
26618259542SPeter Wemm #ifdef B19200
267aae38d10SBaptiste Daroussin     DATA("19200", B19200),
26818259542SPeter Wemm #endif
26918259542SPeter Wemm #ifdef B38400
270aae38d10SBaptiste Daroussin     DATA("38400", B38400),
27118259542SPeter Wemm #endif
2720e3d5408SPeter Wemm #ifdef B19200
273aae38d10SBaptiste Daroussin     DATA("19200", B19200),
2740e3d5408SPeter Wemm #else
2750e3d5408SPeter Wemm #ifdef EXTA
276aae38d10SBaptiste Daroussin     DATA("19200", EXTA),
2770e3d5408SPeter Wemm #endif
2780e3d5408SPeter Wemm #endif
2790e3d5408SPeter Wemm #ifdef B38400
280aae38d10SBaptiste Daroussin     DATA("38400", B38400),
2810e3d5408SPeter Wemm #else
2820e3d5408SPeter Wemm #ifdef EXTB
283aae38d10SBaptiste Daroussin     DATA("38400", EXTB),
2840e3d5408SPeter Wemm #endif
2850e3d5408SPeter Wemm #endif
2860e3d5408SPeter Wemm #ifdef B57600
287aae38d10SBaptiste Daroussin     DATA("57600", B57600),
288aae38d10SBaptiste Daroussin #endif
289aae38d10SBaptiste Daroussin #ifdef B76800
290aae38d10SBaptiste Daroussin     DATA("76800", B57600),
2910e3d5408SPeter Wemm #endif
2920e3d5408SPeter Wemm #ifdef B115200
293aae38d10SBaptiste Daroussin     DATA("115200", B115200),
294aae38d10SBaptiste Daroussin #endif
295aae38d10SBaptiste Daroussin #ifdef B153600
296aae38d10SBaptiste Daroussin     DATA("153600", B153600),
2970e3d5408SPeter Wemm #endif
2980e3d5408SPeter Wemm #ifdef B230400
299aae38d10SBaptiste Daroussin     DATA("230400", B230400),
300aae38d10SBaptiste Daroussin #endif
301aae38d10SBaptiste Daroussin #ifdef B307200
302aae38d10SBaptiste Daroussin     DATA("307200", B307200),
3030e3d5408SPeter Wemm #endif
3040e3d5408SPeter Wemm #ifdef B460800
305aae38d10SBaptiste Daroussin     DATA("460800", B460800),
3060e3d5408SPeter Wemm #endif
307aae38d10SBaptiste Daroussin #ifdef B500000
308aae38d10SBaptiste Daroussin     DATA("500000", B500000),
309aae38d10SBaptiste Daroussin #endif
310aae38d10SBaptiste Daroussin #ifdef B576000
311aae38d10SBaptiste Daroussin     DATA("576000", B576000),
312aae38d10SBaptiste Daroussin #endif
313aae38d10SBaptiste Daroussin #ifdef B921600
314aae38d10SBaptiste Daroussin     DATA("921600", B921600),
315aae38d10SBaptiste Daroussin #endif
316aae38d10SBaptiste Daroussin #ifdef B1000000
317aae38d10SBaptiste Daroussin     DATA("1000000", B1000000),
318aae38d10SBaptiste Daroussin #endif
319aae38d10SBaptiste Daroussin #ifdef B1152000
320aae38d10SBaptiste Daroussin     DATA("1152000", B1152000),
321aae38d10SBaptiste Daroussin #endif
322aae38d10SBaptiste Daroussin #ifdef B1500000
323aae38d10SBaptiste Daroussin     DATA("1500000", B1500000),
324aae38d10SBaptiste Daroussin #endif
325aae38d10SBaptiste Daroussin #ifdef B2000000
326aae38d10SBaptiste Daroussin     DATA("2000000", B2000000),
327aae38d10SBaptiste Daroussin #endif
328aae38d10SBaptiste Daroussin #ifdef B2500000
329aae38d10SBaptiste Daroussin     DATA("2500000", B2500000),
330aae38d10SBaptiste Daroussin #endif
331aae38d10SBaptiste Daroussin #ifdef B3000000
332aae38d10SBaptiste Daroussin     DATA("3000000", B3000000),
333aae38d10SBaptiste Daroussin #endif
334aae38d10SBaptiste Daroussin #ifdef B3500000
335aae38d10SBaptiste Daroussin     DATA("3500000", B3500000),
336aae38d10SBaptiste Daroussin #endif
337aae38d10SBaptiste Daroussin #ifdef B4000000
338aae38d10SBaptiste Daroussin     DATA("4000000", B4000000),
339aae38d10SBaptiste Daroussin #endif
3400e3d5408SPeter Wemm };
341aae38d10SBaptiste Daroussin #undef DATA
3427a656419SBaptiste Daroussin #endif
3430e3d5408SPeter Wemm 
3440e3d5408SPeter Wemm static int
tbaudrate(char * rate)3450e3d5408SPeter Wemm tbaudrate(char *rate)
3460e3d5408SPeter Wemm {
347aae38d10SBaptiste Daroussin     const SPEEDS *sp = 0;
348aae38d10SBaptiste Daroussin     size_t n;
3490e3d5408SPeter Wemm 
3500e3d5408SPeter Wemm     /* The baudrate number can be preceded by a 'B', which is ignored. */
3510e3d5408SPeter Wemm     if (*rate == 'B')
3520e3d5408SPeter Wemm 	++rate;
3530e3d5408SPeter Wemm 
354aae38d10SBaptiste Daroussin     for (n = 0; n < SIZEOF(speeds); ++n) {
355aae38d10SBaptiste Daroussin 	if (n > 0 && (speeds[n].speed <= speeds[n - 1].speed)) {
356aae38d10SBaptiste Daroussin 	    /* if the speeds are not increasing, likely a numeric overflow */
357aae38d10SBaptiste Daroussin 	    break;
358aae38d10SBaptiste Daroussin 	}
359aae38d10SBaptiste Daroussin 	if (!CaselessCmp(rate, speeds[n].string)) {
360aae38d10SBaptiste Daroussin 	    sp = speeds + n;
3610e3d5408SPeter Wemm 	    break;
3620e3d5408SPeter Wemm 	}
3630e3d5408SPeter Wemm     }
364aae38d10SBaptiste Daroussin     if (sp == 0)
3650e3d5408SPeter Wemm 	err("unknown baud rate %s", rate);
3660e3d5408SPeter Wemm     return (sp->speed);
3670e3d5408SPeter Wemm }
3680e3d5408SPeter Wemm 
3690e3d5408SPeter Wemm /*
3700e3d5408SPeter Wemm  * Syntax for -m:
3710e3d5408SPeter Wemm  * [port-type][test baudrate]:terminal-type
3720e3d5408SPeter Wemm  * The baud rate tests are: >, <, @, =, !
3730e3d5408SPeter Wemm  */
3740e3d5408SPeter Wemm static void
add_mapping(const char * port,char * arg)3750e3d5408SPeter Wemm add_mapping(const char *port, char *arg)
3760e3d5408SPeter Wemm {
3770e3d5408SPeter Wemm     MAP *mapp;
3780e3d5408SPeter Wemm     char *copy, *p;
3790e3d5408SPeter Wemm     const char *termp;
3800e3d5408SPeter Wemm     char *base = 0;
3810e3d5408SPeter Wemm 
3820e3d5408SPeter Wemm     copy = strdup(arg);
38306bfebdeSXin LI     mapp = typeMalloc(MAP, 1);
3840e3d5408SPeter Wemm     if (copy == 0 || mapp == 0)
3850e3d5408SPeter Wemm 	failed("malloc");
38606bfebdeSXin LI 
38706bfebdeSXin LI     assert(copy != 0);
38806bfebdeSXin LI     assert(mapp != 0);
38906bfebdeSXin LI 
3900e3d5408SPeter Wemm     mapp->next = 0;
3910e3d5408SPeter Wemm     if (maplist == 0)
3920e3d5408SPeter Wemm 	cur = maplist = mapp;
3930e3d5408SPeter Wemm     else {
3940e3d5408SPeter Wemm 	cur->next = mapp;
3950e3d5408SPeter Wemm 	cur = mapp;
3960e3d5408SPeter Wemm     }
3970e3d5408SPeter Wemm 
3980e3d5408SPeter Wemm     mapp->porttype = arg;
3990e3d5408SPeter Wemm     mapp->conditional = 0;
4000e3d5408SPeter Wemm 
4010e3d5408SPeter Wemm     arg = strpbrk(arg, "><@=!:");
4020e3d5408SPeter Wemm 
4030e3d5408SPeter Wemm     if (arg == 0) {		/* [?]term */
4040e3d5408SPeter Wemm 	mapp->type = mapp->porttype;
4050e3d5408SPeter Wemm 	mapp->porttype = 0;
4060e3d5408SPeter Wemm 	goto done;
4070e3d5408SPeter Wemm     }
4080e3d5408SPeter Wemm 
4090e3d5408SPeter Wemm     if (arg == mapp->porttype)	/* [><@=! baud]:term */
4100e3d5408SPeter Wemm 	termp = mapp->porttype = 0;
4110e3d5408SPeter Wemm     else
4120e3d5408SPeter Wemm 	termp = base = arg;
4130e3d5408SPeter Wemm 
41415589c42SPeter Wemm     for (;; ++arg) {		/* Optional conditionals. */
4150e3d5408SPeter Wemm 	switch (*arg) {
4160e3d5408SPeter Wemm 	case '<':
4170e3d5408SPeter Wemm 	    if (mapp->conditional & GT)
4180e3d5408SPeter Wemm 		goto badmopt;
4190e3d5408SPeter Wemm 	    mapp->conditional |= LT;
4200e3d5408SPeter Wemm 	    break;
4210e3d5408SPeter Wemm 	case '>':
4220e3d5408SPeter Wemm 	    if (mapp->conditional & LT)
4230e3d5408SPeter Wemm 		goto badmopt;
4240e3d5408SPeter Wemm 	    mapp->conditional |= GT;
4250e3d5408SPeter Wemm 	    break;
4260e3d5408SPeter Wemm 	case '@':
4270e3d5408SPeter Wemm 	case '=':		/* Not documented. */
4280e3d5408SPeter Wemm 	    mapp->conditional |= EQ;
4290e3d5408SPeter Wemm 	    break;
4300e3d5408SPeter Wemm 	case '!':
4310e3d5408SPeter Wemm 	    mapp->conditional |= NOT;
4320e3d5408SPeter Wemm 	    break;
4330e3d5408SPeter Wemm 	default:
4340e3d5408SPeter Wemm 	    goto next;
4350e3d5408SPeter Wemm 	}
43615589c42SPeter Wemm     }
4370e3d5408SPeter Wemm 
43815589c42SPeter Wemm   next:
43915589c42SPeter Wemm     if (*arg == ':') {
4400e3d5408SPeter Wemm 	if (mapp->conditional)
4410e3d5408SPeter Wemm 	    goto badmopt;
4420e3d5408SPeter Wemm 	++arg;
4430e3d5408SPeter Wemm     } else {			/* Optional baudrate. */
4440e3d5408SPeter Wemm 	arg = strchr(p = arg, ':');
4450e3d5408SPeter Wemm 	if (arg == 0)
4460e3d5408SPeter Wemm 	    goto badmopt;
4470e3d5408SPeter Wemm 	*arg++ = '\0';
4480e3d5408SPeter Wemm 	mapp->speed = tbaudrate(p);
4490e3d5408SPeter Wemm     }
4500e3d5408SPeter Wemm 
4510e3d5408SPeter Wemm     mapp->type = arg;
4520e3d5408SPeter Wemm 
4530e3d5408SPeter Wemm     /* Terminate porttype, if specified. */
4540e3d5408SPeter Wemm     if (termp != 0)
4550e3d5408SPeter Wemm 	*base = '\0';
4560e3d5408SPeter Wemm 
4570e3d5408SPeter Wemm     /* If a NOT conditional, reverse the test. */
4580e3d5408SPeter Wemm     if (mapp->conditional & NOT)
4590e3d5408SPeter Wemm 	mapp->conditional = ~mapp->conditional & (EQ | GT | LT);
4600e3d5408SPeter Wemm 
4610e3d5408SPeter Wemm     /* If user specified a port with an option flag, set it. */
4625d08fb1fSRong-En Fan   done:
4635d08fb1fSRong-En Fan     if (port) {
4645d08fb1fSRong-En Fan 	if (mapp->porttype) {
4655d08fb1fSRong-En Fan 	  badmopt:
4665d08fb1fSRong-En Fan 	    err("illegal -m option format: %s", copy);
4675d08fb1fSRong-En Fan 	}
4680e3d5408SPeter Wemm 	mapp->porttype = port;
4690e3d5408SPeter Wemm     }
4705d08fb1fSRong-En Fan     free(copy);
4710e3d5408SPeter Wemm #ifdef MAPDEBUG
4720e3d5408SPeter Wemm     (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");
4730e3d5408SPeter Wemm     (void) printf("type: %s\n", mapp->type);
4740e3d5408SPeter Wemm     (void) printf("conditional: ");
4750e3d5408SPeter Wemm     p = "";
4760e3d5408SPeter Wemm     if (mapp->conditional & GT) {
4770e3d5408SPeter Wemm 	(void) printf("GT");
4780e3d5408SPeter Wemm 	p = "/";
4790e3d5408SPeter Wemm     }
4800e3d5408SPeter Wemm     if (mapp->conditional & EQ) {
4810e3d5408SPeter Wemm 	(void) printf("%sEQ", p);
4820e3d5408SPeter Wemm 	p = "/";
4830e3d5408SPeter Wemm     }
4840e3d5408SPeter Wemm     if (mapp->conditional & LT)
4850e3d5408SPeter Wemm 	(void) printf("%sLT", p);
4860e3d5408SPeter Wemm     (void) printf("\nspeed: %d\n", mapp->speed);
4870e3d5408SPeter Wemm #endif
4880e3d5408SPeter Wemm }
4890e3d5408SPeter Wemm 
4900e3d5408SPeter Wemm /*
4910e3d5408SPeter Wemm  * Return the type of terminal to use for a port of type 'type', as specified
4920e3d5408SPeter Wemm  * by the first applicable mapping in 'map'.  If no mappings apply, return
4930e3d5408SPeter Wemm  * 'type'.
4940e3d5408SPeter Wemm  */
4950e3d5408SPeter Wemm static const char *
mapped(const char * type)4960e3d5408SPeter Wemm mapped(const char *type)
4970e3d5408SPeter Wemm {
4980e3d5408SPeter Wemm     MAP *mapp;
4990e3d5408SPeter Wemm     int match;
5000e3d5408SPeter Wemm 
5010e3d5408SPeter Wemm     for (mapp = maplist; mapp; mapp = mapp->next)
5020e3d5408SPeter Wemm 	if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {
5030e3d5408SPeter Wemm 	    switch (mapp->conditional) {
5040e3d5408SPeter Wemm 	    case 0:		/* No test specified. */
5050e3d5408SPeter Wemm 		match = TRUE;
5060e3d5408SPeter Wemm 		break;
5070e3d5408SPeter Wemm 	    case EQ:
50873f0a83dSXin LI 		match = ((int) ospeed == mapp->speed);
5090e3d5408SPeter Wemm 		break;
5100e3d5408SPeter Wemm 	    case GE:
51173f0a83dSXin LI 		match = ((int) ospeed >= mapp->speed);
5120e3d5408SPeter Wemm 		break;
5130e3d5408SPeter Wemm 	    case GT:
51473f0a83dSXin LI 		match = ((int) ospeed > mapp->speed);
5150e3d5408SPeter Wemm 		break;
5160e3d5408SPeter Wemm 	    case LE:
51773f0a83dSXin LI 		match = ((int) ospeed <= mapp->speed);
5180e3d5408SPeter Wemm 		break;
5190e3d5408SPeter Wemm 	    case LT:
52073f0a83dSXin LI 		match = ((int) ospeed < mapp->speed);
5210e3d5408SPeter Wemm 		break;
5220e3d5408SPeter Wemm 	    default:
5230e3d5408SPeter Wemm 		match = FALSE;
5240e3d5408SPeter Wemm 	    }
5250e3d5408SPeter Wemm 	    if (match)
5260e3d5408SPeter Wemm 		return (mapp->type);
5270e3d5408SPeter Wemm 	}
5280e3d5408SPeter Wemm     /* No match found; return given type. */
5290e3d5408SPeter Wemm     return (type);
5300e3d5408SPeter Wemm }
5310e3d5408SPeter Wemm 
5320e3d5408SPeter Wemm /**************************************************************************
5330e3d5408SPeter Wemm  *
5340e3d5408SPeter Wemm  * Entry fetching
5350e3d5408SPeter Wemm  *
5360e3d5408SPeter Wemm  **************************************************************************/
5370e3d5408SPeter Wemm 
5380e3d5408SPeter Wemm /*
5390e3d5408SPeter Wemm  * Figure out what kind of terminal we're dealing with, and then read in
5400e3d5408SPeter Wemm  * its termcap entry.
5410e3d5408SPeter Wemm  */
5420e3d5408SPeter Wemm static const char *
get_termcap_entry(int fd,char * userarg)543aae38d10SBaptiste Daroussin get_termcap_entry(int fd, char *userarg)
5440e3d5408SPeter Wemm {
5457a69bbfbSPeter Wemm     int errret;
5460e3d5408SPeter Wemm     char *p;
5470e3d5408SPeter Wemm     const char *ttype;
548*21817992SBaptiste Daroussin #if HAVE_PATH_TTYS
5490e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5500e3d5408SPeter Wemm     struct ttyent *t;
5510e3d5408SPeter Wemm #else
5520e3d5408SPeter Wemm     FILE *fp;
5530e3d5408SPeter Wemm #endif
5540e3d5408SPeter Wemm     char *ttypath;
555*21817992SBaptiste Daroussin #endif /* HAVE_PATH_TTYS */
5560e3d5408SPeter Wemm 
557aae38d10SBaptiste Daroussin     (void) fd;
558aae38d10SBaptiste Daroussin 
5590e3d5408SPeter Wemm     if (userarg) {
5600e3d5408SPeter Wemm 	ttype = userarg;
5610e3d5408SPeter Wemm 	goto found;
5620e3d5408SPeter Wemm     }
5630e3d5408SPeter Wemm 
5640e3d5408SPeter Wemm     /* Try the environment. */
5650e3d5408SPeter Wemm     if ((ttype = getenv("TERM")) != 0)
5660e3d5408SPeter Wemm 	goto map;
5670e3d5408SPeter Wemm 
568*21817992SBaptiste Daroussin #if HAVE_PATH_TTYS
569aae38d10SBaptiste Daroussin     if ((ttypath = ttyname(fd)) != 0) {
57018259542SPeter Wemm 	p = _nc_basename(ttypath);
5710e3d5408SPeter Wemm #if HAVE_GETTTYNAM
5720e3d5408SPeter Wemm 	/*
5730e3d5408SPeter Wemm 	 * We have the 4.3BSD library call getttynam(3); that means
5740e3d5408SPeter Wemm 	 * there's an /etc/ttys to look up device-to-type mappings in.
5750e3d5408SPeter Wemm 	 * Try ttyname(3); check for dialup or other mapping.
5760e3d5408SPeter Wemm 	 */
5770e3d5408SPeter Wemm 	if ((t = getttynam(p))) {
5780e3d5408SPeter Wemm 	    ttype = t->ty_type;
5790e3d5408SPeter Wemm 	    goto map;
5800e3d5408SPeter Wemm 	}
5810e3d5408SPeter Wemm #else
5820e3d5408SPeter Wemm 	if ((fp = fopen("/etc/ttytype", "r")) != 0
5830e3d5408SPeter Wemm 	    || (fp = fopen("/etc/ttys", "r")) != 0) {
5840e3d5408SPeter Wemm 	    char buffer[BUFSIZ];
5850e3d5408SPeter Wemm 	    char *s, *t, *d;
5860e3d5408SPeter Wemm 
5870e3d5408SPeter Wemm 	    while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {
5880e3d5408SPeter Wemm 		for (s = buffer, t = d = 0; *s; s++) {
58939f2269fSPeter Wemm 		    if (isspace(UChar(*s)))
5900e3d5408SPeter Wemm 			*s = '\0';
5910e3d5408SPeter Wemm 		    else if (t == 0)
5920e3d5408SPeter Wemm 			t = s;
5930e3d5408SPeter Wemm 		    else if (d == 0 && s != buffer && s[-1] == '\0')
5940e3d5408SPeter Wemm 			d = s;
5950e3d5408SPeter Wemm 		}
5960e3d5408SPeter Wemm 		if (t != 0 && d != 0 && !strcmp(d, p)) {
5970e3d5408SPeter Wemm 		    ttype = strdup(t);
5980e3d5408SPeter Wemm 		    fclose(fp);
5990e3d5408SPeter Wemm 		    goto map;
6000e3d5408SPeter Wemm 		}
6010e3d5408SPeter Wemm 	    }
6020e3d5408SPeter Wemm 	    fclose(fp);
6030e3d5408SPeter Wemm 	}
6040e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */
6050e3d5408SPeter Wemm     }
606*21817992SBaptiste Daroussin #endif /* HAVE_PATH_TTYS */
6070e3d5408SPeter Wemm 
6080e3d5408SPeter Wemm     /* If still undefined, use "unknown". */
6090e3d5408SPeter Wemm     ttype = "unknown";
6100e3d5408SPeter Wemm 
6110e3d5408SPeter Wemm   map:ttype = mapped(ttype);
6120e3d5408SPeter Wemm 
6130e3d5408SPeter Wemm     /*
6140e3d5408SPeter Wemm      * If not a path, remove TERMCAP from the environment so we get a
6150e3d5408SPeter Wemm      * real entry from /etc/termcap.  This prevents us from being fooled
6160e3d5408SPeter Wemm      * by out of date stuff in the environment.
6170e3d5408SPeter Wemm      */
61873f0a83dSXin LI   found:
61973f0a83dSXin LI     if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) {
6200e3d5408SPeter Wemm 	/* 'unsetenv("TERMCAP")' is not portable.
6210e3d5408SPeter Wemm 	 * The 'environ' array is better.
6220e3d5408SPeter Wemm 	 */
6230e3d5408SPeter Wemm 	int n;
6240e3d5408SPeter Wemm 	for (n = 0; environ[n] != 0; n++) {
62573f0a83dSXin LI 	    if (!strncmp("TERMCAP=", environ[n], (size_t) 8)) {
6260e3d5408SPeter Wemm 		while ((environ[n] = environ[n + 1]) != 0) {
6270e3d5408SPeter Wemm 		    n++;
6280e3d5408SPeter Wemm 		}
6290e3d5408SPeter Wemm 		break;
6300e3d5408SPeter Wemm 	    }
6310e3d5408SPeter Wemm 	}
6320e3d5408SPeter Wemm     }
6330e3d5408SPeter Wemm 
6340e3d5408SPeter Wemm     /*
6350e3d5408SPeter Wemm      * ttype now contains a pointer to the type of the terminal.
6360e3d5408SPeter Wemm      * If the first character is '?', ask the user.
6370e3d5408SPeter Wemm      */
6380e3d5408SPeter Wemm     if (ttype[0] == '?') {
6390e3d5408SPeter Wemm 	if (ttype[1] != '\0')
6400e3d5408SPeter Wemm 	    ttype = askuser(ttype + 1);
6410e3d5408SPeter Wemm 	else
6420e3d5408SPeter Wemm 	    ttype = askuser(0);
6430e3d5408SPeter Wemm     }
6440e3d5408SPeter Wemm     /* Find the terminfo entry.  If it doesn't exist, ask the user. */
645aae38d10SBaptiste Daroussin     while (setupterm((NCURSES_CONST char *) ttype, fd, &errret)
6467a69bbfbSPeter Wemm 	   != OK) {
6470e3d5408SPeter Wemm 	if (errret == 0) {
6484a1a9510SRong-En Fan 	    (void) fprintf(stderr, "%s: unknown terminal type %s\n",
6494a1a9510SRong-En Fan 			   _nc_progname, ttype);
6500e3d5408SPeter Wemm 	    ttype = 0;
65115589c42SPeter Wemm 	} else {
65215589c42SPeter Wemm 	    (void) fprintf(stderr,
6534a1a9510SRong-En Fan 			   "%s: can't initialize terminal type %s (error %d)\n",
6544a1a9510SRong-En Fan 			   _nc_progname, ttype, errret);
6550e3d5408SPeter Wemm 	    ttype = 0;
6560e3d5408SPeter Wemm 	}
6570e3d5408SPeter Wemm 	ttype = askuser(ttype);
6580e3d5408SPeter Wemm     }
6590e3d5408SPeter Wemm #if BROKEN_LINKER
6600e3d5408SPeter Wemm     tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */
6610e3d5408SPeter Wemm #endif
6620e3d5408SPeter Wemm     return (ttype);
6630e3d5408SPeter Wemm }
6640e3d5408SPeter Wemm 
6650e3d5408SPeter Wemm /**************************************************************************
6660e3d5408SPeter Wemm  *
6670e3d5408SPeter Wemm  * Main sequence
6680e3d5408SPeter Wemm  *
6690e3d5408SPeter Wemm  **************************************************************************/
6700e3d5408SPeter Wemm 
6710e3d5408SPeter Wemm /*
6720e3d5408SPeter Wemm  * Convert the obsolete argument forms into something that getopt can handle.
6730e3d5408SPeter Wemm  * This means that -e, -i and -k get default arguments supplied for them.
6740e3d5408SPeter Wemm  */
6750e3d5408SPeter Wemm static void
obsolete(char ** argv)6760e3d5408SPeter Wemm obsolete(char **argv)
6770e3d5408SPeter Wemm {
6780e3d5408SPeter Wemm     for (; *argv; ++argv) {
6790e3d5408SPeter Wemm 	char *parm = argv[0];
6800e3d5408SPeter Wemm 
68115589c42SPeter Wemm 	if (parm[0] == '-' && parm[1] == '\0') {
6820e3d5408SPeter Wemm 	    argv[0] = strdup("-q");
6830e3d5408SPeter Wemm 	    continue;
6840e3d5408SPeter Wemm 	}
6850e3d5408SPeter Wemm 
6860e3d5408SPeter Wemm 	if ((parm[0] != '-')
6870e3d5408SPeter Wemm 	    || (argv[1] && argv[1][0] != '-')
6880e3d5408SPeter Wemm 	    || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k')
6890e3d5408SPeter Wemm 	    || (parm[2] != '\0'))
6900e3d5408SPeter Wemm 	    continue;
6910e3d5408SPeter Wemm 	switch (argv[0][1]) {
6920e3d5408SPeter Wemm 	case 'e':
6930e3d5408SPeter Wemm 	    argv[0] = strdup("-e^H");
6940e3d5408SPeter Wemm 	    break;
6950e3d5408SPeter Wemm 	case 'i':
6960e3d5408SPeter Wemm 	    argv[0] = strdup("-i^C");
6970e3d5408SPeter Wemm 	    break;
6980e3d5408SPeter Wemm 	case 'k':
6990e3d5408SPeter Wemm 	    argv[0] = strdup("-k^U");
7000e3d5408SPeter Wemm 	    break;
7010e3d5408SPeter Wemm 	}
7020e3d5408SPeter Wemm     }
7030e3d5408SPeter Wemm }
7040e3d5408SPeter Wemm 
7050e3d5408SPeter Wemm static void
print_shell_commands(const char * ttype)706aae38d10SBaptiste Daroussin print_shell_commands(const char *ttype)
707aae38d10SBaptiste Daroussin {
708aae38d10SBaptiste Daroussin     const char *p;
709aae38d10SBaptiste Daroussin     int len;
710aae38d10SBaptiste Daroussin     char *var;
711aae38d10SBaptiste Daroussin     char *leaf;
712aae38d10SBaptiste Daroussin     /*
713aae38d10SBaptiste Daroussin      * Figure out what shell we're using.  A hack, we look for an
714aae38d10SBaptiste Daroussin      * environmental variable SHELL ending in "csh".
715aae38d10SBaptiste Daroussin      */
716aae38d10SBaptiste Daroussin     if ((var = getenv("SHELL")) != 0
717aae38d10SBaptiste Daroussin 	&& ((len = (int) strlen(leaf = _nc_basename(var))) >= 3)
718aae38d10SBaptiste Daroussin 	&& !strcmp(leaf + len - 3, "csh"))
719aae38d10SBaptiste Daroussin 	p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n";
720aae38d10SBaptiste Daroussin     else
721aae38d10SBaptiste Daroussin 	p = "TERM=%s;\n";
722aae38d10SBaptiste Daroussin     (void) printf(p, ttype);
723aae38d10SBaptiste Daroussin }
724aae38d10SBaptiste Daroussin 
725aae38d10SBaptiste Daroussin static void
usage(void)7264a1a9510SRong-En Fan usage(void)
7270e3d5408SPeter Wemm {
728aae38d10SBaptiste Daroussin #define SKIP(s)			/* nothing */
729aae38d10SBaptiste Daroussin #define KEEP(s) s "\n"
730aae38d10SBaptiste Daroussin     static const char msg[] =
7314a1a9510SRong-En Fan     {
732aae38d10SBaptiste Daroussin 	KEEP("")
733aae38d10SBaptiste Daroussin 	KEEP("Options:")
734aae38d10SBaptiste Daroussin 	SKIP("  -a arpanet  (obsolete)")
735aae38d10SBaptiste Daroussin 	KEEP("  -c          set control characters")
736aae38d10SBaptiste Daroussin 	SKIP("  -d dialup   (obsolete)")
737aae38d10SBaptiste Daroussin 	KEEP("  -e ch       erase character")
738aae38d10SBaptiste Daroussin 	KEEP("  -I          no initialization strings")
739aae38d10SBaptiste Daroussin 	KEEP("  -i ch       interrupt character")
740aae38d10SBaptiste Daroussin 	KEEP("  -k ch       kill character")
741aae38d10SBaptiste Daroussin 	KEEP("  -m mapping  map identifier to type")
742aae38d10SBaptiste Daroussin 	SKIP("  -p plugboard (obsolete)")
743aae38d10SBaptiste Daroussin 	KEEP("  -Q          do not output control key settings")
744aae38d10SBaptiste Daroussin 	KEEP("  -q          display term only, do no changes")
745aae38d10SBaptiste Daroussin 	KEEP("  -r          display term on stderr")
746aae38d10SBaptiste Daroussin 	SKIP("  -S          (obsolete)")
747aae38d10SBaptiste Daroussin 	KEEP("  -s          output TERM set command")
748aae38d10SBaptiste Daroussin 	KEEP("  -V          print curses-version")
749aae38d10SBaptiste Daroussin 	KEEP("  -w          set window-size")
750aae38d10SBaptiste Daroussin 	KEEP("")
751aae38d10SBaptiste Daroussin 	KEEP("If neither -c/-w are given, both are assumed.")
7524a1a9510SRong-En Fan     };
753aae38d10SBaptiste Daroussin #undef KEEP
754aae38d10SBaptiste Daroussin #undef SKIP
7554a1a9510SRong-En Fan     (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname);
756aae38d10SBaptiste Daroussin     fputs(msg, stderr);
757aae38d10SBaptiste Daroussin     ExitProgram(EXIT_FAILURE);
75839f2269fSPeter Wemm     /* NOTREACHED */
7590e3d5408SPeter Wemm }
7600e3d5408SPeter Wemm 
76115589c42SPeter Wemm static char
arg_to_char(void)76215589c42SPeter Wemm arg_to_char(void)
7630e3d5408SPeter Wemm {
7645d08fb1fSRong-En Fan     return (char) ((optarg[0] == '^' && optarg[1] != '\0')
7650e3d5408SPeter Wemm 		   ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1]))
7665d08fb1fSRong-En Fan 		   : optarg[0]);
7670e3d5408SPeter Wemm }
7680e3d5408SPeter Wemm 
7690e3d5408SPeter Wemm int
main(int argc,char ** argv)7700e3d5408SPeter Wemm main(int argc, char **argv)
7710e3d5408SPeter Wemm {
7720e3d5408SPeter Wemm     int ch, noinit, noset, quiet, Sflag, sflag, showterm;
7730e3d5408SPeter Wemm     const char *ttype;
774aae38d10SBaptiste Daroussin     int terasechar = -1;	/* new erase character */
775aae38d10SBaptiste Daroussin     int intrchar = -1;		/* new interrupt character */
776aae38d10SBaptiste Daroussin     int tkillchar = -1;		/* new kill character */
777aae38d10SBaptiste Daroussin     int my_fd;
778aae38d10SBaptiste Daroussin     bool opt_c = FALSE;		/* set control-chars */
779aae38d10SBaptiste Daroussin     bool opt_w = FALSE;		/* set window-size */
780aae38d10SBaptiste Daroussin     TTY mode, oldmode;
7810e3d5408SPeter Wemm 
782*21817992SBaptiste Daroussin     _nc_progname = _nc_rootname(*argv);
7830e3d5408SPeter Wemm     obsolete(argv);
7840e3d5408SPeter Wemm     noinit = noset = quiet = Sflag = sflag = showterm = 0;
785aae38d10SBaptiste Daroussin     while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:p:qQrSsVw")) != -1) {
7860e3d5408SPeter Wemm 	switch (ch) {
7874a1a9510SRong-En Fan 	case 'c':		/* set control-chars */
7884a1a9510SRong-En Fan 	    opt_c = TRUE;
7890e3d5408SPeter Wemm 	    break;
7900e3d5408SPeter Wemm 	case 'a':		/* OBSOLETE: map identifier to type */
7910e3d5408SPeter Wemm 	    add_mapping("arpanet", optarg);
7920e3d5408SPeter Wemm 	    break;
7930e3d5408SPeter Wemm 	case 'd':		/* OBSOLETE: map identifier to type */
7940e3d5408SPeter Wemm 	    add_mapping("dialup", optarg);
7950e3d5408SPeter Wemm 	    break;
7960e3d5408SPeter Wemm 	case 'e':		/* erase character */
7970e3d5408SPeter Wemm 	    terasechar = arg_to_char();
7980e3d5408SPeter Wemm 	    break;
7990e3d5408SPeter Wemm 	case 'I':		/* no initialization strings */
8000e3d5408SPeter Wemm 	    noinit = 1;
8010e3d5408SPeter Wemm 	    break;
8020e3d5408SPeter Wemm 	case 'i':		/* interrupt character */
8030e3d5408SPeter Wemm 	    intrchar = arg_to_char();
8040e3d5408SPeter Wemm 	    break;
8050e3d5408SPeter Wemm 	case 'k':		/* kill character */
8060e3d5408SPeter Wemm 	    tkillchar = arg_to_char();
8070e3d5408SPeter Wemm 	    break;
8080e3d5408SPeter Wemm 	case 'm':		/* map identifier to type */
8090e3d5408SPeter Wemm 	    add_mapping(0, optarg);
8100e3d5408SPeter Wemm 	    break;
8110e3d5408SPeter Wemm 	case 'p':		/* OBSOLETE: map identifier to type */
8120e3d5408SPeter Wemm 	    add_mapping("plugboard", optarg);
8130e3d5408SPeter Wemm 	    break;
8140e3d5408SPeter Wemm 	case 'Q':		/* don't output control key settings */
8150e3d5408SPeter Wemm 	    quiet = 1;
8160e3d5408SPeter Wemm 	    break;
8174a1a9510SRong-En Fan 	case 'q':		/* display term only */
8184a1a9510SRong-En Fan 	    noset = 1;
8190e3d5408SPeter Wemm 	    break;
8200e3d5408SPeter Wemm 	case 'r':		/* display term on stderr */
8210e3d5408SPeter Wemm 	    showterm = 1;
8220e3d5408SPeter Wemm 	    break;
8234a1a9510SRong-En Fan 	case 'S':		/* OBSOLETE: output TERM & TERMCAP */
8244a1a9510SRong-En Fan 	    Sflag = 1;
8254a1a9510SRong-En Fan 	    break;
8260e3d5408SPeter Wemm 	case 's':		/* output TERM set command */
8270e3d5408SPeter Wemm 	    sflag = 1;
8280e3d5408SPeter Wemm 	    break;
8294a1a9510SRong-En Fan 	case 'V':		/* print curses-version */
83018259542SPeter Wemm 	    puts(curses_version());
8314a1a9510SRong-En Fan 	    ExitProgram(EXIT_SUCCESS);
8324a1a9510SRong-En Fan 	case 'w':		/* set window-size */
8334a1a9510SRong-En Fan 	    opt_w = TRUE;
8344a1a9510SRong-En Fan 	    break;
8350e3d5408SPeter Wemm 	case '?':
8360e3d5408SPeter Wemm 	default:
8374a1a9510SRong-En Fan 	    usage();
8380e3d5408SPeter Wemm 	}
8390e3d5408SPeter Wemm     }
8404a1a9510SRong-En Fan 
8410e3d5408SPeter Wemm     argc -= optind;
8420e3d5408SPeter Wemm     argv += optind;
8430e3d5408SPeter Wemm 
8440e3d5408SPeter Wemm     if (argc > 1)
8454a1a9510SRong-En Fan 	usage();
8464a1a9510SRong-En Fan 
8474a1a9510SRong-En Fan     if (!opt_c && !opt_w)
8484a1a9510SRong-En Fan 	opt_c = opt_w = TRUE;
8494a1a9510SRong-En Fan 
850aae38d10SBaptiste Daroussin     my_fd = save_tty_settings(&mode, TRUE);
851aae38d10SBaptiste Daroussin     oldmode = mode;
8524a1a9510SRong-En Fan #ifdef TERMIOS
8535d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) cfgetospeed(&mode);
8547a656419SBaptiste Daroussin #elif defined(EXP_WIN32_DRIVER)
8557a656419SBaptiste Daroussin     ospeed = 0;
8564a1a9510SRong-En Fan #else
8575d08fb1fSRong-En Fan     ospeed = (NCURSES_OSPEED) mode.sg_ospeed;
8584a1a9510SRong-En Fan #endif
8594a1a9510SRong-En Fan 
86006bfebdeSXin LI     if (same_program(_nc_progname, PROG_RESET)) {
861aae38d10SBaptiste Daroussin 	reset_start(stderr, TRUE, FALSE);
862*21817992SBaptiste Daroussin 	reset_tty_settings(my_fd, &mode, noset);
863aae38d10SBaptiste Daroussin     } else {
864aae38d10SBaptiste Daroussin 	reset_start(stderr, FALSE, TRUE);
8654a1a9510SRong-En Fan     }
8660e3d5408SPeter Wemm 
867aae38d10SBaptiste Daroussin     ttype = get_termcap_entry(my_fd, *argv);
8680e3d5408SPeter Wemm 
8690e3d5408SPeter Wemm     if (!noset) {
87073f0a83dSXin LI #if HAVE_SIZECHANGE
8714a1a9510SRong-En Fan 	if (opt_w) {
872*21817992SBaptiste Daroussin 	    NCURSES_INT2 my_rows = lines;
873*21817992SBaptiste Daroussin 	    NCURSES_INT2 my_cols = columns;
874*21817992SBaptiste Daroussin 	    set_window_size(my_fd, &my_rows, &my_cols);
875*21817992SBaptiste Daroussin 	    lines = my_rows;
876*21817992SBaptiste Daroussin 	    columns = my_cols;
8774a1a9510SRong-En Fan 	}
8780e3d5408SPeter Wemm #endif
8794a1a9510SRong-En Fan 	if (opt_c) {
880aae38d10SBaptiste Daroussin 	    set_control_chars(&mode, terasechar, intrchar, tkillchar);
881aae38d10SBaptiste Daroussin 	    set_conversions(&mode);
8820e3d5408SPeter Wemm 
883aae38d10SBaptiste Daroussin 	    if (!noinit) {
884aae38d10SBaptiste Daroussin 		if (send_init_strings(my_fd, &oldmode)) {
885*21817992SBaptiste Daroussin 		    const char *name;
886*21817992SBaptiste Daroussin 
887aae38d10SBaptiste Daroussin 		    (void) putc('\r', stderr);
888aae38d10SBaptiste Daroussin 		    (void) fflush(stderr);
889*21817992SBaptiste Daroussin 		    if (IsRealTty(my_fd, name)) {
890aae38d10SBaptiste Daroussin 			(void) napms(1000);	/* Settle the terminal. */
8910e3d5408SPeter Wemm 		    }
89215589c42SPeter Wemm 		}
893*21817992SBaptiste Daroussin 	    }
894aae38d10SBaptiste Daroussin 
895aae38d10SBaptiste Daroussin 	    update_tty_settings(&oldmode, &mode);
896aae38d10SBaptiste Daroussin 	}
8974a1a9510SRong-En Fan     }
8980e3d5408SPeter Wemm 
899aae38d10SBaptiste Daroussin     if (noset) {
9000e3d5408SPeter Wemm 	(void) printf("%s\n", ttype);
901aae38d10SBaptiste Daroussin     } else {
9020e3d5408SPeter Wemm 	if (showterm)
9030e3d5408SPeter Wemm 	    (void) fprintf(stderr, "Terminal type is %s.\n", ttype);
9040e3d5408SPeter Wemm 	/*
9050e3d5408SPeter Wemm 	 * If erase, kill and interrupt characters could have been
9060e3d5408SPeter Wemm 	 * modified and not -Q, display the changes.
9070e3d5408SPeter Wemm 	 */
9080e3d5408SPeter Wemm 	if (!quiet) {
909aae38d10SBaptiste Daroussin 	    print_tty_chars(&oldmode, &mode);
9100e3d5408SPeter Wemm 	}
9110e3d5408SPeter Wemm     }
9120e3d5408SPeter Wemm 
9130e3d5408SPeter Wemm     if (Sflag)
9140e3d5408SPeter Wemm 	err("The -S option is not supported under terminfo.");
9150e3d5408SPeter Wemm 
9160e3d5408SPeter Wemm     if (sflag) {
917aae38d10SBaptiste Daroussin 	print_shell_commands(ttype);
9180e3d5408SPeter Wemm     }
9190e3d5408SPeter Wemm 
9204a1a9510SRong-En Fan     ExitProgram(EXIT_SUCCESS);
9210e3d5408SPeter Wemm }
922