150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * tset.c - terminal initialization utility 3750276Speter * 3850276Speter * This code was mostly swiped from 4.4BSD tset, with some obsolescent 3950276Speter * cruft removed and substantial portions rewritten. A Regents of the 4050276Speter * University of California copyright applies to some portions of the 4150276Speter * code, and is reproduced below: 4250276Speter */ 4350276Speter/*- 4450276Speter * Copyright (c) 1980, 1991, 1993 4550276Speter * The Regents of the University of California. All rights reserved. 4650276Speter * 4750276Speter * Redistribution and use in source and binary forms, with or without 4850276Speter * modification, are permitted provided that the following conditions 4950276Speter * are met: 5050276Speter * 1. Redistributions of source code must retain the above copyright 5150276Speter * notice, this list of conditions and the following disclaimer. 5250276Speter * 2. Redistributions in binary form must reproduce the above copyright 5350276Speter * notice, this list of conditions and the following disclaimer in the 5450276Speter * documentation and/or other materials provided with the distribution. 5550276Speter * 3. All advertising materials mentioning features or use of this software 5650276Speter * must display the following acknowledgement: 5750276Speter * This product includes software developed by the University of 5850276Speter * California, Berkeley and its contributors. 5950276Speter * 4. Neither the name of the University nor the names of its contributors 6050276Speter * may be used to endorse or promote products derived from this software 6150276Speter * without specific prior written permission. 6250276Speter * 6350276Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 6450276Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6550276Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6650276Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6750276Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6850276Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 6950276Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 7050276Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 7150276Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 7250276Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 7350276Speter * SUCH DAMAGE. 7450276Speter */ 7550276Speter 76174993Srafan#define USE_LIBTINFO 7750276Speter#define __INTERNAL_CAPS_VISIBLE /* we need to see has_hardware_tabs */ 7850276Speter#include <progs.priv.h> 7950276Speter 8050276Speter#include <errno.h> 8150276Speter#include <stdio.h> 8250276Speter#include <termcap.h> 8350276Speter#include <fcntl.h> 8450276Speter 8550276Speter#if HAVE_GETTTYNAM && HAVE_TTYENT_H 8650276Speter#include <ttyent.h> 8750276Speter#endif 8850276Speter#ifdef NeXT 8950276Speterchar *ttyname(int fd); 9050276Speter#endif 9150276Speter 92184989Srafan#if HAVE_SIZECHANGE 93184989Srafan# if !defined(sun) || !TERMIOS 94184989Srafan# if HAVE_SYS_IOCTL_H 95184989Srafan# include <sys/ioctl.h> 96184989Srafan# endif 97184989Srafan# endif 9850276Speter#endif 9950276Speter 10050276Speter#if NEED_PTEM_H 10150276Speter/* they neglected to define struct winsize in termios.h -- it's only 10250276Speter in termio.h */ 10397049Speter#include <sys/stream.h> 10497049Speter#include <sys/ptem.h> 10550276Speter#endif 10650276Speter 10750276Speter#include <dump_entry.h> 10866963Speter#include <transform.h> 10950276Speter 110184989SrafanMODULE_ID("$Id: tset.c,v 1.76 2008/10/11 19:26:19 tom Exp $") 11150276Speter 112184989Srafan/* 113184989Srafan * SCO defines TIOCGSIZE and the corresponding struct. Other systems (SunOS, 114184989Srafan * Solaris, IRIX) define TIOCGWINSZ and struct winsize. 115184989Srafan */ 116184989Srafan#ifdef TIOCGSIZE 117184989Srafan# define IOCTL_GET_WINSIZE TIOCGSIZE 118184989Srafan# define IOCTL_SET_WINSIZE TIOCSSIZE 119184989Srafan# define STRUCT_WINSIZE struct ttysize 120184989Srafan# define WINSIZE_ROWS(n) n.ts_lines 121184989Srafan# define WINSIZE_COLS(n) n.ts_cols 122184989Srafan#else 123184989Srafan# ifdef TIOCGWINSZ 124184989Srafan# define IOCTL_GET_WINSIZE TIOCGWINSZ 125184989Srafan# define IOCTL_SET_WINSIZE TIOCSWINSZ 126184989Srafan# define STRUCT_WINSIZE struct winsize 127184989Srafan# define WINSIZE_ROWS(n) n.ws_row 128184989Srafan# define WINSIZE_COLS(n) n.ws_col 129184989Srafan# endif 130184989Srafan#endif 131184989Srafan 13250276Speterextern char **environ; 13350276Speter 13450276Speter#undef CTRL 13550276Speter#define CTRL(x) ((x) & 0x1f) 13650276Speter 13750276Speterconst char *_nc_progname = "tset"; 13850276Speter 13997049Speterstatic TTY mode, oldmode, original; 14050276Speter 141166124Srafanstatic bool opt_c; /* set control-chars */ 142166124Srafanstatic bool opt_w; /* set window-size */ 143166124Srafan 14497049Speterstatic bool can_restore = FALSE; 14566963Speterstatic bool isreset = FALSE; /* invoked as reset */ 14662449Speterstatic int terasechar = -1; /* new erase character */ 14762449Speterstatic int intrchar = -1; /* new interrupt character */ 14862449Speterstatic int tkillchar = -1; /* new kill character */ 14962449Speterstatic int tlines, tcolumns; /* window size */ 15050276Speter 15197049Speter#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c)) 15250276Speter 15350276Speterstatic int 15462449SpeterCaselessCmp(const char *a, const char *b) 15562449Speter{ /* strcasecmp isn't portable */ 15662449Speter while (*a && *b) { 15762449Speter int cmp = LOWERCASE(*a) - LOWERCASE(*b); 15862449Speter if (cmp != 0) 15962449Speter break; 16062449Speter a++, b++; 16162449Speter } 16262449Speter return LOWERCASE(*a) - LOWERCASE(*b); 16350276Speter} 16450276Speter 16550276Speterstatic void 16697049Speterexit_error(void) 16797049Speter{ 16897049Speter if (can_restore) 16997049Speter SET_TTY(STDERR_FILENO, &original); 17097049Speter (void) fprintf(stderr, "\n"); 17197049Speter fflush(stderr); 172166124Srafan ExitProgram(EXIT_FAILURE); 17397049Speter /* NOTREACHED */ 17497049Speter} 17597049Speter 17697049Speterstatic void 17762449Spetererr(const char *fmt,...) 17850276Speter{ 17962449Speter va_list ap; 18062449Speter va_start(ap, fmt); 181166124Srafan (void) fprintf(stderr, "%s: ", _nc_progname); 18262449Speter (void) vfprintf(stderr, fmt, ap); 18362449Speter va_end(ap); 18497049Speter exit_error(); 18562449Speter /* NOTREACHED */ 18650276Speter} 18750276Speter 18850276Speterstatic void 18950276Speterfailed(const char *msg) 19050276Speter{ 19162449Speter char temp[BUFSIZ]; 192166124Srafan unsigned len = strlen(_nc_progname) + 2; 193166124Srafan 194184989Srafan if ((int) len < (int) sizeof(temp) - 12) { 195166124Srafan strcpy(temp, _nc_progname); 196166124Srafan strcat(temp, ": "); 197166124Srafan } else { 198166124Srafan strcpy(temp, "tset: "); 199166124Srafan } 200166124Srafan perror(strncat(temp, msg, sizeof(temp) - strlen(temp) - 2)); 20197049Speter exit_error(); 20262449Speter /* NOTREACHED */ 20350276Speter} 20450276Speter 20550276Speterstatic void 20650276Spetercat(char *file) 20750276Speter{ 20897049Speter FILE *fp; 20997049Speter size_t nr; 21062449Speter char buf[BUFSIZ]; 21150276Speter 21297049Speter if ((fp = fopen(file, "r")) == 0) 21362449Speter failed(file); 21450276Speter 21597049Speter while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) 21697049Speter if (fwrite(buf, sizeof(char), nr, stderr) != nr) 21797049Speter failed("write to stderr"); 21897049Speter fclose(fp); 21950276Speter} 22050276Speter 22150276Speterstatic int 22250276Speteroutc(int c) 22350276Speter{ 22462449Speter return putc(c, stderr); 22550276Speter} 22650276Speter 22750276Speter/* Prompt the user for a terminal type. */ 22850276Speterstatic const char * 22950276Speteraskuser(const char *dflt) 23050276Speter{ 23162449Speter static char answer[256]; 23262449Speter char *p; 23350276Speter 23462449Speter /* We can get recalled; if so, don't continue uselessly. */ 235166124Srafan clearerr(stdin); 23662449Speter if (feof(stdin) || ferror(stdin)) { 23762449Speter (void) fprintf(stderr, "\n"); 23897049Speter exit_error(); 23997049Speter /* NOTREACHED */ 24062449Speter } 24162449Speter for (;;) { 24262449Speter if (dflt) 24362449Speter (void) fprintf(stderr, "Terminal type? [%s] ", dflt); 24462449Speter else 24562449Speter (void) fprintf(stderr, "Terminal type? "); 24662449Speter (void) fflush(stderr); 24762449Speter 24862449Speter if (fgets(answer, sizeof(answer), stdin) == 0) { 24962449Speter if (dflt == 0) { 25097049Speter exit_error(); 25197049Speter /* NOTREACHED */ 25262449Speter } 25362449Speter return (dflt); 25450276Speter } 25550276Speter 25662449Speter if ((p = strchr(answer, '\n')) != 0) 25762449Speter *p = '\0'; 25862449Speter if (answer[0]) 25962449Speter return (answer); 26062449Speter if (dflt != 0) 26162449Speter return (dflt); 26262449Speter } 26350276Speter} 26450276Speter 26550276Speter/************************************************************************** 26650276Speter * 26750276Speter * Mapping logic begins here 26850276Speter * 26950276Speter **************************************************************************/ 27050276Speter 27150276Speter/* Baud rate conditionals for mapping. */ 27250276Speter#define GT 0x01 27350276Speter#define EQ 0x02 27450276Speter#define LT 0x04 27550276Speter#define NOT 0x08 27650276Speter#define GE (GT | EQ) 27750276Speter#define LE (LT | EQ) 27850276Speter 27950276Spetertypedef struct map { 28062449Speter struct map *next; /* Linked list of maps. */ 28162449Speter const char *porttype; /* Port type, or "" for any. */ 28262449Speter const char *type; /* Terminal type to select. */ 28362449Speter int conditional; /* Baud rate conditionals bitmask. */ 28466963Speter int speed; /* Baud rate to compare against. */ 28550276Speter} MAP; 28650276Speter 28750276Speterstatic MAP *cur, *maplist; 28850276Speter 28950276Spetertypedef struct speeds { 29062449Speter const char *string; 29162449Speter int speed; 29250276Speter} SPEEDS; 29350276Speter 29462449Speterstatic const SPEEDS speeds[] = 29562449Speter{ 29662449Speter {"0", B0}, 29762449Speter {"50", B50}, 29862449Speter {"75", B75}, 29962449Speter {"110", B110}, 30062449Speter {"134", B134}, 30162449Speter {"134.5", B134}, 30262449Speter {"150", B150}, 30362449Speter {"200", B200}, 30462449Speter {"300", B300}, 30562449Speter {"600", B600}, 30662449Speter {"1200", B1200}, 30762449Speter {"1800", B1800}, 30862449Speter {"2400", B2400}, 30962449Speter {"4800", B4800}, 31062449Speter {"9600", B9600}, 31166963Speter /* sgttyb may define up to this point */ 31266963Speter#ifdef B19200 31362449Speter {"19200", B19200}, 31466963Speter#endif 31566963Speter#ifdef B38400 31662449Speter {"38400", B38400}, 31766963Speter#endif 31866963Speter#ifdef B19200 31962449Speter {"19200", B19200}, 32066963Speter#endif 32166963Speter#ifdef B38400 32262449Speter {"38400", B38400}, 32366963Speter#endif 32450276Speter#ifdef B19200 32562449Speter {"19200", B19200}, 32650276Speter#else 32750276Speter#ifdef EXTA 32862449Speter {"19200", EXTA}, 32950276Speter#endif 33050276Speter#endif 33150276Speter#ifdef B38400 33262449Speter {"38400", B38400}, 33350276Speter#else 33450276Speter#ifdef EXTB 33562449Speter {"38400", EXTB}, 33650276Speter#endif 33750276Speter#endif 33850276Speter#ifdef B57600 33962449Speter {"57600", B57600}, 34050276Speter#endif 34150276Speter#ifdef B115200 34262449Speter {"115200", B115200}, 34350276Speter#endif 34450276Speter#ifdef B230400 34562449Speter {"230400", B230400}, 34650276Speter#endif 34750276Speter#ifdef B460800 34862449Speter {"460800", B460800}, 34950276Speter#endif 35062449Speter {(char *) 0, 0} 35150276Speter}; 35250276Speter 35350276Speterstatic int 35450276Spetertbaudrate(char *rate) 35550276Speter{ 35662449Speter const SPEEDS *sp; 35762449Speter int found = FALSE; 35850276Speter 35962449Speter /* The baudrate number can be preceded by a 'B', which is ignored. */ 36062449Speter if (*rate == 'B') 36162449Speter ++rate; 36250276Speter 36362449Speter for (sp = speeds; sp->string; ++sp) { 36462449Speter if (!CaselessCmp(rate, sp->string)) { 36562449Speter found = TRUE; 36662449Speter break; 36750276Speter } 36862449Speter } 36962449Speter if (!found) 37062449Speter err("unknown baud rate %s", rate); 37162449Speter return (sp->speed); 37250276Speter} 37350276Speter 37450276Speter/* 37550276Speter * Syntax for -m: 37650276Speter * [port-type][test baudrate]:terminal-type 37750276Speter * The baud rate tests are: >, <, @, =, ! 37850276Speter */ 37950276Speterstatic void 38050276Speteradd_mapping(const char *port, char *arg) 38150276Speter{ 38262449Speter MAP *mapp; 38362449Speter char *copy, *p; 38462449Speter const char *termp; 38562449Speter char *base = 0; 38650276Speter 38762449Speter copy = strdup(arg); 388166124Srafan mapp = (MAP *) malloc(sizeof(MAP)); 38962449Speter if (copy == 0 || mapp == 0) 39062449Speter failed("malloc"); 39162449Speter mapp->next = 0; 39262449Speter if (maplist == 0) 39362449Speter cur = maplist = mapp; 39462449Speter else { 39562449Speter cur->next = mapp; 39662449Speter cur = mapp; 39762449Speter } 39850276Speter 39962449Speter mapp->porttype = arg; 40062449Speter mapp->conditional = 0; 40150276Speter 40262449Speter arg = strpbrk(arg, "><@=!:"); 40350276Speter 40462449Speter if (arg == 0) { /* [?]term */ 40562449Speter mapp->type = mapp->porttype; 40662449Speter mapp->porttype = 0; 40762449Speter goto done; 40862449Speter } 40950276Speter 41062449Speter if (arg == mapp->porttype) /* [><@=! baud]:term */ 41162449Speter termp = mapp->porttype = 0; 41262449Speter else 41362449Speter termp = base = arg; 41450276Speter 41562449Speter for (;; ++arg) { /* Optional conditionals. */ 41662449Speter switch (*arg) { 41762449Speter case '<': 41862449Speter if (mapp->conditional & GT) 41962449Speter goto badmopt; 42062449Speter mapp->conditional |= LT; 42162449Speter break; 42262449Speter case '>': 42362449Speter if (mapp->conditional & LT) 42462449Speter goto badmopt; 42562449Speter mapp->conditional |= GT; 42662449Speter break; 42762449Speter case '@': 42862449Speter case '=': /* Not documented. */ 42962449Speter mapp->conditional |= EQ; 43062449Speter break; 43162449Speter case '!': 43262449Speter mapp->conditional |= NOT; 43362449Speter break; 43462449Speter default: 43562449Speter goto next; 43650276Speter } 43762449Speter } 43850276Speter 43962449Speter next: 44062449Speter if (*arg == ':') { 44162449Speter if (mapp->conditional) 44262449Speter goto badmopt; 44362449Speter ++arg; 44462449Speter } else { /* Optional baudrate. */ 44562449Speter arg = strchr(p = arg, ':'); 44662449Speter if (arg == 0) 44762449Speter goto badmopt; 44862449Speter *arg++ = '\0'; 44962449Speter mapp->speed = tbaudrate(p); 45062449Speter } 45150276Speter 45262449Speter if (arg == (char *) 0) /* Non-optional type. */ 45362449Speter goto badmopt; 45450276Speter 45562449Speter mapp->type = arg; 45650276Speter 45762449Speter /* Terminate porttype, if specified. */ 45862449Speter if (termp != 0) 45962449Speter *base = '\0'; 46050276Speter 46162449Speter /* If a NOT conditional, reverse the test. */ 46262449Speter if (mapp->conditional & NOT) 46362449Speter mapp->conditional = ~mapp->conditional & (EQ | GT | LT); 46450276Speter 46562449Speter /* If user specified a port with an option flag, set it. */ 466184989Srafan done: 467184989Srafan if (port) { 468184989Srafan if (mapp->porttype) { 469184989Srafan badmopt: 470184989Srafan err("illegal -m option format: %s", copy); 471184989Srafan } 47262449Speter mapp->porttype = port; 47362449Speter } 474184989Srafan free(copy); 47550276Speter#ifdef MAPDEBUG 47662449Speter (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY"); 47762449Speter (void) printf("type: %s\n", mapp->type); 47862449Speter (void) printf("conditional: "); 47962449Speter p = ""; 48062449Speter if (mapp->conditional & GT) { 48162449Speter (void) printf("GT"); 48262449Speter p = "/"; 48362449Speter } 48462449Speter if (mapp->conditional & EQ) { 48562449Speter (void) printf("%sEQ", p); 48662449Speter p = "/"; 48762449Speter } 48862449Speter if (mapp->conditional & LT) 48962449Speter (void) printf("%sLT", p); 49062449Speter (void) printf("\nspeed: %d\n", mapp->speed); 49150276Speter#endif 49250276Speter} 49350276Speter 49450276Speter/* 49550276Speter * Return the type of terminal to use for a port of type 'type', as specified 49650276Speter * by the first applicable mapping in 'map'. If no mappings apply, return 49750276Speter * 'type'. 49850276Speter */ 49950276Speterstatic const char * 50050276Spetermapped(const char *type) 50150276Speter{ 50262449Speter MAP *mapp; 50362449Speter int match; 50450276Speter 50562449Speter for (mapp = maplist; mapp; mapp = mapp->next) 50662449Speter if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) { 50762449Speter switch (mapp->conditional) { 50862449Speter case 0: /* No test specified. */ 50962449Speter match = TRUE; 51062449Speter break; 51162449Speter case EQ: 51262449Speter match = (ospeed == mapp->speed); 51362449Speter break; 51462449Speter case GE: 51562449Speter match = (ospeed >= mapp->speed); 51662449Speter break; 51762449Speter case GT: 51862449Speter match = (ospeed > mapp->speed); 51962449Speter break; 52062449Speter case LE: 52162449Speter match = (ospeed <= mapp->speed); 52262449Speter break; 52362449Speter case LT: 52462449Speter match = (ospeed < mapp->speed); 52562449Speter break; 52662449Speter default: 52762449Speter match = FALSE; 52862449Speter } 52962449Speter if (match) 53062449Speter return (mapp->type); 53162449Speter } 53262449Speter /* No match found; return given type. */ 53362449Speter return (type); 53450276Speter} 53550276Speter 53650276Speter/************************************************************************** 53750276Speter * 53850276Speter * Entry fetching 53950276Speter * 54050276Speter **************************************************************************/ 54150276Speter 54250276Speter/* 54350276Speter * Figure out what kind of terminal we're dealing with, and then read in 54450276Speter * its termcap entry. 54550276Speter */ 54650276Speterstatic const char * 54750276Speterget_termcap_entry(char *userarg) 54850276Speter{ 54976726Speter int errret; 55062449Speter char *p; 55162449Speter const char *ttype; 55250276Speter#if HAVE_GETTTYNAM 55362449Speter struct ttyent *t; 55450276Speter#else 55562449Speter FILE *fp; 55650276Speter#endif 55762449Speter char *ttypath; 55850276Speter 55962449Speter if (userarg) { 56062449Speter ttype = userarg; 56162449Speter goto found; 56262449Speter } 56350276Speter 56462449Speter /* Try the environment. */ 56562449Speter if ((ttype = getenv("TERM")) != 0) 56662449Speter goto map; 56750276Speter 56862449Speter if ((ttypath = ttyname(STDERR_FILENO)) != 0) { 56966963Speter p = _nc_basename(ttypath); 57050276Speter#if HAVE_GETTTYNAM 57162449Speter /* 57262449Speter * We have the 4.3BSD library call getttynam(3); that means 57362449Speter * there's an /etc/ttys to look up device-to-type mappings in. 57462449Speter * Try ttyname(3); check for dialup or other mapping. 57562449Speter */ 57662449Speter if ((t = getttynam(p))) { 57762449Speter ttype = t->ty_type; 57862449Speter goto map; 57962449Speter } 58050276Speter#else 58162449Speter if ((fp = fopen("/etc/ttytype", "r")) != 0 58262449Speter || (fp = fopen("/etc/ttys", "r")) != 0) { 58362449Speter char buffer[BUFSIZ]; 58462449Speter char *s, *t, *d; 58550276Speter 58662449Speter while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) { 58762449Speter for (s = buffer, t = d = 0; *s; s++) { 58897049Speter if (isspace(UChar(*s))) 58962449Speter *s = '\0'; 59062449Speter else if (t == 0) 59162449Speter t = s; 59262449Speter else if (d == 0 && s != buffer && s[-1] == '\0') 59362449Speter d = s; 59450276Speter } 59562449Speter if (t != 0 && d != 0 && !strcmp(d, p)) { 59662449Speter ttype = strdup(t); 59762449Speter fclose(fp); 59862449Speter goto map; 59962449Speter } 60062449Speter } 60162449Speter fclose(fp); 60262449Speter } 60350276Speter#endif /* HAVE_GETTTYNAM */ 60462449Speter } 60550276Speter 60662449Speter /* If still undefined, use "unknown". */ 60762449Speter ttype = "unknown"; 60850276Speter 60962449Speter map:ttype = mapped(ttype); 61050276Speter 61162449Speter /* 61262449Speter * If not a path, remove TERMCAP from the environment so we get a 61362449Speter * real entry from /etc/termcap. This prevents us from being fooled 61462449Speter * by out of date stuff in the environment. 61562449Speter */ 616166124Srafan found:if ((p = getenv("TERMCAP")) != 0 && !_nc_is_abs_path(p)) { 61762449Speter /* 'unsetenv("TERMCAP")' is not portable. 61862449Speter * The 'environ' array is better. 61950276Speter */ 62062449Speter int n; 62162449Speter for (n = 0; environ[n] != 0; n++) { 62262449Speter if (!strncmp("TERMCAP=", environ[n], 8)) { 62362449Speter while ((environ[n] = environ[n + 1]) != 0) { 62462449Speter n++; 62550276Speter } 62662449Speter break; 62762449Speter } 62850276Speter } 62962449Speter } 63050276Speter 63162449Speter /* 63262449Speter * ttype now contains a pointer to the type of the terminal. 63362449Speter * If the first character is '?', ask the user. 63462449Speter */ 63562449Speter if (ttype[0] == '?') { 63662449Speter if (ttype[1] != '\0') 63762449Speter ttype = askuser(ttype + 1); 63862449Speter else 63962449Speter ttype = askuser(0); 64062449Speter } 64162449Speter /* Find the terminfo entry. If it doesn't exist, ask the user. */ 64276726Speter while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret) 64376726Speter != OK) { 64462449Speter if (errret == 0) { 645166124Srafan (void) fprintf(stderr, "%s: unknown terminal type %s\n", 646166124Srafan _nc_progname, ttype); 64762449Speter ttype = 0; 64862449Speter } else { 64962449Speter (void) fprintf(stderr, 650166124Srafan "%s: can't initialize terminal type %s (error %d)\n", 651166124Srafan _nc_progname, ttype, errret); 65262449Speter ttype = 0; 65350276Speter } 65462449Speter ttype = askuser(ttype); 65562449Speter } 65650276Speter#if BROKEN_LINKER 65762449Speter tgetflag("am"); /* force lib_termcap.o to be linked for 'ospeed' */ 65850276Speter#endif 65962449Speter return (ttype); 66050276Speter} 66150276Speter 66250276Speter/************************************************************************** 66350276Speter * 66450276Speter * Mode-setting logic 66550276Speter * 66650276Speter **************************************************************************/ 66750276Speter 66850276Speter/* some BSD systems have these built in, some systems are missing 669166124Srafan * one or more definitions. The safest solution is to override unless the 670166124Srafan * commonly-altered ones are defined. 67150276Speter */ 672166124Srafan#if !(defined(CERASE) && defined(CINTR) && defined(CKILL) && defined(CQUIT)) 67350276Speter#undef CEOF 67450276Speter#undef CERASE 67550276Speter#undef CINTR 67650276Speter#undef CKILL 67750276Speter#undef CLNEXT 67850276Speter#undef CRPRNT 67950276Speter#undef CQUIT 68050276Speter#undef CSTART 68150276Speter#undef CSTOP 68250276Speter#undef CSUSP 683166124Srafan#endif 68450276Speter 68550276Speter/* control-character defaults */ 686166124Srafan#ifndef CEOF 68750276Speter#define CEOF CTRL('D') 688166124Srafan#endif 689166124Srafan#ifndef CERASE 69050276Speter#define CERASE CTRL('H') 691166124Srafan#endif 692166124Srafan#ifndef CINTR 69350276Speter#define CINTR 127 /* ^? */ 694166124Srafan#endif 695166124Srafan#ifndef CKILL 69650276Speter#define CKILL CTRL('U') 697166124Srafan#endif 698166124Srafan#ifndef CLNEXT 69950276Speter#define CLNEXT CTRL('v') 700166124Srafan#endif 701166124Srafan#ifndef CRPRNT 70250276Speter#define CRPRNT CTRL('r') 703166124Srafan#endif 704166124Srafan#ifndef CQUIT 70550276Speter#define CQUIT CTRL('\\') 706166124Srafan#endif 707166124Srafan#ifndef CSTART 70850276Speter#define CSTART CTRL('Q') 709166124Srafan#endif 710166124Srafan#ifndef CSTOP 71150276Speter#define CSTOP CTRL('S') 712166124Srafan#endif 713166124Srafan#ifndef CSUSP 71450276Speter#define CSUSP CTRL('Z') 715166124Srafan#endif 71650276Speter 717166124Srafan#if defined(_POSIX_VDISABLE) 718166124Srafan#define DISABLED(val) (((_POSIX_VDISABLE != -1) \ 719166124Srafan && ((val) == _POSIX_VDISABLE)) \ 720166124Srafan || ((val) <= 0)) 721166124Srafan#else 722166124Srafan#define DISABLED(val) ((int)(val) <= 0) 723166124Srafan#endif 72450276Speter 725166124Srafan#define CHK(val, dft) (DISABLED(val) ? dft : val) 726166124Srafan 72762449Speterstatic bool set_tabs(void); 72850276Speter 72950276Speter/* 73050276Speter * Reset the terminal mode bits to a sensible state. Very useful after 73150276Speter * a child program dies in raw mode. 73250276Speter */ 73350276Speterstatic void 73450276Speterreset_mode(void) 73550276Speter{ 73650276Speter#ifdef TERMIOS 73762449Speter tcgetattr(STDERR_FILENO, &mode); 73850276Speter#else 73962449Speter stty(STDERR_FILENO, &mode); 74050276Speter#endif 74150276Speter 74250276Speter#ifdef TERMIOS 74350276Speter#if defined(VDISCARD) && defined(CDISCARD) 74462449Speter mode.c_cc[VDISCARD] = CHK(mode.c_cc[VDISCARD], CDISCARD); 74550276Speter#endif 74662449Speter mode.c_cc[VEOF] = CHK(mode.c_cc[VEOF], CEOF); 74762449Speter mode.c_cc[VERASE] = CHK(mode.c_cc[VERASE], CERASE); 74850276Speter#if defined(VFLUSH) && defined(CFLUSH) 74962449Speter mode.c_cc[VFLUSH] = CHK(mode.c_cc[VFLUSH], CFLUSH); 75050276Speter#endif 75162449Speter mode.c_cc[VINTR] = CHK(mode.c_cc[VINTR], CINTR); 75262449Speter mode.c_cc[VKILL] = CHK(mode.c_cc[VKILL], CKILL); 75350276Speter#if defined(VLNEXT) && defined(CLNEXT) 75462449Speter mode.c_cc[VLNEXT] = CHK(mode.c_cc[VLNEXT], CLNEXT); 75550276Speter#endif 75662449Speter mode.c_cc[VQUIT] = CHK(mode.c_cc[VQUIT], CQUIT); 75750276Speter#if defined(VREPRINT) && defined(CRPRNT) 75862449Speter mode.c_cc[VREPRINT] = CHK(mode.c_cc[VREPRINT], CRPRNT); 75950276Speter#endif 76050276Speter#if defined(VSTART) && defined(CSTART) 76162449Speter mode.c_cc[VSTART] = CHK(mode.c_cc[VSTART], CSTART); 76250276Speter#endif 76350276Speter#if defined(VSTOP) && defined(CSTOP) 76462449Speter mode.c_cc[VSTOP] = CHK(mode.c_cc[VSTOP], CSTOP); 76550276Speter#endif 76650276Speter#if defined(VSUSP) && defined(CSUSP) 76762449Speter mode.c_cc[VSUSP] = CHK(mode.c_cc[VSUSP], CSUSP); 76850276Speter#endif 76950276Speter#if defined(VWERASE) && defined(CWERASE) 77062449Speter mode.c_cc[VWERASE] = CHK(mode.c_cc[VWERASE], CWERASE); 77150276Speter#endif 77250276Speter 77362449Speter mode.c_iflag &= ~(IGNBRK | PARMRK | INPCK | ISTRIP | INLCR | IGNCR 77450276Speter#ifdef IUCLC 77566963Speter | IUCLC 77650276Speter#endif 77750276Speter#ifdef IXANY 77866963Speter | IXANY 77950276Speter#endif 78066963Speter | IXOFF); 78150276Speter 78262449Speter mode.c_iflag |= (BRKINT | IGNPAR | ICRNL | IXON 78350276Speter#ifdef IMAXBEL 78466963Speter | IMAXBEL 78550276Speter#endif 78662449Speter ); 78750276Speter 78862449Speter mode.c_oflag &= ~(0 78950276Speter#ifdef OLCUC 79066963Speter | OLCUC 79150276Speter#endif 79250276Speter#ifdef OCRNL 79366963Speter | OCRNL 79450276Speter#endif 79550276Speter#ifdef ONOCR 79666963Speter | ONOCR 79750276Speter#endif 79850276Speter#ifdef ONLRET 79966963Speter | ONLRET 80050276Speter#endif 80150276Speter#ifdef OFILL 80266963Speter | OFILL 80350276Speter#endif 80450276Speter#ifdef OFDEL 80566963Speter | OFDEL 80650276Speter#endif 80750276Speter#ifdef NLDLY 808174993Srafan | NLDLY 80950276Speter#endif 810184989Srafan#ifdef CRDLY 811174993Srafan | CRDLY 812174993Srafan#endif 813184989Srafan#ifdef TABDLY 814174993Srafan | TABDLY 815174993Srafan#endif 816184989Srafan#ifdef BSDLY 817174993Srafan | BSDLY 818174993Srafan#endif 819184989Srafan#ifdef VTDLY 820174993Srafan | VTDLY 821174993Srafan#endif 822174993Srafan#ifdef FFDLY 823174993Srafan | FFDLY 824174993Srafan#endif 82562449Speter ); 82650276Speter 82762449Speter mode.c_oflag |= (OPOST 82850276Speter#ifdef ONLCR 82966963Speter | ONLCR 83050276Speter#endif 83162449Speter ); 83250276Speter 83362449Speter mode.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD | CLOCAL); 83462449Speter mode.c_cflag |= (CS8 | CREAD); 83562449Speter mode.c_lflag &= ~(ECHONL | NOFLSH 83650276Speter#ifdef TOSTOP 83766963Speter | TOSTOP 83850276Speter#endif 83950276Speter#ifdef ECHOPTR 84066963Speter | ECHOPRT 84150276Speter#endif 84250276Speter#ifdef XCASE 84366963Speter | XCASE 84450276Speter#endif 84562449Speter ); 84650276Speter 84762449Speter mode.c_lflag |= (ISIG | ICANON | ECHO | ECHOE | ECHOK 84850276Speter#ifdef ECHOCTL 84966963Speter | ECHOCTL 85050276Speter#endif 85150276Speter#ifdef ECHOKE 85266963Speter | ECHOKE 85350276Speter#endif 85462449Speter ); 85550276Speter#endif 85650276Speter 85797049Speter SET_TTY(STDERR_FILENO, &mode); 85850276Speter} 85950276Speter 86050276Speter/* 86150276Speter * Returns a "good" value for the erase character. This is loosely based on 86250276Speter * the BSD4.4 logic. 86350276Speter */ 86466963Speter#ifdef TERMIOS 86550276Speterstatic int 86650276Speterdefault_erase(void) 86750276Speter{ 86862449Speter int result; 86950276Speter 87062449Speter if (over_strike 87162449Speter && key_backspace != 0 87262449Speter && strlen(key_backspace) == 1) 87362449Speter result = key_backspace[0]; 87462449Speter else 87562449Speter result = CERASE; 87650276Speter 87762449Speter return result; 87850276Speter} 87966963Speter#endif 88050276Speter 88150276Speter/* 88250276Speter * Update the values of the erase, interrupt, and kill characters in 'mode'. 88350276Speter * 88450276Speter * SVr4 tset (e.g., Solaris 2.5) only modifies the intr, quit or erase 88550276Speter * characters if they're unset, or if we specify them as options. This differs 88650276Speter * from BSD 4.4 tset, which always sets erase. 88750276Speter */ 88850276Speterstatic void 88950276Speterset_control_chars(void) 89050276Speter{ 89150276Speter#ifdef TERMIOS 892166124Srafan if (DISABLED(mode.c_cc[VERASE]) || terasechar >= 0) 893184989Srafan mode.c_cc[VERASE] = (terasechar >= 0) ? terasechar : default_erase(); 89450276Speter 895166124Srafan if (DISABLED(mode.c_cc[VINTR]) || intrchar >= 0) 896184989Srafan mode.c_cc[VINTR] = (intrchar >= 0) ? intrchar : CINTR; 89750276Speter 898166124Srafan if (DISABLED(mode.c_cc[VKILL]) || tkillchar >= 0) 899184989Srafan mode.c_cc[VKILL] = (tkillchar >= 0) ? tkillchar : CKILL; 90050276Speter#endif 90150276Speter} 90250276Speter 90350276Speter/* 90450276Speter * Set up various conversions in 'mode', including parity, tabs, returns, 90550276Speter * echo, and case, according to the termcap entry. If the program we're 90650276Speter * running was named with a leading upper-case character, map external 90750276Speter * uppercase to internal lowercase. 90850276Speter */ 90950276Speterstatic void 91050276Speterset_conversions(void) 91150276Speter{ 91250276Speter#ifdef __OBSOLETE__ 91362449Speter /* 91462449Speter * Conversion logic for some *really* ancient terminal glitches, 91562449Speter * not supported in terminfo. Left here for succeeding generations 91662449Speter * to marvel at. 91762449Speter */ 91862449Speter if (tgetflag("UC")) { 91950276Speter#ifdef IUCLC 92062449Speter mode.c_iflag |= IUCLC; 92162449Speter mode.c_oflag |= OLCUC; 92250276Speter#endif 92362449Speter } else if (tgetflag("LC")) { 92450276Speter#ifdef IUCLC 92562449Speter mode.c_iflag &= ~IUCLC; 92662449Speter mode.c_oflag &= ~OLCUC; 92750276Speter#endif 92862449Speter } 92962449Speter mode.c_iflag &= ~(PARMRK | INPCK); 93062449Speter mode.c_lflag |= ICANON; 93162449Speter if (tgetflag("EP")) { 93262449Speter mode.c_cflag |= PARENB; 93362449Speter mode.c_cflag &= ~PARODD; 93462449Speter } 93562449Speter if (tgetflag("OP")) { 93662449Speter mode.c_cflag |= PARENB; 93762449Speter mode.c_cflag |= PARODD; 93862449Speter } 93950276Speter#endif /* __OBSOLETE__ */ 94050276Speter 94150276Speter#ifdef TERMIOS 94250276Speter#ifdef ONLCR 94362449Speter mode.c_oflag |= ONLCR; 94450276Speter#endif 94562449Speter mode.c_iflag |= ICRNL; 94662449Speter mode.c_lflag |= ECHO; 94750276Speter#ifdef OXTABS 94862449Speter mode.c_oflag |= OXTABS; 94950276Speter#endif /* OXTABS */ 95050276Speter 95162449Speter /* test used to be tgetflag("NL") */ 95262449Speter if (newline != (char *) 0 && newline[0] == '\n' && !newline[1]) { 95362449Speter /* Newline, not linefeed. */ 95450276Speter#ifdef ONLCR 95562449Speter mode.c_oflag &= ~ONLCR; 95650276Speter#endif 95762449Speter mode.c_iflag &= ~ICRNL; 95862449Speter } 95950276Speter#ifdef __OBSOLETE__ 96062449Speter if (tgetflag("HD")) /* Half duplex. */ 96162449Speter mode.c_lflag &= ~ECHO; 96250276Speter#endif /* __OBSOLETE__ */ 96350276Speter#ifdef OXTABS 96462449Speter /* test used to be tgetflag("pt") */ 96562449Speter if (has_hardware_tabs) /* Print tabs. */ 96662449Speter mode.c_oflag &= ~OXTABS; 96750276Speter#endif /* OXTABS */ 96862449Speter mode.c_lflag |= (ECHOE | ECHOK); 96950276Speter#endif 97050276Speter} 97150276Speter 97250276Speter/* Output startup string. */ 97350276Speterstatic void 97450276Speterset_init(void) 97550276Speter{ 97662449Speter char *p; 97762449Speter bool settle; 97850276Speter 97950276Speter#ifdef __OBSOLETE__ 98062449Speter if (pad_char != (char *) 0) /* Get/set pad character. */ 98162449Speter PC = pad_char[0]; 98250276Speter#endif /* OBSOLETE */ 98350276Speter 98450276Speter#ifdef TAB3 98562449Speter if (oldmode.c_oflag & (TAB3 | ONLCR | OCRNL | ONLRET)) { 98662449Speter oldmode.c_oflag &= (TAB3 | ONLCR | OCRNL | ONLRET); 98797049Speter SET_TTY(STDERR_FILENO, &oldmode); 98862449Speter } 98950276Speter#endif 99062449Speter settle = set_tabs(); 99150276Speter 99262449Speter if (isreset) { 99362449Speter if ((p = reset_1string) != 0) { 99462449Speter tputs(p, 0, outc); 99562449Speter settle = TRUE; 99650276Speter } 99762449Speter if ((p = reset_2string) != 0) { 99862449Speter tputs(p, 0, outc); 99962449Speter settle = TRUE; 100062449Speter } 100162449Speter /* What about rf, rs3, as per terminfo man page? */ 100262449Speter /* also might be nice to send rmacs, rmul, rmm */ 100362449Speter if ((p = reset_file) != 0 100462449Speter || (p = init_file) != 0) { 100562449Speter cat(p); 100662449Speter settle = TRUE; 100762449Speter } 100862449Speter } 100950276Speter 101062449Speter if (settle) { 101162449Speter (void) putc('\r', stderr); 101262449Speter (void) fflush(stderr); 101362449Speter (void) napms(1000); /* Settle the terminal. */ 101462449Speter } 101550276Speter} 101650276Speter 101750276Speter/* 101850276Speter * Set the hardware tabs on the terminal, using the ct (clear all tabs), 101950276Speter * st (set one tab) and ch (horizontal cursor addressing) capabilities. 102050276Speter * This is done before if and is, so they can patch in case we blow this. 102150276Speter * Return TRUE if we set any tab stops, FALSE if not. 102250276Speter */ 102350276Speterstatic bool 1024166124Srafanset_tabs(void) 102550276Speter{ 102662449Speter if (set_tab && clear_all_tabs) { 102762449Speter int c; 102850276Speter 102962449Speter (void) putc('\r', stderr); /* Force to left margin. */ 103062449Speter tputs(clear_all_tabs, 0, outc); 103150276Speter 103262449Speter for (c = 8; c < tcolumns; c += 8) { 103362449Speter /* Get to the right column. In BSD tset, this 103462449Speter * used to try a bunch of half-clever things 103562449Speter * with cup and hpa, for an average saving of 103662449Speter * somewhat less than two character times per 1037166124Srafan * tab stop, less than .01 sec at 2400cps. We 103862449Speter * lost all this cruft because it seemed to be 103962449Speter * introducing some odd bugs. 1040166124Srafan * -----------12345678----------- */ 104162449Speter (void) fputs(" ", stderr); 104262449Speter tputs(set_tab, 0, outc); 104350276Speter } 104462449Speter putc('\r', stderr); 104562449Speter return (TRUE); 104662449Speter } 104762449Speter return (FALSE); 104850276Speter} 104950276Speter 105050276Speter/************************************************************************** 105150276Speter * 105250276Speter * Main sequence 105350276Speter * 105450276Speter **************************************************************************/ 105550276Speter 105650276Speter/* 105750276Speter * Tell the user if a control key has been changed from the default value. 105850276Speter */ 105966963Speter#ifdef TERMIOS 106050276Speterstatic void 106150276Speterreport(const char *name, int which, unsigned def) 106250276Speter{ 106362449Speter unsigned older, newer; 106462449Speter char *p; 106550276Speter 106662449Speter newer = mode.c_cc[which]; 106762449Speter older = oldmode.c_cc[which]; 106850276Speter 106962449Speter if (older == newer && older == def) 107062449Speter return; 107150276Speter 107262449Speter (void) fprintf(stderr, "%s %s ", name, older == newer ? "is" : "set to"); 107350276Speter 1074166124Srafan if (DISABLED(newer)) 1075166124Srafan (void) fprintf(stderr, "undef.\n"); 107662449Speter /* 107762449Speter * Check 'delete' before 'backspace', since the key_backspace value 107862449Speter * is ambiguous. 107962449Speter */ 1080166124Srafan else if (newer == 0177) 108162449Speter (void) fprintf(stderr, "delete.\n"); 108262449Speter else if ((p = key_backspace) != 0 108366963Speter && newer == (unsigned char) p[0] 108466963Speter && p[1] == '\0') 108562449Speter (void) fprintf(stderr, "backspace.\n"); 108662449Speter else if (newer < 040) { 108762449Speter newer ^= 0100; 1088166124Srafan (void) fprintf(stderr, "control-%c (^%c).\n", UChar(newer), UChar(newer)); 108962449Speter } else 1090166124Srafan (void) fprintf(stderr, "%c.\n", UChar(newer)); 109166963Speter} 109250276Speter#endif 109350276Speter 109450276Speter/* 109550276Speter * Convert the obsolete argument forms into something that getopt can handle. 109650276Speter * This means that -e, -i and -k get default arguments supplied for them. 109750276Speter */ 109850276Speterstatic void 109950276Speterobsolete(char **argv) 110050276Speter{ 110162449Speter for (; *argv; ++argv) { 110262449Speter char *parm = argv[0]; 110350276Speter 110462449Speter if (parm[0] == '-' && parm[1] == '\0') { 110562449Speter argv[0] = strdup("-q"); 110662449Speter continue; 110762449Speter } 110850276Speter 110962449Speter if ((parm[0] != '-') 111062449Speter || (argv[1] && argv[1][0] != '-') 111162449Speter || (parm[1] != 'e' && parm[1] != 'i' && parm[1] != 'k') 111262449Speter || (parm[2] != '\0')) 111362449Speter continue; 111462449Speter switch (argv[0][1]) { 111562449Speter case 'e': 111662449Speter argv[0] = strdup("-e^H"); 111762449Speter break; 111862449Speter case 'i': 111962449Speter argv[0] = strdup("-i^C"); 112062449Speter break; 112162449Speter case 'k': 112262449Speter argv[0] = strdup("-k^U"); 112362449Speter break; 112450276Speter } 112562449Speter } 112650276Speter} 112750276Speter 112850276Speterstatic void 1129166124Srafanusage(void) 113050276Speter{ 1131166124Srafan static const char *tbl[] = 1132166124Srafan { 1133166124Srafan "" 1134166124Srafan ,"Options:" 1135166124Srafan ," -c set control characters" 1136166124Srafan ," -e ch erase character" 1137166124Srafan ," -I no initialization strings" 1138166124Srafan ," -i ch interrupt character" 1139166124Srafan ," -k ch kill character" 1140166124Srafan ," -m mapping map identifier to type" 1141166124Srafan ," -Q do not output control key settings" 1142166124Srafan ," -r display term on stderr" 1143166124Srafan ," -s output TERM set command" 1144166124Srafan ," -V print curses-version" 1145166124Srafan ," -w set window-size" 1146166124Srafan }; 1147166124Srafan unsigned n; 1148166124Srafan (void) fprintf(stderr, "Usage: %s [options] [terminal]\n", _nc_progname); 1149166124Srafan for (n = 0; n < sizeof(tbl) / sizeof(tbl[0]); ++n) 1150166124Srafan fprintf(stderr, "%s\n", tbl[n]); 115197049Speter exit_error(); 115297049Speter /* NOTREACHED */ 115350276Speter} 115450276Speter 115562449Speterstatic char 115662449Speterarg_to_char(void) 115750276Speter{ 1158184989Srafan return (char) ((optarg[0] == '^' && optarg[1] != '\0') 1159184989Srafan ? ((optarg[1] == '?') ? '\177' : CTRL(optarg[1])) 1160184989Srafan : optarg[0]); 116150276Speter} 116250276Speter 116350276Speterint 116450276Spetermain(int argc, char **argv) 116550276Speter{ 116662449Speter int ch, noinit, noset, quiet, Sflag, sflag, showterm; 116762449Speter const char *p; 116862449Speter const char *ttype; 116950276Speter 117062449Speter obsolete(argv); 117162449Speter noinit = noset = quiet = Sflag = sflag = showterm = 0; 1172174993Srafan while ((ch = getopt(argc, argv, "a:cd:e:Ii:k:m:np:qQSrsVw")) != -1) { 117362449Speter switch (ch) { 1174166124Srafan case 'c': /* set control-chars */ 1175166124Srafan opt_c = TRUE; 117662449Speter break; 117762449Speter case 'a': /* OBSOLETE: map identifier to type */ 117862449Speter add_mapping("arpanet", optarg); 117962449Speter break; 118062449Speter case 'd': /* OBSOLETE: map identifier to type */ 118162449Speter add_mapping("dialup", optarg); 118262449Speter break; 118362449Speter case 'e': /* erase character */ 118462449Speter terasechar = arg_to_char(); 118562449Speter break; 118662449Speter case 'I': /* no initialization strings */ 118762449Speter noinit = 1; 118862449Speter break; 118962449Speter case 'i': /* interrupt character */ 119062449Speter intrchar = arg_to_char(); 119162449Speter break; 119262449Speter case 'k': /* kill character */ 119362449Speter tkillchar = arg_to_char(); 119462449Speter break; 119562449Speter case 'm': /* map identifier to type */ 119662449Speter add_mapping(0, optarg); 119762449Speter break; 119862449Speter case 'n': /* OBSOLETE: set new tty driver */ 119962449Speter break; 120062449Speter case 'p': /* OBSOLETE: map identifier to type */ 120162449Speter add_mapping("plugboard", optarg); 120262449Speter break; 120362449Speter case 'Q': /* don't output control key settings */ 120462449Speter quiet = 1; 120562449Speter break; 1206166124Srafan case 'q': /* display term only */ 1207166124Srafan noset = 1; 120862449Speter break; 120962449Speter case 'r': /* display term on stderr */ 121062449Speter showterm = 1; 121162449Speter break; 1212166124Srafan case 'S': /* OBSOLETE: output TERM & TERMCAP */ 1213166124Srafan Sflag = 1; 1214166124Srafan break; 121562449Speter case 's': /* output TERM set command */ 121662449Speter sflag = 1; 121762449Speter break; 1218166124Srafan case 'V': /* print curses-version */ 121966963Speter puts(curses_version()); 1220166124Srafan ExitProgram(EXIT_SUCCESS); 1221166124Srafan case 'w': /* set window-size */ 1222166124Srafan opt_w = TRUE; 1223166124Srafan break; 122462449Speter case '?': 122562449Speter default: 1226166124Srafan usage(); 122750276Speter } 122862449Speter } 1229166124Srafan 1230166124Srafan _nc_progname = _nc_rootname(*argv); 123162449Speter argc -= optind; 123262449Speter argv += optind; 123350276Speter 123462449Speter if (argc > 1) 1235166124Srafan usage(); 123650276Speter 1237166124Srafan if (!opt_c && !opt_w) 1238166124Srafan opt_c = opt_w = TRUE; 1239166124Srafan 1240166124Srafan if (GET_TTY(STDERR_FILENO, &mode) < 0) 1241166124Srafan failed("standard error"); 1242166124Srafan can_restore = TRUE; 1243166124Srafan original = oldmode = mode; 1244166124Srafan#ifdef TERMIOS 1245184989Srafan ospeed = (NCURSES_OSPEED) cfgetospeed(&mode); 1246166124Srafan#else 1247184989Srafan ospeed = (NCURSES_OSPEED) mode.sg_ospeed; 1248166124Srafan#endif 1249166124Srafan 1250166124Srafan if (!strcmp(_nc_progname, PROG_RESET)) { 1251166124Srafan isreset = TRUE; 1252166124Srafan reset_mode(); 1253166124Srafan } 1254166124Srafan 125562449Speter ttype = get_termcap_entry(*argv); 125650276Speter 125762449Speter if (!noset) { 125862449Speter tcolumns = columns; 125962449Speter tlines = lines; 126050276Speter 1261184989Srafan#if HAVE_SIZECHANGE 1262166124Srafan if (opt_w) { 1263184989Srafan STRUCT_WINSIZE win; 1264184989Srafan /* Set window size if not set already */ 1265184989Srafan (void) ioctl(STDERR_FILENO, IOCTL_GET_WINSIZE, &win); 1266184989Srafan if (WINSIZE_ROWS(win) == 0 && 1267184989Srafan WINSIZE_COLS(win) == 0 && 1268166124Srafan tlines > 0 && tcolumns > 0) { 1269184989Srafan WINSIZE_ROWS(win) = tlines; 1270184989Srafan WINSIZE_COLS(win) = tcolumns; 1271184989Srafan (void) ioctl(STDERR_FILENO, IOCTL_SET_WINSIZE, &win); 1272166124Srafan } 127362449Speter } 127450276Speter#endif 1275166124Srafan if (opt_c) { 1276166124Srafan set_control_chars(); 1277166124Srafan set_conversions(); 127850276Speter 1279166124Srafan if (!noinit) 1280166124Srafan set_init(); 128150276Speter 1282166124Srafan /* Set the modes if they've changed. */ 1283166124Srafan if (memcmp(&mode, &oldmode, sizeof(mode))) { 1284166124Srafan SET_TTY(STDERR_FILENO, &mode); 1285166124Srafan } 128650276Speter } 128762449Speter } 128850276Speter 128962449Speter /* Get the terminal name from the entry. */ 129062449Speter ttype = _nc_first_name(cur_term->type.term_names); 129150276Speter 129262449Speter if (noset) 129362449Speter (void) printf("%s\n", ttype); 129462449Speter else { 129562449Speter if (showterm) 129662449Speter (void) fprintf(stderr, "Terminal type is %s.\n", ttype); 129762449Speter /* 129862449Speter * If erase, kill and interrupt characters could have been 129962449Speter * modified and not -Q, display the changes. 130062449Speter */ 130166963Speter#ifdef TERMIOS 130262449Speter if (!quiet) { 130362449Speter report("Erase", VERASE, CERASE); 1304166124Srafan report("Kill", VKILL, CKILL); 1305166124Srafan report("Interrupt", VINTR, CINTR); 130650276Speter } 130766963Speter#endif 130862449Speter } 130950276Speter 131062449Speter if (Sflag) 131162449Speter err("The -S option is not supported under terminfo."); 131250276Speter 131362449Speter if (sflag) { 1314166124Srafan int len; 1315166124Srafan char *var; 1316166124Srafan char *leaf; 131762449Speter /* 131862449Speter * Figure out what shell we're using. A hack, we look for an 131962449Speter * environmental variable SHELL ending in "csh". 132062449Speter */ 1321166124Srafan if ((var = getenv("SHELL")) != 0 1322184989Srafan && ((len = (int) strlen(leaf = _nc_basename(var))) >= 3) 1323166124Srafan && !strcmp(leaf + len - 3, "csh")) 132462449Speter p = "set noglob;\nsetenv TERM %s;\nunset noglob;\n"; 132562449Speter else 132662449Speter p = "TERM=%s;\n"; 132762449Speter (void) printf(p, ttype); 132862449Speter } 132950276Speter 1330166124Srafan ExitProgram(EXIT_SUCCESS); 133150276Speter} 1332