1  | 
     | 
     | 
    /* $OpenBSD: read_entry.c,v 1.17 2015/12/03 11:29:55 nicm Exp $ */  | 
    
    
    2  | 
     | 
     | 
     | 
    
    
    3  | 
     | 
     | 
    /****************************************************************************  | 
    
    
    4  | 
     | 
     | 
     * Copyright (c) 1998-2007,2008 Free Software Foundation, Inc.              *  | 
    
    
    5  | 
     | 
     | 
     *                                                                          *  | 
    
    
    6  | 
     | 
     | 
     * Permission is hereby granted, free of charge, to any person obtaining a  *  | 
    
    
    7  | 
     | 
     | 
     * copy of this software and associated documentation files (the            *  | 
    
    
    8  | 
     | 
     | 
     * "Software"), to deal in the Software without restriction, including      *  | 
    
    
    9  | 
     | 
     | 
     * without limitation the rights to use, copy, modify, merge, publish,      *  | 
    
    
    10  | 
     | 
     | 
     * distribute, distribute with modifications, sublicense, and/or sell       *  | 
    
    
    11  | 
     | 
     | 
     * copies of the Software, and to permit persons to whom the Software is    *  | 
    
    
    12  | 
     | 
     | 
     * furnished to do so, subject to the following conditions:                 *  | 
    
    
    13  | 
     | 
     | 
     *                                                                          *  | 
    
    
    14  | 
     | 
     | 
     * The above copyright notice and this permission notice shall be included  *  | 
    
    
    15  | 
     | 
     | 
     * in all copies or substantial portions of the Software.                   *  | 
    
    
    16  | 
     | 
     | 
     *                                                                          *  | 
    
    
    17  | 
     | 
     | 
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *  | 
    
    
    18  | 
     | 
     | 
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *  | 
    
    
    19  | 
     | 
     | 
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *  | 
    
    
    20  | 
     | 
     | 
     * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *  | 
    
    
    21  | 
     | 
     | 
     * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *  | 
    
    
    22  | 
     | 
     | 
     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *  | 
    
    
    23  | 
     | 
     | 
     * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *  | 
    
    
    24  | 
     | 
     | 
     *                                                                          *  | 
    
    
    25  | 
     | 
     | 
     * Except as contained in this notice, the name(s) of the above copyright   *  | 
    
    
    26  | 
     | 
     | 
     * holders shall not be used in advertising or otherwise to promote the     *  | 
    
    
    27  | 
     | 
     | 
     * sale, use or other dealings in this Software without prior written       *  | 
    
    
    28  | 
     | 
     | 
     * authorization.                                                           *  | 
    
    
    29  | 
     | 
     | 
     ****************************************************************************/  | 
    
    
    30  | 
     | 
     | 
     | 
    
    
    31  | 
     | 
     | 
    /****************************************************************************  | 
    
    
    32  | 
     | 
     | 
     *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *  | 
    
    
    33  | 
     | 
     | 
     *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *  | 
    
    
    34  | 
     | 
     | 
     *     and: Thomas E. Dickey                        1996-on                 *  | 
    
    
    35  | 
     | 
     | 
     ****************************************************************************/  | 
    
    
    36  | 
     | 
     | 
     | 
    
    
    37  | 
     | 
     | 
    /*  | 
    
    
    38  | 
     | 
     | 
     *	read_entry.c -- Routine for reading in a compiled terminfo file  | 
    
    
    39  | 
     | 
     | 
     */  | 
    
    
    40  | 
     | 
     | 
     | 
    
    
    41  | 
     | 
     | 
    #include <curses.priv.h>  | 
    
    
    42  | 
     | 
     | 
    #include <hashed_db.h>  | 
    
    
    43  | 
     | 
     | 
     | 
    
    
    44  | 
     | 
     | 
    #include <tic.h>  | 
    
    
    45  | 
     | 
     | 
    #include <term_entry.h>  | 
    
    
    46  | 
     | 
     | 
     | 
    
    
    47  | 
     | 
     | 
    MODULE_ID("$Id: read_entry.c,v 1.17 2015/12/03 11:29:55 nicm Exp $") | 
    
    
    48  | 
     | 
     | 
     | 
    
    
    49  | 
     | 
     | 
    #define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))  | 
    
    
    50  | 
     | 
     | 
     | 
    
    
    51  | 
     | 
     | 
    #if USE_DATABASE  | 
    
    
    52  | 
     | 
     | 
    static void  | 
    
    
    53  | 
     | 
     | 
    convert_shorts(char *buf, short *Numbers, int count)  | 
    
    
    54  | 
     | 
     | 
    { | 
    
    
    55  | 
     | 
     | 
        int i;  | 
    
    
    56  | 
    ✓✓ | 
    120  | 
        for (i = 0; i < count; i++) { | 
    
    
    57  | 
    ✓✓✓✗
  | 
    81  | 
    	if (IS_NEG1(buf + 2 * i))  | 
    
    
    58  | 
     | 
    30  | 
    	    Numbers[i] = ABSENT_NUMERIC;  | 
    
    
    59  | 
    ✓✓✓✗
  | 
    24  | 
    	else if (IS_NEG2(buf + 2 * i))  | 
    
    
    60  | 
     | 
    3  | 
    	    Numbers[i] = CANCELLED_NUMERIC;  | 
    
    
    61  | 
     | 
     | 
    	else  | 
    
    
    62  | 
     | 
    18  | 
    	    Numbers[i] = LOW_MSB(buf + 2 * i);  | 
    
    
    63  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); | 
    
    
    64  | 
     | 
     | 
        }  | 
    
    
    65  | 
     | 
    6  | 
    }  | 
    
    
    66  | 
     | 
     | 
     | 
    
    
    67  | 
     | 
     | 
    static void  | 
    
    
    68  | 
     | 
     | 
    convert_strings(char *buf, char **Strings, int count, int size, char *table)  | 
    
    
    69  | 
     | 
     | 
    { | 
    
    
    70  | 
     | 
     | 
        int i;  | 
    
    
    71  | 
     | 
     | 
        char *p;  | 
    
    
    72  | 
     | 
     | 
     | 
    
    
    73  | 
    ✓✓ | 
    2301  | 
        for (i = 0; i < count; i++) { | 
    
    
    74  | 
    ✓✓✓✗
  | 
    1974  | 
    	if (IS_NEG1(buf + 2 * i)) { | 
    
    
    75  | 
     | 
     | 
    	    Strings[i] = ABSENT_STRING;  | 
    
    
    76  | 
    ✗✓✗✗
  | 
    1137  | 
    	} else if (IS_NEG2(buf + 2 * i)) { | 
    
    
    77  | 
     | 
     | 
    	    Strings[i] = CANCELLED_STRING;  | 
    
    
    78  | 
    ✗✓ | 
    300  | 
    	} else if ((int) LOW_MSB(buf + 2 * i) > size) { | 
    
    
    79  | 
     | 
     | 
    	    Strings[i] = ABSENT_STRING;  | 
    
    
    80  | 
     | 
     | 
    	} else { | 
    
    
    81  | 
     | 
    300  | 
    	    Strings[i] = (LOW_MSB(buf + 2 * i) + table);  | 
    
    
    82  | 
     | 
     | 
    	    TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i]))); | 
    
    
    83  | 
     | 
     | 
    	}  | 
    
    
    84  | 
     | 
     | 
     | 
    
    
    85  | 
     | 
     | 
    	/* make sure all strings are NUL terminated */  | 
    
    
    86  | 
    ✓✗✓✓
  | 
    2274  | 
    	if (VALID_STRING(Strings[i])) { | 
    
    
    87  | 
    ✓✗ | 
    4098  | 
    	    for (p = Strings[i]; p <= table + size; p++)  | 
    
    
    88  | 
    ✓✓ | 
    2049  | 
    		if (*p == '\0')  | 
    
    
    89  | 
     | 
     | 
    		    break;  | 
    
    
    90  | 
     | 
     | 
    	    /* if there is no NUL, ignore the string */  | 
    
    
    91  | 
    ✗✓ | 
    300  | 
    	    if (p > table + size)  | 
    
    
    92  | 
     | 
     | 
    		Strings[i] = ABSENT_STRING;  | 
    
    
    93  | 
     | 
     | 
    	}  | 
    
    
    94  | 
     | 
     | 
        }  | 
    
    
    95  | 
     | 
    9  | 
    }  | 
    
    
    96  | 
     | 
     | 
     | 
    
    
    97  | 
     | 
     | 
    static int  | 
    
    
    98  | 
     | 
     | 
    fake_read(char *src, int *offset, int limit, char *dst, unsigned want)  | 
    
    
    99  | 
     | 
     | 
    { | 
    
    
    100  | 
     | 
    78  | 
        int have = (limit - *offset);  | 
    
    
    101  | 
     | 
     | 
     | 
    
    
    102  | 
    ✓✗ | 
    39  | 
        if (have > 0) { | 
    
    
    103  | 
    ✗✓ | 
    39  | 
    	if ((int) want > have)  | 
    
    
    104  | 
     | 
     | 
    	    want = have;  | 
    
    
    105  | 
     | 
    39  | 
    	memcpy(dst, src + *offset, want);  | 
    
    
    106  | 
     | 
    39  | 
    	*offset += want;  | 
    
    
    107  | 
     | 
    39  | 
        } else { | 
    
    
    108  | 
     | 
     | 
    	want = 0;  | 
    
    
    109  | 
     | 
     | 
        }  | 
    
    
    110  | 
     | 
    39  | 
        return (int) want;  | 
    
    
    111  | 
     | 
     | 
    }  | 
    
    
    112  | 
     | 
     | 
     | 
    
    
    113  | 
     | 
     | 
    #define Read(buf, count) fake_read(buffer, &offset, limit, buf, count)  | 
    
    
    114  | 
     | 
     | 
     | 
    
    
    115  | 
     | 
     | 
    #define read_shorts(buf, count) \  | 
    
    
    116  | 
     | 
     | 
    	(Read(buf, (unsigned) (count)*2) == (int) (count)*2)  | 
    
    
    117  | 
     | 
     | 
     | 
    
    
    118  | 
     | 
     | 
    #define even_boundary(value) \  | 
    
    
    119  | 
     | 
     | 
        if ((value) % 2 != 0) Read(buf, 1)  | 
    
    
    120  | 
     | 
     | 
     | 
    
    
    121  | 
     | 
     | 
    NCURSES_EXPORT(int)  | 
    
    
    122  | 
     | 
     | 
    _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit)  | 
    
    
    123  | 
     | 
     | 
    /* return 1 if read, 0 if not found or garbled */  | 
    
    
    124  | 
     | 
     | 
    { | 
    
    
    125  | 
     | 
    6  | 
        int offset = 0;  | 
    
    
    126  | 
     | 
     | 
        int name_size, bool_count, num_count, str_count, str_size;  | 
    
    
    127  | 
     | 
     | 
        int i;  | 
    
    
    128  | 
     | 
    3  | 
        char buf[MAX_ENTRY_SIZE + 1];  | 
    
    
    129  | 
     | 
     | 
        char *string_table;  | 
    
    
    130  | 
     | 
     | 
        unsigned want, have;  | 
    
    
    131  | 
     | 
     | 
     | 
    
    
    132  | 
     | 
     | 
        TR(TRACE_DATABASE, ("READ termtype header @%d", offset)); | 
    
    
    133  | 
     | 
     | 
     | 
    
    
    134  | 
     | 
    3  | 
        memset(ptr, 0, sizeof(*ptr));  | 
    
    
    135  | 
     | 
     | 
     | 
    
    
    136  | 
     | 
     | 
        /* grab the header */  | 
    
    
    137  | 
    ✗✓ | 
    6  | 
        if (!read_shorts(buf, 6)  | 
    
    
    138  | 
    ✓✗ | 
    6  | 
    	|| !IS_TIC_MAGIC(buf)) { | 
    
    
    139  | 
     | 
     | 
    	return (TGETENT_NO);  | 
    
    
    140  | 
     | 
     | 
        }  | 
    
    
    141  | 
     | 
     | 
     | 
    
    
    142  | 
     | 
    3  | 
        name_size = LOW_MSB(buf + 2);  | 
    
    
    143  | 
     | 
    3  | 
        bool_count = LOW_MSB(buf + 4);  | 
    
    
    144  | 
     | 
    3  | 
        num_count = LOW_MSB(buf + 6);  | 
    
    
    145  | 
     | 
    3  | 
        str_count = LOW_MSB(buf + 8);  | 
    
    
    146  | 
     | 
    3  | 
        str_size = LOW_MSB(buf + 10);  | 
    
    
    147  | 
     | 
     | 
     | 
    
    
    148  | 
     | 
     | 
        TR(TRACE_DATABASE,  | 
    
    
    149  | 
     | 
     | 
           ("TERMTYPE name_size=%d, bool=%d/%d, num=%d/%d str=%d/%d(%d)", | 
    
    
    150  | 
     | 
     | 
    	name_size, bool_count, BOOLCOUNT, num_count, NUMCOUNT,  | 
    
    
    151  | 
     | 
     | 
    	str_count, STRCOUNT, str_size));  | 
    
    
    152  | 
     | 
     | 
        if (name_size < 0  | 
    
    
    153  | 
    ✗✓ | 
    3  | 
    	|| bool_count < 0  | 
    
    
    154  | 
     | 
     | 
    	|| num_count < 0  | 
    
    
    155  | 
     | 
     | 
    	|| str_count < 0  | 
    
    
    156  | 
     | 
     | 
    	|| str_size < 0) { | 
    
    
    157  | 
     | 
     | 
    	return (TGETENT_NO);  | 
    
    
    158  | 
     | 
     | 
        }  | 
    
    
    159  | 
     | 
     | 
     | 
    
    
    160  | 
     | 
    3  | 
        want = str_size + name_size + 1;  | 
    
    
    161  | 
    ✓✗ | 
    3  | 
        if (str_size) { | 
    
    
    162  | 
     | 
     | 
    	/* try to allocate space for the string table */  | 
    
    
    163  | 
    ✗✓ | 
    6  | 
    	if (str_count * 2 >= (int) sizeof(buf)  | 
    
    
    164  | 
    ✓✗ | 
    6  | 
    	    || (string_table = typeMalloc(char, want)) == 0) { | 
    
    
    165  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    166  | 
     | 
     | 
    	}  | 
    
    
    167  | 
     | 
     | 
        } else { | 
    
    
    168  | 
     | 
     | 
    	str_count = 0;  | 
    
    
    169  | 
     | 
     | 
    	if ((string_table = typeMalloc(char, want)) == 0) { | 
    
    
    170  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    171  | 
     | 
     | 
    	}  | 
    
    
    172  | 
     | 
     | 
        }  | 
    
    
    173  | 
     | 
     | 
     | 
    
    
    174  | 
     | 
     | 
        /* grab the name (a null-terminated string) */  | 
    
    
    175  | 
     | 
    3  | 
        want = min(MAX_NAME_SIZE, (unsigned) name_size);  | 
    
    
    176  | 
     | 
    3  | 
        ptr->str_table = string_table;  | 
    
    
    177  | 
     | 
    3  | 
        ptr->term_names = string_table;  | 
    
    
    178  | 
    ✗✓ | 
    3  | 
        if ((have = Read(ptr->term_names, want)) != want) { | 
    
    
    179  | 
     | 
     | 
    	memset(ptr->term_names + have, 0, want - have);  | 
    
    
    180  | 
     | 
     | 
        }  | 
    
    
    181  | 
     | 
    3  | 
        ptr->term_names[want] = '\0';  | 
    
    
    182  | 
     | 
    3  | 
        string_table += (want + 1);  | 
    
    
    183  | 
     | 
     | 
     | 
    
    
    184  | 
    ✗✓ | 
    3  | 
        if (have > MAX_NAME_SIZE)  | 
    
    
    185  | 
     | 
     | 
    	offset = (have - MAX_NAME_SIZE);  | 
    
    
    186  | 
     | 
     | 
     | 
    
    
    187  | 
     | 
     | 
        /* grab the booleans */  | 
    
    
    188  | 
    ✗✓ | 
    6  | 
        if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL,  | 
    
    
    189  | 
     | 
    3  | 
    				     max(BOOLCOUNT, bool_count))) == 0  | 
    
    
    190  | 
    ✓✗ | 
    6  | 
    	|| Read(ptr->Booleans, (unsigned) bool_count) < bool_count) { | 
    
    
    191  | 
     | 
     | 
    	return (TGETENT_NO);  | 
    
    
    192  | 
     | 
     | 
        }  | 
    
    
    193  | 
     | 
     | 
     | 
    
    
    194  | 
     | 
     | 
        /*  | 
    
    
    195  | 
     | 
     | 
         * If booleans end on an odd byte, skip it.  The machine they  | 
    
    
    196  | 
     | 
     | 
         * originally wrote terminfo on must have been a 16-bit  | 
    
    
    197  | 
     | 
     | 
         * word-oriented machine that would trap out if you tried a  | 
    
    
    198  | 
     | 
     | 
         * word access off a 2-byte boundary.  | 
    
    
    199  | 
     | 
     | 
         */  | 
    
    
    200  | 
    ✓✗ | 
    6  | 
        even_boundary(name_size + bool_count);  | 
    
    
    201  | 
     | 
     | 
     | 
    
    
    202  | 
     | 
     | 
        /* grab the numbers */  | 
    
    
    203  | 
    ✗✓ | 
    6  | 
        if ((ptr->Numbers = TYPE_CALLOC(short, max(NUMCOUNT, num_count))) == 0  | 
    
    
    204  | 
    ✓✗ | 
    6  | 
    	|| !read_shorts(buf, num_count)) { | 
    
    
    205  | 
     | 
     | 
    	return (TGETENT_NO);  | 
    
    
    206  | 
     | 
     | 
        }  | 
    
    
    207  | 
     | 
    3  | 
        convert_shorts(buf, ptr->Numbers, num_count);  | 
    
    
    208  | 
     | 
     | 
     | 
    
    
    209  | 
    ✗✓ | 
    3  | 
        if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0)  | 
    
    
    210  | 
     | 
     | 
    	  return (TGETENT_NO);  | 
    
    
    211  | 
     | 
     | 
     | 
    
    
    212  | 
    ✓✗ | 
    3  | 
        if (str_count) { | 
    
    
    213  | 
     | 
     | 
    	/* grab the string offsets */  | 
    
    
    214  | 
    ✗✓ | 
    3  | 
    	if (!read_shorts(buf, str_count)) { | 
    
    
    215  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    216  | 
     | 
     | 
    	}  | 
    
    
    217  | 
     | 
     | 
    	/* finally, grab the string table itself */  | 
    
    
    218  | 
    ✗✓ | 
    3  | 
    	if (Read(string_table, (unsigned) str_size) != str_size)  | 
    
    
    219  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    220  | 
     | 
    3  | 
    	convert_strings(buf, ptr->Strings, str_count, str_size, string_table);  | 
    
    
    221  | 
     | 
    3  | 
        }  | 
    
    
    222  | 
     | 
     | 
    #if NCURSES_XNAMES  | 
    
    
    223  | 
     | 
     | 
     | 
    
    
    224  | 
     | 
    3  | 
        ptr->num_Booleans = BOOLCOUNT;  | 
    
    
    225  | 
     | 
    3  | 
        ptr->num_Numbers = NUMCOUNT;  | 
    
    
    226  | 
     | 
    3  | 
        ptr->num_Strings = STRCOUNT;  | 
    
    
    227  | 
     | 
     | 
     | 
    
    
    228  | 
     | 
     | 
        /*  | 
    
    
    229  | 
     | 
     | 
         * Read extended entries, if any, after the normal end of terminfo data.  | 
    
    
    230  | 
     | 
     | 
         */  | 
    
    
    231  | 
    ✗✓ | 
    3  | 
        even_boundary(str_size);  | 
    
    
    232  | 
     | 
     | 
        TR(TRACE_DATABASE, ("READ extended_header @%d", offset)); | 
    
    
    233  | 
    ✓✗✓✗
  | 
    6  | 
        if (_nc_user_definable && read_shorts(buf, 5)) { | 
    
    
    234  | 
     | 
    3  | 
    	int ext_bool_count = LOW_MSB(buf + 0);  | 
    
    
    235  | 
     | 
    3  | 
    	int ext_num_count = LOW_MSB(buf + 2);  | 
    
    
    236  | 
     | 
    3  | 
    	int ext_str_count = LOW_MSB(buf + 4);  | 
    
    
    237  | 
     | 
    3  | 
    	int ext_str_size = LOW_MSB(buf + 6);  | 
    
    
    238  | 
     | 
    3  | 
    	int ext_str_limit = LOW_MSB(buf + 8);  | 
    
    
    239  | 
     | 
    3  | 
    	unsigned need = (ext_bool_count + ext_num_count + ext_str_count);  | 
    
    
    240  | 
     | 
     | 
    	int base = 0;  | 
    
    
    241  | 
     | 
     | 
     | 
    
    
    242  | 
     | 
    3  | 
    	if (need >= sizeof(buf)  | 
    
    
    243  | 
    ✗✓ | 
    6  | 
    	    || ext_str_size >= (int) sizeof(buf)  | 
    
    
    244  | 
     | 
    3  | 
    	    || ext_str_limit >= (int) sizeof(buf)  | 
    
    
    245  | 
     | 
     | 
    	    || ext_bool_count < 0  | 
    
    
    246  | 
     | 
     | 
    	    || ext_num_count < 0  | 
    
    
    247  | 
     | 
     | 
    	    || ext_str_count < 0  | 
    
    
    248  | 
     | 
     | 
    	    || ext_str_size < 0  | 
    
    
    249  | 
     | 
     | 
    	    || ext_str_limit < 0)  | 
    
    
    250  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    251  | 
     | 
     | 
     | 
    
    
    252  | 
     | 
    3  | 
    	ptr->num_Booleans = BOOLCOUNT + ext_bool_count;  | 
    
    
    253  | 
     | 
    3  | 
    	ptr->num_Numbers = NUMCOUNT + ext_num_count;  | 
    
    
    254  | 
     | 
    3  | 
    	ptr->num_Strings = STRCOUNT + ext_str_count;  | 
    
    
    255  | 
     | 
     | 
     | 
    
    
    256  | 
     | 
    3  | 
    	ptr->Booleans = typeRealloc(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans);  | 
    
    
    257  | 
     | 
    3  | 
    	ptr->Numbers = typeRealloc(short, ptr->num_Numbers, ptr->Numbers);  | 
    
    
    258  | 
     | 
    3  | 
    	ptr->Strings = typeRealloc(char *, ptr->num_Strings, ptr->Strings);  | 
    
    
    259  | 
     | 
     | 
     | 
    
    
    260  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("extended header is %d/%d/%d(%d:%d)", | 
    
    
    261  | 
     | 
     | 
    			    ext_bool_count, ext_num_count, ext_str_count,  | 
    
    
    262  | 
     | 
     | 
    			    ext_str_size, ext_str_limit));  | 
    
    
    263  | 
     | 
     | 
     | 
    
    
    264  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("READ %d extended-booleans @%d", | 
    
    
    265  | 
     | 
     | 
    			    ext_bool_count, offset));  | 
    
    
    266  | 
    ✓✗ | 
    3  | 
    	if ((ptr->ext_Booleans = ext_bool_count) != 0) { | 
    
    
    267  | 
    ✗✓ | 
    6  | 
    	    if (Read(ptr->Booleans + BOOLCOUNT, (unsigned)  | 
    
    
    268  | 
     | 
    3  | 
    		     ext_bool_count) != ext_bool_count)  | 
    
    
    269  | 
     | 
     | 
    		return (TGETENT_NO);  | 
    
    
    270  | 
     | 
     | 
    	}  | 
    
    
    271  | 
    ✓✗ | 
    6  | 
    	even_boundary(ext_bool_count);  | 
    
    
    272  | 
     | 
     | 
     | 
    
    
    273  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("READ %d extended-numbers @%d", | 
    
    
    274  | 
     | 
     | 
    			    ext_num_count, offset));  | 
    
    
    275  | 
    ✓✗ | 
    3  | 
    	if ((ptr->ext_Numbers = ext_num_count) != 0) { | 
    
    
    276  | 
    ✗✓ | 
    3  | 
    	    if (!read_shorts(buf, ext_num_count))  | 
    
    
    277  | 
     | 
     | 
    		return (TGETENT_NO);  | 
    
    
    278  | 
     | 
     | 
    	    TR(TRACE_DATABASE, ("Before converting extended-numbers")); | 
    
    
    279  | 
     | 
    3  | 
    	    convert_shorts(buf, ptr->Numbers + NUMCOUNT, ext_num_count);  | 
    
    
    280  | 
     | 
    3  | 
    	}  | 
    
    
    281  | 
     | 
     | 
     | 
    
    
    282  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset)); | 
    
    
    283  | 
    ✓✗✗✓
  | 
    6  | 
    	if ((ext_str_count || need)  | 
    
    
    284  | 
     | 
    3  | 
    	    && !read_shorts(buf, ext_str_count + need))  | 
    
    
    285  | 
     | 
     | 
    	    return (TGETENT_NO);  | 
    
    
    286  | 
     | 
     | 
     | 
    
    
    287  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d", | 
    
    
    288  | 
     | 
     | 
    			    ext_str_limit, offset));  | 
    
    
    289  | 
     | 
     | 
     | 
    
    
    290  | 
    ✓✗ | 
    3  | 
    	if (ext_str_limit) { | 
    
    
    291  | 
    ✗✓ | 
    3  | 
    	    if ((ptr->ext_str_table = typeMalloc(char, ext_str_limit)) == 0)  | 
    
    
    292  | 
     | 
     | 
    		  return (TGETENT_NO);  | 
    
    
    293  | 
    ✗✓ | 
    3  | 
    	    if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit)  | 
    
    
    294  | 
     | 
     | 
    		return (TGETENT_NO);  | 
    
    
    295  | 
     | 
     | 
    	    TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table))); | 
    
    
    296  | 
     | 
     | 
    	}  | 
    
    
    297  | 
     | 
     | 
     | 
    
    
    298  | 
    ✓✗ | 
    3  | 
    	if ((ptr->ext_Strings = ext_str_count) != 0) { | 
    
    
    299  | 
     | 
     | 
    	    TR(TRACE_DATABASE,  | 
    
    
    300  | 
     | 
     | 
    	       ("Before computing extended-string capabilities str_count=%d, ext_str_count=%d", | 
    
    
    301  | 
     | 
     | 
    		str_count, ext_str_count));  | 
    
    
    302  | 
     | 
    6  | 
    	    convert_strings(buf, ptr->Strings + str_count, ext_str_count,  | 
    
    
    303  | 
     | 
    3  | 
    			    ext_str_limit, ptr->ext_str_table);  | 
    
    
    304  | 
    ✓✓ | 
    48  | 
    	    for (i = ext_str_count - 1; i >= 0; i--) { | 
    
    
    305  | 
     | 
     | 
    		TR(TRACE_DATABASE, ("MOVE from [%d:%d] %s", | 
    
    
    306  | 
     | 
     | 
    				    i, i + str_count,  | 
    
    
    307  | 
     | 
     | 
    				    _nc_visbuf(ptr->Strings[i + str_count])));  | 
    
    
    308  | 
     | 
    21  | 
    		ptr->Strings[i + STRCOUNT] = ptr->Strings[i + str_count];  | 
    
    
    309  | 
    ✓✗✓✓
  | 
    42  | 
    		if (VALID_STRING(ptr->Strings[i + STRCOUNT]))  | 
    
    
    310  | 
     | 
    6  | 
    		    base += (strlen(ptr->Strings[i + STRCOUNT]) + 1);  | 
    
    
    311  | 
     | 
     | 
    		TR(TRACE_DATABASE, ("... to    [%d] %s", | 
    
    
    312  | 
     | 
     | 
    				    i + STRCOUNT,  | 
    
    
    313  | 
     | 
     | 
    				    _nc_visbuf(ptr->Strings[i + STRCOUNT])));  | 
    
    
    314  | 
     | 
     | 
    	    }  | 
    
    
    315  | 
     | 
     | 
    	}  | 
    
    
    316  | 
     | 
     | 
     | 
    
    
    317  | 
    ✓✗ | 
    3  | 
    	if (need) { | 
    
    
    318  | 
    ✗✓ | 
    3  | 
    	    if (ext_str_count >= (MAX_ENTRY_SIZE * 2))  | 
    
    
    319  | 
     | 
     | 
    		  return (TGETENT_NO);  | 
    
    
    320  | 
    ✗✓ | 
    3  | 
    	    if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0)  | 
    
    
    321  | 
     | 
     | 
    		  return (TGETENT_NO);  | 
    
    
    322  | 
     | 
     | 
    	    TR(TRACE_DATABASE,  | 
    
    
    323  | 
     | 
     | 
    	       ("ext_NAMES starting @%d in extended_strings, first = %s", | 
    
    
    324  | 
     | 
     | 
    		base, _nc_visbuf(ptr->ext_str_table + base)));  | 
    
    
    325  | 
     | 
    6  | 
    	    convert_strings(buf + (2 * ext_str_count),  | 
    
    
    326  | 
     | 
     | 
    			    ptr->ext_Names,  | 
    
    
    327  | 
     | 
     | 
    			    (int) need,  | 
    
    
    328  | 
     | 
    3  | 
    			    ext_str_limit, ptr->ext_str_table + base);  | 
    
    
    329  | 
     | 
    3  | 
    	}  | 
    
    
    330  | 
     | 
     | 
     | 
    
    
    331  | 
     | 
     | 
    	T(("...done reading terminfo bool %d(%d) num %d(%d) str %d(%d)", | 
    
    
    332  | 
     | 
     | 
    	   ptr->num_Booleans, ptr->ext_Booleans,  | 
    
    
    333  | 
     | 
     | 
    	   ptr->num_Numbers, ptr->ext_Numbers,  | 
    
    
    334  | 
     | 
     | 
    	   ptr->num_Strings, ptr->ext_Strings));  | 
    
    
    335  | 
     | 
     | 
     | 
    
    
    336  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("extend: num_Booleans:%d", ptr->num_Booleans)); | 
    
    
    337  | 
    ✓✗ | 
    3  | 
        } else  | 
    
    
    338  | 
     | 
     | 
    #endif /* NCURSES_XNAMES */  | 
    
    
    339  | 
     | 
     | 
        { | 
    
    
    340  | 
     | 
     | 
    	T(("...done reading terminfo bool %d num %d str %d", | 
    
    
    341  | 
     | 
     | 
    	   bool_count, num_count, str_count));  | 
    
    
    342  | 
     | 
     | 
    #if NCURSES_XNAMES  | 
    
    
    343  | 
     | 
     | 
    	TR(TRACE_DATABASE, ("normal: num_Booleans:%d", ptr->num_Booleans)); | 
    
    
    344  | 
     | 
     | 
    #endif  | 
    
    
    345  | 
     | 
     | 
        }  | 
    
    
    346  | 
     | 
     | 
     | 
    
    
    347  | 
    ✓✓ | 
    12  | 
        for (i = bool_count; i < BOOLCOUNT; i++)  | 
    
    
    348  | 
     | 
    3  | 
    	ptr->Booleans[i] = FALSE;  | 
    
    
    349  | 
    ✓✓ | 
    144  | 
        for (i = num_count; i < NUMCOUNT; i++)  | 
    
    
    350  | 
     | 
    69  | 
    	ptr->Numbers[i] = ABSENT_NUMERIC;  | 
    
    
    351  | 
    ✓✓ | 
    324  | 
        for (i = str_count; i < STRCOUNT; i++)  | 
    
    
    352  | 
     | 
    159  | 
    	ptr->Strings[i] = ABSENT_STRING;  | 
    
    
    353  | 
     | 
     | 
     | 
    
    
    354  | 
     | 
    3  | 
        return (TGETENT_YES);  | 
    
    
    355  | 
     | 
    3  | 
    }  | 
    
    
    356  | 
     | 
     | 
     | 
    
    
    357  | 
     | 
     | 
    /*  | 
    
    
    358  | 
     | 
     | 
     *	int  | 
    
    
    359  | 
     | 
     | 
     *	_nc_read_file_entry(filename, ptr)  | 
    
    
    360  | 
     | 
     | 
     *  | 
    
    
    361  | 
     | 
     | 
     *	Read the compiled terminfo entry in the given file into the  | 
    
    
    362  | 
     | 
     | 
     *	structure pointed to by ptr, allocating space for the string  | 
    
    
    363  | 
     | 
     | 
     *	table.  | 
    
    
    364  | 
     | 
     | 
     */  | 
    
    
    365  | 
     | 
     | 
    NCURSES_EXPORT(int)  | 
    
    
    366  | 
     | 
     | 
    _nc_read_file_entry(const char *const filename, TERMTYPE *ptr)  | 
    
    
    367  | 
     | 
     | 
    /* return 1 if read, 0 if not found or garbled */  | 
    
    
    368  | 
     | 
     | 
    { | 
    
    
    369  | 
     | 
     | 
        int code, fd = -1;  | 
    
    
    370  | 
     | 
     | 
        int limit;  | 
    
    
    371  | 
     | 
    6  | 
        char buffer[MAX_ENTRY_SIZE + 1];  | 
    
    
    372  | 
     | 
     | 
     | 
    
    
    373  | 
    ✗✓ | 
    6  | 
        if (_nc_access(filename, R_OK) < 0  | 
    
    
    374  | 
    ✓✗ | 
    6  | 
    	|| (fd = open(filename, O_RDONLY | O_BINARY)) < 0) { | 
    
    
    375  | 
     | 
     | 
    	T(("cannot open terminfo %s (errno=%d)", filename, errno)); | 
    
    
    376  | 
     | 
     | 
    	code = TGETENT_NO;  | 
    
    
    377  | 
     | 
     | 
        } else { | 
    
    
    378  | 
    ✓✗ | 
    3  | 
    	if ((limit = read(fd, buffer, sizeof(buffer))) > 0) { | 
    
    
    379  | 
     | 
     | 
     | 
    
    
    380  | 
     | 
     | 
    	    T(("read terminfo %s", filename)); | 
    
    
    381  | 
    ✗✓ | 
    3  | 
    	    if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) { | 
    
    
    382  | 
     | 
     | 
    		_nc_free_termtype(ptr);  | 
    
    
    383  | 
     | 
     | 
    	    }  | 
    
    
    384  | 
     | 
     | 
    	} else { | 
    
    
    385  | 
     | 
     | 
    	    code = TGETENT_NO;  | 
    
    
    386  | 
     | 
     | 
    	}  | 
    
    
    387  | 
     | 
    3  | 
    	close(fd);  | 
    
    
    388  | 
     | 
     | 
        }  | 
    
    
    389  | 
     | 
     | 
     | 
    
    
    390  | 
     | 
    3  | 
        return (code);  | 
    
    
    391  | 
     | 
    3  | 
    }  | 
    
    
    392  | 
     | 
     | 
     | 
    
    
    393  | 
     | 
     | 
    /*  | 
    
    
    394  | 
     | 
     | 
     * Build a terminfo pathname and try to read the data.  Returns TGETENT_YES on  | 
    
    
    395  | 
     | 
     | 
     * success, TGETENT_NO on failure.  | 
    
    
    396  | 
     | 
     | 
     */  | 
    
    
    397  | 
     | 
     | 
    static int  | 
    
    
    398  | 
     | 
     | 
    _nc_read_tic_entry(char *filename,  | 
    
    
    399  | 
     | 
     | 
    		   unsigned limit,  | 
    
    
    400  | 
     | 
     | 
    		   const char *const path,  | 
    
    
    401  | 
     | 
     | 
    		   const char *name,  | 
    
    
    402  | 
     | 
     | 
    		   TERMTYPE *const tp)  | 
    
    
    403  | 
     | 
     | 
    { | 
    
    
    404  | 
     | 
     | 
        int result = TGETENT_NO;  | 
    
    
    405  | 
     | 
     | 
     | 
    
    
    406  | 
     | 
     | 
        /*  | 
    
    
    407  | 
     | 
     | 
         * If we are looking in a directory, assume the entry is a file under that,  | 
    
    
    408  | 
     | 
     | 
         * according to the normal rules.  | 
    
    
    409  | 
     | 
     | 
         *  | 
    
    
    410  | 
     | 
     | 
         * FIXME - add caseless-filename fixup.  | 
    
    
    411  | 
     | 
     | 
         */  | 
    
    
    412  | 
     | 
    12  | 
        unsigned need = 4 + strlen(path) + strlen(name);  | 
    
    
    413  | 
    ✓✗ | 
    6  | 
        if (need <= limit) { | 
    
    
    414  | 
     | 
    6  | 
    	    (void) snprintf(filename, limit, "%s/" LEAF_FMT "/%s", path, *name, name);  | 
    
    
    415  | 
    ✓✓ | 
    6  | 
    	    if (_nc_is_dir_path(path))  | 
    
    
    416  | 
     | 
    3  | 
    		    result = _nc_read_file_entry(filename, tp);  | 
    
    
    417  | 
     | 
     | 
        }  | 
    
    
    418  | 
     | 
     | 
     | 
    
    
    419  | 
     | 
     | 
    #if USE_HASHED_DB  | 
    
    
    420  | 
     | 
     | 
        else { | 
    
    
    421  | 
     | 
     | 
    	static const char suffix[] = DBM_SUFFIX;  | 
    
    
    422  | 
     | 
     | 
    	DB *capdbp;  | 
    
    
    423  | 
     | 
     | 
    	unsigned lens = sizeof(suffix) - 1;  | 
    
    
    424  | 
     | 
     | 
    	unsigned size = strlen(path);  | 
    
    
    425  | 
     | 
     | 
    	unsigned need = lens + size;  | 
    
    
    426  | 
     | 
     | 
     | 
    
    
    427  | 
     | 
     | 
    	if (need <= limit) { | 
    
    
    428  | 
     | 
     | 
    	    if (size >= lens  | 
    
    
    429  | 
     | 
     | 
    		&& !strcmp(path + size - lens, suffix))  | 
    
    
    430  | 
     | 
     | 
    		(void) strlcpy(filename, path, limit);  | 
    
    
    431  | 
     | 
     | 
    	    else  | 
    
    
    432  | 
     | 
     | 
    		(void) snprintf(filename, limit, "%s%s", path, suffix);  | 
    
    
    433  | 
     | 
     | 
     | 
    
    
    434  | 
     | 
     | 
    	    /*  | 
    
    
    435  | 
     | 
     | 
    	     * It would be nice to optimize the dbopen/close activity, as  | 
    
    
    436  | 
     | 
     | 
    	     * done in the cgetent implementation for tc= clauses.  However,  | 
    
    
    437  | 
     | 
     | 
    	     * since we support multiple database locations, we cannot do  | 
    
    
    438  | 
     | 
     | 
    	     * that.  | 
    
    
    439  | 
     | 
     | 
    	     */  | 
    
    
    440  | 
     | 
     | 
    	    if ((capdbp = _nc_db_open(filename, FALSE)) != 0) { | 
    
    
    441  | 
     | 
     | 
    		DBT key, data;  | 
    
    
    442  | 
     | 
     | 
    		int reccnt = 0;  | 
    
    
    443  | 
     | 
     | 
    		char *save = strdup(name);  | 
    
    
    444  | 
     | 
     | 
     | 
    
    
    445  | 
     | 
     | 
    		memset(&key, 0, sizeof(key));  | 
    
    
    446  | 
     | 
     | 
    		key.data = save;  | 
    
    
    447  | 
     | 
     | 
    		key.size = strlen(save);  | 
    
    
    448  | 
     | 
     | 
     | 
    
    
    449  | 
     | 
     | 
    		/*  | 
    
    
    450  | 
     | 
     | 
    		 * This lookup could return termcap data, which we do not want.  | 
    
    
    451  | 
     | 
     | 
    		 * We are looking for compiled (binary) terminfo data.  | 
    
    
    452  | 
     | 
     | 
    		 *  | 
    
    
    453  | 
     | 
     | 
    		 * cgetent uses a two-level lookup.  On the first it uses the  | 
    
    
    454  | 
     | 
     | 
    		 * given name to return a record containing only the aliases  | 
    
    
    455  | 
     | 
     | 
    		 * for an entry.  On the second (using that list of aliases as  | 
    
    
    456  | 
     | 
     | 
    		 * a key), it returns the content of the terminal description.  | 
    
    
    457  | 
     | 
     | 
    		 * We expect second lookup to return data beginning with the  | 
    
    
    458  | 
     | 
     | 
    		 * same set of aliases.  | 
    
    
    459  | 
     | 
     | 
    		 *  | 
    
    
    460  | 
     | 
     | 
    		 * For compiled terminfo, the list of aliases in the second  | 
    
    
    461  | 
     | 
     | 
    		 * case will be null-terminated.  A termcap entry will not be,  | 
    
    
    462  | 
     | 
     | 
    		 * and will run on into the description.  So we can easily  | 
    
    
    463  | 
     | 
     | 
    		 * distinguish between the two (source/binary) by checking the  | 
    
    
    464  | 
     | 
     | 
    		 * lengths.  | 
    
    
    465  | 
     | 
     | 
    		 */  | 
    
    
    466  | 
     | 
     | 
    		while (_nc_db_get(capdbp, &key, &data) == 0) { | 
    
    
    467  | 
     | 
     | 
    		    int used = data.size - 1;  | 
    
    
    468  | 
     | 
     | 
    		    char *have = (char *) data.data;  | 
    
    
    469  | 
     | 
     | 
     | 
    
    
    470  | 
     | 
     | 
    		    if (*have++ == 0) { | 
    
    
    471  | 
     | 
     | 
    			if (data.size > key.size  | 
    
    
    472  | 
     | 
     | 
    			    && IS_TIC_MAGIC(have)) { | 
    
    
    473  | 
     | 
     | 
    			    result = _nc_read_termtype(tp, have, used);  | 
    
    
    474  | 
     | 
     | 
    			    if (result == TGETENT_NO) { | 
    
    
    475  | 
     | 
     | 
    				_nc_free_termtype(tp);  | 
    
    
    476  | 
     | 
     | 
    			    }  | 
    
    
    477  | 
     | 
     | 
    			}  | 
    
    
    478  | 
     | 
     | 
    			break;  | 
    
    
    479  | 
     | 
     | 
    		    }  | 
    
    
    480  | 
     | 
     | 
     | 
    
    
    481  | 
     | 
     | 
    		    /*  | 
    
    
    482  | 
     | 
     | 
    		     * Just in case we have a corrupt database, do not waste  | 
    
    
    483  | 
     | 
     | 
    		     * time with it.  | 
    
    
    484  | 
     | 
     | 
    		     */  | 
    
    
    485  | 
     | 
     | 
    		    if (++reccnt >= 3)  | 
    
    
    486  | 
     | 
     | 
    			break;  | 
    
    
    487  | 
     | 
     | 
     | 
    
    
    488  | 
     | 
     | 
    		    /*  | 
    
    
    489  | 
     | 
     | 
    		     * Prepare for the second level.  | 
    
    
    490  | 
     | 
     | 
    		     */  | 
    
    
    491  | 
     | 
     | 
    		    key.data = have;  | 
    
    
    492  | 
     | 
     | 
    		    key.size = used;  | 
    
    
    493  | 
     | 
     | 
    		}  | 
    
    
    494  | 
     | 
     | 
     | 
    
    
    495  | 
     | 
     | 
    		_nc_db_close(capdbp);  | 
    
    
    496  | 
     | 
     | 
    		free(save);  | 
    
    
    497  | 
     | 
     | 
    	    }  | 
    
    
    498  | 
     | 
     | 
    	}  | 
    
    
    499  | 
     | 
     | 
        }  | 
    
    
    500  | 
     | 
     | 
    #endif  | 
    
    
    501  | 
     | 
    6  | 
        return result;  | 
    
    
    502  | 
     | 
     | 
    }  | 
    
    
    503  | 
     | 
     | 
    #endif /* USE_DATABASE */  | 
    
    
    504  | 
     | 
     | 
     | 
    
    
    505  | 
     | 
     | 
    /*  | 
    
    
    506  | 
     | 
     | 
     *	_nc_read_entry(char *name, char *filename, TERMTYPE *tp)  | 
    
    
    507  | 
     | 
     | 
     *  | 
    
    
    508  | 
     | 
     | 
     *	Find and read the compiled entry for a given terminal type,  | 
    
    
    509  | 
     | 
     | 
     *	if it exists.  We take pains here to make sure no combination  | 
    
    
    510  | 
     | 
     | 
     *	of environment variables and terminal type name can be used to  | 
    
    
    511  | 
     | 
     | 
     *	overrun the file buffer.  | 
    
    
    512  | 
     | 
     | 
     */  | 
    
    
    513  | 
     | 
     | 
     | 
    
    
    514  | 
     | 
     | 
    NCURSES_EXPORT(int)  | 
    
    
    515  | 
     | 
     | 
    _nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp)  | 
    
    
    516  | 
     | 
     | 
    { | 
    
    
    517  | 
     | 
     | 
        int code = TGETENT_NO;  | 
    
    
    518  | 
     | 
     | 
     | 
    
    
    519  | 
     | 
    6  | 
        snprintf(filename, PATH_MAX, "%s", name);  | 
    
    
    520  | 
    ✓✗ | 
    6  | 
        if (strlen(name) == 0  | 
    
    
    521  | 
    ✓✗ | 
    6  | 
    	|| strcmp(name, ".") == 0  | 
    
    
    522  | 
    ✓✗ | 
    6  | 
    	|| strcmp(name, "..") == 0  | 
    
    
    523  | 
    ✓✗ | 
    6  | 
    	|| _nc_pathlast(name) != 0  | 
    
    
    524  | 
    ✓✗ | 
    6  | 
    	|| strchr(name, NCURSES_PATHSEP) != 0) { | 
    
    
    525  | 
     | 
     | 
    	T(("illegal or missing entry name '%s'", name)); | 
    
    
    526  | 
     | 
     | 
        } else { | 
    
    
    527  | 
     | 
     | 
    #if USE_DATABASE  | 
    
    
    528  | 
     | 
    3  | 
    	DBDIRS state = dbdTIC;  | 
    
    
    529  | 
     | 
    3  | 
    	int offset = 0;  | 
    
    
    530  | 
     | 
     | 
    	const char *path;  | 
    
    
    531  | 
     | 
     | 
     | 
    
    
    532  | 
    ✓✗ | 
    12  | 
    	while ((path = _nc_next_db(&state, &offset)) != 0) { | 
    
    
    533  | 
     | 
    6  | 
    	    code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp);  | 
    
    
    534  | 
    ✓✓ | 
    6  | 
    	    if (code == TGETENT_YES) { | 
    
    
    535  | 
     | 
    3  | 
    		_nc_last_db();  | 
    
    
    536  | 
     | 
    3  | 
    		break;  | 
    
    
    537  | 
     | 
     | 
    	    }  | 
    
    
    538  | 
     | 
     | 
    	}  | 
    
    
    539  | 
     | 
     | 
    #endif  | 
    
    
    540  | 
     | 
     | 
    #if USE_TERMCAP  | 
    
    
    541  | 
     | 
     | 
    	if (code != TGETENT_YES) { | 
    
    
    542  | 
     | 
     | 
    	    code = _nc_read_termcap_entry(name, tp);  | 
    
    
    543  | 
     | 
     | 
    	    snprintf(filename, PATH_MAX, "%s", _nc_get_source());  | 
    
    
    544  | 
     | 
     | 
    	}  | 
    
    
    545  | 
     | 
     | 
    #endif  | 
    
    
    546  | 
     | 
    3  | 
        }  | 
    
    
    547  | 
     | 
    3  | 
        return code;  | 
    
    
    548  | 
     | 
     | 
    }  |