10e3d5408SPeter Wemm /**************************************************************************** 2*e1865124SBaptiste Daroussin * Copyright 2018-2019,2020 Thomas E. Dickey * 3*e1865124SBaptiste Daroussin * Copyright 1998-2016,2017 Free Software Foundation, Inc. * 40e3d5408SPeter Wemm * * 50e3d5408SPeter Wemm * Permission is hereby granted, free of charge, to any person obtaining a * 60e3d5408SPeter Wemm * copy of this software and associated documentation files (the * 70e3d5408SPeter Wemm * "Software"), to deal in the Software without restriction, including * 80e3d5408SPeter Wemm * without limitation the rights to use, copy, modify, merge, publish, * 90e3d5408SPeter Wemm * distribute, distribute with modifications, sublicense, and/or sell * 100e3d5408SPeter Wemm * copies of the Software, and to permit persons to whom the Software is * 110e3d5408SPeter Wemm * furnished to do so, subject to the following conditions: * 120e3d5408SPeter Wemm * * 130e3d5408SPeter Wemm * The above copyright notice and this permission notice shall be included * 140e3d5408SPeter Wemm * in all copies or substantial portions of the Software. * 150e3d5408SPeter Wemm * * 160e3d5408SPeter Wemm * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 170e3d5408SPeter Wemm * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 180e3d5408SPeter Wemm * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 190e3d5408SPeter Wemm * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 200e3d5408SPeter Wemm * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 210e3d5408SPeter Wemm * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 220e3d5408SPeter Wemm * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 230e3d5408SPeter Wemm * * 240e3d5408SPeter Wemm * Except as contained in this notice, the name(s) of the above copyright * 250e3d5408SPeter Wemm * holders shall not be used in advertising or otherwise to promote the * 260e3d5408SPeter Wemm * sale, use or other dealings in this Software without prior written * 270e3d5408SPeter Wemm * authorization. * 280e3d5408SPeter Wemm ****************************************************************************/ 290e3d5408SPeter Wemm 300e3d5408SPeter Wemm /**************************************************************************** 310e3d5408SPeter Wemm * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 320e3d5408SPeter Wemm * and: Eric S. Raymond <esr@snark.thyrsus.com> * 334a1a9510SRong-En Fan * and: Thomas E. Dickey 1996-on * 340e3d5408SPeter Wemm ****************************************************************************/ 350e3d5408SPeter Wemm 360e3d5408SPeter Wemm /* 370e3d5408SPeter Wemm * Termcap compatibility support 380e3d5408SPeter Wemm * 390e3d5408SPeter Wemm * If your OS integrator didn't install a terminfo database, you can call 400e3d5408SPeter Wemm * _nc_read_termcap_entry() to support reading and translating capabilities 410e3d5408SPeter Wemm * from the system termcap file. This is a kludge; it will bulk up and slow 420e3d5408SPeter Wemm * down every program that uses ncurses, and translated termcap entries cannot 430e3d5408SPeter Wemm * use full terminfo capabilities. Don't use it unless you absolutely have to; 440e3d5408SPeter Wemm * instead, get your system people to run tic(1) from root on the terminfo 450e3d5408SPeter Wemm * master included with ncurses to translate it into a terminfo database. 460e3d5408SPeter Wemm * 470e3d5408SPeter Wemm * If USE_GETCAP is enabled, we use what is effectively a copy of the 4.4BSD 480e3d5408SPeter Wemm * getcap code to fetch entries. There are disadvantages to this; mainly that 490e3d5408SPeter Wemm * getcap(3) does its own resolution, meaning that entries read in in this way 500e3d5408SPeter Wemm * can't reference the terminfo tree. The only thing it buys is faster startup 510e3d5408SPeter Wemm * time, getcap(3) is much faster than our tic parser. 520e3d5408SPeter Wemm */ 530e3d5408SPeter Wemm 540e3d5408SPeter Wemm #include <curses.priv.h> 550e3d5408SPeter Wemm 560e3d5408SPeter Wemm #include <ctype.h> 5739f2269fSPeter Wemm #include <sys/types.h> 580e3d5408SPeter Wemm #include <tic.h> 590e3d5408SPeter Wemm 60*e1865124SBaptiste Daroussin MODULE_ID("$Id: read_termcap.c,v 1.98 2020/02/02 23:34:34 tom Exp $") 610e3d5408SPeter Wemm 6218259542SPeter Wemm #if !PURE_TERMINFO 630e3d5408SPeter Wemm 640e3d5408SPeter Wemm #define TC_SUCCESS 0 654a1a9510SRong-En Fan #define TC_NOT_FOUND -1 664a1a9510SRong-En Fan #define TC_SYS_ERR -2 674a1a9510SRong-En Fan #define TC_REF_LOOP -3 684a1a9510SRong-En Fan #define TC_UNRESOLVED -4 /* this is not returned by BSD cgetent */ 690e3d5408SPeter Wemm 70aae38d10SBaptiste Daroussin static const char * 7139f2269fSPeter Wemm get_termpath(void) 7239f2269fSPeter Wemm { 73aae38d10SBaptiste Daroussin const char *result; 7439f2269fSPeter Wemm 7539f2269fSPeter Wemm if (!use_terminfo_vars() || (result = getenv("TERMPATH")) == 0) 7639f2269fSPeter Wemm result = TERMPATH; 7773f0a83dSXin LI TR(TRACE_DATABASE, ("TERMPATH is %s", result)); 7839f2269fSPeter Wemm return result; 7939f2269fSPeter Wemm } 8039f2269fSPeter Wemm 8106bfebdeSXin LI /* 8206bfebdeSXin LI * Note: 8306bfebdeSXin LI * getcap(), cgetent(), etc., are BSD functions. A copy of those was added to 8406bfebdeSXin LI * this file in November 1995, derived from the BSD4.4 Lite sources. 8506bfebdeSXin LI * 8606bfebdeSXin LI * The initial adaptation uses 518 lines from that source. 8706bfebdeSXin LI * The current source (in 2009) uses 183 lines of BSD4.4 Lite (441 ignoring 8806bfebdeSXin LI * whitespace). 8906bfebdeSXin LI */ 900e3d5408SPeter Wemm #if USE_GETCAP 910e3d5408SPeter Wemm 920e3d5408SPeter Wemm #if HAVE_BSD_CGETENT 930e3d5408SPeter Wemm #define _nc_cgetcap cgetcap 940e3d5408SPeter Wemm #define _nc_cgetent(buf, oline, db_array, name) cgetent(buf, db_array, name) 950e3d5408SPeter Wemm #define _nc_cgetmatch cgetmatch 960e3d5408SPeter Wemm #define _nc_cgetset cgetset 970e3d5408SPeter Wemm #else 980e3d5408SPeter Wemm static int _nc_cgetmatch(char *, const char *); 9918259542SPeter Wemm static int _nc_getent(char **, unsigned *, int *, int, char **, int, const char 10018259542SPeter Wemm *, int, char *); 1010e3d5408SPeter Wemm static int _nc_nfcmp(const char *, char *); 1020e3d5408SPeter Wemm 1030e3d5408SPeter Wemm /*- 1040e3d5408SPeter Wemm * Copyright (c) 1992, 1993 1050e3d5408SPeter Wemm * The Regents of the University of California. All rights reserved. 1060e3d5408SPeter Wemm * 1070e3d5408SPeter Wemm * This code is derived from software contributed to Berkeley by 1080e3d5408SPeter Wemm * Casey Leedom of Lawrence Livermore National Laboratory. 1090e3d5408SPeter Wemm * 1100e3d5408SPeter Wemm * Redistribution and use in source and binary forms, with or without 1110e3d5408SPeter Wemm * modification, are permitted provided that the following conditions 1120e3d5408SPeter Wemm * are met: 1130e3d5408SPeter Wemm * 1. Redistributions of source code must retain the above copyright 1140e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer. 1150e3d5408SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 1160e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer in the 1170e3d5408SPeter Wemm * documentation and/or other materials provided with the distribution. 11806bfebdeSXin LI * 3. Neither the name of the University nor the names of its contributors 1190e3d5408SPeter Wemm * may be used to endorse or promote products derived from this software 1200e3d5408SPeter Wemm * without specific prior written permission. 1210e3d5408SPeter Wemm * 1220e3d5408SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1230e3d5408SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1240e3d5408SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1250e3d5408SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 1260e3d5408SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1270e3d5408SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1280e3d5408SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1290e3d5408SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1300e3d5408SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1310e3d5408SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1320e3d5408SPeter Wemm * SUCH DAMAGE. 1330e3d5408SPeter Wemm */ 1340e3d5408SPeter Wemm 1350e3d5408SPeter Wemm /* static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94"; */ 1360e3d5408SPeter Wemm 1370e3d5408SPeter Wemm #define BFRAG 1024 1380e3d5408SPeter Wemm #define BSIZE 1024 1390e3d5408SPeter Wemm #define MAX_RECURSION 32 /* maximum getent recursion */ 1400e3d5408SPeter Wemm 1410e3d5408SPeter Wemm static size_t topreclen; /* toprec length */ 1420e3d5408SPeter Wemm static char *toprec; /* Additional record specified by cgetset() */ 1430e3d5408SPeter Wemm static int gottoprec; /* Flag indicating retrieval of toprecord */ 1440e3d5408SPeter Wemm 1450e3d5408SPeter Wemm /* 1460e3d5408SPeter Wemm * Cgetset() allows the addition of a user specified buffer to be added to the 1470e3d5408SPeter Wemm * database array, in effect "pushing" the buffer on top of the virtual 1480e3d5408SPeter Wemm * database. 0 is returned on success, -1 on failure. 1490e3d5408SPeter Wemm */ 1500e3d5408SPeter Wemm static int 1510e3d5408SPeter Wemm _nc_cgetset(const char *ent) 1520e3d5408SPeter Wemm { 1530e3d5408SPeter Wemm if (ent == 0) { 1540e3d5408SPeter Wemm FreeIfNeeded(toprec); 1550e3d5408SPeter Wemm toprec = 0; 1560e3d5408SPeter Wemm topreclen = 0; 1570e3d5408SPeter Wemm return (0); 1580e3d5408SPeter Wemm } 1590e3d5408SPeter Wemm topreclen = strlen(ent); 1600e3d5408SPeter Wemm if ((toprec = typeMalloc(char, topreclen + 1)) == 0) { 1610e3d5408SPeter Wemm errno = ENOMEM; 1620e3d5408SPeter Wemm return (-1); 1630e3d5408SPeter Wemm } 1640e3d5408SPeter Wemm gottoprec = 0; 16573f0a83dSXin LI _nc_STRCPY(toprec, ent, topreclen); 1660e3d5408SPeter Wemm return (0); 1670e3d5408SPeter Wemm } 1680e3d5408SPeter Wemm 1690e3d5408SPeter Wemm /* 1700e3d5408SPeter Wemm * Cgetcap searches the capability record buf for the capability cap with type 1710e3d5408SPeter Wemm * `type'. A pointer to the value of cap is returned on success, 0 if the 1720e3d5408SPeter Wemm * requested capability couldn't be found. 1730e3d5408SPeter Wemm * 1740e3d5408SPeter Wemm * Specifying a type of ':' means that nothing should follow cap (:cap:). In 1750e3d5408SPeter Wemm * this case a pointer to the terminating ':' or NUL will be returned if cap is 1760e3d5408SPeter Wemm * found. 1770e3d5408SPeter Wemm * 1780e3d5408SPeter Wemm * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator) 1790e3d5408SPeter Wemm * return 0. 1800e3d5408SPeter Wemm */ 1810e3d5408SPeter Wemm static char * 1820e3d5408SPeter Wemm _nc_cgetcap(char *buf, const char *cap, int type) 1830e3d5408SPeter Wemm { 1840e3d5408SPeter Wemm register const char *cp; 1850e3d5408SPeter Wemm register char *bp; 1860e3d5408SPeter Wemm 1870e3d5408SPeter Wemm bp = buf; 1880e3d5408SPeter Wemm for (;;) { 1890e3d5408SPeter Wemm /* 1900e3d5408SPeter Wemm * Skip past the current capability field - it's either the 1910e3d5408SPeter Wemm * name field if this is the first time through the loop, or 1920e3d5408SPeter Wemm * the remainder of a field whose name failed to match cap. 1930e3d5408SPeter Wemm */ 1940e3d5408SPeter Wemm for (;;) { 1950e3d5408SPeter Wemm if (*bp == '\0') 1960e3d5408SPeter Wemm return (0); 1970e3d5408SPeter Wemm else if (*bp++ == ':') 1980e3d5408SPeter Wemm break; 1990e3d5408SPeter Wemm } 2000e3d5408SPeter Wemm 2010e3d5408SPeter Wemm /* 2020e3d5408SPeter Wemm * Try to match (cap, type) in buf. 2030e3d5408SPeter Wemm */ 2040e3d5408SPeter Wemm for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++) 2050e3d5408SPeter Wemm continue; 2060e3d5408SPeter Wemm if (*cp != '\0') 2070e3d5408SPeter Wemm continue; 2080e3d5408SPeter Wemm if (*bp == '@') 2090e3d5408SPeter Wemm return (0); 2100e3d5408SPeter Wemm if (type == ':') { 2110e3d5408SPeter Wemm if (*bp != '\0' && *bp != ':') 2120e3d5408SPeter Wemm continue; 2130e3d5408SPeter Wemm return (bp); 2140e3d5408SPeter Wemm } 2150e3d5408SPeter Wemm if (*bp != type) 2160e3d5408SPeter Wemm continue; 2170e3d5408SPeter Wemm bp++; 2180e3d5408SPeter Wemm return (*bp == '@' ? 0 : bp); 2190e3d5408SPeter Wemm } 2200e3d5408SPeter Wemm /* NOTREACHED */ 2210e3d5408SPeter Wemm } 2220e3d5408SPeter Wemm 2230e3d5408SPeter Wemm /* 2240e3d5408SPeter Wemm * Cgetent extracts the capability record name from the NULL terminated file 2250e3d5408SPeter Wemm * array db_array and returns a pointer to a malloc'd copy of it in buf. Buf 2260e3d5408SPeter Wemm * must be retained through all subsequent calls to cgetcap, cgetnum, cgetflag, 2270e3d5408SPeter Wemm * and cgetstr, but may then be freed. 2280e3d5408SPeter Wemm * 2290e3d5408SPeter Wemm * Returns: 2300e3d5408SPeter Wemm * 2310e3d5408SPeter Wemm * positive # on success (i.e., the index in db_array) 2320e3d5408SPeter Wemm * TC_NOT_FOUND if the requested record couldn't be found 2330e3d5408SPeter Wemm * TC_SYS_ERR if a system error was encountered (e.g.,couldn't open a file) 2340e3d5408SPeter Wemm * TC_REF_LOOP if a potential reference loop is detected 2354a1a9510SRong-En Fan * TC_UNRESOLVED if we had too many recurrences to resolve 2360e3d5408SPeter Wemm */ 2370e3d5408SPeter Wemm static int 2380e3d5408SPeter Wemm _nc_cgetent(char **buf, int *oline, char **db_array, const char *name) 2390e3d5408SPeter Wemm { 24015589c42SPeter Wemm unsigned dummy; 2410e3d5408SPeter Wemm 2420e3d5408SPeter Wemm return (_nc_getent(buf, &dummy, oline, 0, db_array, -1, name, 0, 0)); 2430e3d5408SPeter Wemm } 2440e3d5408SPeter Wemm 2450e3d5408SPeter Wemm /* 2460e3d5408SPeter Wemm * Getent implements the functions of cgetent. If fd is non-negative, 2470e3d5408SPeter Wemm * *db_array has already been opened and fd is the open file descriptor. We 2480e3d5408SPeter Wemm * do this to save time and avoid using up file descriptors for tc= 2490e3d5408SPeter Wemm * recursions. 2500e3d5408SPeter Wemm * 2510e3d5408SPeter Wemm * Getent returns the same success/failure codes as cgetent. On success, a 2520e3d5408SPeter Wemm * pointer to a malloc'd capability record with all tc= capabilities fully 2530e3d5408SPeter Wemm * expanded and its length (not including trailing ASCII NUL) are left in 2540e3d5408SPeter Wemm * *cap and *len. 2550e3d5408SPeter Wemm * 2560e3d5408SPeter Wemm * Basic algorithm: 2570e3d5408SPeter Wemm * + Allocate memory incrementally as needed in chunks of size BFRAG 2580e3d5408SPeter Wemm * for capability buffer. 2590e3d5408SPeter Wemm * + Recurse for each tc=name and interpolate result. Stop when all 2600e3d5408SPeter Wemm * names interpolated, a name can't be found, or depth exceeds 2610e3d5408SPeter Wemm * MAX_RECURSION. 2620e3d5408SPeter Wemm */ 2630e3d5408SPeter Wemm #define DOALLOC(size) typeRealloc(char, size, record) 2640e3d5408SPeter Wemm static int 2650e3d5408SPeter Wemm _nc_getent( 2660e3d5408SPeter Wemm char **cap, /* termcap-content */ 26715589c42SPeter Wemm unsigned *len, /* length, needed for recursion */ 2680e3d5408SPeter Wemm int *beginning, /* line-number at match */ 2690e3d5408SPeter Wemm int in_array, /* index in 'db_array[] */ 2700e3d5408SPeter Wemm char **db_array, /* list of files to search */ 2710e3d5408SPeter Wemm int fd, 2720e3d5408SPeter Wemm const char *name, 2730e3d5408SPeter Wemm int depth, 2740e3d5408SPeter Wemm char *nfield) 2750e3d5408SPeter Wemm { 2760e3d5408SPeter Wemm register char *r_end, *rp; 2770e3d5408SPeter Wemm int myfd = FALSE; 2780e3d5408SPeter Wemm char *record = 0; 2790e3d5408SPeter Wemm int tc_not_resolved; 2800e3d5408SPeter Wemm int current; 2810e3d5408SPeter Wemm int lineno; 2820e3d5408SPeter Wemm 2830e3d5408SPeter Wemm /* 2840e3d5408SPeter Wemm * Return with ``loop detected'' error if we've recurred more than 2850e3d5408SPeter Wemm * MAX_RECURSION times. 2860e3d5408SPeter Wemm */ 2870e3d5408SPeter Wemm if (depth > MAX_RECURSION) 2880e3d5408SPeter Wemm return (TC_REF_LOOP); 2890e3d5408SPeter Wemm 2900e3d5408SPeter Wemm /* 2910e3d5408SPeter Wemm * Check if we have a top record from cgetset(). 2920e3d5408SPeter Wemm */ 2930e3d5408SPeter Wemm if (depth == 0 && toprec != 0 && _nc_cgetmatch(toprec, name) == 0) { 2940e3d5408SPeter Wemm if ((record = DOALLOC(topreclen + BFRAG)) == 0) { 2950e3d5408SPeter Wemm errno = ENOMEM; 2960e3d5408SPeter Wemm return (TC_SYS_ERR); 2970e3d5408SPeter Wemm } 29873f0a83dSXin LI _nc_STRCPY(record, toprec, topreclen + BFRAG); 2990e3d5408SPeter Wemm rp = record + topreclen + 1; 3000e3d5408SPeter Wemm r_end = rp + BFRAG; 3010e3d5408SPeter Wemm current = in_array; 3020e3d5408SPeter Wemm } else { 3030e3d5408SPeter Wemm int foundit; 3040e3d5408SPeter Wemm 3050e3d5408SPeter Wemm /* 3060e3d5408SPeter Wemm * Allocate first chunk of memory. 3070e3d5408SPeter Wemm */ 3080e3d5408SPeter Wemm if ((record = DOALLOC(BFRAG)) == 0) { 3090e3d5408SPeter Wemm errno = ENOMEM; 3100e3d5408SPeter Wemm return (TC_SYS_ERR); 3110e3d5408SPeter Wemm } 3120e3d5408SPeter Wemm rp = r_end = record + BFRAG; 3130e3d5408SPeter Wemm foundit = FALSE; 3140e3d5408SPeter Wemm 3150e3d5408SPeter Wemm /* 3160e3d5408SPeter Wemm * Loop through database array until finding the record. 3170e3d5408SPeter Wemm */ 3180e3d5408SPeter Wemm for (current = in_array; db_array[current] != 0; current++) { 3190e3d5408SPeter Wemm int eof = FALSE; 3200e3d5408SPeter Wemm 3210e3d5408SPeter Wemm /* 3220e3d5408SPeter Wemm * Open database if not already open. 3230e3d5408SPeter Wemm */ 3240e3d5408SPeter Wemm if (fd >= 0) { 3250e3d5408SPeter Wemm (void) lseek(fd, (off_t) 0, SEEK_SET); 3260e3d5408SPeter Wemm } else if ((_nc_access(db_array[current], R_OK) < 0) 3270e3d5408SPeter Wemm || (fd = open(db_array[current], O_RDONLY, 0)) < 0) { 3280e3d5408SPeter Wemm /* No error on unfound file. */ 3290e3d5408SPeter Wemm if (errno == ENOENT) 3300e3d5408SPeter Wemm continue; 3310e3d5408SPeter Wemm free(record); 3320e3d5408SPeter Wemm return (TC_SYS_ERR); 3330e3d5408SPeter Wemm } else { 3340e3d5408SPeter Wemm myfd = TRUE; 3350e3d5408SPeter Wemm } 3360e3d5408SPeter Wemm lineno = 0; 3370e3d5408SPeter Wemm 3380e3d5408SPeter Wemm /* 3390e3d5408SPeter Wemm * Find the requested capability record ... 3400e3d5408SPeter Wemm */ 3410e3d5408SPeter Wemm { 3420e3d5408SPeter Wemm char buf[2048]; 3430e3d5408SPeter Wemm register char *b_end = buf; 3440e3d5408SPeter Wemm register char *bp = buf; 3450e3d5408SPeter Wemm register int c; 3460e3d5408SPeter Wemm 3470e3d5408SPeter Wemm /* 3480e3d5408SPeter Wemm * Loop invariants: 3490e3d5408SPeter Wemm * There is always room for one more character in record. 3500e3d5408SPeter Wemm * R_end always points just past end of record. 3510e3d5408SPeter Wemm * Rp always points just past last character in record. 3520e3d5408SPeter Wemm * B_end always points just past last character in buf. 3530e3d5408SPeter Wemm * Bp always points at next character in buf. 3540e3d5408SPeter Wemm */ 3550e3d5408SPeter Wemm 3560e3d5408SPeter Wemm for (;;) { 3570e3d5408SPeter Wemm int first = lineno + 1; 3580e3d5408SPeter Wemm 3590e3d5408SPeter Wemm /* 3600e3d5408SPeter Wemm * Read in a line implementing (\, newline) 3610e3d5408SPeter Wemm * line continuation. 3620e3d5408SPeter Wemm */ 3630e3d5408SPeter Wemm rp = record; 3640e3d5408SPeter Wemm for (;;) { 3650e3d5408SPeter Wemm if (bp >= b_end) { 3660e3d5408SPeter Wemm int n; 3670e3d5408SPeter Wemm 368aae38d10SBaptiste Daroussin n = (int) read(fd, buf, sizeof(buf)); 3690e3d5408SPeter Wemm if (n <= 0) { 3700e3d5408SPeter Wemm if (myfd) 3710e3d5408SPeter Wemm (void) close(fd); 3720e3d5408SPeter Wemm if (n < 0) { 3730e3d5408SPeter Wemm free(record); 3740e3d5408SPeter Wemm return (TC_SYS_ERR); 3750e3d5408SPeter Wemm } 3760e3d5408SPeter Wemm fd = -1; 3770e3d5408SPeter Wemm eof = TRUE; 3780e3d5408SPeter Wemm break; 3790e3d5408SPeter Wemm } 3800e3d5408SPeter Wemm b_end = buf + n; 3810e3d5408SPeter Wemm bp = buf; 3820e3d5408SPeter Wemm } 3830e3d5408SPeter Wemm 3840e3d5408SPeter Wemm c = *bp++; 3850e3d5408SPeter Wemm if (c == '\n') { 3860e3d5408SPeter Wemm lineno++; 38773f0a83dSXin LI /* 38873f0a83dSXin LI * Unlike BSD 4.3, this ignores a backslash at the 38973f0a83dSXin LI * end of a comment-line. That makes it consistent 39073f0a83dSXin LI * with the rest of ncurses -TD 39173f0a83dSXin LI */ 39273f0a83dSXin LI if (rp == record 39373f0a83dSXin LI || *record == '#' 39473f0a83dSXin LI || *(rp - 1) != '\\') 3950e3d5408SPeter Wemm break; 3960e3d5408SPeter Wemm } 397aae38d10SBaptiste Daroussin *rp++ = (char) c; 3980e3d5408SPeter Wemm 3990e3d5408SPeter Wemm /* 4000e3d5408SPeter Wemm * Enforce loop invariant: if no room 4010e3d5408SPeter Wemm * left in record buffer, try to get 4020e3d5408SPeter Wemm * some more. 4030e3d5408SPeter Wemm */ 4040e3d5408SPeter Wemm if (rp >= r_end) { 40515589c42SPeter Wemm unsigned pos; 4060e3d5408SPeter Wemm size_t newsize; 4070e3d5408SPeter Wemm 408aae38d10SBaptiste Daroussin pos = (unsigned) (rp - record); 409aae38d10SBaptiste Daroussin newsize = (size_t) (r_end - record + BFRAG); 4100e3d5408SPeter Wemm record = DOALLOC(newsize); 4110e3d5408SPeter Wemm if (record == 0) { 4120e3d5408SPeter Wemm if (myfd) 4130e3d5408SPeter Wemm (void) close(fd); 4140e3d5408SPeter Wemm errno = ENOMEM; 4150e3d5408SPeter Wemm return (TC_SYS_ERR); 4160e3d5408SPeter Wemm } 4170e3d5408SPeter Wemm r_end = record + newsize; 4180e3d5408SPeter Wemm rp = record + pos; 4190e3d5408SPeter Wemm } 4200e3d5408SPeter Wemm } 4210e3d5408SPeter Wemm /* loop invariant lets us do this */ 4220e3d5408SPeter Wemm *rp++ = '\0'; 4230e3d5408SPeter Wemm 4240e3d5408SPeter Wemm /* 4250e3d5408SPeter Wemm * If encountered eof check next file. 4260e3d5408SPeter Wemm */ 4270e3d5408SPeter Wemm if (eof) 4280e3d5408SPeter Wemm break; 4290e3d5408SPeter Wemm 4300e3d5408SPeter Wemm /* 4310e3d5408SPeter Wemm * Toss blank lines and comments. 4320e3d5408SPeter Wemm */ 4330e3d5408SPeter Wemm if (*record == '\0' || *record == '#') 4340e3d5408SPeter Wemm continue; 4350e3d5408SPeter Wemm 4360e3d5408SPeter Wemm /* 4370e3d5408SPeter Wemm * See if this is the record we want ... 4380e3d5408SPeter Wemm */ 4390e3d5408SPeter Wemm if (_nc_cgetmatch(record, name) == 0 4400e3d5408SPeter Wemm && (nfield == 0 4410e3d5408SPeter Wemm || !_nc_nfcmp(nfield, record))) { 4420e3d5408SPeter Wemm foundit = TRUE; 4430e3d5408SPeter Wemm *beginning = first; 4440e3d5408SPeter Wemm break; /* found it! */ 4450e3d5408SPeter Wemm } 4460e3d5408SPeter Wemm } 4470e3d5408SPeter Wemm } 4480e3d5408SPeter Wemm if (foundit) 4490e3d5408SPeter Wemm break; 4500e3d5408SPeter Wemm } 4510e3d5408SPeter Wemm 45273f0a83dSXin LI if (!foundit) { 45373f0a83dSXin LI free(record); 4540e3d5408SPeter Wemm return (TC_NOT_FOUND); 4550e3d5408SPeter Wemm } 45673f0a83dSXin LI } 4570e3d5408SPeter Wemm 4580e3d5408SPeter Wemm /* 4590e3d5408SPeter Wemm * Got the capability record, but now we have to expand all tc=name 4600e3d5408SPeter Wemm * references in it ... 4610e3d5408SPeter Wemm */ 4620e3d5408SPeter Wemm { 4630e3d5408SPeter Wemm register char *newicap, *s; 4640e3d5408SPeter Wemm register int newilen; 46515589c42SPeter Wemm unsigned ilen; 4660e3d5408SPeter Wemm int diff, iret, tclen, oline; 46773f0a83dSXin LI char *icap = 0, *scan, *tc, *tcstart, *tcend; 4680e3d5408SPeter Wemm 4690e3d5408SPeter Wemm /* 4700e3d5408SPeter Wemm * Loop invariants: 4710e3d5408SPeter Wemm * There is room for one more character in record. 4720e3d5408SPeter Wemm * R_end points just past end of record. 4730e3d5408SPeter Wemm * Rp points just past last character in record. 4740e3d5408SPeter Wemm * Scan points at remainder of record that needs to be 4750e3d5408SPeter Wemm * scanned for tc=name constructs. 4760e3d5408SPeter Wemm */ 4770e3d5408SPeter Wemm scan = record; 4780e3d5408SPeter Wemm tc_not_resolved = FALSE; 4790e3d5408SPeter Wemm for (;;) { 48073f0a83dSXin LI if ((tc = _nc_cgetcap(scan, "tc", '=')) == 0) { 4810e3d5408SPeter Wemm break; 48273f0a83dSXin LI } 4830e3d5408SPeter Wemm 4840e3d5408SPeter Wemm /* 4850e3d5408SPeter Wemm * Find end of tc=name and stomp on the trailing `:' 4860e3d5408SPeter Wemm * (if present) so we can use it to call ourselves. 4870e3d5408SPeter Wemm */ 4880e3d5408SPeter Wemm s = tc; 4890e3d5408SPeter Wemm while (*s != '\0') { 4900e3d5408SPeter Wemm if (*s++ == ':') { 4910e3d5408SPeter Wemm *(s - 1) = '\0'; 4920e3d5408SPeter Wemm break; 4930e3d5408SPeter Wemm } 4940e3d5408SPeter Wemm } 4950e3d5408SPeter Wemm tcstart = tc - 3; 496aae38d10SBaptiste Daroussin tclen = (int) (s - tcstart); 4970e3d5408SPeter Wemm tcend = s; 4980e3d5408SPeter Wemm 49973f0a83dSXin LI icap = 0; 50015589c42SPeter Wemm iret = _nc_getent(&icap, &ilen, &oline, current, db_array, fd, 50115589c42SPeter Wemm tc, depth + 1, 0); 5020e3d5408SPeter Wemm newicap = icap; /* Put into a register. */ 503aae38d10SBaptiste Daroussin newilen = (int) ilen; 5040e3d5408SPeter Wemm if (iret != TC_SUCCESS) { 5050e3d5408SPeter Wemm /* an error */ 5060e3d5408SPeter Wemm if (iret < TC_NOT_FOUND) { 5070e3d5408SPeter Wemm if (myfd) 5080e3d5408SPeter Wemm (void) close(fd); 5090e3d5408SPeter Wemm free(record); 51073f0a83dSXin LI FreeIfNeeded(icap); 5110e3d5408SPeter Wemm return (iret); 5120e3d5408SPeter Wemm } 51373f0a83dSXin LI if (iret == TC_UNRESOLVED) { 5140e3d5408SPeter Wemm tc_not_resolved = TRUE; 5150e3d5408SPeter Wemm /* couldn't resolve tc */ 51673f0a83dSXin LI } else if (iret == TC_NOT_FOUND) { 5170e3d5408SPeter Wemm *(s - 1) = ':'; 5180e3d5408SPeter Wemm scan = s - 1; 5190e3d5408SPeter Wemm tc_not_resolved = TRUE; 5200e3d5408SPeter Wemm continue; 5210e3d5408SPeter Wemm } 5220e3d5408SPeter Wemm } 5230e3d5408SPeter Wemm 5240e3d5408SPeter Wemm /* not interested in name field of tc'ed record */ 5250e3d5408SPeter Wemm s = newicap; 52615589c42SPeter Wemm while (*s != '\0' && *s++ != ':') ; 527aae38d10SBaptiste Daroussin newilen -= (int) (s - newicap); 5280e3d5408SPeter Wemm newicap = s; 5290e3d5408SPeter Wemm 5300e3d5408SPeter Wemm /* make sure interpolated record is `:'-terminated */ 5310e3d5408SPeter Wemm s += newilen; 5320e3d5408SPeter Wemm if (*(s - 1) != ':') { 5330e3d5408SPeter Wemm *s = ':'; /* overwrite NUL with : */ 5340e3d5408SPeter Wemm newilen++; 5350e3d5408SPeter Wemm } 5360e3d5408SPeter Wemm 5370e3d5408SPeter Wemm /* 5380e3d5408SPeter Wemm * Make sure there's enough room to insert the 5390e3d5408SPeter Wemm * new record. 5400e3d5408SPeter Wemm */ 5410e3d5408SPeter Wemm diff = newilen - tclen; 5420e3d5408SPeter Wemm if (diff >= r_end - rp) { 54315589c42SPeter Wemm unsigned pos, tcpos, tcposend; 5440e3d5408SPeter Wemm size_t newsize; 5450e3d5408SPeter Wemm 546aae38d10SBaptiste Daroussin pos = (unsigned) (rp - record); 547aae38d10SBaptiste Daroussin newsize = (size_t) (r_end - record + diff + BFRAG); 548aae38d10SBaptiste Daroussin tcpos = (unsigned) (tcstart - record); 549aae38d10SBaptiste Daroussin tcposend = (unsigned) (tcend - record); 5500e3d5408SPeter Wemm record = DOALLOC(newsize); 5510e3d5408SPeter Wemm if (record == 0) { 5520e3d5408SPeter Wemm if (myfd) 5530e3d5408SPeter Wemm (void) close(fd); 5540e3d5408SPeter Wemm free(icap); 5550e3d5408SPeter Wemm errno = ENOMEM; 5560e3d5408SPeter Wemm return (TC_SYS_ERR); 5570e3d5408SPeter Wemm } 5580e3d5408SPeter Wemm r_end = record + newsize; 5590e3d5408SPeter Wemm rp = record + pos; 5600e3d5408SPeter Wemm tcstart = record + tcpos; 5610e3d5408SPeter Wemm tcend = record + tcposend; 5620e3d5408SPeter Wemm } 5630e3d5408SPeter Wemm 5640e3d5408SPeter Wemm /* 5650e3d5408SPeter Wemm * Insert tc'ed record into our record. 5660e3d5408SPeter Wemm */ 5670e3d5408SPeter Wemm s = tcstart + newilen; 5680e3d5408SPeter Wemm memmove(s, tcend, (size_t) (rp - tcend)); 5690e3d5408SPeter Wemm memmove(tcstart, newicap, (size_t) newilen); 5700e3d5408SPeter Wemm rp += diff; 5710e3d5408SPeter Wemm free(icap); 5720e3d5408SPeter Wemm 5730e3d5408SPeter Wemm /* 5740e3d5408SPeter Wemm * Start scan on `:' so next cgetcap works properly 5750e3d5408SPeter Wemm * (cgetcap always skips first field). 5760e3d5408SPeter Wemm */ 5770e3d5408SPeter Wemm scan = s - 1; 5780e3d5408SPeter Wemm } 5790e3d5408SPeter Wemm } 5800e3d5408SPeter Wemm 5810e3d5408SPeter Wemm /* 5820e3d5408SPeter Wemm * Close file (if we opened it), give back any extra memory, and 5830e3d5408SPeter Wemm * return capability, length and success. 5840e3d5408SPeter Wemm */ 5850e3d5408SPeter Wemm if (myfd) 5860e3d5408SPeter Wemm (void) close(fd); 587aae38d10SBaptiste Daroussin *len = (unsigned) (rp - record - 1); /* don't count NUL */ 5880e3d5408SPeter Wemm if (r_end > rp) { 5890e3d5408SPeter Wemm if ((record = DOALLOC((size_t) (rp - record))) == 0) { 5900e3d5408SPeter Wemm errno = ENOMEM; 5910e3d5408SPeter Wemm return (TC_SYS_ERR); 5920e3d5408SPeter Wemm } 5930e3d5408SPeter Wemm } 5940e3d5408SPeter Wemm 5950e3d5408SPeter Wemm *cap = record; 59673f0a83dSXin LI if (tc_not_resolved) { 5970e3d5408SPeter Wemm return (TC_UNRESOLVED); 59873f0a83dSXin LI } 5990e3d5408SPeter Wemm return (current); 6000e3d5408SPeter Wemm } 6010e3d5408SPeter Wemm 6020e3d5408SPeter Wemm /* 6030e3d5408SPeter Wemm * Cgetmatch will return 0 if name is one of the names of the capability 6040e3d5408SPeter Wemm * record buf, -1 if not. 6050e3d5408SPeter Wemm */ 6060e3d5408SPeter Wemm static int 6070e3d5408SPeter Wemm _nc_cgetmatch(char *buf, const char *name) 6080e3d5408SPeter Wemm { 6090e3d5408SPeter Wemm register const char *np; 6100e3d5408SPeter Wemm register char *bp; 6110e3d5408SPeter Wemm 6120e3d5408SPeter Wemm /* 6130e3d5408SPeter Wemm * Start search at beginning of record. 6140e3d5408SPeter Wemm */ 6150e3d5408SPeter Wemm bp = buf; 6160e3d5408SPeter Wemm for (;;) { 6170e3d5408SPeter Wemm /* 6180e3d5408SPeter Wemm * Try to match a record name. 6190e3d5408SPeter Wemm */ 6200e3d5408SPeter Wemm np = name; 6210e3d5408SPeter Wemm for (;;) { 6220e3d5408SPeter Wemm if (*np == '\0') { 6230e3d5408SPeter Wemm if (*bp == '|' || *bp == ':' || *bp == '\0') 6240e3d5408SPeter Wemm return (0); 6250e3d5408SPeter Wemm else 6260e3d5408SPeter Wemm break; 6270e3d5408SPeter Wemm } else if (*bp++ != *np++) { 6280e3d5408SPeter Wemm break; 6290e3d5408SPeter Wemm } 6300e3d5408SPeter Wemm } 6310e3d5408SPeter Wemm 6320e3d5408SPeter Wemm /* 6330e3d5408SPeter Wemm * Match failed, skip to next name in record. 6340e3d5408SPeter Wemm */ 6350e3d5408SPeter Wemm bp--; /* a '|' or ':' may have stopped the match */ 6360e3d5408SPeter Wemm for (;;) { 6370e3d5408SPeter Wemm if (*bp == '\0' || *bp == ':') 6380e3d5408SPeter Wemm return (-1); /* match failed totally */ 6390e3d5408SPeter Wemm else if (*bp++ == '|') 6400e3d5408SPeter Wemm break; /* found next name */ 6410e3d5408SPeter Wemm } 6420e3d5408SPeter Wemm } 6430e3d5408SPeter Wemm } 6440e3d5408SPeter Wemm 6450e3d5408SPeter Wemm /* 6460e3d5408SPeter Wemm * Compare name field of record. 6470e3d5408SPeter Wemm */ 6480e3d5408SPeter Wemm static int 6490e3d5408SPeter Wemm _nc_nfcmp(const char *nf, char *rec) 6500e3d5408SPeter Wemm { 6510e3d5408SPeter Wemm char *cp, tmp; 6520e3d5408SPeter Wemm int ret; 6530e3d5408SPeter Wemm 65415589c42SPeter Wemm for (cp = rec; *cp != ':'; cp++) ; 6550e3d5408SPeter Wemm 6560e3d5408SPeter Wemm tmp = *(cp + 1); 6570e3d5408SPeter Wemm *(cp + 1) = '\0'; 6580e3d5408SPeter Wemm ret = strcmp(nf, rec); 6590e3d5408SPeter Wemm *(cp + 1) = tmp; 6600e3d5408SPeter Wemm 6610e3d5408SPeter Wemm return (ret); 6620e3d5408SPeter Wemm } 6630e3d5408SPeter Wemm #endif /* HAVE_BSD_CGETENT */ 6640e3d5408SPeter Wemm 6650e3d5408SPeter Wemm /* 6660e3d5408SPeter Wemm * Since ncurses provides its own 'tgetent()', we cannot use the native one. 6670e3d5408SPeter Wemm * So we reproduce the logic to get down to cgetent() -- or our cut-down 6680e3d5408SPeter Wemm * version of that -- to circumvent the problem of configuring against the 6690e3d5408SPeter Wemm * termcap library. 6700e3d5408SPeter Wemm */ 6710e3d5408SPeter Wemm #define USE_BSD_TGETENT 1 6720e3d5408SPeter Wemm 6730e3d5408SPeter Wemm #if USE_BSD_TGETENT 6740e3d5408SPeter Wemm /* 6750e3d5408SPeter Wemm * Copyright (c) 1980, 1993 6760e3d5408SPeter Wemm * The Regents of the University of California. All rights reserved. 6770e3d5408SPeter Wemm * 6780e3d5408SPeter Wemm * Redistribution and use in source and binary forms, with or without 6790e3d5408SPeter Wemm * modification, are permitted provided that the following conditions 6800e3d5408SPeter Wemm * are met: 6810e3d5408SPeter Wemm * 1. Redistributions of source code must retain the above copyright 6820e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer. 6830e3d5408SPeter Wemm * 2. Redistributions in binary form must reproduce the above copyright 6840e3d5408SPeter Wemm * notice, this list of conditions and the following disclaimer in the 6850e3d5408SPeter Wemm * documentation and/or other materials provided with the distribution. 6860e3d5408SPeter Wemm * 3. All advertising materials mentioning features or use of this software 6870e3d5408SPeter Wemm * must display the following acknowledgment: 6880e3d5408SPeter Wemm * This product includes software developed by the University of 6890e3d5408SPeter Wemm * California, Berkeley and its contributors. 6900e3d5408SPeter Wemm * 4. Neither the name of the University nor the names of its contributors 6910e3d5408SPeter Wemm * may be used to endorse or promote products derived from this software 6920e3d5408SPeter Wemm * without specific prior written permission. 6930e3d5408SPeter Wemm * 6940e3d5408SPeter Wemm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 6950e3d5408SPeter Wemm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6960e3d5408SPeter Wemm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 6970e3d5408SPeter Wemm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 6980e3d5408SPeter Wemm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 6990e3d5408SPeter Wemm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 7000e3d5408SPeter Wemm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 7010e3d5408SPeter Wemm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 7020e3d5408SPeter Wemm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 7030e3d5408SPeter Wemm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 7040e3d5408SPeter Wemm * SUCH DAMAGE. 7050e3d5408SPeter Wemm */ 7060e3d5408SPeter Wemm 7070e3d5408SPeter Wemm /* static char sccsid[] = "@(#)termcap.c 8.1 (Berkeley) 6/4/93" */ 7080e3d5408SPeter Wemm 7090e3d5408SPeter Wemm #define PBUFSIZ 512 /* max length of filename path */ 7100e3d5408SPeter Wemm #define PVECSIZ 32 /* max number of names in path */ 7110e3d5408SPeter Wemm #define TBUFSIZ (2048*2) 7120e3d5408SPeter Wemm 7130e3d5408SPeter Wemm /* 7140e3d5408SPeter Wemm * On entry, srcp points to a non ':' character which is the beginning of the 7150e3d5408SPeter Wemm * token, if any. We'll try to return a string that doesn't end with a ':'. 7160e3d5408SPeter Wemm */ 7170e3d5408SPeter Wemm static char * 7180e3d5408SPeter Wemm get_tc_token(char **srcp, int *endp) 7190e3d5408SPeter Wemm { 7200e3d5408SPeter Wemm int ch; 7210e3d5408SPeter Wemm bool found = FALSE; 7220e3d5408SPeter Wemm char *s, *base; 7230e3d5408SPeter Wemm char *tok = 0; 7240e3d5408SPeter Wemm 7250e3d5408SPeter Wemm *endp = TRUE; 7260e3d5408SPeter Wemm for (s = base = *srcp; *s != '\0';) { 7270e3d5408SPeter Wemm ch = *s++; 7280e3d5408SPeter Wemm if (ch == '\\') { 7290e3d5408SPeter Wemm if (*s == '\0') { 7300e3d5408SPeter Wemm break; 7310e3d5408SPeter Wemm } else if (*s++ == '\n') { 7324a1a9510SRong-En Fan while (isspace(UChar(*s))) 7330e3d5408SPeter Wemm s++; 7340e3d5408SPeter Wemm } else { 7350e3d5408SPeter Wemm found = TRUE; 7360e3d5408SPeter Wemm } 7370e3d5408SPeter Wemm } else if (ch == ':') { 7380e3d5408SPeter Wemm if (found) { 7390e3d5408SPeter Wemm tok = base; 7400e3d5408SPeter Wemm s[-1] = '\0'; 7410e3d5408SPeter Wemm *srcp = s; 7420e3d5408SPeter Wemm *endp = FALSE; 7430e3d5408SPeter Wemm break; 7440e3d5408SPeter Wemm } 7450e3d5408SPeter Wemm base = s; 7464a1a9510SRong-En Fan } else if (isgraph(UChar(ch))) { 7470e3d5408SPeter Wemm found = TRUE; 7480e3d5408SPeter Wemm } 7490e3d5408SPeter Wemm } 7500e3d5408SPeter Wemm 7510e3d5408SPeter Wemm /* malformed entry may end without a ':' */ 7520e3d5408SPeter Wemm if (tok == 0 && found) { 7530e3d5408SPeter Wemm tok = base; 7540e3d5408SPeter Wemm } 7550e3d5408SPeter Wemm 7560e3d5408SPeter Wemm return tok; 7570e3d5408SPeter Wemm } 7580e3d5408SPeter Wemm 7590e3d5408SPeter Wemm static char * 7600e3d5408SPeter Wemm copy_tc_token(char *dst, const char *src, size_t len) 7610e3d5408SPeter Wemm { 7620e3d5408SPeter Wemm int ch; 7630e3d5408SPeter Wemm 7640e3d5408SPeter Wemm while ((ch = *src++) != '\0') { 7650e3d5408SPeter Wemm if (ch == '\\' && *src == '\n') { 7664a1a9510SRong-En Fan while (isspace(UChar(*src))) 7670e3d5408SPeter Wemm src++; 7680e3d5408SPeter Wemm continue; 7690e3d5408SPeter Wemm } 7700e3d5408SPeter Wemm if (--len == 0) { 7710e3d5408SPeter Wemm dst = 0; 7720e3d5408SPeter Wemm break; 7730e3d5408SPeter Wemm } 77473f0a83dSXin LI *dst++ = (char) ch; 7750e3d5408SPeter Wemm } 7760e3d5408SPeter Wemm return dst; 7770e3d5408SPeter Wemm } 7780e3d5408SPeter Wemm 7790e3d5408SPeter Wemm /* 7800e3d5408SPeter Wemm * Get an entry for terminal name in buffer bp from the termcap file. 7810e3d5408SPeter Wemm */ 7820e3d5408SPeter Wemm static int 7830e3d5408SPeter Wemm _nc_tgetent(char *bp, char **sourcename, int *lineno, const char *name) 7840e3d5408SPeter Wemm { 7850e3d5408SPeter Wemm static char *the_source; 7860e3d5408SPeter Wemm 7870e3d5408SPeter Wemm register char *p; 7880e3d5408SPeter Wemm register char *cp; 7897a69bbfbSPeter Wemm char *dummy = NULL; 79073f0a83dSXin LI CGETENT_CONST char **fname; 7910e3d5408SPeter Wemm char *home; 7920e3d5408SPeter Wemm int i; 7930e3d5408SPeter Wemm char pathbuf[PBUFSIZ]; /* holds raw path of filenames */ 79473f0a83dSXin LI CGETENT_CONST char *pathvec[PVECSIZ]; /* point to names in pathbuf */ 795aae38d10SBaptiste Daroussin const char *termpath; 79618259542SPeter Wemm string_desc desc; 7970e3d5408SPeter Wemm 79873f0a83dSXin LI *lineno = 1; 7990e3d5408SPeter Wemm fname = pathvec; 8000e3d5408SPeter Wemm p = pathbuf; 80118259542SPeter Wemm cp = use_terminfo_vars()? getenv("TERMCAP") : NULL; 8020e3d5408SPeter Wemm 8030e3d5408SPeter Wemm /* 80415589c42SPeter Wemm * TERMCAP can have one of two things in it. It can be the name of a file 80515589c42SPeter Wemm * to use instead of /etc/termcap. In this case it better start with a 80615589c42SPeter Wemm * "/". Or it can be an entry to use so we don't have to read the file. 80715589c42SPeter Wemm * In this case it has to already have the newlines crunched out. If 80815589c42SPeter Wemm * TERMCAP does not hold a file name then a path of names is searched 80915589c42SPeter Wemm * instead. The path is found in the TERMPATH variable, or becomes 81015589c42SPeter Wemm * "$HOME/.termcap /etc/termcap" if no TERMPATH exists. 8110e3d5408SPeter Wemm */ 81218259542SPeter Wemm _nc_str_init(&desc, pathbuf, sizeof(pathbuf)); 81318259542SPeter Wemm if (cp == NULL) { 81439f2269fSPeter Wemm _nc_safe_strcpy(&desc, get_termpath()); 8154a1a9510SRong-En Fan } else if (!_nc_is_abs_path(cp)) { /* TERMCAP holds an entry */ 81639f2269fSPeter Wemm if ((termpath = get_termpath()) != 0) { 81718259542SPeter Wemm _nc_safe_strcat(&desc, termpath); 8180e3d5408SPeter Wemm } else { 81918259542SPeter Wemm char temp[PBUFSIZ]; 82018259542SPeter Wemm temp[0] = 0; 82118259542SPeter Wemm if ((home = getenv("HOME")) != 0 && *home != '\0' 82218259542SPeter Wemm && strchr(home, ' ') == 0 82318259542SPeter Wemm && strlen(home) < sizeof(temp) - 10) { /* setup path */ 82473f0a83dSXin LI _nc_SPRINTF(temp, _nc_SLIMIT(sizeof(temp)) 82573f0a83dSXin LI "%s/", home); /* $HOME first */ 8260e3d5408SPeter Wemm } 82718259542SPeter Wemm /* if no $HOME look in current directory */ 82873f0a83dSXin LI _nc_STRCAT(temp, ".termcap", sizeof(temp)); 82918259542SPeter Wemm _nc_safe_strcat(&desc, temp); 83039f2269fSPeter Wemm _nc_safe_strcat(&desc, " "); 83139f2269fSPeter Wemm _nc_safe_strcat(&desc, get_termpath()); 83218259542SPeter Wemm } 83318259542SPeter Wemm } else { /* user-defined name in TERMCAP */ 83418259542SPeter Wemm _nc_safe_strcat(&desc, cp); /* still can be tokenized */ 83518259542SPeter Wemm } 8360e3d5408SPeter Wemm 8370e3d5408SPeter Wemm *fname++ = pathbuf; /* tokenize path into vector of names */ 8380e3d5408SPeter Wemm while (*++p) { 8397a69bbfbSPeter Wemm if (*p == ' ' || *p == NCURSES_PATHSEP) { 8400e3d5408SPeter Wemm *p = '\0'; 8410e3d5408SPeter Wemm while (*++p) 8427a69bbfbSPeter Wemm if (*p != ' ' && *p != NCURSES_PATHSEP) 8430e3d5408SPeter Wemm break; 8440e3d5408SPeter Wemm if (*p == '\0') 8450e3d5408SPeter Wemm break; 8460e3d5408SPeter Wemm *fname++ = p; 8470e3d5408SPeter Wemm if (fname >= pathvec + PVECSIZ) { 8480e3d5408SPeter Wemm fname--; 8490e3d5408SPeter Wemm break; 8500e3d5408SPeter Wemm } 8510e3d5408SPeter Wemm } 8520e3d5408SPeter Wemm } 8530e3d5408SPeter Wemm *fname = 0; /* mark end of vector */ 85473f0a83dSXin LI #if !HAVE_BSD_CGETENT 85573f0a83dSXin LI (void) _nc_cgetset(0); 85673f0a83dSXin LI #endif 8574a1a9510SRong-En Fan if (_nc_is_abs_path(cp)) { 8580e3d5408SPeter Wemm if (_nc_cgetset(cp) < 0) { 8590e3d5408SPeter Wemm return (TC_SYS_ERR); 8600e3d5408SPeter Wemm } 8610e3d5408SPeter Wemm } 8620e3d5408SPeter Wemm 8630e3d5408SPeter Wemm i = _nc_cgetent(&dummy, lineno, pathvec, name); 8640e3d5408SPeter Wemm 8650e3d5408SPeter Wemm /* ncurses' termcap-parsing routines cannot handle multiple adjacent 8660e3d5408SPeter Wemm * empty fields, and mistakenly use the last valid cap entry instead of 8670e3d5408SPeter Wemm * the first (breaks tc= includes) 8680e3d5408SPeter Wemm */ 86973f0a83dSXin LI *bp = '\0'; 8700e3d5408SPeter Wemm if (i >= 0) { 8710e3d5408SPeter Wemm char *pd, *ps, *tok; 8720e3d5408SPeter Wemm int endflag = FALSE; 8730e3d5408SPeter Wemm char *list[1023]; 8740e3d5408SPeter Wemm size_t n, count = 0; 8750e3d5408SPeter Wemm 8760e3d5408SPeter Wemm pd = bp; 8770e3d5408SPeter Wemm ps = dummy; 8780e3d5408SPeter Wemm while (!endflag && (tok = get_tc_token(&ps, &endflag)) != 0) { 8790e3d5408SPeter Wemm bool ignore = FALSE; 8800e3d5408SPeter Wemm 8810e3d5408SPeter Wemm for (n = 1; n < count; n++) { 8820e3d5408SPeter Wemm char *s = list[n]; 8830e3d5408SPeter Wemm if (s[0] == tok[0] 8840e3d5408SPeter Wemm && s[1] == tok[1]) { 8850e3d5408SPeter Wemm ignore = TRUE; 8860e3d5408SPeter Wemm break; 8870e3d5408SPeter Wemm } 8880e3d5408SPeter Wemm } 8890e3d5408SPeter Wemm if (ignore != TRUE) { 8900e3d5408SPeter Wemm list[count++] = tok; 89173f0a83dSXin LI pd = copy_tc_token(pd, tok, (size_t) (TBUFSIZ - (2 + pd - bp))); 8920e3d5408SPeter Wemm if (pd == 0) { 8930e3d5408SPeter Wemm i = -1; 8940e3d5408SPeter Wemm break; 8950e3d5408SPeter Wemm } 8960e3d5408SPeter Wemm *pd++ = ':'; 8970e3d5408SPeter Wemm *pd = '\0'; 8980e3d5408SPeter Wemm } 8990e3d5408SPeter Wemm } 9000e3d5408SPeter Wemm } 9010e3d5408SPeter Wemm 9020e3d5408SPeter Wemm FreeIfNeeded(dummy); 9030e3d5408SPeter Wemm FreeIfNeeded(the_source); 9040e3d5408SPeter Wemm the_source = 0; 9050e3d5408SPeter Wemm 9060e3d5408SPeter Wemm /* This is not related to the BSD cgetent(), but to fake up a suitable 9070e3d5408SPeter Wemm * filename for ncurses' error reporting. (If we are not using BSD 9080e3d5408SPeter Wemm * cgetent, then it is the actual filename). 9090e3d5408SPeter Wemm */ 9100e3d5408SPeter Wemm if (i >= 0) { 9114a1a9510SRong-En Fan #if HAVE_BSD_CGETENT 9124a1a9510SRong-En Fan char temp[PATH_MAX]; 9134a1a9510SRong-En Fan 9144a1a9510SRong-En Fan _nc_str_init(&desc, temp, sizeof(temp)); 9154a1a9510SRong-En Fan _nc_safe_strcpy(&desc, pathvec[i]); 9164a1a9510SRong-En Fan _nc_safe_strcat(&desc, ".db"); 9174a1a9510SRong-En Fan if (_nc_access(temp, R_OK) == 0) { 9184a1a9510SRong-En Fan _nc_safe_strcpy(&desc, pathvec[i]); 9194a1a9510SRong-En Fan } 9204a1a9510SRong-En Fan if ((the_source = strdup(temp)) != 0) 9214a1a9510SRong-En Fan *sourcename = the_source; 9224a1a9510SRong-En Fan #else 9230e3d5408SPeter Wemm if ((the_source = strdup(pathvec[i])) != 0) 9240e3d5408SPeter Wemm *sourcename = the_source; 9254a1a9510SRong-En Fan #endif 9260e3d5408SPeter Wemm } 9270e3d5408SPeter Wemm 9280e3d5408SPeter Wemm return (i); 9290e3d5408SPeter Wemm } 9300e3d5408SPeter Wemm #endif /* USE_BSD_TGETENT */ 9310e3d5408SPeter Wemm #endif /* USE_GETCAP */ 9320e3d5408SPeter Wemm 9330e3d5408SPeter Wemm #define MAXPATHS 32 9340e3d5408SPeter Wemm 9350e3d5408SPeter Wemm /* 9360e3d5408SPeter Wemm * Add a filename to the list in 'termpaths[]', checking that we really have 9370e3d5408SPeter Wemm * a right to open the file. 9380e3d5408SPeter Wemm */ 9390e3d5408SPeter Wemm #if !USE_GETCAP 94015589c42SPeter Wemm static int 94115589c42SPeter Wemm add_tc(char *termpaths[], char *path, int count) 9420e3d5408SPeter Wemm { 94339f2269fSPeter Wemm char *save = strchr(path, NCURSES_PATHSEP); 94439f2269fSPeter Wemm if (save != 0) 94539f2269fSPeter Wemm *save = '\0'; 9460e3d5408SPeter Wemm if (count < MAXPATHS 94739f2269fSPeter Wemm && _nc_access(path, R_OK) == 0) { 9480e3d5408SPeter Wemm termpaths[count++] = path; 94973f0a83dSXin LI TR(TRACE_DATABASE, ("Adding termpath %s", path)); 95039f2269fSPeter Wemm } 9510e3d5408SPeter Wemm termpaths[count] = 0; 95239f2269fSPeter Wemm if (save != 0) 95339f2269fSPeter Wemm *save = NCURSES_PATHSEP; 9540e3d5408SPeter Wemm return count; 9550e3d5408SPeter Wemm } 9560e3d5408SPeter Wemm #define ADD_TC(path, count) filecount = add_tc(termpaths, path, count) 9570e3d5408SPeter Wemm #endif /* !USE_GETCAP */ 9580e3d5408SPeter Wemm 9597a69bbfbSPeter Wemm NCURSES_EXPORT(int) 960aae38d10SBaptiste Daroussin _nc_read_termcap_entry(const char *const tn, TERMTYPE2 *const tp) 9610e3d5408SPeter Wemm { 9624a1a9510SRong-En Fan int found = TGETENT_NO; 9630e3d5408SPeter Wemm ENTRY *ep; 9640e3d5408SPeter Wemm #if USE_GETCAP_CACHE 9650e3d5408SPeter Wemm char cwd_buf[PATH_MAX]; 9660e3d5408SPeter Wemm #endif 9670e3d5408SPeter Wemm #if USE_GETCAP 96815589c42SPeter Wemm char *p, tc[TBUFSIZ]; 969aae38d10SBaptiste Daroussin char *tc_buf = 0; 970aae38d10SBaptiste Daroussin #define MY_SIZE sizeof(tc) - 1 9714a1a9510SRong-En Fan int status; 9720e3d5408SPeter Wemm static char *source; 9730e3d5408SPeter Wemm static int lineno; 9740e3d5408SPeter Wemm 97573f0a83dSXin LI TR(TRACE_DATABASE, ("read termcap entry for %s", tn)); 9764a1a9510SRong-En Fan 9774a1a9510SRong-En Fan if (strlen(tn) == 0 9784a1a9510SRong-En Fan || strcmp(tn, ".") == 0 9794a1a9510SRong-En Fan || strcmp(tn, "..") == 0 9804a1a9510SRong-En Fan || _nc_pathlast(tn) != 0) { 98173f0a83dSXin LI TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", tn)); 9824a1a9510SRong-En Fan return TGETENT_NO; 9834a1a9510SRong-En Fan } 9844a1a9510SRong-En Fan 98518259542SPeter Wemm if (use_terminfo_vars() && (p = getenv("TERMCAP")) != 0 9864a1a9510SRong-En Fan && !_nc_is_abs_path(p) && _nc_name_match(p, tn, "|:")) { 98715589c42SPeter Wemm /* TERMCAP holds a termcap entry */ 988aae38d10SBaptiste Daroussin tc_buf = strdup(p); 98915589c42SPeter Wemm _nc_set_source("TERMCAP"); 99015589c42SPeter Wemm } else { 9910e3d5408SPeter Wemm /* we're using getcap(3) */ 9924a1a9510SRong-En Fan if ((status = _nc_tgetent(tc, &source, &lineno, tn)) < 0) 9934a1a9510SRong-En Fan return (status == TC_NOT_FOUND ? TGETENT_NO : TGETENT_ERR); 9940e3d5408SPeter Wemm 9950e3d5408SPeter Wemm _nc_curr_line = lineno; 9960e3d5408SPeter Wemm _nc_set_source(source); 997aae38d10SBaptiste Daroussin tc_buf = tc; 99815589c42SPeter Wemm } 999aae38d10SBaptiste Daroussin if (tc_buf == 0) 1000aae38d10SBaptiste Daroussin return (TGETENT_ERR); 1001aae38d10SBaptiste Daroussin _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, TRUE, NULLHOOK); 1002aae38d10SBaptiste Daroussin if (tc_buf != tc) 1003aae38d10SBaptiste Daroussin free(tc_buf); 10040e3d5408SPeter Wemm #else 10050e3d5408SPeter Wemm /* 10060e3d5408SPeter Wemm * Here is what the 4.4BSD termcap(3) page prescribes: 10070e3d5408SPeter Wemm * 100815589c42SPeter Wemm * It will look in the environment for a TERMCAP variable. If found, and 100915589c42SPeter Wemm * the value does not begin with a slash, and the terminal type name is the 101015589c42SPeter Wemm * same as the environment string TERM, the TERMCAP string is used instead 101115589c42SPeter Wemm * of reading a termcap file. If it does begin with a slash, the string is 101215589c42SPeter Wemm * used as a path name of the termcap file to search. If TERMCAP does not 101315589c42SPeter Wemm * begin with a slash and name is different from TERM, tgetent() searches 101415589c42SPeter Wemm * the files $HOME/.termcap and /usr/share/misc/termcap, in that order, 101515589c42SPeter Wemm * unless the environment variable TERMPATH exists, in which case it 101615589c42SPeter Wemm * specifies a list of file pathnames (separated by spaces or colons) to be 101715589c42SPeter Wemm * searched instead. 10180e3d5408SPeter Wemm * 10190e3d5408SPeter Wemm * It goes on to state: 10200e3d5408SPeter Wemm * 10210e3d5408SPeter Wemm * Whenever multiple files are searched and a tc field occurs in the 102215589c42SPeter Wemm * requested entry, the entry it names must be found in the same file or 102315589c42SPeter Wemm * one of the succeeding files. 10240e3d5408SPeter Wemm * 10250e3d5408SPeter Wemm * However, this restriction is relaxed in ncurses; tc references to 10260e3d5408SPeter Wemm * previous files are permitted. 10270e3d5408SPeter Wemm * 102815589c42SPeter Wemm * This routine returns 1 if an entry is found, 0 if not found, and -1 if 102915589c42SPeter Wemm * the database is not accessible. 10300e3d5408SPeter Wemm */ 10310e3d5408SPeter Wemm FILE *fp; 10320e3d5408SPeter Wemm char *tc, *termpaths[MAXPATHS]; 10330e3d5408SPeter Wemm int filecount = 0; 103439f2269fSPeter Wemm int j, k; 10350e3d5408SPeter Wemm bool use_buffer = FALSE; 103639f2269fSPeter Wemm bool normal = TRUE; 1037aae38d10SBaptiste Daroussin char *tc_buf = 0; 10380e3d5408SPeter Wemm char pathbuf[PATH_MAX]; 103939f2269fSPeter Wemm char *copied = 0; 104039f2269fSPeter Wemm char *cp; 104139f2269fSPeter Wemm struct stat test_stat[MAXPATHS]; 10420e3d5408SPeter Wemm 10430e3d5408SPeter Wemm termpaths[filecount] = 0; 104418259542SPeter Wemm if (use_terminfo_vars() && (tc = getenv("TERMCAP")) != 0) { 10454a1a9510SRong-En Fan if (_nc_is_abs_path(tc)) { /* interpret as a filename */ 10460e3d5408SPeter Wemm ADD_TC(tc, 0); 104739f2269fSPeter Wemm normal = FALSE; 104815589c42SPeter Wemm } else if (_nc_name_match(tc, tn, "|:")) { /* treat as a capability file */ 1049aae38d10SBaptiste Daroussin tc_buf = strdup(tc); 1050aae38d10SBaptiste Daroussin use_buffer = (tc_buf != 0); 105139f2269fSPeter Wemm normal = FALSE; 105239f2269fSPeter Wemm } 105339f2269fSPeter Wemm } 10540e3d5408SPeter Wemm 105539f2269fSPeter Wemm if (normal) { /* normal case */ 105639f2269fSPeter Wemm char envhome[PATH_MAX], *h; 105739f2269fSPeter Wemm 105839f2269fSPeter Wemm copied = strdup(get_termpath()); 105939f2269fSPeter Wemm for (cp = copied; *cp; cp++) { 10607a69bbfbSPeter Wemm if (*cp == NCURSES_PATHSEP) 10610e3d5408SPeter Wemm *cp = '\0'; 106239f2269fSPeter Wemm else if (cp == copied || cp[-1] == '\0') { 10630e3d5408SPeter Wemm ADD_TC(cp, filecount); 10640e3d5408SPeter Wemm } 10650e3d5408SPeter Wemm } 10660e3d5408SPeter Wemm 10670e3d5408SPeter Wemm #define PRIVATE_CAP "%s/.termcap" 10680e3d5408SPeter Wemm 10697a69bbfbSPeter Wemm if (use_terminfo_vars() && (h = getenv("HOME")) != NULL && *h != '\0' 107015589c42SPeter Wemm && (strlen(h) + sizeof(PRIVATE_CAP)) < PATH_MAX) { 10710e3d5408SPeter Wemm /* user's .termcap, if any, should override it */ 107273f0a83dSXin LI _nc_STRCPY(envhome, h, sizeof(envhome)); 107373f0a83dSXin LI _nc_SPRINTF(pathbuf, _nc_SLIMIT(sizeof(pathbuf)) 107473f0a83dSXin LI PRIVATE_CAP, envhome); 10750e3d5408SPeter Wemm ADD_TC(pathbuf, filecount); 10760e3d5408SPeter Wemm } 10770e3d5408SPeter Wemm } 10780e3d5408SPeter Wemm 107939f2269fSPeter Wemm /* 108039f2269fSPeter Wemm * Probably /etc/termcap is a symlink to /usr/share/misc/termcap. 108139f2269fSPeter Wemm * Avoid reading the same file twice. 108239f2269fSPeter Wemm */ 10834a1a9510SRong-En Fan #if HAVE_LINK 108439f2269fSPeter Wemm for (j = 0; j < filecount; j++) { 108539f2269fSPeter Wemm bool omit = FALSE; 108639f2269fSPeter Wemm if (stat(termpaths[j], &test_stat[j]) != 0 108773f0a83dSXin LI || !S_ISREG(test_stat[j].st_mode)) { 108839f2269fSPeter Wemm omit = TRUE; 108939f2269fSPeter Wemm } else { 109039f2269fSPeter Wemm for (k = 0; k < j; k++) { 109139f2269fSPeter Wemm if (test_stat[k].st_dev == test_stat[j].st_dev 109239f2269fSPeter Wemm && test_stat[k].st_ino == test_stat[j].st_ino) { 109339f2269fSPeter Wemm omit = TRUE; 109439f2269fSPeter Wemm break; 109539f2269fSPeter Wemm } 109639f2269fSPeter Wemm } 109739f2269fSPeter Wemm } 109839f2269fSPeter Wemm if (omit) { 109973f0a83dSXin LI TR(TRACE_DATABASE, ("Path %s is a duplicate", termpaths[j])); 110039f2269fSPeter Wemm for (k = j + 1; k < filecount; k++) { 110139f2269fSPeter Wemm termpaths[k - 1] = termpaths[k]; 110239f2269fSPeter Wemm test_stat[k - 1] = test_stat[k]; 110339f2269fSPeter Wemm } 110439f2269fSPeter Wemm --filecount; 110539f2269fSPeter Wemm --j; 110639f2269fSPeter Wemm } 110739f2269fSPeter Wemm } 110839f2269fSPeter Wemm #endif 110939f2269fSPeter Wemm 11100e3d5408SPeter Wemm /* parse the sources */ 111115589c42SPeter Wemm if (use_buffer) { 11120e3d5408SPeter Wemm _nc_set_source("TERMCAP"); 11130e3d5408SPeter Wemm 11140e3d5408SPeter Wemm /* 11150e3d5408SPeter Wemm * We don't suppress warning messages here. The presumption is 11160e3d5408SPeter Wemm * that since it's just a single entry, they won't be a pain. 11170e3d5408SPeter Wemm */ 11180e3d5408SPeter Wemm _nc_read_entry_source((FILE *) 0, tc_buf, FALSE, FALSE, NULLHOOK); 1119aae38d10SBaptiste Daroussin free(tc_buf); 11200e3d5408SPeter Wemm } else { 11210e3d5408SPeter Wemm int i; 11220e3d5408SPeter Wemm 11230e3d5408SPeter Wemm for (i = 0; i < filecount; i++) { 11240e3d5408SPeter Wemm 112573f0a83dSXin LI TR(TRACE_DATABASE, ("Looking for %s in %s", tn, termpaths[i])); 112639f2269fSPeter Wemm if (_nc_access(termpaths[i], R_OK) == 0 112739f2269fSPeter Wemm && (fp = fopen(termpaths[i], "r")) != (FILE *) 0) { 11280e3d5408SPeter Wemm _nc_set_source(termpaths[i]); 11290e3d5408SPeter Wemm 11300e3d5408SPeter Wemm /* 113115589c42SPeter Wemm * Suppress warning messages. Otherwise you get 400 lines of 113215589c42SPeter Wemm * crap from archaic termcap files as ncurses complains about 113315589c42SPeter Wemm * all the obsolete capabilities. 11340e3d5408SPeter Wemm */ 11350e3d5408SPeter Wemm _nc_read_entry_source(fp, (char *) 0, FALSE, TRUE, NULLHOOK); 11360e3d5408SPeter Wemm 11370e3d5408SPeter Wemm (void) fclose(fp); 11380e3d5408SPeter Wemm } 11390e3d5408SPeter Wemm } 11400e3d5408SPeter Wemm } 114139f2269fSPeter Wemm if (copied != 0) 114239f2269fSPeter Wemm free(copied); 11430e3d5408SPeter Wemm #endif /* USE_GETCAP */ 11440e3d5408SPeter Wemm 11450e3d5408SPeter Wemm if (_nc_head == 0) 11464a1a9510SRong-En Fan return (TGETENT_ERR); 11470e3d5408SPeter Wemm 11480e3d5408SPeter Wemm /* resolve all use references */ 1149aae38d10SBaptiste Daroussin if (_nc_resolve_uses2(TRUE, FALSE) != TRUE) 1150aae38d10SBaptiste Daroussin return (TGETENT_ERR); 11510e3d5408SPeter Wemm 11520e3d5408SPeter Wemm /* find a terminal matching tn, if we can */ 11530e3d5408SPeter Wemm #if USE_GETCAP_CACHE 115415589c42SPeter Wemm if (getcwd(cwd_buf, sizeof(cwd_buf)) != 0) { 11550e3d5408SPeter Wemm _nc_set_writedir((char *) 0); /* note: this does a chdir */ 11560e3d5408SPeter Wemm #endif 11570e3d5408SPeter Wemm for_entry_list(ep) { 115815589c42SPeter Wemm if (_nc_name_match(ep->tterm.term_names, tn, "|:")) { 11590e3d5408SPeter Wemm /* 11604a1a9510SRong-En Fan * Make a local copy of the terminal capabilities, delinked 11614a1a9510SRong-En Fan * from the list. 11620e3d5408SPeter Wemm */ 11630e3d5408SPeter Wemm *tp = ep->tterm; 116473f0a83dSXin LI _nc_free_entry(_nc_head, &(ep->tterm)); 11650e3d5408SPeter Wemm 11660e3d5408SPeter Wemm /* 116715589c42SPeter Wemm * OK, now try to write the type to user's terminfo directory. 116815589c42SPeter Wemm * Next time he loads this, it will come through terminfo. 11690e3d5408SPeter Wemm * 117015589c42SPeter Wemm * Advantage: Second and subsequent fetches of this entry will 117115589c42SPeter Wemm * be very fast. 11720e3d5408SPeter Wemm * 117315589c42SPeter Wemm * Disadvantage: After the first time a termcap type is loaded 117415589c42SPeter Wemm * by its user, editing it in the /etc/termcap file, or in 117515589c42SPeter Wemm * TERMCAP, or in a local ~/.termcap, will be ineffective 117615589c42SPeter Wemm * unless the terminfo entry is explicitly removed. 11770e3d5408SPeter Wemm */ 11780e3d5408SPeter Wemm #if USE_GETCAP_CACHE 11790e3d5408SPeter Wemm (void) _nc_write_entry(tp); 11800e3d5408SPeter Wemm #endif 11814a1a9510SRong-En Fan found = TGETENT_YES; 11820e3d5408SPeter Wemm break; 11830e3d5408SPeter Wemm } 11840e3d5408SPeter Wemm } 11850e3d5408SPeter Wemm #if USE_GETCAP_CACHE 11860e3d5408SPeter Wemm chdir(cwd_buf); 11870e3d5408SPeter Wemm } 11880e3d5408SPeter Wemm #endif 11890e3d5408SPeter Wemm 11900e3d5408SPeter Wemm return (found); 11910e3d5408SPeter Wemm } 11920e3d5408SPeter Wemm #else 11937a69bbfbSPeter Wemm extern 11947a69bbfbSPeter Wemm NCURSES_EXPORT(void) 11957a69bbfbSPeter Wemm _nc_read_termcap(void); 11967a69bbfbSPeter Wemm NCURSES_EXPORT(void) 119715589c42SPeter Wemm _nc_read_termcap(void) 119815589c42SPeter Wemm { 119915589c42SPeter Wemm } 12000e3d5408SPeter Wemm #endif /* PURE_TERMINFO */ 1201