10e3d5408SPeter Wemm /**************************************************************************** 2*06bfebdeSXin LI * Copyright (c) 1998-2009,2010 Free Software Foundation, Inc. * 30e3d5408SPeter Wemm * * 40e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 50e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 60e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 70e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 80e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 90e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 100e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 110e3d5408SPeter Wemm * * 120e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 130e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 140e3d5408SPeter Wemm * * 150e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 160e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 170e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 180e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 190e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 200e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 210e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 220e3d5408SPeter Wemm * * 230e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 240e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 250e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 260e3d5408SPeter Wemm * authorization. * 270e3d5408SPeter Wemm ****************************************************************************/ 280e3d5408SPeter Wemm 290e3d5408SPeter Wemm /**************************************************************************** 300e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 310e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 324a1a9510SRong-En Fan * and: Thomas E. Dickey 1996-on * 330e3d5408SPeter Wemm ****************************************************************************/ 340e3d5408SPeter Wemm 350e3d5408SPeter Wemm /* 36*06bfebdeSXin LI * Notes: 37*06bfebdeSXin LI * The initial adaptation from 4.4BSD Lite sources in September 1995 used 686 38*06bfebdeSXin LI * lines from that version, and made changes/additions for 150 lines. There 39*06bfebdeSXin LI * was no reformatting, so with/without ignoring whitespace, the amount of 40*06bfebdeSXin LI * change is the same. 41*06bfebdeSXin LI * 42*06bfebdeSXin LI * Comparing with current (2009) source, excluding this comment: 43*06bfebdeSXin LI * a) 209 lines match identically to the 4.4BSD Lite sources, with 771 lines 44*06bfebdeSXin LI * changed/added. 45*06bfebdeSXin LI * a) Ignoring whitespace, the current version still uses 516 lines from the 46*06bfebdeSXin LI * 4.4BSD Lite sources, with 402 lines changed/added. 47*06bfebdeSXin LI * 48*06bfebdeSXin LI * Raymond's original comment on this follows... 49*06bfebdeSXin LI */ 50*06bfebdeSXin LI 51*06bfebdeSXin LI /* 520e3d5408SPeter Wemm * tset.c - terminal initialization utility 530e3d5408SPeter Wemm * 540e3d5408SPeter Wemm * This code was mostly swiped from 4.4BSD tset, with some obsolescent 550e3d5408SPeter Wemm * cruft removed and substantial portions rewritten. A Regents of the 560e3d5408SPeter Wemm * University of California copyright applies to some portions of the 570e3d5408SPeter Wemm * code, and is reproduced below: 580e3d5408SPeter Wemm */ 590e3d5408SPeter Wemm /*- 600e3d5408SPeter Wemm * Copyright (c) 1980, 1991, 1993 610e3d5408SPeter Wemm * The Regents of the University of California. All rights reserved. 620e3d5408SPeter Wemm * 630e3d5408SPeter Wemm * Redistribution and use in source and binary forms, with or without 640e3d5408SPeter Wemm * modification, are permitted provided that the following conditions 650e3d5408SPeter Wemm * are met: 660e3d5408SPeter Wemm * 1. Redistributions of source code must retain the above copyright 670e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer. 680e3d5408SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 690e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer in the 700e3d5408SPeter Wemm * documentation and/or other materials provided with the distribution. 71*06bfebdeSXin LI * 3. Neither the name of the University nor the names of its contributors 720e3d5408SPeter Wemm * may be used to endorse or promote products derived from this software 730e3d5408SPeter Wemm * without specific prior written permission. 740e3d5408SPeter Wemm * 750e3d5408SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 760e3d5408SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 770e3d5408SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 780e3d5408SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 790e3d5408SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 800e3d5408SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 810e3d5408SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 820e3d5408SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 830e3d5408SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 840e3d5408SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 850e3d5408SPeter Wemm * SUCH DAMAGE. 860e3d5408SPeter Wemm */ 870e3d5408SPeter Wemm 885ca44d1cSRong-En Fan #define USE_LIBTINFO 890e3d5408SPeter Wemm #define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ 900e3d5408SPeter Wemm #include <progs.priv.h> 910e3d5408SPeter Wemm 920e3d5408SPeter Wemm #include <errno.h> 930e3d5408SPeter Wemm #include <stdio.h> 940e3d5408SPeter Wemm #include <termcap.h> 950e3d5408SPeter Wemm #include <fcntl.h> 960e3d5408SPeter Wemm 970e3d5408SPeter Wemm #if HAVE_GETTTYNAM && HAVE_TTYENT_H 980e3d5408SPeter Wemm #include <ttyent.h> 990e3d5408SPeter Wemm #endif 1000e3d5408SPeter Wemm #ifdef NeXT 1010e3d5408SPeter Wemm char *ttyname(int fd); 1020e3d5408SPeter Wemm #endif 1030e3d5408SPeter Wemm 1045d08fb1fSRong-En Fan #if HAVE_SIZECHANGE 1055d08fb1fSRong-En Fan # if !defined(sun) || !TERMIOS 1065d08fb1fSRong-En Fan # if HAVE_SYS_IOCTL_H 1070e3d5408SPeter Wemm # include <sys/ioctl.h> 1080e3d5408SPeter Wemm # endif 1095d08fb1fSRong-En Fan # endif 1105d08fb1fSRong-En Fan #endif 1110e3d5408SPeter Wemm 1120e3d5408SPeter Wemm #if NEED_PTEM_H 1130e3d5408SPeter Wemm /* they neglected to define struct winsize in termios.h -- it's only 1140e3d5408SPeter Wemm in termio.h */ 1150e3d5408SPeter Wemm #include <sys/stream.h> 1160e3d5408SPeter Wemm #include <sys/ptem.h> 1170e3d5408SPeter Wemm #endif 1180e3d5408SPeter Wemm 1190e3d5408SPeter Wemm #include <dump_entry.h> 12018259542SPeter Wemm #include <transform.h> 1210e3d5408SPeter Wemm 122*06bfebdeSXin LI MODULE_ID("$Id: tset.c,v 1.82 2010/05/01 21:42:46 tom Exp $") 1235d08fb1fSRong-En Fan 1245d08fb1fSRong-En Fan /* 1255d08fb1fSRong-En Fan * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, 1265d08fb1fSRong-En Fan * Solaris, IRIX) define TIOCGWINSZ and struct winsize. 1275d08fb1fSRong-En Fan */ 1285d08fb1fSRong-En Fan #ifdef TIOCGSIZE 1295d08fb1fSRong-En Fan # define IOCTL_GET_WINSIZE TIOCGSIZE 1305d08fb1fSRong-En Fan # define IOCTL_SET_WINSIZE TIOCSSIZE 1315d08fb1fSRong-En Fan # define STRUCT_WINSIZE struct ttysize 1325d08fb1fSRong-En Fan # define WINSIZE_ROWS(n) n.ts_lines 1335d08fb1fSRong-En Fan # define WINSIZE_COLS(n) n.ts_cols 1345d08fb1fSRong-En Fan #else 1355d08fb1fSRong-En Fan # ifdef TIOCGWINSZ 1365d08fb1fSRong-En Fan # define IOCTL_GET_WINSIZE TIOCGWINSZ 1375d08fb1fSRong-En Fan # define IOCTL_SET_WINSIZE TIOCSWINSZ 1385d08fb1fSRong-En Fan # define STRUCT_WINSIZE struct winsize 1395d08fb1fSRong-En Fan # define WINSIZE_ROWS(n) n.ws_row 1405d08fb1fSRong-En Fan # define WINSIZE_COLS(n) n.ws_col 1415d08fb1fSRong-En Fan # endif 1425d08fb1fSRong-En Fan #endif 1430e3d5408SPeter Wemm 144*06bfebdeSXin LI #ifndef environ 1450e3d5408SPeter Wemm extern char **environ; 146*06bfebdeSXin LI #endif 1470e3d5408SPeter Wemm 1480e3d5408SPeter Wemm #undef CTRL 1490e3d5408SPeter Wemm #define CTRL(x) ((x) & 0x1f) 1500e3d5408SPeter Wemm 1510e3d5408SPeter Wemm const char *_nc_progname = "tset"; 1520e3d5408SPeter Wemm 15339f2269fSPeter Wemm static TTY mode, oldmode, original; 1540e3d5408SPeter Wemm 1554a1a9510SRong-En Fan static bool opt_c; /* set control-chars */ 1564a1a9510SRong-En Fan static bool opt_w; /* set window-size */ 1574a1a9510SRong-En Fan 15839f2269fSPeter Wemm static bool can_restore = FALSE; 15918259542SPeter Wemm static bool isreset = FALSE; /* invoked as reset */ 1600e3d5408SPeter Wemm static int terasechar = -1; /* new erase character */ 1610e3d5408SPeter Wemm static int intrchar = -1; /* new interrupt character */ 1620e3d5408SPeter Wemm static int tkillchar = -1; /* new kill character */ 1630e3d5408SPeter Wemm static int tlines, tcolumns; /* window size */ 1640e3d5408SPeter Wemm 16539f2269fSPeter Wemm #define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) 1660e3d5408SPeter Wemm 1670e3d5408SPeter Wemm static int 16815589c42SPeter Wemm CaselessCmp(const char *a, const char *b) 16915589c42SPeter Wemm { /* strcasecmp isn't portable */ 1700e3d5408SPeter Wemm while (*a && *b) { 1710e3d5408SPeter Wemm int cmp = LOWERCASE(*a) - LOWERCASE(*b); 1720e3d5408SPeter Wemm if (cmp != 0) 1730e3d5408SPeter Wemm break; 1740e3d5408SPeter Wemm a++, b++; 1750e3d5408SPeter Wemm } 1760e3d5408SPeter Wemm return LOWERCASE(*a) - LOWERCASE(*b); 1770e3d5408SPeter Wemm } 1780e3d5408SPeter Wemm 1790e3d5408SPeter Wemm static void 18039f2269fSPeter Wemm exit_error(void) 18139f2269fSPeter Wemm { 18239f2269fSPeter Wemm if (can_restore) 18339f2269fSPeter Wemm SET_TTY(STDERR_FILENO, &original); 18439f2269fSPeter Wemm (void) fprintf(stderr, "\n"); 18539f2269fSPeter Wemm fflush(stderr); 1864a1a9510SRong-En Fan ExitProgram(EXIT_FAILURE); 18739f2269fSPeter Wemm /* NOTREACHED */ 18839f2269fSPeter Wemm } 18939f2269fSPeter Wemm 19039f2269fSPeter Wemm static void 1910e3d5408SPeter Wemm err(const char *fmt,...) 1920e3d5408SPeter Wemm { 1930e3d5408SPeter Wemm va_list ap; 1940e3d5408SPeter Wemm va_start(ap, fmt); 1954a1a9510SRong-En Fan (void) fprintf(stderr, "%s: ", _nc_progname); 1960e3d5408SPeter Wemm (void) vfprintf(stderr, fmt, ap); 1970e3d5408SPeter Wemm va_end(ap); 19839f2269fSPeter Wemm exit_error(); 1990e3d5408SPeter Wemm /* NOTREACHED */ 2000e3d5408SPeter Wemm } 2010e3d5408SPeter Wemm 2020e3d5408SPeter Wemm static void 2030e3d5408SPeter Wemm failed(const char *msg) 2040e3d5408SPeter Wemm { 2050e3d5408SPeter Wemm char temp[BUFSIZ]; 2064a1a9510SRong-En Fan unsigned len = strlen(_nc_progname) + 2; 2074a1a9510SRong-En Fan 2085d08fb1fSRong-En Fan if ((int) len < (int) sizeof(temp) - 12) { 2094a1a9510SRong-En Fan strcpy(temp, _nc_progname); 2104a1a9510SRong-En Fan strcat(temp, ": "); 2114a1a9510SRong-En Fan } else { 2124a1a9510SRong-En Fan strcpy(temp, "tset: "); 2134a1a9510SRong-En Fan } 2144a1a9510SRong-En Fan perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2)); 21539f2269fSPeter Wemm exit_error(); 2160e3d5408SPeter Wemm /* NOTREACHED */ 2170e3d5408SPeter Wemm } 2180e3d5408SPeter Wemm 2190e3d5408SPeter Wemm static void 2200e3d5408SPeter Wemm cat(char *file) 2210e3d5408SPeter Wemm { 22239f2269fSPeter Wemm FILE *fp; 22339f2269fSPeter Wemm size_t nr; 2240e3d5408SPeter Wemm char buf[BUFSIZ]; 2250e3d5408SPeter Wemm 22639f2269fSPeter Wemm if ((fp = fopen(file, "r")) == 0) 2270e3d5408SPeter Wemm failed(file); 2280e3d5408SPeter Wemm 22939f2269fSPeter Wemm while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) 23039f2269fSPeter Wemm if (fwrite(buf, sizeof(char), nr, stderr) != nr) 2310e3d5408SPeter Wemm failed("write to stderr"); 23239f2269fSPeter Wemm fclose(fp); 2330e3d5408SPeter Wemm } 2340e3d5408SPeter Wemm 2350e3d5408SPeter Wemm static int 2360e3d5408SPeter Wemm outc(int c) 2370e3d5408SPeter Wemm { 2380e3d5408SPeter Wemm return putc(c, stderr); 2390e3d5408SPeter Wemm } 2400e3d5408SPeter Wemm 2410e3d5408SPeter Wemm /* Prompt the user for a terminal type. */ 2420e3d5408SPeter Wemm static const char * 2430e3d5408SPeter Wemm askuser(const char *dflt) 2440e3d5408SPeter Wemm { 2450e3d5408SPeter Wemm static char answer[256]; 2460e3d5408SPeter Wemm char *p; 2470e3d5408SPeter Wemm 2480e3d5408SPeter Wemm /* We can get recalled; if so, don't continue uselessly. */ 2494a1a9510SRong-En Fan clearerr(stdin); 2500e3d5408SPeter Wemm if (feof(stdin) || ferror(stdin)) { 2510e3d5408SPeter Wemm (void) fprintf(stderr, "\n"); 25239f2269fSPeter Wemm exit_error(); 25339f2269fSPeter Wemm /* NOTREACHED */ 2540e3d5408SPeter Wemm } 2550e3d5408SPeter Wemm for (;;) { 2560e3d5408SPeter Wemm if (dflt) 2570e3d5408SPeter Wemm (void) fprintf(stderr, "Terminal type? [%s] ", dflt); 2580e3d5408SPeter Wemm else 2590e3d5408SPeter Wemm (void) fprintf(stderr, "Terminal type? "); 2600e3d5408SPeter Wemm (void) fflush(stderr); 2610e3d5408SPeter Wemm 2620e3d5408SPeter Wemm if (fgets(answer, sizeof(answer), stdin) == 0) { 2630e3d5408SPeter Wemm if (dflt == 0) { 26439f2269fSPeter Wemm exit_error(); 26539f2269fSPeter Wemm /* NOTREACHED */ 2660e3d5408SPeter Wemm } 2670e3d5408SPeter Wemm return (dflt); 2680e3d5408SPeter Wemm } 2690e3d5408SPeter Wemm 2700e3d5408SPeter Wemm if ((p = strchr(answer, '\n')) != 0) 2710e3d5408SPeter Wemm *p = '\0'; 2720e3d5408SPeter Wemm if (answer[0]) 2730e3d5408SPeter Wemm return (answer); 2740e3d5408SPeter Wemm if (dflt != 0) 2750e3d5408SPeter Wemm return (dflt); 2760e3d5408SPeter Wemm } 2770e3d5408SPeter Wemm } 2780e3d5408SPeter Wemm 2790e3d5408SPeter Wemm /************************************************************************** 2800e3d5408SPeter Wemm * 2810e3d5408SPeter Wemm * Mapping logic begins here 2820e3d5408SPeter Wemm * 2830e3d5408SPeter Wemm **************************************************************************/ 2840e3d5408SPeter Wemm 2850e3d5408SPeter Wemm /* Baud rate conditionals for mapping. */ 2860e3d5408SPeter Wemm #define GT 0x01 2870e3d5408SPeter Wemm #define EQ 0x02 2880e3d5408SPeter Wemm #define LT 0x04 2890e3d5408SPeter Wemm #define NOT 0x08 2900e3d5408SPeter Wemm #define GE (GT | EQ) 2910e3d5408SPeter Wemm #define LE (LT | EQ) 2920e3d5408SPeter Wemm 2930e3d5408SPeter Wemm typedef struct map { 2940e3d5408SPeter Wemm struct map *next; /* Linked list of maps. */ 2950e3d5408SPeter Wemm const char *porttype; /* Port type, or "" for any. */ 2960e3d5408SPeter Wemm const char *type; /* Terminal type to select. */ 2970e3d5408SPeter Wemm int conditional; /* Baud rate conditionals bitmask. */ 29818259542SPeter Wemm int speed; /* Baud rate to compare against. */ 2990e3d5408SPeter Wemm } MAP; 3000e3d5408SPeter Wemm 3010e3d5408SPeter Wemm static MAP *cur, *maplist; 3020e3d5408SPeter Wemm 3030e3d5408SPeter Wemm typedef struct speeds { 3040e3d5408SPeter Wemm const char *string; 3050e3d5408SPeter Wemm int speed; 3060e3d5408SPeter Wemm } SPEEDS; 3070e3d5408SPeter Wemm 30815589c42SPeter Wemm static const SPEEDS speeds[] = 30915589c42SPeter Wemm { 3100e3d5408SPeter Wemm {"0", B0}, 3110e3d5408SPeter Wemm {"50", B50}, 3120e3d5408SPeter Wemm {"75", B75}, 3130e3d5408SPeter Wemm {"110", B110}, 3140e3d5408SPeter Wemm {"134", B134}, 3150e3d5408SPeter Wemm {"134.5", B134}, 3160e3d5408SPeter Wemm {"150", B150}, 3170e3d5408SPeter Wemm {"200", B200}, 3180e3d5408SPeter Wemm {"300", B300}, 3190e3d5408SPeter Wemm {"600", B600}, 3200e3d5408SPeter Wemm {"1200", B1200}, 3210e3d5408SPeter Wemm {"1800", B1800}, 3220e3d5408SPeter Wemm {"2400", B2400}, 3230e3d5408SPeter Wemm {"4800", B4800}, 3240e3d5408SPeter Wemm {"9600", B9600}, 32518259542SPeter Wemm /* sgttyb may define up to this point */ 32618259542SPeter Wemm #ifdef B19200 3270e3d5408SPeter Wemm {"19200", B19200}, 32818259542SPeter Wemm #endif 32918259542SPeter Wemm #ifdef B38400 3300e3d5408SPeter Wemm {"38400", B38400}, 33118259542SPeter Wemm #endif 33218259542SPeter Wemm #ifdef B19200 3330e3d5408SPeter Wemm {"19200", B19200}, 33418259542SPeter Wemm #endif 33518259542SPeter Wemm #ifdef B38400 3360e3d5408SPeter Wemm {"38400", B38400}, 33718259542SPeter Wemm #endif 3380e3d5408SPeter Wemm #ifdef B19200 3390e3d5408SPeter Wemm {"19200", B19200}, 3400e3d5408SPeter Wemm #else 3410e3d5408SPeter Wemm #ifdef EXTA 3420e3d5408SPeter Wemm {"19200", EXTA}, 3430e3d5408SPeter Wemm #endif 3440e3d5408SPeter Wemm #endif 3450e3d5408SPeter Wemm #ifdef B38400 3460e3d5408SPeter Wemm {"38400", B38400}, 3470e3d5408SPeter Wemm #else 3480e3d5408SPeter Wemm #ifdef EXTB 3490e3d5408SPeter Wemm {"38400", EXTB}, 3500e3d5408SPeter Wemm #endif 3510e3d5408SPeter Wemm #endif 3520e3d5408SPeter Wemm #ifdef B57600 3530e3d5408SPeter Wemm {"57600", B57600}, 3540e3d5408SPeter Wemm #endif 3550e3d5408SPeter Wemm #ifdef B115200 3560e3d5408SPeter Wemm {"115200", B115200}, 3570e3d5408SPeter Wemm #endif 3580e3d5408SPeter Wemm #ifdef B230400 3590e3d5408SPeter Wemm {"230400", B230400}, 3600e3d5408SPeter Wemm #endif 3610e3d5408SPeter Wemm #ifdef B460800 3620e3d5408SPeter Wemm {"460800", B460800}, 3630e3d5408SPeter Wemm #endif 3640e3d5408SPeter Wemm {(char *) 0, 0} 3650e3d5408SPeter Wemm }; 3660e3d5408SPeter Wemm 3670e3d5408SPeter Wemm static int 3680e3d5408SPeter Wemm tbaudrate(char *rate) 3690e3d5408SPeter Wemm { 3700e3d5408SPeter Wemm const SPEEDS *sp; 3710e3d5408SPeter Wemm int found = FALSE; 3720e3d5408SPeter Wemm 3730e3d5408SPeter Wemm /* The baudrate number can be preceded by a 'B', which is ignored. */ 3740e3d5408SPeter Wemm if (*rate == 'B') 3750e3d5408SPeter Wemm ++rate; 3760e3d5408SPeter Wemm 3770e3d5408SPeter Wemm for (sp = speeds; sp->string; ++sp) { 3780e3d5408SPeter Wemm if (!CaselessCmp(rate, sp->string)) { 3790e3d5408SPeter Wemm found = TRUE; 3800e3d5408SPeter Wemm break; 3810e3d5408SPeter Wemm } 3820e3d5408SPeter Wemm } 3830e3d5408SPeter Wemm if (!found) 3840e3d5408SPeter Wemm err("unknown baud rate %s", rate); 3850e3d5408SPeter Wemm return (sp->speed); 3860e3d5408SPeter Wemm } 3870e3d5408SPeter Wemm 3880e3d5408SPeter Wemm /* 3890e3d5408SPeter Wemm * Syntax for -m: 3900e3d5408SPeter Wemm * [port-type][test baudrate]:terminal-type 3910e3d5408SPeter Wemm * The baud rate tests are: >, <, @, =, ! 3920e3d5408SPeter Wemm */ 3930e3d5408SPeter Wemm static void 3940e3d5408SPeter Wemm add_mapping(const char *port, char *arg) 3950e3d5408SPeter Wemm { 3960e3d5408SPeter Wemm MAP *mapp; 3970e3d5408SPeter Wemm char *copy, *p; 3980e3d5408SPeter Wemm const char *termp; 3990e3d5408SPeter Wemm char *base = 0; 4000e3d5408SPeter Wemm 4010e3d5408SPeter Wemm copy = strdup(arg); 402*06bfebdeSXin LI mapp = typeMalloc(MAP, 1); 4030e3d5408SPeter Wemm if (copy == 0 || mapp == 0) 4040e3d5408SPeter Wemm failed("malloc"); 405*06bfebdeSXin LI 406*06bfebdeSXin LI assert(copy != 0); 407*06bfebdeSXin LI assert(mapp != 0); 408*06bfebdeSXin LI 4090e3d5408SPeter Wemm mapp->next = 0; 4100e3d5408SPeter Wemm if (maplist == 0) 4110e3d5408SPeter Wemm cur = maplist = mapp; 4120e3d5408SPeter Wemm else { 4130e3d5408SPeter Wemm cur->next = mapp; 4140e3d5408SPeter Wemm cur = mapp; 4150e3d5408SPeter Wemm } 4160e3d5408SPeter Wemm 4170e3d5408SPeter Wemm mapp->porttype = arg; 4180e3d5408SPeter Wemm mapp->conditional = 0; 4190e3d5408SPeter Wemm 4200e3d5408SPeter Wemm arg = strpbrk(arg, "><@=!:"); 4210e3d5408SPeter Wemm 4220e3d5408SPeter Wemm if (arg == 0) { /* [?]term */ 4230e3d5408SPeter Wemm mapp->type = mapp->porttype; 4240e3d5408SPeter Wemm mapp->porttype = 0; 4250e3d5408SPeter Wemm goto done; 4260e3d5408SPeter Wemm } 4270e3d5408SPeter Wemm 4280e3d5408SPeter Wemm if (arg == mapp->porttype) /* [><@=! baud]:term */ 4290e3d5408SPeter Wemm termp = mapp->porttype = 0; 4300e3d5408SPeter Wemm else 4310e3d5408SPeter Wemm termp = base = arg; 4320e3d5408SPeter Wemm 43315589c42SPeter Wemm for (;; ++arg) { /* Optional conditionals. */ 4340e3d5408SPeter Wemm switch (*arg) { 4350e3d5408SPeter Wemm case '<': 4360e3d5408SPeter Wemm if (mapp->conditional & GT) 4370e3d5408SPeter Wemm goto badmopt; 4380e3d5408SPeter Wemm mapp->conditional |= LT; 4390e3d5408SPeter Wemm break; 4400e3d5408SPeter Wemm case '>': 4410e3d5408SPeter Wemm if (mapp->conditional & LT) 4420e3d5408SPeter Wemm goto badmopt; 4430e3d5408SPeter Wemm mapp->conditional |= GT; 4440e3d5408SPeter Wemm break; 4450e3d5408SPeter Wemm case '@': 4460e3d5408SPeter Wemm case '=': /* Not documented. */ 4470e3d5408SPeter Wemm mapp->conditional |= EQ; 4480e3d5408SPeter Wemm break; 4490e3d5408SPeter Wemm case '!': 4500e3d5408SPeter Wemm mapp->conditional |= NOT; 4510e3d5408SPeter Wemm break; 4520e3d5408SPeter Wemm default: 4530e3d5408SPeter Wemm goto next; 4540e3d5408SPeter Wemm } 45515589c42SPeter Wemm } 4560e3d5408SPeter Wemm 45715589c42SPeter Wemm next: 45815589c42SPeter Wemm if (*arg == ':') { 4590e3d5408SPeter Wemm if (mapp->conditional) 4600e3d5408SPeter Wemm goto badmopt; 4610e3d5408SPeter Wemm ++arg; 4620e3d5408SPeter Wemm } else { /* Optional baudrate. */ 4630e3d5408SPeter Wemm arg = strchr(p = arg, ':'); 4640e3d5408SPeter Wemm if (arg == 0) 4650e3d5408SPeter Wemm goto badmopt; 4660e3d5408SPeter Wemm *arg++ = '\0'; 4670e3d5408SPeter Wemm mapp->speed = tbaudrate(p); 4680e3d5408SPeter Wemm } 4690e3d5408SPeter Wemm 4700e3d5408SPeter Wemm if (arg == (char *) 0) /* Non-optional type. */ 4710e3d5408SPeter Wemm goto badmopt; 4720e3d5408SPeter Wemm 4730e3d5408SPeter Wemm mapp->type = arg; 4740e3d5408SPeter Wemm 4750e3d5408SPeter Wemm /* Terminate porttype, if specified. */ 4760e3d5408SPeter Wemm if (termp != 0) 4770e3d5408SPeter Wemm *base = '\0'; 4780e3d5408SPeter Wemm 4790e3d5408SPeter Wemm /* If a NOT conditional, reverse the test. */ 4800e3d5408SPeter Wemm if (mapp->conditional & NOT) 4810e3d5408SPeter Wemm mapp->conditional = ~mapp->conditional & (EQ | GT | LT); 4820e3d5408SPeter Wemm 4830e3d5408SPeter Wemm /* If user specified a port with an option flag, set it. */ 4845d08fb1fSRong-En Fan done: 4855d08fb1fSRong-En Fan if (port) { 4865d08fb1fSRong-En Fan if (mapp->porttype) { 4875d08fb1fSRong-En Fan badmopt: 4885d08fb1fSRong-En Fan err("illegal -m option format: %s", copy); 4895d08fb1fSRong-En Fan } 4900e3d5408SPeter Wemm mapp->porttype = port; 4910e3d5408SPeter Wemm } 4925d08fb1fSRong-En Fan free(copy); 4930e3d5408SPeter Wemm #ifdef MAPDEBUG 4940e3d5408SPeter Wemm (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); 4950e3d5408SPeter Wemm (void) printf("type: %s\n", mapp->type); 4960e3d5408SPeter Wemm (void) printf("conditional: "); 4970e3d5408SPeter Wemm p = ""; 4980e3d5408SPeter Wemm if (mapp->conditional & GT) { 4990e3d5408SPeter Wemm (void) printf("GT"); 5000e3d5408SPeter Wemm p = "/"; 5010e3d5408SPeter Wemm } 5020e3d5408SPeter Wemm if (mapp->conditional & EQ) { 5030e3d5408SPeter Wemm (void) printf("%sEQ", p); 5040e3d5408SPeter Wemm p = "/"; 5050e3d5408SPeter Wemm } 5060e3d5408SPeter Wemm if (mapp->conditional & LT) 5070e3d5408SPeter Wemm (void) printf("%sLT", p); 5080e3d5408SPeter Wemm (void) printf("\nspeed: %d\n", mapp->speed); 5090e3d5408SPeter Wemm #endif 5100e3d5408SPeter Wemm } 5110e3d5408SPeter Wemm 5120e3d5408SPeter Wemm /* 5130e3d5408SPeter Wemm * Return the type of terminal to use for a port of type 'type', as specified 5140e3d5408SPeter Wemm * by the first applicable mapping in 'map'. If no mappings apply, return 5150e3d5408SPeter Wemm * 'type'. 5160e3d5408SPeter Wemm */ 5170e3d5408SPeter Wemm static const char * 5180e3d5408SPeter Wemm mapped(const char *type) 5190e3d5408SPeter Wemm { 5200e3d5408SPeter Wemm MAP *mapp; 5210e3d5408SPeter Wemm int match; 5220e3d5408SPeter Wemm 5230e3d5408SPeter Wemm for (mapp = maplist; mapp; mapp = mapp->next) 5240e3d5408SPeter Wemm if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) { 5250e3d5408SPeter Wemm switch (mapp->conditional) { 5260e3d5408SPeter Wemm case 0: /* No test specified. */ 5270e3d5408SPeter Wemm match = TRUE; 5280e3d5408SPeter Wemm break; 5290e3d5408SPeter Wemm case EQ: 5300e3d5408SPeter Wemm match = (ospeed == mapp->speed); 5310e3d5408SPeter Wemm break; 5320e3d5408SPeter Wemm case GE: 5330e3d5408SPeter Wemm match = (ospeed >= mapp->speed); 5340e3d5408SPeter Wemm break; 5350e3d5408SPeter Wemm case GT: 5360e3d5408SPeter Wemm match = (ospeed > mapp->speed); 5370e3d5408SPeter Wemm break; 5380e3d5408SPeter Wemm case LE: 5390e3d5408SPeter Wemm match = (ospeed <= mapp->speed); 5400e3d5408SPeter Wemm break; 5410e3d5408SPeter Wemm case LT: 5420e3d5408SPeter Wemm match = (ospeed < mapp->speed); 5430e3d5408SPeter Wemm break; 5440e3d5408SPeter Wemm default: 5450e3d5408SPeter Wemm match = FALSE; 5460e3d5408SPeter Wemm } 5470e3d5408SPeter Wemm if (match) 5480e3d5408SPeter Wemm return (mapp->type); 5490e3d5408SPeter Wemm } 5500e3d5408SPeter Wemm /* No match found; return given type. */ 5510e3d5408SPeter Wemm return (type); 5520e3d5408SPeter Wemm } 5530e3d5408SPeter Wemm 5540e3d5408SPeter Wemm /************************************************************************** 5550e3d5408SPeter Wemm * 5560e3d5408SPeter Wemm * Entry fetching 5570e3d5408SPeter Wemm * 5580e3d5408SPeter Wemm **************************************************************************/ 5590e3d5408SPeter Wemm 5600e3d5408SPeter Wemm /* 5610e3d5408SPeter Wemm * Figure out what kind of terminal we're dealing with, and then read in 5620e3d5408SPeter Wemm * its termcap entry. 5630e3d5408SPeter Wemm */ 5640e3d5408SPeter Wemm static const char * 5650e3d5408SPeter Wemm get_termcap_entry(char *userarg) 5660e3d5408SPeter Wemm { 5677a69bbfbSPeter Wemm int errret; 5680e3d5408SPeter Wemm char *p; 5690e3d5408SPeter Wemm const char *ttype; 5700e3d5408SPeter Wemm #if HAVE_GETTTYNAM 5710e3d5408SPeter Wemm struct ttyent *t; 5720e3d5408SPeter Wemm #else 5730e3d5408SPeter Wemm FILE *fp; 5740e3d5408SPeter Wemm #endif 5750e3d5408SPeter Wemm char *ttypath; 5760e3d5408SPeter Wemm 5770e3d5408SPeter Wemm if (userarg) { 5780e3d5408SPeter Wemm ttype = userarg; 5790e3d5408SPeter Wemm goto found; 5800e3d5408SPeter Wemm } 5810e3d5408SPeter Wemm 5820e3d5408SPeter Wemm /* Try the environment. */ 5830e3d5408SPeter Wemm if ((ttype = getenv("TERM")) != 0) 5840e3d5408SPeter Wemm goto map; 5850e3d5408SPeter Wemm 5860e3d5408SPeter Wemm if ((ttypath = ttyname(STDERR_FILENO)) != 0) { 58718259542SPeter Wemm p = _nc_basename(ttypath); 5880e3d5408SPeter Wemm #if HAVE_GETTTYNAM 5890e3d5408SPeter Wemm /* 5900e3d5408SPeter Wemm * We have the 4.3BSD library call getttynam(3); that means 5910e3d5408SPeter Wemm * there's an /etc/ttys to look up device-to-type mappings in. 5920e3d5408SPeter Wemm * Try ttyname(3); check for dialup or other mapping. 5930e3d5408SPeter Wemm */ 5940e3d5408SPeter Wemm if ((t = getttynam(p))) { 5950e3d5408SPeter Wemm ttype = t->ty_type; 5960e3d5408SPeter Wemm goto map; 5970e3d5408SPeter Wemm } 5980e3d5408SPeter Wemm #else 5990e3d5408SPeter Wemm if ((fp = fopen("/etc/ttytype", "r")) != 0 6000e3d5408SPeter Wemm || (fp = fopen("/etc/ttys", "r")) != 0) { 6010e3d5408SPeter Wemm char buffer[BUFSIZ]; 6020e3d5408SPeter Wemm char *s, *t, *d; 6030e3d5408SPeter Wemm 6040e3d5408SPeter Wemm while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) { 6050e3d5408SPeter Wemm for (s = buffer, t = d = 0; *s; s++) { 60639f2269fSPeter Wemm if (isspace(UChar(*s))) 6070e3d5408SPeter Wemm *s = '\0'; 6080e3d5408SPeter Wemm else if (t == 0) 6090e3d5408SPeter Wemm t = s; 6100e3d5408SPeter Wemm else if (d == 0 && s != buffer && s[-1] == '\0') 6110e3d5408SPeter Wemm d = s; 6120e3d5408SPeter Wemm } 6130e3d5408SPeter Wemm if (t != 0 && d != 0 && !strcmp(d, p)) { 6140e3d5408SPeter Wemm ttype = strdup(t); 6150e3d5408SPeter Wemm fclose(fp); 6160e3d5408SPeter Wemm goto map; 6170e3d5408SPeter Wemm } 6180e3d5408SPeter Wemm } 6190e3d5408SPeter Wemm fclose(fp); 6200e3d5408SPeter Wemm } 6210e3d5408SPeter Wemm #endif /* HAVE_GETTTYNAM */ 6220e3d5408SPeter Wemm } 6230e3d5408SPeter Wemm 6240e3d5408SPeter Wemm /* If still undefined, use "unknown". */ 6250e3d5408SPeter Wemm ttype = "unknown"; 6260e3d5408SPeter Wemm 6270e3d5408SPeter Wemm map:ttype = mapped(ttype); 6280e3d5408SPeter Wemm 6290e3d5408SPeter Wemm /* 6300e3d5408SPeter Wemm * If not a path, remove TERMCAP from the environment so we get a 6310e3d5408SPeter Wemm * real entry from /etc/termcap. This prevents us from being fooled 6320e3d5408SPeter Wemm * by out of date stuff in the environment. 6330e3d5408SPeter Wemm */ 6344a1a9510SRong-En Fan found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { 6350e3d5408SPeter Wemm /* 'unsetenv("TERMCAP")' is not portable. 6360e3d5408SPeter Wemm * The 'environ' array is better. 6370e3d5408SPeter Wemm */ 6380e3d5408SPeter Wemm int n; 6390e3d5408SPeter Wemm for (n = 0; environ[n] != 0; n++) { 6400e3d5408SPeter Wemm if (!strncmp("TERMCAP=", environ[n], 8)) { 6410e3d5408SPeter Wemm while ((environ[n] = environ[n + 1]) != 0) { 6420e3d5408SPeter Wemm n++; 6430e3d5408SPeter Wemm } 6440e3d5408SPeter Wemm break; 6450e3d5408SPeter Wemm } 6460e3d5408SPeter Wemm } 6470e3d5408SPeter Wemm } 6480e3d5408SPeter Wemm 6490e3d5408SPeter Wemm /* 6500e3d5408SPeter Wemm * ttype now contains a pointer to the type of the terminal. 6510e3d5408SPeter Wemm * If the first character is '?', ask the user. 6520e3d5408SPeter Wemm */ 6530e3d5408SPeter Wemm if (ttype[0] == '?') { 6540e3d5408SPeter Wemm if (ttype[1] != '\0') 6550e3d5408SPeter Wemm ttype = askuser(ttype + 1); 6560e3d5408SPeter Wemm else 6570e3d5408SPeter Wemm ttype = askuser(0); 6580e3d5408SPeter Wemm } 6590e3d5408SPeter Wemm /* Find the terminfo entry. If it doesn't exist, ask the user. */ 6607a69bbfbSPeter Wemm while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret) 6617a69bbfbSPeter Wemm != OK) { 6620e3d5408SPeter Wemm if (errret == 0) { 6634a1a9510SRong-En Fan (void) fprintf(stderr, "%s: unknown terminal type %s\n", 6644a1a9510SRong-En Fan _nc_progname, ttype); 6650e3d5408SPeter Wemm ttype = 0; 66615589c42SPeter Wemm } else { 66715589c42SPeter Wemm (void) fprintf(stderr, 6684a1a9510SRong-En Fan "%s: can't initialize terminal type %s (error %d)\n", 6694a1a9510SRong-En Fan _nc_progname, ttype, errret); 6700e3d5408SPeter Wemm ttype = 0; 6710e3d5408SPeter Wemm } 6720e3d5408SPeter Wemm ttype = askuser(ttype); 6730e3d5408SPeter Wemm } 6740e3d5408SPeter Wemm #if BROKEN_LINKER 6750e3d5408SPeter Wemm tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */ 6760e3d5408SPeter Wemm #endif 6770e3d5408SPeter Wemm return (ttype); 6780e3d5408SPeter Wemm } 6790e3d5408SPeter Wemm 6800e3d5408SPeter Wemm /************************************************************************** 6810e3d5408SPeter Wemm * 6820e3d5408SPeter Wemm * Mode-setting logic 6830e3d5408SPeter Wemm * 6840e3d5408SPeter Wemm **************************************************************************/ 6850e3d5408SPeter Wemm 6860e3d5408SPeter Wemm /* some BSD systems have these built in, some systems are missing 6874a1a9510SRong-En Fan * one or more definitions. The safest solution is to override unless the 6884a1a9510SRong-En Fan * commonly-altered ones are defined. 6890e3d5408SPeter Wemm */ 6904a1a9510SRong-En Fan #if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT)) 6910e3d5408SPeter Wemm #undef CEOF 6920e3d5408SPeter Wemm #undef CERASE 6930e3d5408SPeter Wemm #undef CINTR 6940e3d5408SPeter Wemm #undef CKILL 6950e3d5408SPeter Wemm #undef CLNEXT 6960e3d5408SPeter Wemm #undef CRPRNT 6970e3d5408SPeter Wemm #undef CQUIT 6980e3d5408SPeter Wemm #undef CSTART 6990e3d5408SPeter Wemm #undef CSTOP 7000e3d5408SPeter Wemm #undef CSUSP 7014a1a9510SRong-En Fan #endif 7020e3d5408SPeter Wemm 7030e3d5408SPeter Wemm /* control-character defaults */ 7044a1a9510SRong-En Fan #ifndef CEOF 7050e3d5408SPeter Wemm #define CEOF CTRL('D') 7064a1a9510SRong-En Fan #endif 7074a1a9510SRong-En Fan #ifndef CERASE 7080e3d5408SPeter Wemm #define CERASE CTRL('H') 7094a1a9510SRong-En Fan #endif 7104a1a9510SRong-En Fan #ifndef CINTR 7110e3d5408SPeter Wemm #define CINTR 127 /* ^? */ 7124a1a9510SRong-En Fan #endif 7134a1a9510SRong-En Fan #ifndef CKILL 7140e3d5408SPeter Wemm #define CKILL CTRL('U') 7154a1a9510SRong-En Fan #endif 7164a1a9510SRong-En Fan #ifndef CLNEXT 7170e3d5408SPeter Wemm #define CLNEXT CTRL('v') 7184a1a9510SRong-En Fan #endif 7194a1a9510SRong-En Fan #ifndef CRPRNT 7200e3d5408SPeter Wemm #define CRPRNT CTRL('r') 7214a1a9510SRong-En Fan #endif 7224a1a9510SRong-En Fan #ifndef CQUIT 7230e3d5408SPeter Wemm #define CQUIT CTRL('\\') 7244a1a9510SRong-En Fan #endif 7254a1a9510SRong-En Fan #ifndef CSTART 7260e3d5408SPeter Wemm #define CSTART CTRL('Q') 7274a1a9510SRong-En Fan #endif 7284a1a9510SRong-En Fan #ifndef CSTOP 7290e3d5408SPeter Wemm #define CSTOP CTRL('S') 7304a1a9510SRong-En Fan #endif 7314a1a9510SRong-En Fan #ifndef CSUSP 7320e3d5408SPeter Wemm #define CSUSP CTRL('Z') 7334a1a9510SRong-En Fan #endif 7340e3d5408SPeter Wemm 7354a1a9510SRong-En Fan #if defined(_POSIX_VDISABLE) 7364a1a9510SRong-En Fan #define DISABLED(val) (((_POSIX_VDISABLE != -1) \ 7374a1a9510SRong-En Fan && ((val) == _POSIX_VDISABLE)) \ 7384a1a9510SRong-En Fan || ((val) <= 0)) 7394a1a9510SRong-En Fan #else 7404a1a9510SRong-En Fan #define DISABLED(val) ((int)(val) <= 0) 7414a1a9510SRong-En Fan #endif 7424a1a9510SRong-En Fan 7434a1a9510SRong-En Fan #define CHK(val, dft) (DISABLED(val) ? dft : val) 7440e3d5408SPeter Wemm 7450e3d5408SPeter Wemm static bool set_tabs(void); 7460e3d5408SPeter Wemm 7470e3d5408SPeter Wemm /* 7480e3d5408SPeter Wemm * Reset the terminal mode bits to a sensible state. Very useful after 7490e3d5408SPeter Wemm * a child program dies in raw mode. 7500e3d5408SPeter Wemm */ 7510e3d5408SPeter Wemm static void 7520e3d5408SPeter Wemm reset_mode(void) 7530e3d5408SPeter Wemm { 7540e3d5408SPeter Wemm #ifdef TERMIOS 7550e3d5408SPeter Wemm tcgetattr(STDERR_FILENO, &mode); 7560e3d5408SPeter Wemm #else 7570e3d5408SPeter Wemm stty(STDERR_FILENO, &mode); 7580e3d5408SPeter Wemm #endif 7590e3d5408SPeter Wemm 7600e3d5408SPeter Wemm #ifdef TERMIOS 7610e3d5408SPeter Wemm #if defined(VDISCARD) && defined(CDISCARD) 7620e3d5408SPeter Wemm mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 7630e3d5408SPeter Wemm #endif 7640e3d5408SPeter Wemm mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 7650e3d5408SPeter Wemm mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 7660e3d5408SPeter Wemm #if defined(VFLUSH) && defined(CFLUSH) 7670e3d5408SPeter Wemm mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 7680e3d5408SPeter Wemm #endif 7690e3d5408SPeter Wemm mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 7700e3d5408SPeter Wemm mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 7710e3d5408SPeter Wemm #if defined(VLNEXT) && defined(CLNEXT) 7720e3d5408SPeter Wemm mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 7730e3d5408SPeter Wemm #endif 7740e3d5408SPeter Wemm mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 7750e3d5408SPeter Wemm #if defined(VREPRINT) && defined(CRPRNT) 7760e3d5408SPeter Wemm mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 7770e3d5408SPeter Wemm #endif 7780e3d5408SPeter Wemm #if defined(VSTART) && defined(CSTART) 7790e3d5408SPeter Wemm mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 7800e3d5408SPeter Wemm #endif 7810e3d5408SPeter Wemm #if defined(VSTOP) && defined(CSTOP) 7820e3d5408SPeter Wemm mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 7830e3d5408SPeter Wemm #endif 7840e3d5408SPeter Wemm #if defined(VSUSP) && defined(CSUSP) 7850e3d5408SPeter Wemm mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 7860e3d5408SPeter Wemm #endif 7870e3d5408SPeter Wemm #if defined(VWERASE) && defined(CWERASE) 7880e3d5408SPeter Wemm mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 7890e3d5408SPeter Wemm #endif 7900e3d5408SPeter Wemm 7910e3d5408SPeter Wemm mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 7920e3d5408SPeter Wemm #ifdef IUCLC 7930e3d5408SPeter Wemm | IUCLC 7940e3d5408SPeter Wemm #endif 7950e3d5408SPeter Wemm #ifdef IXANY 7960e3d5408SPeter Wemm | IXANY 7970e3d5408SPeter Wemm #endif 7980e3d5408SPeter Wemm | IXOFF); 7990e3d5408SPeter Wemm 8000e3d5408SPeter Wemm mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 8010e3d5408SPeter Wemm #ifdef IMAXBEL 8020e3d5408SPeter Wemm | IMAXBEL 8030e3d5408SPeter Wemm #endif 8040e3d5408SPeter Wemm ); 8050e3d5408SPeter Wemm 8060e3d5408SPeter Wemm mode.c_oflag &= ~(0 8070e3d5408SPeter Wemm #ifdef OLCUC 8080e3d5408SPeter Wemm | OLCUC 8090e3d5408SPeter Wemm #endif 8100e3d5408SPeter Wemm #ifdef OCRNL 8110e3d5408SPeter Wemm | OCRNL 8120e3d5408SPeter Wemm #endif 8130e3d5408SPeter Wemm #ifdef ONOCR 8140e3d5408SPeter Wemm | ONOCR 8150e3d5408SPeter Wemm #endif 8160e3d5408SPeter Wemm #ifdef ONLRET 8170e3d5408SPeter Wemm | ONLRET 8180e3d5408SPeter Wemm #endif 8190e3d5408SPeter Wemm #ifdef OFILL 8200e3d5408SPeter Wemm | OFILL 8210e3d5408SPeter Wemm #endif 8220e3d5408SPeter Wemm #ifdef OFDEL 8230e3d5408SPeter Wemm | OFDEL 8240e3d5408SPeter Wemm #endif 8250e3d5408SPeter Wemm #ifdef NLDLY 8265ca44d1cSRong-En Fan | NLDLY 8275ca44d1cSRong-En Fan #endif 8285ca44d1cSRong-En Fan #ifdef CRDLY 8295ca44d1cSRong-En Fan | CRDLY 8305ca44d1cSRong-En Fan #endif 8315ca44d1cSRong-En Fan #ifdef TABDLY 8325ca44d1cSRong-En Fan | TABDLY 8335ca44d1cSRong-En Fan #endif 8345ca44d1cSRong-En Fan #ifdef BSDLY 8355ca44d1cSRong-En Fan | BSDLY 8365ca44d1cSRong-En Fan #endif 8375ca44d1cSRong-En Fan #ifdef VTDLY 8385ca44d1cSRong-En Fan | VTDLY 8395ca44d1cSRong-En Fan #endif 8405ca44d1cSRong-En Fan #ifdef FFDLY 8415ca44d1cSRong-En Fan | FFDLY 8420e3d5408SPeter Wemm #endif 8430e3d5408SPeter Wemm ); 8440e3d5408SPeter Wemm 8450e3d5408SPeter Wemm mode.c_oflag |= (OPOST 8460e3d5408SPeter Wemm #ifdef ONLCR 8470e3d5408SPeter Wemm | ONLCR 8480e3d5408SPeter Wemm #endif 8490e3d5408SPeter Wemm ); 8500e3d5408SPeter Wemm 8510e3d5408SPeter Wemm mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 8520e3d5408SPeter Wemm mode.c_cflag |= (CS8 | CREAD); 8530e3d5408SPeter Wemm mode.c_lflag &= ~(ECHONL | NOFLSH 8540e3d5408SPeter Wemm #ifdef TOSTOP 8550e3d5408SPeter Wemm | TOSTOP 8560e3d5408SPeter Wemm #endif 8570e3d5408SPeter Wemm #ifdef ECHOPTR 8580e3d5408SPeter Wemm | ECHOPRT 8590e3d5408SPeter Wemm #endif 8600e3d5408SPeter Wemm #ifdef XCASE 8610e3d5408SPeter Wemm | XCASE 8620e3d5408SPeter Wemm #endif 8630e3d5408SPeter Wemm ); 8640e3d5408SPeter Wemm 8650e3d5408SPeter Wemm mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 8660e3d5408SPeter Wemm #ifdef ECHOCTL 8670e3d5408SPeter Wemm | ECHOCTL 8680e3d5408SPeter Wemm #endif 8690e3d5408SPeter Wemm #ifdef ECHOKE 8700e3d5408SPeter Wemm | ECHOKE 8710e3d5408SPeter Wemm #endif 8720e3d5408SPeter Wemm ); 8730e3d5408SPeter Wemm #endif 8740e3d5408SPeter Wemm 87539f2269fSPeter Wemm SET_TTY(STDERR_FILENO, &mode); 8760e3d5408SPeter Wemm } 8770e3d5408SPeter Wemm 8780e3d5408SPeter Wemm /* 8790e3d5408SPeter Wemm * Returns a "good" value for the erase character. This is loosely based on 8800e3d5408SPeter Wemm * the BSD4.4 logic. 8810e3d5408SPeter Wemm */ 88218259542SPeter Wemm #ifdef TERMIOS 8830e3d5408SPeter Wemm static int 8840e3d5408SPeter Wemm default_erase(void) 8850e3d5408SPeter Wemm { 8860e3d5408SPeter Wemm int result; 8870e3d5408SPeter Wemm 8880e3d5408SPeter Wemm if (over_strike 8890e3d5408SPeter Wemm && key_backspace != 0 8900e3d5408SPeter Wemm && strlen(key_backspace) == 1) 8910e3d5408SPeter Wemm result = key_backspace[0]; 8920e3d5408SPeter Wemm else 8930e3d5408SPeter Wemm result = CERASE; 8940e3d5408SPeter Wemm 8950e3d5408SPeter Wemm return result; 8960e3d5408SPeter Wemm } 89718259542SPeter Wemm #endif 8980e3d5408SPeter Wemm 8990e3d5408SPeter Wemm /* 9000e3d5408SPeter Wemm * Update the values of the erase, interrupt, and kill characters in 'mode'. 9010e3d5408SPeter Wemm * 9020e3d5408SPeter Wemm * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase 9030e3d5408SPeter Wemm * characters if they're unset, or if we specify them as options. This differs 9040e3d5408SPeter Wemm * from BSD 4.4 tset, which always sets erase. 9050e3d5408SPeter Wemm */ 9060e3d5408SPeter Wemm static void 9070e3d5408SPeter Wemm set_control_chars(void) 9080e3d5408SPeter Wemm { 9090e3d5408SPeter Wemm #ifdef TERMIOS 9104a1a9510SRong-En Fan if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) 9115d08fb1fSRong-En Fan mode.c_cc[VERASE] = (terasechar >= 0) ? terasechar : default_erase(); 9120e3d5408SPeter Wemm 9134a1a9510SRong-En Fan if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) 9145d08fb1fSRong-En Fan mode.c_cc[VINTR] = (intrchar >= 0) ? intrchar : CINTR; 9150e3d5408SPeter Wemm 9164a1a9510SRong-En Fan if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) 9175d08fb1fSRong-En Fan mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL; 9180e3d5408SPeter Wemm #endif 9190e3d5408SPeter Wemm } 9200e3d5408SPeter Wemm 9210e3d5408SPeter Wemm /* 9220e3d5408SPeter Wemm * Set up various conversions in 'mode', including parity, tabs, returns, 9230e3d5408SPeter Wemm * echo, and case, according to the termcap entry. If the program we're 9240e3d5408SPeter Wemm * running was named with a leading upper-case character, map external 9250e3d5408SPeter Wemm * uppercase to internal lowercase. 9260e3d5408SPeter Wemm */ 9270e3d5408SPeter Wemm static void 9280e3d5408SPeter Wemm set_conversions(void) 9290e3d5408SPeter Wemm { 9300e3d5408SPeter Wemm #ifdef __OBSOLETE__ 9310e3d5408SPeter Wemm /* 9320e3d5408SPeter Wemm * Conversion logic for some *really* ancient terminal glitches, 9330e3d5408SPeter Wemm * not supported in terminfo. Left here for succeeding generations 9340e3d5408SPeter Wemm * to marvel at. 9350e3d5408SPeter Wemm */ 9360e3d5408SPeter Wemm if (tgetflag("UC")) { 9370e3d5408SPeter Wemm #ifdef IUCLC 9380e3d5408SPeter Wemm mode.c_iflag |= IUCLC; 9390e3d5408SPeter Wemm mode.c_oflag |= OLCUC; 9400e3d5408SPeter Wemm #endif 9410e3d5408SPeter Wemm } else if (tgetflag("LC")) { 9420e3d5408SPeter Wemm #ifdef IUCLC 9430e3d5408SPeter Wemm mode.c_iflag &= ~IUCLC; 9440e3d5408SPeter Wemm mode.c_oflag &= ~OLCUC; 9450e3d5408SPeter Wemm #endif 9460e3d5408SPeter Wemm } 9470e3d5408SPeter Wemm mode.c_iflag &= ~(PARMRK | INPCK); 9480e3d5408SPeter Wemm mode.c_lflag |= ICANON; 9490e3d5408SPeter Wemm if (tgetflag("EP")) { 9500e3d5408SPeter Wemm mode.c_cflag |= PARENB; 9510e3d5408SPeter Wemm mode.c_cflag &= ~PARODD; 9520e3d5408SPeter Wemm } 9530e3d5408SPeter Wemm if (tgetflag("OP")) { 9540e3d5408SPeter Wemm mode.c_cflag |= PARENB; 9550e3d5408SPeter Wemm mode.c_cflag |= PARODD; 9560e3d5408SPeter Wemm } 9570e3d5408SPeter Wemm #endif /* __OBSOLETE__ */ 9580e3d5408SPeter Wemm 9590e3d5408SPeter Wemm #ifdef TERMIOS 9600e3d5408SPeter Wemm #ifdef ONLCR 9610e3d5408SPeter Wemm mode.c_oflag |= ONLCR; 9620e3d5408SPeter Wemm #endif 9630e3d5408SPeter Wemm mode.c_iflag |= ICRNL; 9640e3d5408SPeter Wemm mode.c_lflag |= ECHO; 9650e3d5408SPeter Wemm #ifdef OXTABS 9660e3d5408SPeter Wemm mode.c_oflag |= OXTABS; 9670e3d5408SPeter Wemm #endif /* OXTABS */ 9680e3d5408SPeter Wemm 9690e3d5408SPeter Wemm /* test used to be tgetflag("NL") */ 9700e3d5408SPeter Wemm if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) { 9710e3d5408SPeter Wemm /* Newline, not linefeed. */ 9720e3d5408SPeter Wemm #ifdef ONLCR 9730e3d5408SPeter Wemm mode.c_oflag &= ~ONLCR; 9740e3d5408SPeter Wemm #endif 9750e3d5408SPeter Wemm mode.c_iflag &= ~ICRNL; 9760e3d5408SPeter Wemm } 9770e3d5408SPeter Wemm #ifdef __OBSOLETE__ 9780e3d5408SPeter Wemm if (tgetflag("HD")) /* Half duplex. */ 9790e3d5408SPeter Wemm mode.c_lflag &= ~ECHO; 9800e3d5408SPeter Wemm #endif /* __OBSOLETE__ */ 9810e3d5408SPeter Wemm #ifdef OXTABS 9820e3d5408SPeter Wemm /* test used to be tgetflag("pt") */ 9830e3d5408SPeter Wemm if (has_hardware_tabs) /* Print tabs. */ 9840e3d5408SPeter Wemm mode.c_oflag &= ~OXTABS; 9850e3d5408SPeter Wemm #endif /* OXTABS */ 9860e3d5408SPeter Wemm mode.c_lflag |= (ECHOE | ECHOK); 9870e3d5408SPeter Wemm #endif 9880e3d5408SPeter Wemm } 9890e3d5408SPeter Wemm 9900e3d5408SPeter Wemm /* Output startup string. */ 9910e3d5408SPeter Wemm static void 9920e3d5408SPeter Wemm set_init(void) 9930e3d5408SPeter Wemm { 9940e3d5408SPeter Wemm char *p; 9950e3d5408SPeter Wemm bool settle; 9960e3d5408SPeter Wemm 9970e3d5408SPeter Wemm #ifdef __OBSOLETE__ 9980e3d5408SPeter Wemm if (pad_char != (char *) 0) /* Get/set pad character. */ 9990e3d5408SPeter Wemm PC = pad_char[0]; 10000e3d5408SPeter Wemm #endif /* OBSOLETE */ 10010e3d5408SPeter Wemm 10020e3d5408SPeter Wemm #ifdef TAB3 10030e3d5408SPeter Wemm if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 10040e3d5408SPeter Wemm oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 100539f2269fSPeter Wemm SET_TTY(STDERR_FILENO, &oldmode); 10060e3d5408SPeter Wemm } 10070e3d5408SPeter Wemm #endif 10080e3d5408SPeter Wemm settle = set_tabs(); 10090e3d5408SPeter Wemm 10100e3d5408SPeter Wemm if (isreset) { 10110e3d5408SPeter Wemm if ((p = reset_1string) != 0) { 10120e3d5408SPeter Wemm tputs(p, 0, outc); 10130e3d5408SPeter Wemm settle = TRUE; 10140e3d5408SPeter Wemm } 10150e3d5408SPeter Wemm if ((p = reset_2string) != 0) { 10160e3d5408SPeter Wemm tputs(p, 0, outc); 10170e3d5408SPeter Wemm settle = TRUE; 10180e3d5408SPeter Wemm } 10190e3d5408SPeter Wemm /* What about rf, rs3, as per terminfo man page? */ 10200e3d5408SPeter Wemm /* also might be nice to send rmacs, rmul, rmm */ 10210e3d5408SPeter Wemm if ((p = reset_file) != 0 10220e3d5408SPeter Wemm || (p = init_file) != 0) { 10230e3d5408SPeter Wemm cat(p); 10240e3d5408SPeter Wemm settle = TRUE; 10250e3d5408SPeter Wemm } 10260e3d5408SPeter Wemm } 10270e3d5408SPeter Wemm 10280e3d5408SPeter Wemm if (settle) { 10290e3d5408SPeter Wemm (void) putc('\r', stderr); 10300e3d5408SPeter Wemm (void) fflush(stderr); 10310e3d5408SPeter Wemm (void) napms(1000); /* Settle the terminal. */ 10320e3d5408SPeter Wemm } 10330e3d5408SPeter Wemm } 10340e3d5408SPeter Wemm 10350e3d5408SPeter Wemm /* 10360e3d5408SPeter Wemm * Set the hardware tabs on the terminal, using the ct (clear all tabs), 10370e3d5408SPeter Wemm * st (set one tab) and ch (horizontal cursor addressing) capabilities. 10380e3d5408SPeter Wemm * This is done before if and is, so they can patch in case we blow this. 10390e3d5408SPeter Wemm * Return TRUE if we set any tab stops, FALSE if not. 10400e3d5408SPeter Wemm */ 10410e3d5408SPeter Wemm static bool 10424a1a9510SRong-En Fan set_tabs(void) 10430e3d5408SPeter Wemm { 10440e3d5408SPeter Wemm if (set_tab && clear_all_tabs) { 10450e3d5408SPeter Wemm int c; 10460e3d5408SPeter Wemm 10470e3d5408SPeter Wemm (void) putc('\r', stderr); /* Force to left margin. */ 10480e3d5408SPeter Wemm tputs(clear_all_tabs, 0, outc); 10490e3d5408SPeter Wemm 10500e3d5408SPeter Wemm for (c = 8; c < tcolumns; c += 8) { 10510e3d5408SPeter Wemm /* Get to the right column. In BSD tset, this 10520e3d5408SPeter Wemm * used to try a bunch of half-clever things 10530e3d5408SPeter Wemm * with cup and hpa, for an average saving of 10540e3d5408SPeter Wemm * somewhat less than two character times per 10554a1a9510SRong-En Fan * tab stop, less than .01 sec at 2400cps. We 10560e3d5408SPeter Wemm * lost all this cruft because it seemed to be 10570e3d5408SPeter Wemm * introducing some odd bugs. 10584a1a9510SRong-En Fan * -----------12345678----------- */ 10590e3d5408SPeter Wemm (void) fputs(" ", stderr); 10600e3d5408SPeter Wemm tputs(set_tab, 0, outc); 10610e3d5408SPeter Wemm } 10620e3d5408SPeter Wemm putc('\r', stderr); 10630e3d5408SPeter Wemm return (TRUE); 10640e3d5408SPeter Wemm } 10650e3d5408SPeter Wemm return (FALSE); 10660e3d5408SPeter Wemm } 10670e3d5408SPeter Wemm 10680e3d5408SPeter Wemm /************************************************************************** 10690e3d5408SPeter Wemm * 10700e3d5408SPeter Wemm * Main sequence 10710e3d5408SPeter Wemm * 10720e3d5408SPeter Wemm **************************************************************************/ 10730e3d5408SPeter Wemm 10740e3d5408SPeter Wemm /* 10750e3d5408SPeter Wemm * Tell the user if a control key has been changed from the default value. 10760e3d5408SPeter Wemm */ 107718259542SPeter Wemm #ifdef TERMIOS 10780e3d5408SPeter Wemm static void 10790e3d5408SPeter Wemm report(const char *name, int which, unsigned def) 10800e3d5408SPeter Wemm { 10810e3d5408SPeter Wemm unsigned older, newer; 10820e3d5408SPeter Wemm char *p; 10830e3d5408SPeter Wemm 10840e3d5408SPeter Wemm newer = mode.c_cc[which]; 10850e3d5408SPeter Wemm older = oldmode.c_cc[which]; 10860e3d5408SPeter Wemm 10870e3d5408SPeter Wemm if (older == newer && older == def) 10880e3d5408SPeter Wemm return; 10890e3d5408SPeter Wemm 10900e3d5408SPeter Wemm (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); 10910e3d5408SPeter Wemm 10924a1a9510SRong-En Fan if (DISABLED(newer)) 10934a1a9510SRong-En Fan (void) fprintf(stderr, "undef.\n"); 10940e3d5408SPeter Wemm /* 10950e3d5408SPeter Wemm * Check 'delete' before 'backspace', since the key_backspace value 10960e3d5408SPeter Wemm * is ambiguous. 10970e3d5408SPeter Wemm */ 10984a1a9510SRong-En Fan else if (newer == 0177) 10990e3d5408SPeter Wemm (void) fprintf(stderr, "delete.\n"); 11000e3d5408SPeter Wemm else if ((p = key_backspace) != 0 11010e3d5408SPeter Wemm && newer == (unsigned char) p[0] 11020e3d5408SPeter Wemm && p[1] == '\0') 11030e3d5408SPeter Wemm (void) fprintf(stderr, "backspace.\n"); 11040e3d5408SPeter Wemm else if (newer < 040) { 11050e3d5408SPeter Wemm newer ^= 0100; 11064a1a9510SRong-En Fan (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer)); 11070e3d5408SPeter Wemm } else 11084a1a9510SRong-En Fan (void) fprintf(stderr, "%c.\n", UChar(newer)); 11090e3d5408SPeter Wemm } 111018259542SPeter Wemm #endif 11110e3d5408SPeter Wemm 11120e3d5408SPeter Wemm /* 11130e3d5408SPeter Wemm * Convert the obsolete argument forms into something that getopt can handle. 11140e3d5408SPeter Wemm * This means that -e, -i and -k get default arguments supplied for them. 11150e3d5408SPeter Wemm */ 11160e3d5408SPeter Wemm static void 11170e3d5408SPeter Wemm obsolete(char **argv) 11180e3d5408SPeter Wemm { 11190e3d5408SPeter Wemm for (; *argv; ++argv) { 11200e3d5408SPeter Wemm char *parm = argv[0]; 11210e3d5408SPeter Wemm 112215589c42SPeter Wemm if (parm[0] == '-' && parm[1] == '\0') { 11230e3d5408SPeter Wemm argv[0] = strdup("-q"); 11240e3d5408SPeter Wemm continue; 11250e3d5408SPeter Wemm } 11260e3d5408SPeter Wemm 11270e3d5408SPeter Wemm if ((parm[0] != '-') 11280e3d5408SPeter Wemm || (argv[1] && argv[1][0] != '-') 11290e3d5408SPeter Wemm || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k') 11300e3d5408SPeter Wemm || (parm[2] != '\0')) 11310e3d5408SPeter Wemm continue; 11320e3d5408SPeter Wemm switch (argv[0][1]) { 11330e3d5408SPeter Wemm case 'e': 11340e3d5408SPeter Wemm argv[0] = strdup("-e^H"); 11350e3d5408SPeter Wemm break; 11360e3d5408SPeter Wemm case 'i': 11370e3d5408SPeter Wemm argv[0] = strdup("-i^C"); 11380e3d5408SPeter Wemm break; 11390e3d5408SPeter Wemm case 'k': 11400e3d5408SPeter Wemm argv[0] = strdup("-k^U"); 11410e3d5408SPeter Wemm break; 11420e3d5408SPeter Wemm } 11430e3d5408SPeter Wemm } 11440e3d5408SPeter Wemm } 11450e3d5408SPeter Wemm 11460e3d5408SPeter Wemm static void 11474a1a9510SRong-En Fan usage(void) 11480e3d5408SPeter Wemm { 11494a1a9510SRong-En Fan static const char *tbl[] = 11504a1a9510SRong-En Fan { 11514a1a9510SRong-En Fan "" 11524a1a9510SRong-En Fan ,"Options:" 11534a1a9510SRong-En Fan ," -c set control characters" 11544a1a9510SRong-En Fan ," -e ch erase character" 11554a1a9510SRong-En Fan ," -I no initialization strings" 11564a1a9510SRong-En Fan ," -i ch interrupt character" 11574a1a9510SRong-En Fan ," -k ch kill character" 11584a1a9510SRong-En Fan ," -m mapping map identifier to type" 11594a1a9510SRong-En Fan ," -Q do not output control key settings" 11604a1a9510SRong-En Fan ," -r display term on stderr" 11614a1a9510SRong-En Fan ," -s output TERM set command" 11624a1a9510SRong-En Fan ," -V print curses-version" 11634a1a9510SRong-En Fan ," -w set window-size" 11644a1a9510SRong-En Fan }; 11654a1a9510SRong-En Fan unsigned n; 11664a1a9510SRong-En Fan (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname); 11674a1a9510SRong-En Fan for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n) 11684a1a9510SRong-En Fan fprintf(stderr, "%s\n", tbl[n]); 116939f2269fSPeter Wemm exit_error(); 117039f2269fSPeter Wemm /* NOTREACHED */ 11710e3d5408SPeter Wemm } 11720e3d5408SPeter Wemm 117315589c42SPeter Wemm static char 117415589c42SPeter Wemm arg_to_char(void) 11750e3d5408SPeter Wemm { 11765d08fb1fSRong-En Fan return (char) ((optarg[0] == '^' && optarg[1] != '\0') 11770e3d5408SPeter Wemm ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) 11785d08fb1fSRong-En Fan : optarg[0]); 11790e3d5408SPeter Wemm } 11800e3d5408SPeter Wemm 11810e3d5408SPeter Wemm int 11820e3d5408SPeter Wemm main(int argc, char **argv) 11830e3d5408SPeter Wemm { 11840e3d5408SPeter Wemm int ch, noinit, noset, quiet, Sflag, sflag, showterm; 11850e3d5408SPeter Wemm const char *p; 11860e3d5408SPeter Wemm const char *ttype; 11870e3d5408SPeter Wemm 11880e3d5408SPeter Wemm obsolete(argv); 11890e3d5408SPeter Wemm noinit = noset = quiet = Sflag = sflag = showterm = 0; 11905ca44d1cSRong-En Fan while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) { 11910e3d5408SPeter Wemm switch (ch) { 11924a1a9510SRong-En Fan case 'c': /* set control-chars */ 11934a1a9510SRong-En Fan opt_c = TRUE; 11940e3d5408SPeter Wemm break; 11950e3d5408SPeter Wemm case 'a': /* OBSOLETE: map identifier to type */ 11960e3d5408SPeter Wemm add_mapping("arpanet", optarg); 11970e3d5408SPeter Wemm break; 11980e3d5408SPeter Wemm case 'd': /* OBSOLETE: map identifier to type */ 11990e3d5408SPeter Wemm add_mapping("dialup", optarg); 12000e3d5408SPeter Wemm break; 12010e3d5408SPeter Wemm case 'e': /* erase character */ 12020e3d5408SPeter Wemm terasechar = arg_to_char(); 12030e3d5408SPeter Wemm break; 12040e3d5408SPeter Wemm case 'I': /* no initialization strings */ 12050e3d5408SPeter Wemm noinit = 1; 12060e3d5408SPeter Wemm break; 12070e3d5408SPeter Wemm case 'i': /* interrupt character */ 12080e3d5408SPeter Wemm intrchar = arg_to_char(); 12090e3d5408SPeter Wemm break; 12100e3d5408SPeter Wemm case 'k': /* kill character */ 12110e3d5408SPeter Wemm tkillchar = arg_to_char(); 12120e3d5408SPeter Wemm break; 12130e3d5408SPeter Wemm case 'm': /* map identifier to type */ 12140e3d5408SPeter Wemm add_mapping(0, optarg); 12150e3d5408SPeter Wemm break; 12160e3d5408SPeter Wemm case 'n': /* OBSOLETE: set new tty driver */ 12170e3d5408SPeter Wemm break; 12180e3d5408SPeter Wemm case 'p': /* OBSOLETE: map identifier to type */ 12190e3d5408SPeter Wemm add_mapping("plugboard", optarg); 12200e3d5408SPeter Wemm break; 12210e3d5408SPeter Wemm case 'Q': /* don't output control key settings */ 12220e3d5408SPeter Wemm quiet = 1; 12230e3d5408SPeter Wemm break; 12244a1a9510SRong-En Fan case 'q': /* display term only */ 12254a1a9510SRong-En Fan noset = 1; 12260e3d5408SPeter Wemm break; 12270e3d5408SPeter Wemm case 'r': /* display term on stderr */ 12280e3d5408SPeter Wemm showterm = 1; 12290e3d5408SPeter Wemm break; 12304a1a9510SRong-En Fan case 'S': /* OBSOLETE: output TERM & TERMCAP */ 12314a1a9510SRong-En Fan Sflag = 1; 12324a1a9510SRong-En Fan break; 12330e3d5408SPeter Wemm case 's': /* output TERM set command */ 12340e3d5408SPeter Wemm sflag = 1; 12350e3d5408SPeter Wemm break; 12364a1a9510SRong-En Fan case 'V': /* print curses-version */ 123718259542SPeter Wemm puts(curses_version()); 12384a1a9510SRong-En Fan ExitProgram(EXIT_SUCCESS); 12394a1a9510SRong-En Fan case 'w': /* set window-size */ 12404a1a9510SRong-En Fan opt_w = TRUE; 12414a1a9510SRong-En Fan break; 12420e3d5408SPeter Wemm case '?': 12430e3d5408SPeter Wemm default: 12444a1a9510SRong-En Fan usage(); 12450e3d5408SPeter Wemm } 12460e3d5408SPeter Wemm } 12474a1a9510SRong-En Fan 12484a1a9510SRong-En Fan _nc_progname = _nc_rootname(*argv); 12490e3d5408SPeter Wemm argc -= optind; 12500e3d5408SPeter Wemm argv += optind; 12510e3d5408SPeter Wemm 12520e3d5408SPeter Wemm if (argc > 1) 12534a1a9510SRong-En Fan usage(); 12544a1a9510SRong-En Fan 12554a1a9510SRong-En Fan if (!opt_c && !opt_w) 12564a1a9510SRong-En Fan opt_c = opt_w = TRUE; 12574a1a9510SRong-En Fan 12584a1a9510SRong-En Fan if (GET_TTY(STDERR_FILENO, &mode) < 0) 12594a1a9510SRong-En Fan failed("standard error"); 12604a1a9510SRong-En Fan can_restore = TRUE; 12614a1a9510SRong-En Fan original = oldmode = mode; 12624a1a9510SRong-En Fan #ifdef TERMIOS 12635d08fb1fSRong-En Fan ospeed = (NCURSES_OSPEED) cfgetospeed(&mode); 12644a1a9510SRong-En Fan #else 12655d08fb1fSRong-En Fan ospeed = (NCURSES_OSPEED) mode.sg_ospeed; 12664a1a9510SRong-En Fan #endif 12674a1a9510SRong-En Fan 1268*06bfebdeSXin LI if (same_program(_nc_progname, PROG_RESET)) { 12694a1a9510SRong-En Fan isreset = TRUE; 12704a1a9510SRong-En Fan reset_mode(); 12714a1a9510SRong-En Fan } 12720e3d5408SPeter Wemm 1273*06bfebdeSXin LI (void) get_termcap_entry(*argv); 12740e3d5408SPeter Wemm 12750e3d5408SPeter Wemm if (!noset) { 12760e3d5408SPeter Wemm tcolumns = columns; 12770e3d5408SPeter Wemm tlines = lines; 12780e3d5408SPeter Wemm 12795d08fb1fSRong-En Fan #if HAVE_SIZECHANGE 12804a1a9510SRong-En Fan if (opt_w) { 12815d08fb1fSRong-En Fan STRUCT_WINSIZE win; 12825d08fb1fSRong-En Fan /* Set window size if not set already */ 12835d08fb1fSRong-En Fan (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win); 12845d08fb1fSRong-En Fan if (WINSIZE_ROWS(win) == 0 && 12855d08fb1fSRong-En Fan WINSIZE_COLS(win) == 0 && 12860e3d5408SPeter Wemm tlines > 0 && tcolumns > 0) { 12875d08fb1fSRong-En Fan WINSIZE_ROWS(win) = tlines; 12885d08fb1fSRong-En Fan WINSIZE_COLS(win) = tcolumns; 12895d08fb1fSRong-En Fan (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win); 12900e3d5408SPeter Wemm } 12914a1a9510SRong-En Fan } 12920e3d5408SPeter Wemm #endif 12934a1a9510SRong-En Fan if (opt_c) { 12940e3d5408SPeter Wemm set_control_chars(); 12950e3d5408SPeter Wemm set_conversions(); 12960e3d5408SPeter Wemm 12970e3d5408SPeter Wemm if (!noinit) 12980e3d5408SPeter Wemm set_init(); 12990e3d5408SPeter Wemm 13000e3d5408SPeter Wemm /* Set the modes if they've changed. */ 130115589c42SPeter Wemm if (memcmp(&mode, &oldmode, sizeof(mode))) { 130239f2269fSPeter Wemm SET_TTY(STDERR_FILENO, &mode); 13030e3d5408SPeter Wemm } 130415589c42SPeter Wemm } 13054a1a9510SRong-En Fan } 13060e3d5408SPeter Wemm 13070e3d5408SPeter Wemm /* Get the terminal name from the entry. */ 13080e3d5408SPeter Wemm ttype = _nc_first_name(cur_term->type.term_names); 13090e3d5408SPeter Wemm 13100e3d5408SPeter Wemm if (noset) 13110e3d5408SPeter Wemm (void) printf("%s\n", ttype); 13120e3d5408SPeter Wemm else { 13130e3d5408SPeter Wemm if (showterm) 13140e3d5408SPeter Wemm (void) fprintf(stderr, "Terminal type is %s.\n", ttype); 13150e3d5408SPeter Wemm /* 13160e3d5408SPeter Wemm * If erase, kill and interrupt characters could have been 13170e3d5408SPeter Wemm * modified and not -Q, display the changes. 13180e3d5408SPeter Wemm */ 131918259542SPeter Wemm #ifdef TERMIOS 13200e3d5408SPeter Wemm if (!quiet) { 13210e3d5408SPeter Wemm report("Erase", VERASE, CERASE); 13224a1a9510SRong-En Fan report("Kill", VKILL, CKILL); 13234a1a9510SRong-En Fan report("Interrupt", VINTR, CINTR); 13240e3d5408SPeter Wemm } 132518259542SPeter Wemm #endif 13260e3d5408SPeter Wemm } 13270e3d5408SPeter Wemm 13280e3d5408SPeter Wemm if (Sflag) 13290e3d5408SPeter Wemm err("The -S option is not supported under terminfo."); 13300e3d5408SPeter Wemm 13310e3d5408SPeter Wemm if (sflag) { 13324a1a9510SRong-En Fan int len; 13334a1a9510SRong-En Fan char *var; 13344a1a9510SRong-En Fan char *leaf; 13350e3d5408SPeter Wemm /* 13360e3d5408SPeter Wemm * Figure out what shell we're using. A hack, we look for an 13370e3d5408SPeter Wemm * environmental variable SHELL ending in "csh". 13380e3d5408SPeter Wemm */ 13394a1a9510SRong-En Fan if ((var = getenv("SHELL")) != 0 13405d08fb1fSRong-En Fan && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3) 13414a1a9510SRong-En Fan && !strcmp(leaf + len - 3, "csh")) 13420e3d5408SPeter Wemm p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; 13430e3d5408SPeter Wemm else 13440e3d5408SPeter Wemm p = "TERM=%s;\n"; 13450e3d5408SPeter Wemm (void) printf(p, ttype); 13460e3d5408SPeter Wemm } 13470e3d5408SPeter Wemm 13484a1a9510SRong-En Fan ExitProgram(EXIT_SUCCESS); 13490e3d5408SPeter Wemm } 1350