1fdd4e1e0SJan Lentfer /****************************************************************************
2*32bb5217SDaniel Fojt  * Copyright 2018-2019,2020 Thomas E. Dickey                                *
3*32bb5217SDaniel Fojt  * Copyright 1998-2016,2017 Free Software Foundation, Inc.                  *
4fdd4e1e0SJan Lentfer  *                                                                          *
5fdd4e1e0SJan Lentfer  * Permission is hereby granted, free of charge, to any person obtaining a  *
6fdd4e1e0SJan Lentfer  * copy of this software and associated documentation files (the            *
7fdd4e1e0SJan Lentfer  * "Software"), to deal in the Software without restriction, including      *
8fdd4e1e0SJan Lentfer  * without limitation the rights to use, copy, modify, merge, publish,      *
9fdd4e1e0SJan Lentfer  * distribute, distribute with modifications, sublicense, and/or sell       *
10fdd4e1e0SJan Lentfer  * copies of the Software, and to permit persons to whom the Software is    *
11fdd4e1e0SJan Lentfer  * furnished to do so, subject to the following conditions:                 *
12fdd4e1e0SJan Lentfer  *                                                                          *
13fdd4e1e0SJan Lentfer  * The above copyright notice and this permission notice shall be included  *
14fdd4e1e0SJan Lentfer  * in all copies or substantial portions of the Software.                   *
15fdd4e1e0SJan Lentfer  *                                                                          *
16fdd4e1e0SJan Lentfer  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
17fdd4e1e0SJan Lentfer  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
18fdd4e1e0SJan Lentfer  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
19fdd4e1e0SJan Lentfer  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
20fdd4e1e0SJan Lentfer  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
21fdd4e1e0SJan Lentfer  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
22fdd4e1e0SJan Lentfer  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
23fdd4e1e0SJan Lentfer  *                                                                          *
24fdd4e1e0SJan Lentfer  * Except as contained in this notice, the name(s) of the above copyright   *
25fdd4e1e0SJan Lentfer  * holders shall not be used in advertising or otherwise to promote the     *
26fdd4e1e0SJan Lentfer  * sale, use or other dealings in this Software without prior written       *
27fdd4e1e0SJan Lentfer  * authorization.                                                           *
28fdd4e1e0SJan Lentfer  ****************************************************************************/
29fdd4e1e0SJan Lentfer 
30fdd4e1e0SJan Lentfer /****************************************************************************
31fdd4e1e0SJan Lentfer  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
32fdd4e1e0SJan Lentfer  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
331d102085SJan Lentfer  *     and: Thomas E. Dickey                        1996-on                 *
34fdd4e1e0SJan Lentfer  ****************************************************************************/
35fdd4e1e0SJan Lentfer 
36fdd4e1e0SJan Lentfer /*
37fdd4e1e0SJan Lentfer  *	read_entry.c -- Routine for reading in a compiled terminfo file
38fdd4e1e0SJan Lentfer  */
39fdd4e1e0SJan Lentfer 
40fdd4e1e0SJan Lentfer #include <curses.priv.h>
411d102085SJan Lentfer #include <hashed_db.h>
42fdd4e1e0SJan Lentfer 
43fdd4e1e0SJan Lentfer #include <tic.h>
44fdd4e1e0SJan Lentfer 
45*32bb5217SDaniel Fojt MODULE_ID("$Id: read_entry.c,v 1.157 2020/02/02 23:34:34 tom Exp $")
46fdd4e1e0SJan Lentfer 
471d102085SJan Lentfer #define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts))
48fdd4e1e0SJan Lentfer 
493468e90cSJohn Marino #define MyNumber(n) (short) LOW_MSB(n)
503468e90cSJohn Marino 
51*32bb5217SDaniel Fojt #define SIZEOF_32BITS 4
52*32bb5217SDaniel Fojt 
533468e90cSJohn Marino #if NCURSES_USE_DATABASE
54*32bb5217SDaniel Fojt #if NCURSES_EXT_NUMBERS
55*32bb5217SDaniel Fojt static size_t
convert_16bits(char * buf,NCURSES_INT2 * Numbers,int count)56*32bb5217SDaniel Fojt convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count)
57*32bb5217SDaniel Fojt {
58*32bb5217SDaniel Fojt     int i;
59*32bb5217SDaniel Fojt     size_t j;
60*32bb5217SDaniel Fojt     size_t size = SIZEOF_SHORT;
61*32bb5217SDaniel Fojt     for (i = 0; i < count; i++) {
62*32bb5217SDaniel Fojt 	unsigned mask = 0xff;
63*32bb5217SDaniel Fojt 	unsigned char ch = 0;
64*32bb5217SDaniel Fojt 	Numbers[i] = 0;
65*32bb5217SDaniel Fojt 	for (j = 0; j < size; ++j) {
66*32bb5217SDaniel Fojt 	    ch = UChar(*buf++);
67*32bb5217SDaniel Fojt 	    Numbers[i] |= (ch << (8 * j));
68*32bb5217SDaniel Fojt 	    mask <<= 8;
69*32bb5217SDaniel Fojt 	}
70*32bb5217SDaniel Fojt 	if (ch & 0x80) {
71*32bb5217SDaniel Fojt 	    while (mask != 0) {
72*32bb5217SDaniel Fojt 		Numbers[i] |= (int) mask;
73*32bb5217SDaniel Fojt 		mask <<= 8;
74*32bb5217SDaniel Fojt 	    }
75*32bb5217SDaniel Fojt 	}
76*32bb5217SDaniel Fojt 	TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i]));
77*32bb5217SDaniel Fojt     }
78*32bb5217SDaniel Fojt     return size;
79*32bb5217SDaniel Fojt }
80*32bb5217SDaniel Fojt 
81*32bb5217SDaniel Fojt static size_t
convert_32bits(char * buf,NCURSES_INT2 * Numbers,int count)82*32bb5217SDaniel Fojt convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count)
83*32bb5217SDaniel Fojt {
84*32bb5217SDaniel Fojt     int i;
85*32bb5217SDaniel Fojt     size_t j;
86*32bb5217SDaniel Fojt     size_t size = SIZEOF_INT2;
87*32bb5217SDaniel Fojt     unsigned char ch;
88*32bb5217SDaniel Fojt 
89*32bb5217SDaniel Fojt     assert(sizeof(NCURSES_INT2) == size);
90*32bb5217SDaniel Fojt     for (i = 0; i < count; i++) {
91*32bb5217SDaniel Fojt 	Numbers[i] = 0;
92*32bb5217SDaniel Fojt 	for (j = 0; j < size; ++j) {
93*32bb5217SDaniel Fojt 	    ch = UChar(*buf++);
94*32bb5217SDaniel Fojt 	    Numbers[i] |= (ch << (8 * j));
95*32bb5217SDaniel Fojt 	}
96*32bb5217SDaniel Fojt 	/* "unsigned" and NCURSES_INT2 are the same size - no sign-extension */
97*32bb5217SDaniel Fojt 	TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i]));
98*32bb5217SDaniel Fojt     }
99*32bb5217SDaniel Fojt     return size;
100*32bb5217SDaniel Fojt }
101*32bb5217SDaniel Fojt #else
102*32bb5217SDaniel Fojt static size_t
103*32bb5217SDaniel Fojt convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count)
104*32bb5217SDaniel Fojt {
105*32bb5217SDaniel Fojt     int i, j;
106*32bb5217SDaniel Fojt     unsigned char ch;
107*32bb5217SDaniel Fojt     for (i = 0; i < count; i++) {
108*32bb5217SDaniel Fojt 	int value = 0;
109*32bb5217SDaniel Fojt 	for (j = 0; j < SIZEOF_32BITS; ++j) {
110*32bb5217SDaniel Fojt 	    ch = UChar(*buf++);
111*32bb5217SDaniel Fojt 	    value |= (ch << (8 * j));
112*32bb5217SDaniel Fojt 	}
113*32bb5217SDaniel Fojt 	if (value == -1)
114*32bb5217SDaniel Fojt 	    Numbers[i] = ABSENT_NUMERIC;
115*32bb5217SDaniel Fojt 	else if (value == -2)
116*32bb5217SDaniel Fojt 	    Numbers[i] = CANCELLED_NUMERIC;
117*32bb5217SDaniel Fojt 	else if (value > MAX_OF_TYPE(NCURSES_INT2))
118*32bb5217SDaniel Fojt 	    Numbers[i] = MAX_OF_TYPE(NCURSES_INT2);
119*32bb5217SDaniel Fojt 	else
120*32bb5217SDaniel Fojt 	    Numbers[i] = (short) value;
121*32bb5217SDaniel Fojt 	TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i]));
122*32bb5217SDaniel Fojt     }
123*32bb5217SDaniel Fojt     return SIZEOF_SHORT;
124*32bb5217SDaniel Fojt }
125*32bb5217SDaniel Fojt 
126*32bb5217SDaniel Fojt static size_t
127*32bb5217SDaniel Fojt convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count)
128fdd4e1e0SJan Lentfer {
129fdd4e1e0SJan Lentfer     int i;
130fdd4e1e0SJan Lentfer     for (i = 0; i < count; i++) {
131fdd4e1e0SJan Lentfer 	if (IS_NEG1(buf + 2 * i))
132fdd4e1e0SJan Lentfer 	    Numbers[i] = ABSENT_NUMERIC;
133fdd4e1e0SJan Lentfer 	else if (IS_NEG2(buf + 2 * i))
134fdd4e1e0SJan Lentfer 	    Numbers[i] = CANCELLED_NUMERIC;
135fdd4e1e0SJan Lentfer 	else
1363468e90cSJohn Marino 	    Numbers[i] = MyNumber(buf + 2 * i);
137fdd4e1e0SJan Lentfer 	TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i]));
138fdd4e1e0SJan Lentfer     }
139*32bb5217SDaniel Fojt     return SIZEOF_SHORT;
140fdd4e1e0SJan Lentfer }
141*32bb5217SDaniel Fojt #endif
142fdd4e1e0SJan Lentfer 
143fdd4e1e0SJan Lentfer static void
convert_strings(char * buf,char ** Strings,int count,int size,char * table)144fdd4e1e0SJan Lentfer convert_strings(char *buf, char **Strings, int count, int size, char *table)
145fdd4e1e0SJan Lentfer {
146fdd4e1e0SJan Lentfer     int i;
147fdd4e1e0SJan Lentfer     char *p;
148fdd4e1e0SJan Lentfer 
149fdd4e1e0SJan Lentfer     for (i = 0; i < count; i++) {
150fdd4e1e0SJan Lentfer 	if (IS_NEG1(buf + 2 * i)) {
151fdd4e1e0SJan Lentfer 	    Strings[i] = ABSENT_STRING;
152fdd4e1e0SJan Lentfer 	} else if (IS_NEG2(buf + 2 * i)) {
153fdd4e1e0SJan Lentfer 	    Strings[i] = CANCELLED_STRING;
1543468e90cSJohn Marino 	} else if (MyNumber(buf + 2 * i) > size) {
155fdd4e1e0SJan Lentfer 	    Strings[i] = ABSENT_STRING;
156fdd4e1e0SJan Lentfer 	} else {
1573468e90cSJohn Marino 	    Strings[i] = (MyNumber(buf + 2 * i) + table);
158fdd4e1e0SJan Lentfer 	    TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i])));
159fdd4e1e0SJan Lentfer 	}
160fdd4e1e0SJan Lentfer 
161fdd4e1e0SJan Lentfer 	/* make sure all strings are NUL terminated */
162fdd4e1e0SJan Lentfer 	if (VALID_STRING(Strings[i])) {
163fdd4e1e0SJan Lentfer 	    for (p = Strings[i]; p <= table + size; p++)
164fdd4e1e0SJan Lentfer 		if (*p == '\0')
165fdd4e1e0SJan Lentfer 		    break;
166fdd4e1e0SJan Lentfer 	    /* if there is no NUL, ignore the string */
167fdd4e1e0SJan Lentfer 	    if (p > table + size)
168fdd4e1e0SJan Lentfer 		Strings[i] = ABSENT_STRING;
169fdd4e1e0SJan Lentfer 	}
170fdd4e1e0SJan Lentfer     }
171fdd4e1e0SJan Lentfer }
172fdd4e1e0SJan Lentfer 
1731d102085SJan Lentfer static int
fake_read(char * src,int * offset,int limit,char * dst,unsigned want)1741d102085SJan Lentfer fake_read(char *src, int *offset, int limit, char *dst, unsigned want)
1751d102085SJan Lentfer {
1761d102085SJan Lentfer     int have = (limit - *offset);
1771d102085SJan Lentfer 
1781d102085SJan Lentfer     if (have > 0) {
1791d102085SJan Lentfer 	if ((int) want > have)
18000d8f3c4SJohn Marino 	    want = (unsigned) have;
1813468e90cSJohn Marino 	memcpy(dst, src + *offset, (size_t) want);
18200d8f3c4SJohn Marino 	*offset += (int) want;
1831d102085SJan Lentfer     } else {
1841d102085SJan Lentfer 	want = 0;
1851d102085SJan Lentfer     }
1861d102085SJan Lentfer     return (int) want;
1871d102085SJan Lentfer }
1881d102085SJan Lentfer 
1893468e90cSJohn Marino #define Read(buf, count) fake_read(buffer, &offset, limit, (char *) buf, (unsigned) count)
1901d102085SJan Lentfer 
1911d102085SJan Lentfer #define read_shorts(buf, count) \
192*32bb5217SDaniel Fojt 	(Read(buf, (count)*SIZEOF_SHORT) == (int) (count)*SIZEOF_SHORT)
193*32bb5217SDaniel Fojt 
194*32bb5217SDaniel Fojt #define read_numbers(buf, count) \
195*32bb5217SDaniel Fojt 	(Read(buf, (count)*(unsigned)size_of_numbers) == (int) (count)*size_of_numbers)
196fdd4e1e0SJan Lentfer 
197fdd4e1e0SJan Lentfer #define even_boundary(value) \
1981d102085SJan Lentfer     if ((value) % 2 != 0) Read(buf, 1)
1993468e90cSJohn Marino #endif
200fdd4e1e0SJan Lentfer 
2013468e90cSJohn Marino NCURSES_EXPORT(void)
_nc_init_termtype(TERMTYPE2 * const tp)202*32bb5217SDaniel Fojt _nc_init_termtype(TERMTYPE2 *const tp)
2033468e90cSJohn Marino {
2043468e90cSJohn Marino     unsigned i;
2053468e90cSJohn Marino 
2063468e90cSJohn Marino #if NCURSES_XNAMES
2073468e90cSJohn Marino     tp->num_Booleans = BOOLCOUNT;
2083468e90cSJohn Marino     tp->num_Numbers = NUMCOUNT;
2093468e90cSJohn Marino     tp->num_Strings = STRCOUNT;
2103468e90cSJohn Marino     tp->ext_Booleans = 0;
2113468e90cSJohn Marino     tp->ext_Numbers = 0;
2123468e90cSJohn Marino     tp->ext_Strings = 0;
2133468e90cSJohn Marino #endif
2143468e90cSJohn Marino     if (tp->Booleans == 0)
2153468e90cSJohn Marino 	TYPE_MALLOC(NCURSES_SBOOL, BOOLCOUNT, tp->Booleans);
2163468e90cSJohn Marino     if (tp->Numbers == 0)
217*32bb5217SDaniel Fojt 	TYPE_MALLOC(NCURSES_INT2, NUMCOUNT, tp->Numbers);
2183468e90cSJohn Marino     if (tp->Strings == 0)
2193468e90cSJohn Marino 	TYPE_MALLOC(char *, STRCOUNT, tp->Strings);
2203468e90cSJohn Marino 
2213468e90cSJohn Marino     for_each_boolean(i, tp)
2223468e90cSJohn Marino 	tp->Booleans[i] = FALSE;
2233468e90cSJohn Marino 
2243468e90cSJohn Marino     for_each_number(i, tp)
2253468e90cSJohn Marino 	tp->Numbers[i] = ABSENT_NUMERIC;
2263468e90cSJohn Marino 
2273468e90cSJohn Marino     for_each_string(i, tp)
2283468e90cSJohn Marino 	tp->Strings[i] = ABSENT_STRING;
2293468e90cSJohn Marino }
2303468e90cSJohn Marino 
2313468e90cSJohn Marino #if NCURSES_USE_DATABASE
2323468e90cSJohn Marino #if NCURSES_XNAMES
2333468e90cSJohn Marino static bool
valid_shorts(char * buffer,int limit)2343468e90cSJohn Marino valid_shorts(char *buffer, int limit)
2353468e90cSJohn Marino {
2363468e90cSJohn Marino     bool result = FALSE;
2373468e90cSJohn Marino     int n;
2383468e90cSJohn Marino     for (n = 0; n < limit; ++n) {
2393468e90cSJohn Marino 	if (MyNumber(buffer + (n * 2)) > 0) {
2403468e90cSJohn Marino 	    result = TRUE;
2413468e90cSJohn Marino 	    break;
2423468e90cSJohn Marino 	}
2433468e90cSJohn Marino     }
2443468e90cSJohn Marino     return result;
2453468e90cSJohn Marino }
2463468e90cSJohn Marino #endif
2473468e90cSJohn Marino 
2483468e90cSJohn Marino /*
2493468e90cSJohn Marino  * Return TGETENT_YES if read, TGETENT_NO if not found or garbled.
2503468e90cSJohn Marino  */
2511d102085SJan Lentfer NCURSES_EXPORT(int)
_nc_read_termtype(TERMTYPE2 * ptr,char * buffer,int limit)252*32bb5217SDaniel Fojt _nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit)
253fdd4e1e0SJan Lentfer {
2541d102085SJan Lentfer     int offset = 0;
255fdd4e1e0SJan Lentfer     int name_size, bool_count, num_count, str_count, str_size;
256fdd4e1e0SJan Lentfer     int i;
2573468e90cSJohn Marino     char buf[MAX_ENTRY_SIZE + 2];
2581d102085SJan Lentfer     char *string_table;
259fdd4e1e0SJan Lentfer     unsigned want, have;
260*32bb5217SDaniel Fojt     bool need_ints;
261*32bb5217SDaniel Fojt     size_t (*convert_numbers) (char *, NCURSES_INT2 *, int);
262*32bb5217SDaniel Fojt     int size_of_numbers;
263*32bb5217SDaniel Fojt     int max_entry_size = MAX_ENTRY_SIZE;
264*32bb5217SDaniel Fojt 
265*32bb5217SDaniel Fojt     TR(TRACE_DATABASE,
266*32bb5217SDaniel Fojt        (T_CALLED("_nc_read_termtype(ptr=%p, buffer=%p, limit=%d)"),
267*32bb5217SDaniel Fojt 	(void *) ptr, buffer, limit));
268fdd4e1e0SJan Lentfer 
2691d102085SJan Lentfer     TR(TRACE_DATABASE, ("READ termtype header @%d", offset));
270fdd4e1e0SJan Lentfer 
271fdd4e1e0SJan Lentfer     memset(ptr, 0, sizeof(*ptr));
272fdd4e1e0SJan Lentfer 
273fdd4e1e0SJan Lentfer     /* grab the header */
2741d102085SJan Lentfer     if (!read_shorts(buf, 6)
2751d102085SJan Lentfer 	|| !IS_TIC_MAGIC(buf)) {
276*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
277fdd4e1e0SJan Lentfer     }
278*32bb5217SDaniel Fojt #if NCURSES_EXT_NUMBERS
279*32bb5217SDaniel Fojt     if ((need_ints = (LOW_MSB(buf) == MAGIC2))) {
280*32bb5217SDaniel Fojt 	convert_numbers = convert_32bits;
281*32bb5217SDaniel Fojt 	size_of_numbers = SIZEOF_INT2;
282*32bb5217SDaniel Fojt     } else {
283*32bb5217SDaniel Fojt 	max_entry_size = MAX_ENTRY_SIZE1;
284*32bb5217SDaniel Fojt 	convert_numbers = convert_16bits;
285*32bb5217SDaniel Fojt 	size_of_numbers = SIZEOF_SHORT;
286*32bb5217SDaniel Fojt     }
287*32bb5217SDaniel Fojt #else
288*32bb5217SDaniel Fojt     if ((need_ints = (LOW_MSB(buf) == MAGIC2))) {
289*32bb5217SDaniel Fojt 	convert_numbers = convert_32bits;
290*32bb5217SDaniel Fojt 	size_of_numbers = SIZEOF_32BITS;
291*32bb5217SDaniel Fojt     } else {
292*32bb5217SDaniel Fojt 	convert_numbers = convert_16bits;
293*32bb5217SDaniel Fojt 	size_of_numbers = SIZEOF_INT2;
294*32bb5217SDaniel Fojt     }
295*32bb5217SDaniel Fojt #endif
296fdd4e1e0SJan Lentfer 
297*32bb5217SDaniel Fojt     /* *INDENT-EQLS* */
2983468e90cSJohn Marino     name_size  = MyNumber(buf + 2);
2993468e90cSJohn Marino     bool_count = MyNumber(buf + 4);
3003468e90cSJohn Marino     num_count  = MyNumber(buf + 6);
3013468e90cSJohn Marino     str_count  = MyNumber(buf + 8);
3023468e90cSJohn Marino     str_size   = MyNumber(buf + 10);
303fdd4e1e0SJan Lentfer 
304fdd4e1e0SJan Lentfer     TR(TRACE_DATABASE,
305fdd4e1e0SJan Lentfer        ("TERMTYPE name_size=%d, bool=%d/%d, num=%d/%d str=%d/%d(%d)",
306fdd4e1e0SJan Lentfer 	name_size, bool_count, BOOLCOUNT, num_count, NUMCOUNT,
307fdd4e1e0SJan Lentfer 	str_count, STRCOUNT, str_size));
308fdd4e1e0SJan Lentfer     if (name_size < 0
309fdd4e1e0SJan Lentfer 	|| bool_count < 0
310fdd4e1e0SJan Lentfer 	|| num_count < 0
311fdd4e1e0SJan Lentfer 	|| str_count < 0
312fdd4e1e0SJan Lentfer 	|| str_size < 0) {
313*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
314fdd4e1e0SJan Lentfer     }
315fdd4e1e0SJan Lentfer 
31600d8f3c4SJohn Marino     want = (unsigned) (str_size + name_size + 1);
317fdd4e1e0SJan Lentfer     /* try to allocate space for the string table */
318*32bb5217SDaniel Fojt     if (str_count * SIZEOF_SHORT >= max_entry_size
3191d102085SJan Lentfer 	|| (string_table = typeMalloc(char, want)) == 0) {
320*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
321fdd4e1e0SJan Lentfer     }
322fdd4e1e0SJan Lentfer 
323fdd4e1e0SJan Lentfer     /* grab the name (a null-terminated string) */
324fdd4e1e0SJan Lentfer     want = min(MAX_NAME_SIZE, (unsigned) name_size);
3251d102085SJan Lentfer     ptr->str_table = string_table;
3261d102085SJan Lentfer     ptr->term_names = string_table;
32700d8f3c4SJohn Marino     if ((have = (unsigned) Read(ptr->term_names, want)) != want) {
3283468e90cSJohn Marino 	memset(ptr->term_names + have, 0, (size_t) (want - have));
329fdd4e1e0SJan Lentfer     }
3301d102085SJan Lentfer     ptr->term_names[want] = '\0';
3311d102085SJan Lentfer     string_table += (want + 1);
3321d102085SJan Lentfer 
333fdd4e1e0SJan Lentfer     if (have > MAX_NAME_SIZE)
33400d8f3c4SJohn Marino 	offset = (int) (have - MAX_NAME_SIZE);
335fdd4e1e0SJan Lentfer 
336fdd4e1e0SJan Lentfer     /* grab the booleans */
3371d102085SJan Lentfer     if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL,
3381d102085SJan Lentfer 				     max(BOOLCOUNT, bool_count))) == 0
3391d102085SJan Lentfer 	|| Read(ptr->Booleans, (unsigned) bool_count) < bool_count) {
340*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
341fdd4e1e0SJan Lentfer     }
342fdd4e1e0SJan Lentfer 
343fdd4e1e0SJan Lentfer     /*
344fdd4e1e0SJan Lentfer      * If booleans end on an odd byte, skip it.  The machine they
345fdd4e1e0SJan Lentfer      * originally wrote terminfo on must have been a 16-bit
346fdd4e1e0SJan Lentfer      * word-oriented machine that would trap out if you tried a
347fdd4e1e0SJan Lentfer      * word access off a 2-byte boundary.
348fdd4e1e0SJan Lentfer      */
349fdd4e1e0SJan Lentfer     even_boundary(name_size + bool_count);
350fdd4e1e0SJan Lentfer 
351fdd4e1e0SJan Lentfer     /* grab the numbers */
352*32bb5217SDaniel Fojt     if (!(ptr->Numbers = TYPE_CALLOC(NCURSES_INT2, max(NUMCOUNT, num_count)))
353*32bb5217SDaniel Fojt 	|| !read_numbers(buf, num_count)) {
354*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
355fdd4e1e0SJan Lentfer     }
356*32bb5217SDaniel Fojt     convert_numbers(buf, ptr->Numbers, num_count);
357fdd4e1e0SJan Lentfer 
3583468e90cSJohn Marino     if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0) {
359*32bb5217SDaniel Fojt 	returnDB(TGETENT_NO);
3603468e90cSJohn Marino     }
361fdd4e1e0SJan Lentfer 
362fdd4e1e0SJan Lentfer     if (str_count) {
363fdd4e1e0SJan Lentfer 	/* grab the string offsets */
3641d102085SJan Lentfer 	if (!read_shorts(buf, str_count)) {
365*32bb5217SDaniel Fojt 	    returnDB(TGETENT_NO);
366fdd4e1e0SJan Lentfer 	}
367fdd4e1e0SJan Lentfer 	/* finally, grab the string table itself */
3683468e90cSJohn Marino 	if (Read(string_table, (unsigned) str_size) != str_size) {
369*32bb5217SDaniel Fojt 	    returnDB(TGETENT_NO);
3703468e90cSJohn Marino 	}
3711d102085SJan Lentfer 	convert_strings(buf, ptr->Strings, str_count, str_size, string_table);
372fdd4e1e0SJan Lentfer     }
373fdd4e1e0SJan Lentfer #if NCURSES_XNAMES
374fdd4e1e0SJan Lentfer 
375fdd4e1e0SJan Lentfer     ptr->num_Booleans = BOOLCOUNT;
376fdd4e1e0SJan Lentfer     ptr->num_Numbers = NUMCOUNT;
377fdd4e1e0SJan Lentfer     ptr->num_Strings = STRCOUNT;
378fdd4e1e0SJan Lentfer 
379fdd4e1e0SJan Lentfer     /*
380fdd4e1e0SJan Lentfer      * Read extended entries, if any, after the normal end of terminfo data.
381fdd4e1e0SJan Lentfer      */
382fdd4e1e0SJan Lentfer     even_boundary(str_size);
3831d102085SJan Lentfer     TR(TRACE_DATABASE, ("READ extended_header @%d", offset));
3843468e90cSJohn Marino     if (_nc_user_definable && read_shorts(buf, 5) && valid_shorts(buf, 5)) {
3853468e90cSJohn Marino 	int ext_bool_count = MyNumber(buf + 0);
3863468e90cSJohn Marino 	int ext_num_count = MyNumber(buf + 2);
3873468e90cSJohn Marino 	int ext_str_count = MyNumber(buf + 4);
388*32bb5217SDaniel Fojt 	int ext_str_usage = MyNumber(buf + 6);
3893468e90cSJohn Marino 	int ext_str_limit = MyNumber(buf + 8);
39000d8f3c4SJohn Marino 	unsigned need = (unsigned) (ext_bool_count + ext_num_count + ext_str_count);
391fdd4e1e0SJan Lentfer 	int base = 0;
392fdd4e1e0SJan Lentfer 
393*32bb5217SDaniel Fojt 	if ((int) need >= (max_entry_size / 2)
394*32bb5217SDaniel Fojt 	    || ext_str_usage >= max_entry_size
395*32bb5217SDaniel Fojt 	    || ext_str_limit >= max_entry_size
396fdd4e1e0SJan Lentfer 	    || ext_bool_count < 0
397fdd4e1e0SJan Lentfer 	    || ext_num_count < 0
398fdd4e1e0SJan Lentfer 	    || ext_str_count < 0
399*32bb5217SDaniel Fojt 	    || ext_str_usage < 0
4003468e90cSJohn Marino 	    || ext_str_limit < 0) {
401*32bb5217SDaniel Fojt 	    returnDB(TGETENT_NO);
4023468e90cSJohn Marino 	}
403fdd4e1e0SJan Lentfer 
40400d8f3c4SJohn Marino 	ptr->num_Booleans = UShort(BOOLCOUNT + ext_bool_count);
40500d8f3c4SJohn Marino 	ptr->num_Numbers = UShort(NUMCOUNT + ext_num_count);
40600d8f3c4SJohn Marino 	ptr->num_Strings = UShort(STRCOUNT + ext_str_count);
407fdd4e1e0SJan Lentfer 
4083468e90cSJohn Marino 	TYPE_REALLOC(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans);
409*32bb5217SDaniel Fojt 	TYPE_REALLOC(NCURSES_INT2, ptr->num_Numbers, ptr->Numbers);
4103468e90cSJohn Marino 	TYPE_REALLOC(char *, ptr->num_Strings, ptr->Strings);
411fdd4e1e0SJan Lentfer 
412*32bb5217SDaniel Fojt 	TR(TRACE_DATABASE, ("extended header: "
413*32bb5217SDaniel Fojt 			    "bool %d, "
414*32bb5217SDaniel Fojt 			    "number %d, "
415*32bb5217SDaniel Fojt 			    "string %d(%d:%d)",
416*32bb5217SDaniel Fojt 			    ext_bool_count,
417*32bb5217SDaniel Fojt 			    ext_num_count,
418*32bb5217SDaniel Fojt 			    ext_str_count,
419*32bb5217SDaniel Fojt 			    ext_str_usage,
420*32bb5217SDaniel Fojt 			    ext_str_limit));
421fdd4e1e0SJan Lentfer 
4221d102085SJan Lentfer 	TR(TRACE_DATABASE, ("READ %d extended-booleans @%d",
4231d102085SJan Lentfer 			    ext_bool_count, offset));
42400d8f3c4SJohn Marino 	if ((ptr->ext_Booleans = UShort(ext_bool_count)) != 0) {
4251d102085SJan Lentfer 	    if (Read(ptr->Booleans + BOOLCOUNT, (unsigned)
4263468e90cSJohn Marino 		     ext_bool_count) != ext_bool_count) {
427*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
428fdd4e1e0SJan Lentfer 	    }
4293468e90cSJohn Marino 	}
430fdd4e1e0SJan Lentfer 	even_boundary(ext_bool_count);
431fdd4e1e0SJan Lentfer 
4321d102085SJan Lentfer 	TR(TRACE_DATABASE, ("READ %d extended-numbers @%d",
4331d102085SJan Lentfer 			    ext_num_count, offset));
43400d8f3c4SJohn Marino 	if ((ptr->ext_Numbers = UShort(ext_num_count)) != 0) {
435*32bb5217SDaniel Fojt 	    if (!read_numbers(buf, ext_num_count)) {
436*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
4373468e90cSJohn Marino 	    }
438fdd4e1e0SJan Lentfer 	    TR(TRACE_DATABASE, ("Before converting extended-numbers"));
439*32bb5217SDaniel Fojt 	    convert_numbers(buf, ptr->Numbers + NUMCOUNT, ext_num_count);
440fdd4e1e0SJan Lentfer 	}
441fdd4e1e0SJan Lentfer 
4421d102085SJan Lentfer 	TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset));
443*32bb5217SDaniel Fojt 	if ((ext_str_count + (int) need) >= (max_entry_size / 2)) {
444*32bb5217SDaniel Fojt 	    returnDB(TGETENT_NO);
4453468e90cSJohn Marino 	}
4463468e90cSJohn Marino 	if ((ext_str_count || need)
4473468e90cSJohn Marino 	    && !read_shorts(buf, ext_str_count + (int) need)) {
448*32bb5217SDaniel Fojt 	    returnDB(TGETENT_NO);
4493468e90cSJohn Marino 	}
450fdd4e1e0SJan Lentfer 
4511d102085SJan Lentfer 	TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d",
4521d102085SJan Lentfer 			    ext_str_limit, offset));
453fdd4e1e0SJan Lentfer 
454fdd4e1e0SJan Lentfer 	if (ext_str_limit) {
45500d8f3c4SJohn Marino 	    ptr->ext_str_table = typeMalloc(char, (size_t) ext_str_limit);
4563468e90cSJohn Marino 	    if (ptr->ext_str_table == 0) {
457*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
4583468e90cSJohn Marino 	    }
4593468e90cSJohn Marino 	    if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) {
460*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
4613468e90cSJohn Marino 	    }
462fdd4e1e0SJan Lentfer 	    TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table)));
463fdd4e1e0SJan Lentfer 	}
464fdd4e1e0SJan Lentfer 
46500d8f3c4SJohn Marino 	if ((ptr->ext_Strings = UShort(ext_str_count)) != 0) {
466*32bb5217SDaniel Fojt 	    int check = (ext_bool_count + ext_num_count + ext_str_count);
467*32bb5217SDaniel Fojt 
468fdd4e1e0SJan Lentfer 	    TR(TRACE_DATABASE,
469*32bb5217SDaniel Fojt 	       ("Before computing extended-string capabilities "
470*32bb5217SDaniel Fojt 		"str_count=%d, ext_str_count=%d",
471fdd4e1e0SJan Lentfer 		str_count, ext_str_count));
472fdd4e1e0SJan Lentfer 	    convert_strings(buf, ptr->Strings + str_count, ext_str_count,
473fdd4e1e0SJan Lentfer 			    ext_str_limit, ptr->ext_str_table);
474fdd4e1e0SJan Lentfer 	    for (i = ext_str_count - 1; i >= 0; i--) {
475fdd4e1e0SJan Lentfer 		TR(TRACE_DATABASE, ("MOVE from [%d:%d] %s",
476fdd4e1e0SJan Lentfer 				    i, i + str_count,
477fdd4e1e0SJan Lentfer 				    _nc_visbuf(ptr->Strings[i + str_count])));
478fdd4e1e0SJan Lentfer 		ptr->Strings[i + STRCOUNT] = ptr->Strings[i + str_count];
479*32bb5217SDaniel Fojt 		if (VALID_STRING(ptr->Strings[i + STRCOUNT])) {
48000d8f3c4SJohn Marino 		    base += (int) (strlen(ptr->Strings[i + STRCOUNT]) + 1);
481*32bb5217SDaniel Fojt 		    ++check;
482*32bb5217SDaniel Fojt 		}
483fdd4e1e0SJan Lentfer 		TR(TRACE_DATABASE, ("... to    [%d] %s",
484fdd4e1e0SJan Lentfer 				    i + STRCOUNT,
485fdd4e1e0SJan Lentfer 				    _nc_visbuf(ptr->Strings[i + STRCOUNT])));
486fdd4e1e0SJan Lentfer 	    }
487*32bb5217SDaniel Fojt 	    TR(TRACE_DATABASE, ("Check table-size: %d/%d", check, ext_str_usage));
488*32bb5217SDaniel Fojt #if 0
489*32bb5217SDaniel Fojt 	    /*
490*32bb5217SDaniel Fojt 	     * Phasing in a proper check will be done "later".
491*32bb5217SDaniel Fojt 	     */
492*32bb5217SDaniel Fojt 	    if (check != ext_str_usage)
493*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
494*32bb5217SDaniel Fojt #endif
495fdd4e1e0SJan Lentfer 	}
496fdd4e1e0SJan Lentfer 
497fdd4e1e0SJan Lentfer 	if (need) {
498*32bb5217SDaniel Fojt 	    if (ext_str_count >= (max_entry_size / 2)) {
499*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
5003468e90cSJohn Marino 	    }
5013468e90cSJohn Marino 	    if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0) {
502*32bb5217SDaniel Fojt 		returnDB(TGETENT_NO);
5033468e90cSJohn Marino 	    }
504fdd4e1e0SJan Lentfer 	    TR(TRACE_DATABASE,
505fdd4e1e0SJan Lentfer 	       ("ext_NAMES starting @%d in extended_strings, first = %s",
506fdd4e1e0SJan Lentfer 		base, _nc_visbuf(ptr->ext_str_table + base)));
5071d102085SJan Lentfer 	    convert_strings(buf + (2 * ext_str_count),
5081d102085SJan Lentfer 			    ptr->ext_Names,
5091d102085SJan Lentfer 			    (int) need,
510fdd4e1e0SJan Lentfer 			    ext_str_limit, ptr->ext_str_table + base);
511fdd4e1e0SJan Lentfer 	}
512fdd4e1e0SJan Lentfer 
5133468e90cSJohn Marino 	TR(TRACE_DATABASE,
5143468e90cSJohn Marino 	   ("...done reading terminfo bool %d(%d) num %d(%d) str %d(%d)",
515fdd4e1e0SJan Lentfer 	    ptr->num_Booleans, ptr->ext_Booleans,
516fdd4e1e0SJan Lentfer 	    ptr->num_Numbers, ptr->ext_Numbers,
517fdd4e1e0SJan Lentfer 	    ptr->num_Strings, ptr->ext_Strings));
518fdd4e1e0SJan Lentfer 
519fdd4e1e0SJan Lentfer 	TR(TRACE_DATABASE, ("extend: num_Booleans:%d", ptr->num_Booleans));
520fdd4e1e0SJan Lentfer     } else
521fdd4e1e0SJan Lentfer #endif /* NCURSES_XNAMES */
522fdd4e1e0SJan Lentfer     {
5233468e90cSJohn Marino 	TR(TRACE_DATABASE, ("...done reading terminfo bool %d num %d str %d",
524fdd4e1e0SJan Lentfer 			    bool_count, num_count, str_count));
525fdd4e1e0SJan Lentfer #if NCURSES_XNAMES
526fdd4e1e0SJan Lentfer 	TR(TRACE_DATABASE, ("normal: num_Booleans:%d", ptr->num_Booleans));
527fdd4e1e0SJan Lentfer #endif
528fdd4e1e0SJan Lentfer     }
529fdd4e1e0SJan Lentfer 
530fdd4e1e0SJan Lentfer     for (i = bool_count; i < BOOLCOUNT; i++)
531fdd4e1e0SJan Lentfer 	ptr->Booleans[i] = FALSE;
532fdd4e1e0SJan Lentfer     for (i = num_count; i < NUMCOUNT; i++)
533fdd4e1e0SJan Lentfer 	ptr->Numbers[i] = ABSENT_NUMERIC;
534fdd4e1e0SJan Lentfer     for (i = str_count; i < STRCOUNT; i++)
535fdd4e1e0SJan Lentfer 	ptr->Strings[i] = ABSENT_STRING;
536fdd4e1e0SJan Lentfer 
537*32bb5217SDaniel Fojt     returnDB(TGETENT_YES);
538fdd4e1e0SJan Lentfer }
539fdd4e1e0SJan Lentfer 
5401d102085SJan Lentfer /*
5411d102085SJan Lentfer  *	int
5421d102085SJan Lentfer  *	_nc_read_file_entry(filename, ptr)
5431d102085SJan Lentfer  *
5441d102085SJan Lentfer  *	Read the compiled terminfo entry in the given file into the
5451d102085SJan Lentfer  *	structure pointed to by ptr, allocating space for the string
5461d102085SJan Lentfer  *	table.
5471d102085SJan Lentfer  */
548fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
_nc_read_file_entry(const char * const filename,TERMTYPE2 * ptr)549*32bb5217SDaniel Fojt _nc_read_file_entry(const char *const filename, TERMTYPE2 *ptr)
550fdd4e1e0SJan Lentfer /* return 1 if read, 0 if not found or garbled */
551fdd4e1e0SJan Lentfer {
55200d8f3c4SJohn Marino     FILE *fp = 0;
55300d8f3c4SJohn Marino     int code;
554fdd4e1e0SJan Lentfer 
555fdd4e1e0SJan Lentfer     if (_nc_access(filename, R_OK) < 0
556*32bb5217SDaniel Fojt 	|| (fp = fopen(filename, BIN_R)) == 0) {
5573468e90cSJohn Marino 	TR(TRACE_DATABASE, ("cannot open terminfo %s (errno=%d)", filename, errno));
5581d102085SJan Lentfer 	code = TGETENT_NO;
559fdd4e1e0SJan Lentfer     } else {
560*32bb5217SDaniel Fojt 	int limit;
561*32bb5217SDaniel Fojt 	char buffer[MAX_ENTRY_SIZE + 1];
562*32bb5217SDaniel Fojt 
56300d8f3c4SJohn Marino 	if ((limit = (int) fread(buffer, sizeof(char), sizeof(buffer), fp))
56400d8f3c4SJohn Marino 	    > 0) {
5651d102085SJan Lentfer 
5663468e90cSJohn Marino 	    TR(TRACE_DATABASE, ("read terminfo %s", filename));
5671d102085SJan Lentfer 	    if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) {
568*32bb5217SDaniel Fojt 		_nc_free_termtype2(ptr);
5691d102085SJan Lentfer 	    }
5701d102085SJan Lentfer 	} else {
5711d102085SJan Lentfer 	    code = TGETENT_NO;
5721d102085SJan Lentfer 	}
57300d8f3c4SJohn Marino 	fclose(fp);
574fdd4e1e0SJan Lentfer     }
575fdd4e1e0SJan Lentfer 
576fdd4e1e0SJan Lentfer     return (code);
577fdd4e1e0SJan Lentfer }
578fdd4e1e0SJan Lentfer 
5793468e90cSJohn Marino #if USE_HASHED_DB
5803468e90cSJohn Marino /*
5813468e90cSJohn Marino  * Return if if we can build the filename of a ".db" file.
5823468e90cSJohn Marino  */
5833468e90cSJohn Marino static bool
make_db_filename(char * filename,unsigned limit,const char * const path)5843468e90cSJohn Marino make_db_filename(char *filename, unsigned limit, const char *const path)
5853468e90cSJohn Marino {
5863468e90cSJohn Marino     static const char suffix[] = DBM_SUFFIX;
5873468e90cSJohn Marino 
5883468e90cSJohn Marino     size_t lens = sizeof(suffix) - 1;
5893468e90cSJohn Marino     size_t size = strlen(path);
5903468e90cSJohn Marino     size_t test = lens + size;
5913468e90cSJohn Marino     bool result = FALSE;
5923468e90cSJohn Marino 
5933468e90cSJohn Marino     if (test < limit) {
5943468e90cSJohn Marino 	if (size >= lens
5953468e90cSJohn Marino 	    && !strcmp(path + size - lens, suffix))
5963468e90cSJohn Marino 	    _nc_STRCPY(filename, path, limit);
5973468e90cSJohn Marino 	else
5983468e90cSJohn Marino 	    _nc_SPRINTF(filename, _nc_SLIMIT(limit) "%s%s", path, suffix);
5993468e90cSJohn Marino 	result = TRUE;
6003468e90cSJohn Marino     }
6013468e90cSJohn Marino     return result;
6023468e90cSJohn Marino }
6033468e90cSJohn Marino #endif
6043468e90cSJohn Marino 
6053468e90cSJohn Marino /*
6063468e90cSJohn Marino  * Return true if we can build the name of a filesystem entry.
6073468e90cSJohn Marino  */
6083468e90cSJohn Marino static bool
make_dir_filename(char * filename,unsigned limit,const char * const path,const char * name)6093468e90cSJohn Marino make_dir_filename(char *filename,
6103468e90cSJohn Marino 		  unsigned limit,
6113468e90cSJohn Marino 		  const char *const path,
6123468e90cSJohn Marino 		  const char *name)
6133468e90cSJohn Marino {
6143468e90cSJohn Marino     bool result = FALSE;
6153468e90cSJohn Marino 
6163468e90cSJohn Marino #if NCURSES_USE_TERMCAP
6173468e90cSJohn Marino     if (_nc_is_dir_path(path))
6183468e90cSJohn Marino #endif
6193468e90cSJohn Marino     {
6203468e90cSJohn Marino 	unsigned need = (unsigned) (LEAF_LEN + 3 + strlen(path) + strlen(name));
6213468e90cSJohn Marino 
6223468e90cSJohn Marino 	if (need <= limit) {
6233468e90cSJohn Marino 	    _nc_SPRINTF(filename, _nc_SLIMIT(limit)
6243468e90cSJohn Marino 			"%s/" LEAF_FMT "/%s", path, *name, name);
6253468e90cSJohn Marino 	    result = TRUE;
6263468e90cSJohn Marino 	}
6273468e90cSJohn Marino     }
6283468e90cSJohn Marino     return result;
6293468e90cSJohn Marino }
6303468e90cSJohn Marino 
631*32bb5217SDaniel Fojt static int
lookup_b64(int * target,const char ** source)632*32bb5217SDaniel Fojt lookup_b64(int *target, const char **source)
633*32bb5217SDaniel Fojt {
634*32bb5217SDaniel Fojt     int result = 3;
635*32bb5217SDaniel Fojt     int j;
636*32bb5217SDaniel Fojt     /*
637*32bb5217SDaniel Fojt      * ncurses' quickdump writes only RFC 4648 "url/filename-safe" encoding,
638*32bb5217SDaniel Fojt      * but accepts RFC-3548
639*32bb5217SDaniel Fojt      */
640*32bb5217SDaniel Fojt     for (j = 0; j < 4; ++j) {
641*32bb5217SDaniel Fojt 	int ch = UChar(**source);
642*32bb5217SDaniel Fojt 	*source += 1;
643*32bb5217SDaniel Fojt 	if (ch >= 'A' && ch <= 'Z') {
644*32bb5217SDaniel Fojt 	    target[j] = (ch - 'A');
645*32bb5217SDaniel Fojt 	} else if (ch >= 'a' && ch <= 'z') {
646*32bb5217SDaniel Fojt 	    target[j] = 26 + (ch - 'a');
647*32bb5217SDaniel Fojt 	} else if (ch >= '0' && ch <= '9') {
648*32bb5217SDaniel Fojt 	    target[j] = 52 + (ch - '0');
649*32bb5217SDaniel Fojt 	} else if (ch == '-' || ch == '+') {
650*32bb5217SDaniel Fojt 	    target[j] = 62;
651*32bb5217SDaniel Fojt 	} else if (ch == '_' || ch == '/') {
652*32bb5217SDaniel Fojt 	    target[j] = 63;
653*32bb5217SDaniel Fojt 	} else if (ch == '=') {
654*32bb5217SDaniel Fojt 	    target[j] = 64;
655*32bb5217SDaniel Fojt 	    result--;
656*32bb5217SDaniel Fojt 	} else {
657*32bb5217SDaniel Fojt 	    result = -1;
658*32bb5217SDaniel Fojt 	    break;
659*32bb5217SDaniel Fojt 	}
660*32bb5217SDaniel Fojt     }
661*32bb5217SDaniel Fojt     return result;
662*32bb5217SDaniel Fojt }
663*32bb5217SDaniel Fojt 
664*32bb5217SDaniel Fojt static int
decode_hex(const char ** source)665*32bb5217SDaniel Fojt decode_hex(const char **source)
666*32bb5217SDaniel Fojt {
667*32bb5217SDaniel Fojt     int result = 0;
668*32bb5217SDaniel Fojt     int nibble;
669*32bb5217SDaniel Fojt     int ch;
670*32bb5217SDaniel Fojt 
671*32bb5217SDaniel Fojt     for (nibble = 0; nibble < 2; ++nibble) {
672*32bb5217SDaniel Fojt 	result <<= 4;
673*32bb5217SDaniel Fojt 	ch = UChar(**source);
674*32bb5217SDaniel Fojt 	*source += 1;
675*32bb5217SDaniel Fojt 	if (ch >= '0' && ch <= '9') {
676*32bb5217SDaniel Fojt 	    ch -= '0';
677*32bb5217SDaniel Fojt 	} else if (ch >= 'A' && ch <= 'F') {
678*32bb5217SDaniel Fojt 	    ch -= 'A';
679*32bb5217SDaniel Fojt 	    ch += 10;
680*32bb5217SDaniel Fojt 	} else if (ch >= 'a' && ch <= 'f') {
681*32bb5217SDaniel Fojt 	    ch -= 'a';
682*32bb5217SDaniel Fojt 	    ch += 10;
683*32bb5217SDaniel Fojt 	} else {
684*32bb5217SDaniel Fojt 	    result = -1;
685*32bb5217SDaniel Fojt 	    break;
686*32bb5217SDaniel Fojt 	}
687*32bb5217SDaniel Fojt 	result |= ch;
688*32bb5217SDaniel Fojt     }
689*32bb5217SDaniel Fojt     return result;
690*32bb5217SDaniel Fojt }
691*32bb5217SDaniel Fojt 
692*32bb5217SDaniel Fojt static int
decode_quickdump(char * target,const char * source)693*32bb5217SDaniel Fojt decode_quickdump(char *target, const char *source)
694*32bb5217SDaniel Fojt {
695*32bb5217SDaniel Fojt     char *base = target;
696*32bb5217SDaniel Fojt     int result = 0;
697*32bb5217SDaniel Fojt 
698*32bb5217SDaniel Fojt     if (!strncmp(source, "b64:", (size_t) 4)) {
699*32bb5217SDaniel Fojt 	source += 4;
700*32bb5217SDaniel Fojt 	while (*source != '\0') {
701*32bb5217SDaniel Fojt 	    int bits[4];
702*32bb5217SDaniel Fojt 	    int ch = lookup_b64(bits, &source);
703*32bb5217SDaniel Fojt 	    if (ch < 0 || (ch + target - base) >= MAX_ENTRY_SIZE) {
704*32bb5217SDaniel Fojt 		result = 0;
705*32bb5217SDaniel Fojt 		break;
706*32bb5217SDaniel Fojt 	    }
707*32bb5217SDaniel Fojt 	    result += ch;
708*32bb5217SDaniel Fojt 	    *target++ = (char) ((bits[0] << 2) | (bits[1] >> 4));
709*32bb5217SDaniel Fojt 	    if (bits[2] < 64) {
710*32bb5217SDaniel Fojt 		*target++ = (char) ((bits[1] << 4) | (bits[2] >> 2));
711*32bb5217SDaniel Fojt 		if (bits[3] < 64) {
712*32bb5217SDaniel Fojt 		    *target++ = (char) ((bits[2] << 6) | bits[3]);
713*32bb5217SDaniel Fojt 		}
714*32bb5217SDaniel Fojt 	    }
715*32bb5217SDaniel Fojt 	}
716*32bb5217SDaniel Fojt     } else if (!strncmp(source, "hex:", (size_t) 4)) {
717*32bb5217SDaniel Fojt 	source += 4;
718*32bb5217SDaniel Fojt 	while (*source != '\0') {
719*32bb5217SDaniel Fojt 	    int ch = decode_hex(&source);
720*32bb5217SDaniel Fojt 	    if (ch < 0 || (target - base) >= MAX_ENTRY_SIZE) {
721*32bb5217SDaniel Fojt 		result = 0;
722*32bb5217SDaniel Fojt 		break;
723*32bb5217SDaniel Fojt 	    }
724*32bb5217SDaniel Fojt 	    *target++ = (char) ch;
725*32bb5217SDaniel Fojt 	    ++result;
726*32bb5217SDaniel Fojt 	}
727*32bb5217SDaniel Fojt     }
728*32bb5217SDaniel Fojt     return result;
729*32bb5217SDaniel Fojt }
730*32bb5217SDaniel Fojt 
731fdd4e1e0SJan Lentfer /*
7321d102085SJan Lentfer  * Build a terminfo pathname and try to read the data.  Returns TGETENT_YES on
7331d102085SJan Lentfer  * success, TGETENT_NO on failure.
734fdd4e1e0SJan Lentfer  */
735fdd4e1e0SJan Lentfer static int
_nc_read_tic_entry(char * filename,unsigned limit,const char * const path,const char * name,TERMTYPE2 * const tp)7361d102085SJan Lentfer _nc_read_tic_entry(char *filename,
7371d102085SJan Lentfer 		   unsigned limit,
7381d102085SJan Lentfer 		   const char *const path,
7391d102085SJan Lentfer 		   const char *name,
740*32bb5217SDaniel Fojt 		   TERMTYPE2 *const tp)
741fdd4e1e0SJan Lentfer {
7423468e90cSJohn Marino     int code = TGETENT_NO;
7431d102085SJan Lentfer #if USE_HASHED_DB
7441d102085SJan Lentfer     DB *capdbp;
745*32bb5217SDaniel Fojt #endif
746*32bb5217SDaniel Fojt     char buffer[MAX_ENTRY_SIZE + 1];
747*32bb5217SDaniel Fojt     int used;
7481d102085SJan Lentfer 
749*32bb5217SDaniel Fojt     TR(TRACE_DATABASE,
750*32bb5217SDaniel Fojt        (T_CALLED("_nc_read_tic_entry(file=%p, path=%s, name=%s)"),
751*32bb5217SDaniel Fojt 	filename, path, name));
752*32bb5217SDaniel Fojt 
753*32bb5217SDaniel Fojt     assert(TGETENT_YES == TRUE);	/* simplify call for _nc_name_match */
754*32bb5217SDaniel Fojt 
755*32bb5217SDaniel Fojt     if ((used = decode_quickdump(buffer, path)) != 0
756*32bb5217SDaniel Fojt 	&& (code = _nc_read_termtype(tp, buffer, used)) == TGETENT_YES
757*32bb5217SDaniel Fojt 	&& (code = _nc_name_match(tp->term_names, name, "|")) == TGETENT_YES) {
758*32bb5217SDaniel Fojt 	TR(TRACE_DATABASE, ("loaded quick-dump for %s", name));
759*32bb5217SDaniel Fojt 	/* shorten name shown by infocmp */
760*32bb5217SDaniel Fojt 	_nc_STRCPY(filename, "$TERMINFO", limit);
761*32bb5217SDaniel Fojt     } else
762*32bb5217SDaniel Fojt #if USE_HASHED_DB
7633468e90cSJohn Marino 	if (make_db_filename(filename, limit, path)
7643468e90cSJohn Marino 	    && (capdbp = _nc_db_open(filename, FALSE)) != 0) {
7651d102085SJan Lentfer 
7661d102085SJan Lentfer 	DBT key, data;
7671d102085SJan Lentfer 	int reccnt = 0;
7681d102085SJan Lentfer 	char *save = strdup(name);
7691d102085SJan Lentfer 
7701d102085SJan Lentfer 	memset(&key, 0, sizeof(key));
7711d102085SJan Lentfer 	key.data = save;
7721d102085SJan Lentfer 	key.size = strlen(save);
7731d102085SJan Lentfer 
7741d102085SJan Lentfer 	/*
7753468e90cSJohn Marino 	 * This lookup could return termcap data, which we do not want.  We are
7763468e90cSJohn Marino 	 * looking for compiled (binary) terminfo data.
7771d102085SJan Lentfer 	 *
7783468e90cSJohn Marino 	 * cgetent uses a two-level lookup.  On the first it uses the given
7793468e90cSJohn Marino 	 * name to return a record containing only the aliases for an entry.
7803468e90cSJohn Marino 	 * On the second (using that list of aliases as a key), it returns the
7813468e90cSJohn Marino 	 * content of the terminal description.  We expect second lookup to
7823468e90cSJohn Marino 	 * return data beginning with the same set of aliases.
7831d102085SJan Lentfer 	 *
7843468e90cSJohn Marino 	 * For compiled terminfo, the list of aliases in the second case will
7853468e90cSJohn Marino 	 * be null-terminated.  A termcap entry will not be, and will run on
7863468e90cSJohn Marino 	 * into the description.  So we can easily distinguish between the two
7873468e90cSJohn Marino 	 * (source/binary) by checking the lengths.
7881d102085SJan Lentfer 	 */
7891d102085SJan Lentfer 	while (_nc_db_get(capdbp, &key, &data) == 0) {
7901d102085SJan Lentfer 	    char *have = (char *) data.data;
791*32bb5217SDaniel Fojt 	    used = (int) data.size - 1;
7921d102085SJan Lentfer 
7931d102085SJan Lentfer 	    if (*have++ == 0) {
7941d102085SJan Lentfer 		if (data.size > key.size
7951d102085SJan Lentfer 		    && IS_TIC_MAGIC(have)) {
7963468e90cSJohn Marino 		    code = _nc_read_termtype(tp, have, used);
7973468e90cSJohn Marino 		    if (code == TGETENT_NO) {
798*32bb5217SDaniel Fojt 			_nc_free_termtype2(tp);
7991d102085SJan Lentfer 		    }
8001d102085SJan Lentfer 		}
8011d102085SJan Lentfer 		break;
802fdd4e1e0SJan Lentfer 	    }
803fdd4e1e0SJan Lentfer 
804fdd4e1e0SJan Lentfer 	    /*
8053468e90cSJohn Marino 	     * Just in case we have a corrupt database, do not waste time with
8063468e90cSJohn Marino 	     * it.
807fdd4e1e0SJan Lentfer 	     */
8081d102085SJan Lentfer 	    if (++reccnt >= 3)
809fdd4e1e0SJan Lentfer 		break;
810fdd4e1e0SJan Lentfer 
811fdd4e1e0SJan Lentfer 	    /*
8121d102085SJan Lentfer 	     * Prepare for the second level.
8131d102085SJan Lentfer 	     */
8141d102085SJan Lentfer 	    key.data = have;
8151d102085SJan Lentfer 	    key.size = used;
8161d102085SJan Lentfer 	}
8171d102085SJan Lentfer 
8181d102085SJan Lentfer 	free(save);
8193468e90cSJohn Marino     } else			/* may be either filesystem or flat file */
8203468e90cSJohn Marino #endif
8213468e90cSJohn Marino     if (make_dir_filename(filename, limit, path, name)) {
8223468e90cSJohn Marino 	code = _nc_read_file_entry(filename, tp);
8231d102085SJan Lentfer     }
8243468e90cSJohn Marino #if NCURSES_USE_TERMCAP
825*32bb5217SDaniel Fojt     if (code != TGETENT_YES) {
8263468e90cSJohn Marino 	code = _nc_read_termcap_entry(name, tp);
8273468e90cSJohn Marino 	_nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX)
8283468e90cSJohn Marino 		    "%.*s", PATH_MAX - 1, _nc_get_source());
8291d102085SJan Lentfer     }
8301d102085SJan Lentfer #endif
831*32bb5217SDaniel Fojt     returnDB(code);
8321d102085SJan Lentfer }
8333468e90cSJohn Marino #endif /* NCURSES_USE_DATABASE */
8341d102085SJan Lentfer 
8351d102085SJan Lentfer /*
836*32bb5217SDaniel Fojt  * Find and read the compiled entry for a given terminal type, if it exists.
837*32bb5217SDaniel Fojt  * We take pains here to make sure no combination of environment variables and
838*32bb5217SDaniel Fojt  * terminal type name can be used to overrun the file buffer.
839fdd4e1e0SJan Lentfer  */
840fdd4e1e0SJan Lentfer NCURSES_EXPORT(int)
_nc_read_entry2(const char * const name,char * const filename,TERMTYPE2 * const tp)841*32bb5217SDaniel Fojt _nc_read_entry2(const char *const name, char *const filename, TERMTYPE2 *const tp)
842fdd4e1e0SJan Lentfer {
8431d102085SJan Lentfer     int code = TGETENT_NO;
844fdd4e1e0SJan Lentfer 
845*32bb5217SDaniel Fojt     if (name == 0)
846*32bb5217SDaniel Fojt 	return _nc_read_entry2("", filename, tp);
847*32bb5217SDaniel Fojt 
8483468e90cSJohn Marino     _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX)
8493468e90cSJohn Marino 		"%.*s", PATH_MAX - 1, name);
8503468e90cSJohn Marino 
8511d102085SJan Lentfer     if (strlen(name) == 0
8521d102085SJan Lentfer 	|| strcmp(name, ".") == 0
8531d102085SJan Lentfer 	|| strcmp(name, "..") == 0
8541d102085SJan Lentfer 	|| _nc_pathlast(name) != 0
8551d102085SJan Lentfer 	|| strchr(name, NCURSES_PATHSEP) != 0) {
8563468e90cSJohn Marino 	TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", name));
8571d102085SJan Lentfer     } else {
8583468e90cSJohn Marino #if NCURSES_USE_DATABASE
8593468e90cSJohn Marino 	DBDIRS state;
8603468e90cSJohn Marino 	int offset;
8611d102085SJan Lentfer 	const char *path;
862fdd4e1e0SJan Lentfer 
8633468e90cSJohn Marino 	_nc_first_db(&state, &offset);
8643468e90cSJohn Marino 	code = TGETENT_ERR;
8651d102085SJan Lentfer 	while ((path = _nc_next_db(&state, &offset)) != 0) {
8661d102085SJan Lentfer 	    code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp);
8671d102085SJan Lentfer 	    if (code == TGETENT_YES) {
8681d102085SJan Lentfer 		_nc_last_db();
8691d102085SJan Lentfer 		break;
870fdd4e1e0SJan Lentfer 	    }
871fdd4e1e0SJan Lentfer 	}
8723468e90cSJohn Marino #elif NCURSES_USE_TERMCAP
8731d102085SJan Lentfer 	if (code != TGETENT_YES) {
8741d102085SJan Lentfer 	    code = _nc_read_termcap_entry(name, tp);
8753468e90cSJohn Marino 	    _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX)
8763468e90cSJohn Marino 			"%.*s", PATH_MAX - 1, _nc_get_source());
8771d102085SJan Lentfer 	}
8781d102085SJan Lentfer #endif
8791d102085SJan Lentfer     }
8801d102085SJan Lentfer     return code;
881fdd4e1e0SJan Lentfer }
882*32bb5217SDaniel Fojt 
883*32bb5217SDaniel Fojt #if NCURSES_EXT_NUMBERS
884*32bb5217SDaniel Fojt /*
885*32bb5217SDaniel Fojt  * This entrypoint is used by tack 1.07
886*32bb5217SDaniel Fojt  */
887*32bb5217SDaniel Fojt NCURSES_EXPORT(int)
_nc_read_entry(const char * const name,char * const filename,TERMTYPE * const tp)888*32bb5217SDaniel Fojt _nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp)
889*32bb5217SDaniel Fojt {
890*32bb5217SDaniel Fojt     TERMTYPE2 dummy;
891*32bb5217SDaniel Fojt     int rc;
892*32bb5217SDaniel Fojt     rc = _nc_read_entry2(name, filename, &dummy);
893*32bb5217SDaniel Fojt     if (rc == TGETENT_YES)
894*32bb5217SDaniel Fojt 	_nc_export_termtype2(tp, &dummy);
895*32bb5217SDaniel Fojt     return rc;
896*32bb5217SDaniel Fojt }
897*32bb5217SDaniel Fojt #endif
898