⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tset.c

📁 ncurses-5.4
💻 C
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************** * Copyright (c) 1998-2002,2003 Free Software Foundation, Inc.              * *                                                                          * * Permission is hereby granted, free of charge, to any person obtaining a  * * copy of this software and associated documentation files (the            * * "Software"), to deal in the Software without restriction, including      * * without limitation the rights to use, copy, modify, merge, publish,      * * distribute, distribute with modifications, sublicense, and/or sell       * * copies of the Software, and to permit persons to whom the Software is    * * furnished to do so, subject to the following conditions:                 * *                                                                          * * The above copyright notice and this permission notice shall be included  * * in all copies or substantial portions of the Software.                   * *                                                                          * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  * * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   * * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   * * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    * * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    * * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               * *                                                                          * * Except as contained in this notice, the name(s) of the above copyright   * * holders shall not be used in advertising or otherwise to promote the     * * sale, use or other dealings in this Software without prior written       * * authorization.                                                           * ****************************************************************************//**************************************************************************** *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               * *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         * ****************************************************************************//* * tset.c - terminal initialization utility * * This code was mostly swiped from 4.4BSD tset, with some obsolescent * cruft removed and substantial portions rewritten.  A Regents of the * University of California copyright applies to some portions of the * code, and is reproduced below: *//*- * Copyright (c) 1980, 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#define __INTERNAL_CAPS_VISIBLE	/* we need to see has_hardware_tabs */#include <progs.priv.h>#include <errno.h>#include <stdio.h>#include <termcap.h>#include <fcntl.h>#if HAVE_GETTTYNAM && HAVE_TTYENT_H#include <ttyent.h>#endif#ifdef NeXTchar *ttyname(int fd);#endif/* this is just to stifle a missing-prototype warning */#ifdef linux# include <sys/ioctl.h>#endif#if NEED_PTEM_H/* they neglected to define struct winsize in termios.h -- it's only   in termio.h	*/#include <sys/stream.h>#include <sys/ptem.h>#endif#include <curses.h>		/* for bool typedef */#include <dump_entry.h>#include <transform.h>MODULE_ID("$Id: tset.c,v 0.56 2003/12/06 17:21:01 tom Exp $")extern char **environ;#undef CTRL#define CTRL(x)	((x) & 0x1f)const char *_nc_progname = "tset";static TTY mode, oldmode, original;static bool can_restore = FALSE;static bool isreset = FALSE;	/* invoked as reset */static int terasechar = -1;	/* new erase character */static int intrchar = -1;	/* new interrupt character */static int tkillchar = -1;	/* new kill character */static int tlines, tcolumns;	/* window size */#define LOWERCASE(c) ((isalpha(UChar(c)) && isupper(UChar(c))) ? tolower(UChar(c)) : (c))static intCaselessCmp(const char *a, const char *b){				/* strcasecmp isn't portable */    while (*a && *b) {	int cmp = LOWERCASE(*a) - LOWERCASE(*b);	if (cmp != 0)	    break;	a++, b++;    }    return LOWERCASE(*a) - LOWERCASE(*b);}static voidexit_error(void){    if (can_restore)	SET_TTY(STDERR_FILENO, &original);    (void) fprintf(stderr, "\n");    fflush(stderr);    ExitProgram(EXIT_FAILURE);    /* NOTREACHED */}static voiderr(const char *fmt,...){    va_list ap;    va_start(ap, fmt);    (void) fprintf(stderr, "tset: ");    (void) vfprintf(stderr, fmt, ap);    va_end(ap);    exit_error();    /* NOTREACHED */}static voidfailed(const char *msg){    char temp[BUFSIZ];    perror(strncat(strcpy(temp, "tset: "), msg, sizeof(temp) - 10));    exit_error();    /* NOTREACHED */}static voidcat(char *file){    FILE *fp;    size_t nr;    char buf[BUFSIZ];    if ((fp = fopen(file, "r")) == 0)	failed(file);    while ((nr = fread(buf, sizeof(char), sizeof(buf), fp)) != 0)	if (fwrite(buf, sizeof(char), nr, stderr) != nr)	      failed("write to stderr");    fclose(fp);}static intoutc(int c){    return putc(c, stderr);}/* Prompt the user for a terminal type. */static const char *askuser(const char *dflt){    static char answer[256];    char *p;    /* We can get recalled; if so, don't continue uselessly. */    clearerr(stdin);    if (feof(stdin) || ferror(stdin)) {	(void) fprintf(stderr, "\n");	exit_error();	/* NOTREACHED */    }    for (;;) {	if (dflt)	    (void) fprintf(stderr, "Terminal type? [%s] ", dflt);	else	    (void) fprintf(stderr, "Terminal type? ");	(void) fflush(stderr);	if (fgets(answer, sizeof(answer), stdin) == 0) {	    if (dflt == 0) {		exit_error();		/* NOTREACHED */	    }	    return (dflt);	}	if ((p = strchr(answer, '\n')) != 0)	    *p = '\0';	if (answer[0])	    return (answer);	if (dflt != 0)	    return (dflt);    }}/************************************************************************** * * Mapping logic begins here * **************************************************************************//* Baud rate conditionals for mapping. */#define	GT		0x01#define	EQ		0x02#define	LT		0x04#define	NOT		0x08#define	GE		(GT | EQ)#define	LE		(LT | EQ)typedef struct map {    struct map *next;		/* Linked list of maps. */    const char *porttype;	/* Port type, or "" for any. */    const char *type;		/* Terminal type to select. */    int conditional;		/* Baud rate conditionals bitmask. */    int speed;			/* Baud rate to compare against. */} MAP;static MAP *cur, *maplist;typedef struct speeds {    const char *string;    int speed;} SPEEDS;static const SPEEDS speeds[] ={    {"0", B0},    {"50", B50},    {"75", B75},    {"110", B110},    {"134", B134},    {"134.5", B134},    {"150", B150},    {"200", B200},    {"300", B300},    {"600", B600},    {"1200", B1200},    {"1800", B1800},    {"2400", B2400},    {"4800", B4800},    {"9600", B9600},    /* sgttyb may define up to this point */#ifdef B19200    {"19200", B19200},#endif#ifdef B38400    {"38400", B38400},#endif#ifdef B19200    {"19200", B19200},#endif#ifdef B38400    {"38400", B38400},#endif#ifdef B19200    {"19200", B19200},#else#ifdef EXTA    {"19200", EXTA},#endif#endif#ifdef B38400    {"38400", B38400},#else#ifdef EXTB    {"38400", EXTB},#endif#endif#ifdef B57600    {"57600", B57600},#endif#ifdef B115200    {"115200", B115200},#endif#ifdef B230400    {"230400", B230400},#endif#ifdef B460800    {"460800", B460800},#endif    {(char *) 0, 0}};static inttbaudrate(char *rate){    const SPEEDS *sp;    int found = FALSE;    /* The baudrate number can be preceded by a 'B', which is ignored. */    if (*rate == 'B')	++rate;    for (sp = speeds; sp->string; ++sp) {	if (!CaselessCmp(rate, sp->string)) {	    found = TRUE;	    break;	}    }    if (!found)	err("unknown baud rate %s", rate);    return (sp->speed);}/* * Syntax for -m: * [port-type][test baudrate]:terminal-type * The baud rate tests are: >, <, @, =, ! */static voidadd_mapping(const char *port, char *arg){    MAP *mapp;    char *copy, *p;    const char *termp;    char *base = 0;    copy = strdup(arg);    mapp = (MAP *) malloc(sizeof(MAP));    if (copy == 0 || mapp == 0)	failed("malloc");    mapp->next = 0;    if (maplist == 0)	cur = maplist = mapp;    else {	cur->next = mapp;	cur = mapp;    }    mapp->porttype = arg;    mapp->conditional = 0;    arg = strpbrk(arg, "><@=!:");    if (arg == 0) {		/* [?]term */	mapp->type = mapp->porttype;	mapp->porttype = 0;	goto done;    }    if (arg == mapp->porttype)	/* [><@=! baud]:term */	termp = mapp->porttype = 0;    else	termp = base = arg;    for (;; ++arg) {		/* Optional conditionals. */	switch (*arg) {	case '<':	    if (mapp->conditional & GT)		goto badmopt;	    mapp->conditional |= LT;	    break;	case '>':	    if (mapp->conditional & LT)		goto badmopt;	    mapp->conditional |= GT;	    break;	case '@':	case '=':		/* Not documented. */	    mapp->conditional |= EQ;	    break;	case '!':	    mapp->conditional |= NOT;	    break;	default:	    goto next;	}    }  next:    if (*arg == ':') {	if (mapp->conditional)	    goto badmopt;	++arg;    } else {			/* Optional baudrate. */	arg = strchr(p = arg, ':');	if (arg == 0)	    goto badmopt;	*arg++ = '\0';	mapp->speed = tbaudrate(p);    }    if (arg == (char *) 0)	/* Non-optional type. */	goto badmopt;    mapp->type = arg;    /* Terminate porttype, if specified. */    if (termp != 0)	*base = '\0';    /* If a NOT conditional, reverse the test. */    if (mapp->conditional & NOT)	mapp->conditional = ~mapp->conditional & (EQ | GT | LT);    /* If user specified a port with an option flag, set it. */  done:if (port) {	if (mapp->porttype)	  badmopt:err("illegal -m option format: %s", copy);	mapp->porttype = port;    }#ifdef MAPDEBUG    (void) printf("port: %s\n", mapp->porttype ? mapp->porttype : "ANY");    (void) printf("type: %s\n", mapp->type);    (void) printf("conditional: ");    p = "";    if (mapp->conditional & GT) {	(void) printf("GT");	p = "/";    }    if (mapp->conditional & EQ) {	(void) printf("%sEQ", p);	p = "/";    }    if (mapp->conditional & LT)	(void) printf("%sLT", p);    (void) printf("\nspeed: %d\n", mapp->speed);#endif}/* * Return the type of terminal to use for a port of type 'type', as specified * by the first applicable mapping in 'map'.  If no mappings apply, return * 'type'. */static const char *mapped(const char *type){    MAP *mapp;    int match;    for (mapp = maplist; mapp; mapp = mapp->next)	if (mapp->porttype == 0 || !strcmp(mapp->porttype, type)) {	    switch (mapp->conditional) {	    case 0:		/* No test specified. */		match = TRUE;		break;	    case EQ:		match = (ospeed == mapp->speed);		break;	    case GE:		match = (ospeed >= mapp->speed);		break;	    case GT:		match = (ospeed > mapp->speed);		break;	    case LE:		match = (ospeed <= mapp->speed);		break;	    case LT:		match = (ospeed < mapp->speed);		break;	    default:		match = FALSE;	    }	    if (match)		return (mapp->type);	}    /* No match found; return given type. */    return (type);}/************************************************************************** * * Entry fetching * **************************************************************************//* * Figure out what kind of terminal we're dealing with, and then read in * its termcap entry. */static const char *get_termcap_entry(char *userarg){    int errret;    char *p;    const char *ttype;#if HAVE_GETTTYNAM    struct ttyent *t;#else    FILE *fp;#endif    char *ttypath;    if (userarg) {	ttype = userarg;	goto found;    }    /* Try the environment. */    if ((ttype = getenv("TERM")) != 0)	goto map;    if ((ttypath = ttyname(STDERR_FILENO)) != 0) {	p = _nc_basename(ttypath);#if HAVE_GETTTYNAM	/*	 * We have the 4.3BSD library call getttynam(3); that means	 * there's an /etc/ttys to look up device-to-type mappings in.	 * Try ttyname(3); check for dialup or other mapping.	 */	if ((t = getttynam(p))) {	    ttype = t->ty_type;	    goto map;	}#else	if ((fp = fopen("/etc/ttytype", "r")) != 0	    || (fp = fopen("/etc/ttys", "r")) != 0) {	    char buffer[BUFSIZ];	    char *s, *t, *d;	    while (fgets(buffer, sizeof(buffer) - 1, fp) != 0) {		for (s = buffer, t = d = 0; *s; s++) {		    if (isspace(UChar(*s)))			*s = '\0';		    else if (t == 0)			t = s;		    else if (d == 0 && s != buffer && s[-1] == '\0')			d = s;		}		if (t != 0 && d != 0 && !strcmp(d, p)) {		    ttype = strdup(t);		    fclose(fp);		    goto map;		}	    }	    fclose(fp);	}#endif /* HAVE_GETTTYNAM */    }    /* If still undefined, use "unknown". */    ttype = "unknown";  map:ttype = mapped(ttype);    /*     * If not a path, remove TERMCAP from the environment so we get a     * real entry from /etc/termcap.  This prevents us from being fooled     * by out of date stuff in the environment.     */  found:if ((p = getenv("TERMCAP")) != 0 && *p != '/') {	/* 'unsetenv("TERMCAP")' is not portable.	 * The 'environ' array is better.	 */	int n;	for (n = 0; environ[n] != 0; n++) {	    if (!strncmp("TERMCAP=", environ[n], 8)) {		while ((environ[n] = environ[n + 1]) != 0) {		    n++;		}		break;	    }	}    }    /*     * ttype now contains a pointer to the type of the terminal.     * If the first character is '?', ask the user.     */    if (ttype[0] == '?') {	if (ttype[1] != '\0')	    ttype = askuser(ttype + 1);	else	    ttype = askuser(0);    }    /* Find the terminfo entry.  If it doesn't exist, ask the user. */    while (setupterm((NCURSES_CONST char *) ttype, STDOUT_FILENO, &errret)	   != OK) {	if (errret == 0) {	    (void) fprintf(stderr, "tset: unknown terminal type %s\n",			   ttype);	    ttype = 0;	} else {	    (void) fprintf(stderr,			   "tset: can't initialize terminal type %s (error %d)\n",			   ttype, errret);	    ttype = 0;	}	ttype = askuser(ttype);    }#if BROKEN_LINKER    tgetflag("am");		/* force lib_termcap.o to be linked for 'ospeed' */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -