X-Git-Url: https://ncurses.scripts.mit.edu/?p=ncurses.git;a=blobdiff_plain;f=ncurses%2Ftinfo%2Fread_entry.c;h=7102a5f2a2761a62286dafd5152700badf5eee90;hp=a237d60dbfbfbe6fbbccba0f85bfac84a6ea0197;hb=d76c9bfec68e0efa6e1b8e95b32b66caf25cfc12;hpb=af4c589f0c605e1a1dd3825678a0b1a97df02d37 diff --git a/ncurses/tinfo/read_entry.c b/ncurses/tinfo/read_entry.c index a237d60d..7102a5f2 100644 --- a/ncurses/tinfo/read_entry.c +++ b/ncurses/tinfo/read_entry.c @@ -1,5 +1,5 @@ /**************************************************************************** - * Copyright (c) 1998-2010,2011 Free Software Foundation, Inc. * + * Copyright (c) 1998-2018,2019 Free Software Foundation, Inc. * * * * Permission is hereby granted, free of charge, to any person obtaining a * * copy of this software and associated documentation files (the * @@ -41,13 +41,89 @@ #include -MODULE_ID("$Id: read_entry.c,v 1.116 2011/09/27 00:35:20 tom Exp $") +MODULE_ID("$Id: read_entry.c,v 1.155 2019/07/20 20:23:11 tom Exp $") #define TYPE_CALLOC(type,elts) typeCalloc(type, (unsigned)(elts)) -#if USE_DATABASE -static void -convert_shorts(char *buf, short *Numbers, int count) +#define MyNumber(n) (short) LOW_MSB(n) + +#define SIZEOF_32BITS 4 + +#if NCURSES_USE_DATABASE +#if NCURSES_EXT_NUMBERS +static size_t +convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i; + size_t j; + size_t size = SIZEOF_SHORT; + for (i = 0; i < count; i++) { + unsigned mask = 0xff; + unsigned char ch = 0; + Numbers[i] = 0; + for (j = 0; j < size; ++j) { + ch = UChar(*buf++); + Numbers[i] |= (ch << (8 * j)); + mask <<= 8; + } + if (ch & 0x80) { + while (mask != 0) { + Numbers[i] |= (int) mask; + mask <<= 8; + } + } + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return size; +} + +static size_t +convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i; + size_t j; + size_t size = SIZEOF_INT2; + unsigned char ch; + + assert(sizeof(NCURSES_INT2) == size); + for (i = 0; i < count; i++) { + Numbers[i] = 0; + for (j = 0; j < size; ++j) { + ch = UChar(*buf++); + Numbers[i] |= (ch << (8 * j)); + } + /* "unsigned" and NCURSES_INT2 are the same size - no sign-extension */ + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return size; +} +#else +static size_t +convert_32bits(char *buf, NCURSES_INT2 *Numbers, int count) +{ + int i, j; + unsigned char ch; + for (i = 0; i < count; i++) { + int value = 0; + for (j = 0; j < SIZEOF_32BITS; ++j) { + ch = UChar(*buf++); + value |= (ch << (8 * j)); + } + if (value == -1) + Numbers[i] = ABSENT_NUMERIC; + else if (value == -2) + Numbers[i] = CANCELLED_NUMERIC; + else if (value > MAX_OF_TYPE(NCURSES_INT2)) + Numbers[i] = MAX_OF_TYPE(NCURSES_INT2); + else + Numbers[i] = (short) value; + TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); + } + return SIZEOF_SHORT; +} + +static size_t +convert_16bits(char *buf, NCURSES_INT2 *Numbers, int count) { int i; for (i = 0; i < count; i++) { @@ -56,10 +132,12 @@ convert_shorts(char *buf, short *Numbers, int count) else if (IS_NEG2(buf + 2 * i)) Numbers[i] = CANCELLED_NUMERIC; else - Numbers[i] = (short) LOW_MSB(buf + 2 * i); + Numbers[i] = MyNumber(buf + 2 * i); TR(TRACE_DATABASE, ("get Numbers[%d]=%d", i, Numbers[i])); } + return SIZEOF_SHORT; } +#endif static void convert_strings(char *buf, char **Strings, int count, int size, char *table) @@ -72,10 +150,10 @@ convert_strings(char *buf, char **Strings, int count, int size, char *table) Strings[i] = ABSENT_STRING; } else if (IS_NEG2(buf + 2 * i)) { Strings[i] = CANCELLED_STRING; - } else if ((int) LOW_MSB(buf + 2 * i) > size) { + } else if (MyNumber(buf + 2 * i) > size) { Strings[i] = ABSENT_STRING; } else { - Strings[i] = (LOW_MSB(buf + 2 * i) + table); + Strings[i] = (MyNumber(buf + 2 * i) + table); TR(TRACE_DATABASE, ("Strings[%d] = %s", i, _nc_visbuf(Strings[i]))); } @@ -99,7 +177,7 @@ fake_read(char *src, int *offset, int limit, char *dst, unsigned want) if (have > 0) { if ((int) want > have) want = (unsigned) have; - memcpy(dst, src + *offset, want); + memcpy(dst, src + *offset, (size_t) want); *offset += (int) want; } else { want = 0; @@ -107,26 +185,85 @@ fake_read(char *src, int *offset, int limit, char *dst, unsigned want) return (int) want; } -#define Read(buf, count) fake_read(buffer, &offset, limit, buf, count) +#define Read(buf, count) fake_read(buffer, &offset, limit, (char *) buf, (unsigned) count) #define read_shorts(buf, count) \ - (Read(buf, (unsigned) (count)*2) == (int) (count)*2) + (Read(buf, (count)*SIZEOF_SHORT) == (int) (count)*SIZEOF_SHORT) + +#define read_numbers(buf, count) \ + (Read(buf, (count)*(unsigned)size_of_numbers) == (int) (count)*size_of_numbers) #define even_boundary(value) \ if ((value) % 2 != 0) Read(buf, 1) +#endif + +NCURSES_EXPORT(void) +_nc_init_termtype(TERMTYPE2 *const tp) +{ + unsigned i; + +#if NCURSES_XNAMES + tp->num_Booleans = BOOLCOUNT; + tp->num_Numbers = NUMCOUNT; + tp->num_Strings = STRCOUNT; + tp->ext_Booleans = 0; + tp->ext_Numbers = 0; + tp->ext_Strings = 0; +#endif + if (tp->Booleans == 0) + TYPE_MALLOC(NCURSES_SBOOL, BOOLCOUNT, tp->Booleans); + if (tp->Numbers == 0) + TYPE_MALLOC(NCURSES_INT2, NUMCOUNT, tp->Numbers); + if (tp->Strings == 0) + TYPE_MALLOC(char *, STRCOUNT, tp->Strings); + + for_each_boolean(i, tp) + tp->Booleans[i] = FALSE; + + for_each_number(i, tp) + tp->Numbers[i] = ABSENT_NUMERIC; + + for_each_string(i, tp) + tp->Strings[i] = ABSENT_STRING; +} + +#if NCURSES_USE_DATABASE +#if NCURSES_XNAMES +static bool +valid_shorts(char *buffer, int limit) +{ + bool result = FALSE; + int n; + for (n = 0; n < limit; ++n) { + if (MyNumber(buffer + (n * 2)) > 0) { + result = TRUE; + break; + } + } + return result; +} +#endif /* * Return TGETENT_YES if read, TGETENT_NO if not found or garbled. */ NCURSES_EXPORT(int) -_nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) +_nc_read_termtype(TERMTYPE2 *ptr, char *buffer, int limit) { int offset = 0; int name_size, bool_count, num_count, str_count, str_size; int i; - char buf[MAX_ENTRY_SIZE + 1]; + char buf[MAX_ENTRY_SIZE + 2]; char *string_table; unsigned want, have; + bool need_ints; + size_t (*convert_numbers) (char *, NCURSES_INT2 *, int); + int size_of_numbers; + int max_entry_size = MAX_ENTRY_SIZE; + + TR(TRACE_DATABASE, + (T_CALLED("_nc_read_termtype(ptr=%p, buffer=%p, limit=%d)"), + (void *) ptr, buffer, limit)); TR(TRACE_DATABASE, ("READ termtype header @%d", offset)); @@ -135,14 +272,33 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) /* grab the header */ if (!read_shorts(buf, 6) || !IS_TIC_MAGIC(buf)) { - return (TGETENT_NO); + returnDB(TGETENT_NO); + } +#if NCURSES_EXT_NUMBERS + if ((need_ints = (LOW_MSB(buf) == MAGIC2))) { + convert_numbers = convert_32bits; + size_of_numbers = SIZEOF_INT2; + } else { + max_entry_size = MAX_ENTRY_SIZE1; + convert_numbers = convert_16bits; + size_of_numbers = SIZEOF_SHORT; + } +#else + if ((need_ints = (LOW_MSB(buf) == MAGIC2))) { + convert_numbers = convert_32bits; + size_of_numbers = SIZEOF_32BITS; + } else { + convert_numbers = convert_16bits; + size_of_numbers = SIZEOF_INT2; } +#endif - name_size = LOW_MSB(buf + 2); - bool_count = LOW_MSB(buf + 4); - num_count = LOW_MSB(buf + 6); - str_count = LOW_MSB(buf + 8); - str_size = LOW_MSB(buf + 10); + /* *INDENT-EQLS* */ + name_size = MyNumber(buf + 2); + bool_count = MyNumber(buf + 4); + num_count = MyNumber(buf + 6); + str_count = MyNumber(buf + 8); + str_size = MyNumber(buf + 10); TR(TRACE_DATABASE, ("TERMTYPE name_size=%d, bool=%d/%d, num=%d/%d str=%d/%d(%d)", @@ -153,21 +309,14 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) || num_count < 0 || str_count < 0 || str_size < 0) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } want = (unsigned) (str_size + name_size + 1); - if (str_size) { - /* try to allocate space for the string table */ - if (str_count * 2 >= (int) sizeof(buf) - || (string_table = typeMalloc(char, want)) == 0) { - return (TGETENT_NO); - } - } else { - str_count = 0; - if ((string_table = typeMalloc(char, want)) == 0) { - return (TGETENT_NO); - } + /* try to allocate space for the string table */ + if (str_count * SIZEOF_SHORT >= max_entry_size + || (string_table = typeMalloc(char, want)) == 0) { + returnDB(TGETENT_NO); } /* grab the name (a null-terminated string) */ @@ -175,7 +324,7 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) ptr->str_table = string_table; ptr->term_names = string_table; if ((have = (unsigned) Read(ptr->term_names, want)) != want) { - memset(ptr->term_names + have, 0, want - have); + memset(ptr->term_names + have, 0, (size_t) (want - have)); } ptr->term_names[want] = '\0'; string_table += (want + 1); @@ -187,7 +336,7 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) if ((ptr->Booleans = TYPE_CALLOC(NCURSES_SBOOL, max(BOOLCOUNT, bool_count))) == 0 || Read(ptr->Booleans, (unsigned) bool_count) < bool_count) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } /* @@ -199,23 +348,25 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) even_boundary(name_size + bool_count); /* grab the numbers */ - if ((ptr->Numbers = TYPE_CALLOC(short, max(NUMCOUNT, num_count))) == 0 - || !read_shorts(buf, num_count)) { - return (TGETENT_NO); + if (!(ptr->Numbers = TYPE_CALLOC(NCURSES_INT2, max(NUMCOUNT, num_count))) + || !read_numbers(buf, num_count)) { + returnDB(TGETENT_NO); } - convert_shorts(buf, ptr->Numbers, num_count); + convert_numbers(buf, ptr->Numbers, num_count); - if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0) - return (TGETENT_NO); + if ((ptr->Strings = TYPE_CALLOC(char *, max(STRCOUNT, str_count))) == 0) { + returnDB(TGETENT_NO); + } if (str_count) { /* grab the string offsets */ if (!read_shorts(buf, str_count)) { - return (TGETENT_NO); + returnDB(TGETENT_NO); } /* finally, grab the string table itself */ - if (Read(string_table, (unsigned) str_size) != str_size) - return (TGETENT_NO); + if (Read(string_table, (unsigned) str_size) != str_size) { + returnDB(TGETENT_NO); + } convert_strings(buf, ptr->Strings, str_count, str_size, string_table); } #if NCURSES_XNAMES @@ -229,75 +380,93 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) */ even_boundary(str_size); TR(TRACE_DATABASE, ("READ extended_header @%d", offset)); - if (_nc_user_definable && read_shorts(buf, 5)) { - int ext_bool_count = LOW_MSB(buf + 0); - int ext_num_count = LOW_MSB(buf + 2); - int ext_str_count = LOW_MSB(buf + 4); - int ext_str_size = LOW_MSB(buf + 6); - int ext_str_limit = LOW_MSB(buf + 8); + if (_nc_user_definable && read_shorts(buf, 5) && valid_shorts(buf, 5)) { + int ext_bool_count = MyNumber(buf + 0); + int ext_num_count = MyNumber(buf + 2); + int ext_str_count = MyNumber(buf + 4); + int ext_str_usage = MyNumber(buf + 6); + int ext_str_limit = MyNumber(buf + 8); unsigned need = (unsigned) (ext_bool_count + ext_num_count + ext_str_count); int base = 0; - if (need >= sizeof(buf) - || ext_str_size >= (int) sizeof(buf) - || ext_str_limit >= (int) sizeof(buf) + if ((int) need >= (max_entry_size / 2) + || ext_str_usage >= max_entry_size + || ext_str_limit >= max_entry_size || ext_bool_count < 0 || ext_num_count < 0 || ext_str_count < 0 - || ext_str_size < 0 - || ext_str_limit < 0) - return (TGETENT_NO); + || ext_str_usage < 0 + || ext_str_limit < 0) { + returnDB(TGETENT_NO); + } ptr->num_Booleans = UShort(BOOLCOUNT + ext_bool_count); ptr->num_Numbers = UShort(NUMCOUNT + ext_num_count); ptr->num_Strings = UShort(STRCOUNT + ext_str_count); - ptr->Booleans = typeRealloc(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans); - ptr->Numbers = typeRealloc(short, ptr->num_Numbers, ptr->Numbers); - ptr->Strings = typeRealloc(char *, ptr->num_Strings, ptr->Strings); + TYPE_REALLOC(NCURSES_SBOOL, ptr->num_Booleans, ptr->Booleans); + TYPE_REALLOC(NCURSES_INT2, ptr->num_Numbers, ptr->Numbers); + TYPE_REALLOC(char *, ptr->num_Strings, ptr->Strings); - TR(TRACE_DATABASE, ("extended header is %d/%d/%d(%d:%d)", - ext_bool_count, ext_num_count, ext_str_count, - ext_str_size, ext_str_limit)); + TR(TRACE_DATABASE, ("extended header: " + "bool %d, " + "number %d, " + "string %d(%d:%d)", + ext_bool_count, + ext_num_count, + ext_str_count, + ext_str_usage, + ext_str_limit)); TR(TRACE_DATABASE, ("READ %d extended-booleans @%d", ext_bool_count, offset)); if ((ptr->ext_Booleans = UShort(ext_bool_count)) != 0) { if (Read(ptr->Booleans + BOOLCOUNT, (unsigned) - ext_bool_count) != ext_bool_count) - return (TGETENT_NO); + ext_bool_count) != ext_bool_count) { + returnDB(TGETENT_NO); + } } even_boundary(ext_bool_count); TR(TRACE_DATABASE, ("READ %d extended-numbers @%d", ext_num_count, offset)); if ((ptr->ext_Numbers = UShort(ext_num_count)) != 0) { - if (!read_shorts(buf, ext_num_count)) - return (TGETENT_NO); + if (!read_numbers(buf, ext_num_count)) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("Before converting extended-numbers")); - convert_shorts(buf, ptr->Numbers + NUMCOUNT, ext_num_count); + convert_numbers(buf, ptr->Numbers + NUMCOUNT, ext_num_count); } TR(TRACE_DATABASE, ("READ extended-offsets @%d", offset)); + if ((ext_str_count + (int) need) >= (max_entry_size / 2)) { + returnDB(TGETENT_NO); + } if ((ext_str_count || need) - && !read_shorts(buf, ext_str_count + (int) need)) - return (TGETENT_NO); + && !read_shorts(buf, ext_str_count + (int) need)) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("READ %d bytes of extended-strings @%d", ext_str_limit, offset)); if (ext_str_limit) { ptr->ext_str_table = typeMalloc(char, (size_t) ext_str_limit); - if (ptr->ext_str_table == 0) - return (TGETENT_NO); - if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) - return (TGETENT_NO); + if (ptr->ext_str_table == 0) { + returnDB(TGETENT_NO); + } + if (Read(ptr->ext_str_table, (unsigned) ext_str_limit) != ext_str_limit) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("first extended-string is %s", _nc_visbuf(ptr->ext_str_table))); } if ((ptr->ext_Strings = UShort(ext_str_count)) != 0) { + int check = (ext_bool_count + ext_num_count + ext_str_count); + TR(TRACE_DATABASE, - ("Before computing extended-string capabilities str_count=%d, ext_str_count=%d", + ("Before computing extended-string capabilities " + "str_count=%d, ext_str_count=%d", str_count, ext_str_count)); convert_strings(buf, ptr->Strings + str_count, ext_str_count, ext_str_limit, ptr->ext_str_table); @@ -306,19 +475,31 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) i, i + str_count, _nc_visbuf(ptr->Strings[i + str_count]))); ptr->Strings[i + STRCOUNT] = ptr->Strings[i + str_count]; - if (VALID_STRING(ptr->Strings[i + STRCOUNT])) + if (VALID_STRING(ptr->Strings[i + STRCOUNT])) { base += (int) (strlen(ptr->Strings[i + STRCOUNT]) + 1); + ++check; + } TR(TRACE_DATABASE, ("... to [%d] %s", i + STRCOUNT, _nc_visbuf(ptr->Strings[i + STRCOUNT]))); } + TR(TRACE_DATABASE, ("Check table-size: %d/%d", check, ext_str_usage)); +#if 0 + /* + * Phasing in a proper check will be done "later". + */ + if (check != ext_str_usage) + returnDB(TGETENT_NO); +#endif } if (need) { - if (ext_str_count >= (MAX_ENTRY_SIZE * 2)) - return (TGETENT_NO); - if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0) - return (TGETENT_NO); + if (ext_str_count >= (max_entry_size / 2)) { + returnDB(TGETENT_NO); + } + if ((ptr->ext_Names = TYPE_CALLOC(char *, need)) == 0) { + returnDB(TGETENT_NO); + } TR(TRACE_DATABASE, ("ext_NAMES starting @%d in extended_strings, first = %s", base, _nc_visbuf(ptr->ext_str_table + base))); @@ -352,7 +533,7 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) for (i = str_count; i < STRCOUNT; i++) ptr->Strings[i] = ABSENT_STRING; - return (TGETENT_YES); + returnDB(TGETENT_YES); } /* @@ -364,25 +545,26 @@ _nc_read_termtype(TERMTYPE *ptr, char *buffer, int limit) * table. */ NCURSES_EXPORT(int) -_nc_read_file_entry(const char *const filename, TERMTYPE *ptr) +_nc_read_file_entry(const char *const filename, TERMTYPE2 *ptr) /* return 1 if read, 0 if not found or garbled */ { FILE *fp = 0; int code; - int limit; - char buffer[MAX_ENTRY_SIZE + 1]; if (_nc_access(filename, R_OK) < 0 - || (fp = fopen(filename, "rb")) == 0) { + || (fp = fopen(filename, BIN_R)) == 0) { TR(TRACE_DATABASE, ("cannot open terminfo %s (errno=%d)", filename, errno)); code = TGETENT_NO; } else { + int limit; + char buffer[MAX_ENTRY_SIZE + 1]; + if ((limit = (int) fread(buffer, sizeof(char), sizeof(buffer), fp)) > 0) { TR(TRACE_DATABASE, ("read terminfo %s", filename)); if ((code = _nc_read_termtype(ptr, buffer, limit)) == TGETENT_NO) { - _nc_free_termtype(ptr); + _nc_free_termtype2(ptr); } } else { code = TGETENT_NO; @@ -402,17 +584,17 @@ make_db_filename(char *filename, unsigned limit, const char *const path) { static const char suffix[] = DBM_SUFFIX; - unsigned lens = sizeof(suffix) - 1; - unsigned size = strlen(path); - unsigned test = lens + size; + size_t lens = sizeof(suffix) - 1; + size_t size = strlen(path); + size_t test = lens + size; bool result = FALSE; if (test < limit) { if (size >= lens && !strcmp(path + size - lens, suffix)) - (void) strcpy(filename, path); + _nc_STRCPY(filename, path, limit); else - (void) sprintf(filename, "%s%s", path, suffix); + _nc_SPRINTF(filename, _nc_SLIMIT(limit) "%s%s", path, suffix); result = TRUE; } return result; @@ -430,20 +612,121 @@ make_dir_filename(char *filename, { bool result = FALSE; -#if USE_TERMCAP +#if NCURSES_USE_TERMCAP if (_nc_is_dir_path(path)) #endif { unsigned need = (unsigned) (LEAF_LEN + 3 + strlen(path) + strlen(name)); if (need <= limit) { - (void) sprintf(filename, "%s/" LEAF_FMT "/%s", path, *name, name); + _nc_SPRINTF(filename, _nc_SLIMIT(limit) + "%s/" LEAF_FMT "/%s", path, *name, name); result = TRUE; } } return result; } +static int +lookup_b64(int *target, const char **source) +{ + int result = 3; + int j; + /* + * ncurses' quickdump writes only RFC 4648 "url/filename-safe" encoding, + * but accepts RFC-3548 + */ + for (j = 0; j < 4; ++j) { + int ch = UChar(**source); + *source += 1; + if (ch >= 'A' && ch <= 'Z') { + target[j] = (ch - 'A'); + } else if (ch >= 'a' && ch <= 'z') { + target[j] = 26 + (ch - 'a'); + } else if (ch >= '0' && ch <= '9') { + target[j] = 52 + (ch - '0'); + } else if (ch == '-' || ch == '+') { + target[j] = 62; + } else if (ch == '_' || ch == '/') { + target[j] = 63; + } else if (ch == '=') { + target[j] = 64; + result--; + } else { + result = -1; + break; + } + } + return result; +} + +static int +decode_hex(const char **source) +{ + int result = 0; + int nibble; + int ch; + + for (nibble = 0; nibble < 2; ++nibble) { + result <<= 4; + ch = UChar(**source); + *source += 1; + if (ch >= '0' && ch <= '9') { + ch -= '0'; + } else if (ch >= 'A' && ch <= 'F') { + ch -= 'A'; + ch += 10; + } else if (ch >= 'a' && ch <= 'f') { + ch -= 'a'; + ch += 10; + } else { + result = -1; + break; + } + result |= ch; + } + return result; +} + +static int +decode_quickdump(char *target, const char *source) +{ + char *base = target; + int result = 0; + + if (!strncmp(source, "b64:", (size_t) 4)) { + source += 4; + while (*source != '\0') { + int bits[4]; + int ch = lookup_b64(bits, &source); + if (ch < 0 || (ch + target - base) >= MAX_ENTRY_SIZE) { + result = 0; + break; + } + result += ch; + *target++ = (char) ((bits[0] << 2) | (bits[1] >> 4)); + if (bits[2] < 64) { + *target++ = (char) ((bits[1] << 4) | (bits[2] >> 2)); + if (bits[3] < 64) { + *target++ = (char) ((bits[2] << 6) | bits[3]); + } + } + } + } else if (!strncmp(source, "hex:", (size_t) 4)) { + source += 4; + while (*source != '\0') { + int ch = decode_hex(&source); + if (ch < 0 || (target - base) >= MAX_ENTRY_SIZE) { + result = 0; + break; + } + *target++ = (char) ch; + ++result; + } + } + return result; +} + /* * Build a terminfo pathname and try to read the data. Returns TGETENT_YES on * success, TGETENT_NO on failure. @@ -453,15 +736,31 @@ _nc_read_tic_entry(char *filename, unsigned limit, const char *const path, const char *name, - TERMTYPE *const tp) + TERMTYPE2 *const tp) { int code = TGETENT_NO; - #if USE_HASHED_DB DB *capdbp; +#endif + char buffer[MAX_ENTRY_SIZE + 1]; + int used; + + TR(TRACE_DATABASE, + (T_CALLED("_nc_read_tic_entry(file=%p, path=%s, name=%s)"), + filename, path, name)); - if (make_db_filename(filename, limit, path) - && (capdbp = _nc_db_open(filename, FALSE)) != 0) { + assert(TGETENT_YES == TRUE); /* simplify call for _nc_name_match */ + + if ((used = decode_quickdump(buffer, path)) != 0 + && (code = _nc_read_termtype(tp, buffer, used)) == TGETENT_YES + && (code = _nc_name_match(tp->term_names, name, "|")) == TGETENT_YES) { + TR(TRACE_DATABASE, ("loaded quick-dump for %s", name)); + /* shorten name shown by infocmp */ + _nc_STRCPY(filename, "$TERMINFO", limit); + } else +#if USE_HASHED_DB + if (make_db_filename(filename, limit, path) + && (capdbp = _nc_db_open(filename, FALSE)) != 0) { DBT key, data; int reccnt = 0; @@ -487,15 +786,15 @@ _nc_read_tic_entry(char *filename, * (source/binary) by checking the lengths. */ while (_nc_db_get(capdbp, &key, &data) == 0) { - int used = data.size - 1; char *have = (char *) data.data; + used = (int) data.size - 1; if (*have++ == 0) { if (data.size > key.size && IS_TIC_MAGIC(have)) { code = _nc_read_termtype(tp, have, used); if (code == TGETENT_NO) { - _nc_free_termtype(tp); + _nc_free_termtype2(tp); } } break; @@ -521,31 +820,33 @@ _nc_read_tic_entry(char *filename, if (make_dir_filename(filename, limit, path, name)) { code = _nc_read_file_entry(filename, tp); } -#if USE_TERMCAP - else if (code != TGETENT_YES) { +#if NCURSES_USE_TERMCAP + if (code != TGETENT_YES) { code = _nc_read_termcap_entry(name, tp); - sprintf(filename, "%.*s", PATH_MAX - 1, _nc_get_source()); + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, _nc_get_source()); } #endif - return code; + returnDB(code); } -#endif /* USE_DATABASE */ +#endif /* NCURSES_USE_DATABASE */ /* - * _nc_read_entry(char *name, char *filename, TERMTYPE *tp) - * - * Find and read the compiled entry for a given terminal type, - * if it exists. We take pains here to make sure no combination - * of environment variables and terminal type name can be used to - * overrun the file buffer. + * Find and read the compiled entry for a given terminal type, if it exists. + * We take pains here to make sure no combination of environment variables and + * terminal type name can be used to overrun the file buffer. */ - NCURSES_EXPORT(int) -_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) +_nc_read_entry2(const char *const name, char *const filename, TERMTYPE2 *const tp) { int code = TGETENT_NO; - sprintf(filename, "%.*s", PATH_MAX - 1, name); + if (name == 0) + return _nc_read_entry2("", filename, tp); + + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, name); + if (strlen(name) == 0 || strcmp(name, ".") == 0 || strcmp(name, "..") == 0 @@ -553,26 +854,43 @@ _nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) || strchr(name, NCURSES_PATHSEP) != 0) { TR(TRACE_DATABASE, ("illegal or missing entry name '%s'", name)); } else { -#if USE_DATABASE +#if NCURSES_USE_DATABASE DBDIRS state; int offset; const char *path; _nc_first_db(&state, &offset); + code = TGETENT_ERR; while ((path = _nc_next_db(&state, &offset)) != 0) { - TR(TRACE_DATABASE, ("_nc_read_tic_entry path=%s, name=%s", path, name)); code = _nc_read_tic_entry(filename, PATH_MAX, path, name, tp); if (code == TGETENT_YES) { _nc_last_db(); break; } } -#elif USE_TERMCAP +#elif NCURSES_USE_TERMCAP if (code != TGETENT_YES) { code = _nc_read_termcap_entry(name, tp); - sprintf(filename, "%.*s", PATH_MAX - 1, _nc_get_source()); + _nc_SPRINTF(filename, _nc_SLIMIT(PATH_MAX) + "%.*s", PATH_MAX - 1, _nc_get_source()); } #endif } return code; } + +#if NCURSES_EXT_NUMBERS +/* + * This entrypoint is used by tack. + */ +NCURSES_EXPORT(int) +_nc_read_entry(const char *const name, char *const filename, TERMTYPE *const tp) +{ + TERMTYPE2 dummy; + int rc; + rc = _nc_read_entry2(name, filename, &dummy); + if (rc == TGETENT_YES) + _nc_export_termtype2(tp, &dummy); + return rc; +} +#endif