?? read_termcap.c
字號:
/**************************************************************************** * 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> * ****************************************************************************//* * Termcap compatibility support * * If your OS integrator didn't install a terminfo database, you can call * _nc_read_termcap_entry() to support reading and translating capabilities * from the system termcap file. This is a kludge; it will bulk up and slow * down every program that uses ncurses, and translated termcap entries cannot * use full terminfo capabilities. Don't use it unless you absolutely have to; * instead, get your system people to run tic(1) from root on the terminfo * master included with ncurses to translate it into a terminfo database. * * If USE_GETCAP is enabled, we use what is effectively a copy of the 4.4BSD * getcap code to fetch entries. There are disadvantages to this; mainly that * getcap(3) does its own resolution, meaning that entries read in in this way * can't reference the terminfo tree. The only thing it buys is faster startup * time, getcap(3) is much faster than our tic parser. */#include <curses.priv.h>#include <ctype.h>#include <sys/types.h>#include <sys/stat.h>#include <tic.h>#include <term_entry.h>MODULE_ID("$Id: read_termcap.c,v 1.61 2003/11/08 20:22:45 tom Exp $")#if !PURE_TERMINFO#if defined(__EMX__) || defined(__DJGPP__)#define is_pathname(s) ((((s) != 0) && ((s)[0] == '/')) \ || (((s)[0] != 0) && ((s)[1] == ':')))#else#define is_pathname(s) ((s) != 0 && (s)[0] == '/')#endif#define TC_SUCCESS 0#define TC_UNRESOLVED -1#define TC_NOT_FOUND -2#define TC_SYS_ERR -3#define TC_REF_LOOP -4static char *get_termpath(void){ char *result; if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) result = TERMPATH; T(("TERMPATH is %s", result)); return result;}#if USE_GETCAP#if HAVE_BSD_CGETENT#define _nc_cgetcap cgetcap#define _nc_cgetent(buf, oline, db_array, name) cgetent(buf, db_array, name)#define _nc_cgetmatch cgetmatch#define _nc_cgetset cgetset#elsestatic int _nc_cgetmatch(char *, const char *);static int _nc_getent(char **, unsigned *, int *, int, char **, int, const char *, int, char *);static int _nc_nfcmp(const char *, char *);/*- * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Casey Leedom of Lawrence Livermore National Laboratory. * * 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 acknowledgment: * 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. *//* static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94"; */#define BFRAG 1024#define BSIZE 1024#define MAX_RECURSION 32 /* maximum getent recursion */static size_t topreclen; /* toprec length */static char *toprec; /* Additional record specified by cgetset() */static int gottoprec; /* Flag indicating retrieval of toprecord *//* * Cgetset() allows the addition of a user specified buffer to be added to the * database array, in effect "pushing" the buffer on top of the virtual * database. 0 is returned on success, -1 on failure. */static int_nc_cgetset(const char *ent){ if (ent == 0) { FreeIfNeeded(toprec); toprec = 0; topreclen = 0; return (0); } topreclen = strlen(ent); if ((toprec = typeMalloc(char, topreclen + 1)) == 0) { errno = ENOMEM; return (-1); } gottoprec = 0; (void) strcpy(toprec, ent); return (0);}/* * Cgetcap searches the capability record buf for the capability cap with type * `type'. A pointer to the value of cap is returned on success, 0 if the * requested capability couldn't be found. * * Specifying a type of ':' means that nothing should follow cap (:cap:). In * this case a pointer to the terminating ':' or NUL will be returned if cap is * found. * * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator) * return 0. */static char *_nc_cgetcap(char *buf, const char *cap, int type){ register const char *cp; register char *bp; bp = buf; for (;;) { /* * Skip past the current capability field - it's either the * name field if this is the first time through the loop, or * the remainder of a field whose name failed to match cap. */ for (;;) { if (*bp == '\0') return (0); else if (*bp++ == ':') break; } /* * Try to match (cap, type) in buf. */ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++) continue; if (*cp != '\0') continue; if (*bp == '@') return (0); if (type == ':') { if (*bp != '\0' && *bp != ':') continue; return (bp); } if (*bp != type) continue; bp++; return (*bp == '@' ? 0 : bp); } /* NOTREACHED */}/* * Cgetent extracts the capability record name from the NULL terminated file * array db_array and returns a pointer to a malloc'd copy of it in buf. Buf * must be retained through all subsequent calls to cgetcap, cgetnum, cgetflag, * and cgetstr, but may then be freed. * * Returns: * * positive # on success (i.e., the index in db_array) * TC_UNRESOLVED if we had too many recurrences to resolve * TC_NOT_FOUND if the requested record couldn't be found * TC_SYS_ERR if a system error was encountered (e.g.,couldn't open a file) * TC_REF_LOOP if a potential reference loop is detected */static int_nc_cgetent(char **buf, int *oline, char **db_array, const char *name){ unsigned dummy; return (_nc_getent(buf, &dummy, oline, 0, db_array, -1, name, 0, 0));}/* * Getent implements the functions of cgetent. If fd is non-negative, * *db_array has already been opened and fd is the open file descriptor. We * do this to save time and avoid using up file descriptors for tc= * recursions. * * Getent returns the same success/failure codes as cgetent. On success, a * pointer to a malloc'd capability record with all tc= capabilities fully * expanded and its length (not including trailing ASCII NUL) are left in * *cap and *len. * * Basic algorithm: * + Allocate memory incrementally as needed in chunks of size BFRAG * for capability buffer. * + Recurse for each tc=name and interpolate result. Stop when all * names interpolated, a name can't be found, or depth exceeds * MAX_RECURSION. */#define DOALLOC(size) typeRealloc(char, size, record)static int_nc_getent( char **cap, /* termcap-content */ unsigned *len, /* length, needed for recursion */ int *beginning, /* line-number at match */ int in_array, /* index in 'db_array[] */ char **db_array, /* list of files to search */ int fd, const char *name, int depth, char *nfield){ register char *r_end, *rp; int myfd = FALSE; char *record = 0; int tc_not_resolved; int current; int lineno; /* * Return with ``loop detected'' error if we've recurred more than * MAX_RECURSION times. */ if (depth > MAX_RECURSION) return (TC_REF_LOOP); /* * Check if we have a top record from cgetset(). */ if (depth == 0 && toprec != 0 && _nc_cgetmatch(toprec, name) == 0) { if ((record = DOALLOC(topreclen + BFRAG)) == 0) { errno = ENOMEM; return (TC_SYS_ERR); } (void) strcpy(record, toprec); rp = record + topreclen + 1; r_end = rp + BFRAG; current = in_array; } else { int foundit; /* * Allocate first chunk of memory. */ if ((record = DOALLOC(BFRAG)) == 0) { errno = ENOMEM; return (TC_SYS_ERR); } rp = r_end = record + BFRAG; foundit = FALSE; /* * Loop through database array until finding the record. */ for (current = in_array; db_array[current] != 0; current++) { int eof = FALSE; /* * Open database if not already open. */ if (fd >= 0) { (void) lseek(fd, (off_t) 0, SEEK_SET); } else if ((_nc_access(db_array[current], R_OK) < 0) || (fd = open(db_array[current], O_RDONLY, 0)) < 0) { /* No error on unfound file. */ if (errno == ENOENT) continue; free(record); return (TC_SYS_ERR); } else { myfd = TRUE; } lineno = 0; /* * Find the requested capability record ... */ { char buf[2048]; register char *b_end = buf; register char *bp = buf; register int c; /* * Loop invariants: * There is always room for one more character in record. * R_end always points just past end of record. * Rp always points just past last character in record. * B_end always points just past last character in buf. * Bp always points at next character in buf. */ for (;;) { int first = lineno + 1; /* * Read in a line implementing (\, newline) * line continuation. */ rp = record; for (;;) { if (bp >= b_end) { int n; n = read(fd, buf, sizeof(buf)); if (n <= 0) { if (myfd) (void) close(fd); if (n < 0) { free(record); return (TC_SYS_ERR); } fd = -1; eof = TRUE; break; } b_end = buf + n; bp = buf; } c = *bp++; if (c == '\n') { lineno++; if (rp == record || *(rp - 1) != '\\') break;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -