Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/lib/libterminfo/term.c,v rcsdiff: /ftp/cvs/cvsroot/src/lib/libterminfo/term.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.2 retrieving revision 1.21.2.1 diff -u -p -r1.2 -r1.21.2.1 --- src/lib/libterminfo/term.c 2010/02/05 09:42:21 1.2 +++ src/lib/libterminfo/term.c 2017/05/11 02:58:34 1.21.2.1 @@ -1,7 +1,7 @@ -/* $NetBSD: term.c,v 1.2 2010/02/05 09:42:21 roy Exp $ */ +/* $NetBSD: term.c,v 1.21.2.1 2017/05/11 02:58:34 pgoyette Exp $ */ /* - * Copyright (c) 2009 The NetBSD Foundation, Inc. + * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc. * * This code is derived from software contributed to The NetBSD Foundation * by Roy Marples. @@ -28,55 +28,80 @@ */ #include -__RCSID("$NetBSD: term.c,v 1.2 2010/02/05 09:42:21 roy Exp $"); +__RCSID("$NetBSD: term.c,v 1.21.2.1 2017/05/11 02:58:34 pgoyette Exp $"); #include #include +#include #include #include #include #include -#include #include #include #include #include #include -#define TERMINFO_DIRS "/usr/share/misc/terminfo:/etc/terminfo:/rescue/terminfo" +#define _PATH_TERMINFO "/usr/share/misc/terminfo" static char database[PATH_MAX]; static char pathbuf[PATH_MAX]; const char *_ti_database; +/* Include a generated list of pre-compiled terminfo descriptions. */ +#include "compiled_terms.c" + static int -_ti_readterm(TERMINAL *term, char *cap, size_t caplen, int flags) +allocset(void *pp, int init, size_t nelem, size_t elemsize) { + void **p = pp; + if (*p) { + memset(*p, init, nelem * elemsize); + return 0; + } + + if ((*p = calloc(nelem, elemsize)) == NULL) + return -1; + + if (init != 0) + memset(*p, init, nelem * elemsize); + return 0; +} + +static int +_ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags) +{ + char ver; uint16_t ind, num; size_t len; TERMUSERDEF *ud; + if (caplen == 0) + goto out; + ver = *cap++; + caplen--; /* Only read version 1 structures */ - if (*cap++ != 1) { - errno = EINVAL; + if (ver != 1) + goto out; + + if (allocset(&term->flags, 0, TIFLAGMAX+1, sizeof(*term->flags)) == -1) + return -1; + + if (allocset(&term->nums, -1, TINUMMAX+1, sizeof(*term->nums)) == -1) + return -1; + + if (allocset(&term->strs, 0, TISTRMAX+1, sizeof(*term->strs)) == -1) return -1; - } - term->flags = calloc(TIFLAGMAX + 1, sizeof(char)); - if (term->flags == NULL) - goto err; - term->nums = malloc((TINUMMAX + 1) * sizeof(short)); - if (term->nums == NULL) - goto err; - memset(term->nums, (short)-1, (TINUMMAX + 1) * sizeof(short)); - term->strs = calloc(TISTRMAX + 1, sizeof(char *)); - if (term->strs == NULL) - goto err; - term->_area = malloc(caplen); - if (term->_area == NULL) - goto err; - memcpy(term->_area, cap, caplen); + if (term->_arealen != caplen) { + term->_arealen = caplen; + term->_area = realloc(term->_area, term->_arealen); + if (term->_area == NULL) + return -1; + } + memcpy(term->_area, cap, term->_arealen); cap = term->_area; len = le16dec(cap); @@ -85,8 +110,20 @@ _ti_readterm(TERMINAL *term, char *cap, cap += len; len = le16dec(cap); cap += sizeof(uint16_t); - term->desc = cap; - cap += len; + if (len == 0) + term->_alias = NULL; + else { + term->_alias = cap; + cap += len; + } + len = le16dec(cap); + cap += sizeof(uint16_t); + if (len == 0) + term->desc = NULL; + else { + term->desc = cap; + cap += len; + } num = le16dec(cap); cap += sizeof(uint16_t); @@ -101,7 +138,7 @@ _ti_readterm(TERMINAL *term, char *cap, term->flags[ind] = 0; } } - + num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { @@ -110,13 +147,13 @@ _ti_readterm(TERMINAL *term, char *cap, for (; num != 0; num--) { ind = le16dec(cap); cap += sizeof(uint16_t); - term->nums[ind] = le16dec(cap); + term->nums[ind] = (short)le16dec(cap); if (flags == 0 && !VALID_NUMERIC(term->nums[ind])) term->nums[ind] = ABSENT_NUMERIC; cap += sizeof(uint16_t); } } - + num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { @@ -136,13 +173,20 @@ _ti_readterm(TERMINAL *term, char *cap, cap += len; } } - + num = le16dec(cap); cap += sizeof(uint16_t); if (num != 0) { - term->_nuserdefs = le16dec(cap); - term->_userdefs = malloc(sizeof(*term->_userdefs) * num); + num = le16dec(cap); cap += sizeof(uint16_t); + if (num != term->_nuserdefs) { + free(term->_userdefs); + term->_userdefs = NULL; + term->_nuserdefs = num; + } + if (allocset(&term->_userdefs, 0, term->_nuserdefs, + sizeof(*term->_userdefs)) == -1) + return -1; for (num = 0; num < term->_nuserdefs; num++) { ud = &term->_userdefs[num]; len = le16dec(cap); @@ -161,7 +205,7 @@ _ti_readterm(TERMINAL *term, char *cap, break; case 'n': ud->flag = ABSENT_BOOLEAN; - ud->num = le16dec(cap); + ud->num = (short)le16dec(cap); if (flags == 0 && !VALID_NUMERIC(ud->num)) ud->num = ABSENT_NUMERIC; @@ -182,56 +226,75 @@ _ti_readterm(TERMINAL *term, char *cap, cap += len; break; default: - errno = EINVAL; - goto err; + goto out; } } + } else { + term->_nuserdefs = 0; + if (term->_userdefs) { + free(term->_userdefs); + term->_userdefs = NULL; + } } + return 1; - -err: - _ti_freeterm(term); +out: + errno = EINVAL; return -1; } static int _ti_dbgetterm(TERMINAL *term, const char *path, const char *name, int flags) { - DBM *db; - datum dt; - char *p; + struct cdbr *db; + const void *data; + char *db_name; + const uint8_t *data8; + size_t len, klen; int r; - db = dbm_open(path, O_RDONLY, 0644); + if (asprintf(&db_name, "%s.cdb", path) < 0) + return -1; + + db = cdbr_open(db_name, CDBR_DEFAULT); + free(db_name); if (db == NULL) return -1; + + klen = strlen(name) + 1; + if (cdbr_find(db, name, klen, &data, &len) == -1) + goto fail; + data8 = data; + if (len == 0) + goto fail; + /* Check for alias first, fall through to processing normal entries. */ + if (data8[0] == 2) { + if (klen + 7 > len || le16dec(data8 + 5) != klen) + goto fail; + if (memcmp(data8 + 7, name, klen)) + goto fail; + if (cdbr_get(db, le32dec(data8 + 1), &data, &len)) + goto fail; + data8 = data; + if (data8[0] != 1) + goto fail; + } else if (data8[0] != 1) + goto fail; + else if (klen + 3 >= len || le16dec(data8 + 1) != klen) + goto fail; + else if (memcmp(data8 + 3, name, klen)) + goto fail; + strlcpy(database, path, sizeof(database)); _ti_database = database; - dt.dptr = (void *)__UNCONST(name); - dt.dsize = strlen(name); - dt = dbm_fetch(db, dt); - if (dt.dptr == NULL) { - dbm_close(db); - return 0; - } - for (;;) { - p = (char *)dt.dptr; - if (*p++ != 0) /* not alias */ - break; - dt.dsize = le16dec(p) - 1; - p += sizeof(uint16_t); - dt.dptr = p; - dt = dbm_fetch(db, dt); - if (dt.dptr == NULL) { - dbm_close(db); - return 0; - } - } - - r = _ti_readterm(term, (char *)dt.dptr, dt.dsize, flags); - dbm_close(db); + r = _ti_readterm(term, data, len, flags); + cdbr_close(db); return r; + +fail: + cdbr_close(db); + return 0; } static int @@ -246,7 +309,7 @@ _ti_dbgettermp(TERMINAL *term, const cha do { for (p = path; *path != '\0' && *path != ':'; path++) continue; - l = path - p; + l = (size_t)(path - p); if (l != 0 && l + 1 < sizeof(pathbuf)) { memcpy(pathbuf, p, l); pathbuf[l] = '\0'; @@ -260,45 +323,125 @@ _ti_dbgettermp(TERMINAL *term, const cha return e; } -int -_ti_getterm(TERMINAL *term, const char *name, int flags) +static int +ticcmp(const TIC *tic, const char *name) +{ + char *alias, *s; + size_t len, l; + + if (strcmp(tic->name, name) == 0) + return 0; + if (tic->alias == NULL) + return -1; + + len = strlen(name); + alias = tic->alias; + while (*alias != '\0') { + s = strchr(alias, '|'); + if (s == NULL) + l = strlen(alias); + else + l = (size_t)(s - alias); + if (len == l && memcmp(alias, name, l) == 0) + return 0; + if (s == NULL) + break; + alias = s + 1; + } + return 1; +} + +static int +_ti_findterm(TERMINAL *term, const char *name, int flags) { int r; - char *e, h[PATH_MAX]; + char *c, *e, h[PATH_MAX]; + TIC *tic; + uint8_t *f; + ssize_t len; _DIAGASSERT(term != NULL); _DIAGASSERT(name != NULL); + database[0] = '\0'; _ti_database = NULL; - e = getenv("TERMINFO"); - if (e != NULL) - return _ti_dbgetterm(term, e, name, flags); + r = 0; + + if ((e = getenv("TERMINFO")) != NULL && *e != '\0') { + if (e[0] == '/') + return _ti_dbgetterm(term, e, name, flags); + } + + c = NULL; + if (e == NULL && (c = getenv("TERMCAP")) != NULL) { + if (*c != '\0' && *c != '/') { + c = strdup(c); + if (c != NULL) { + e = captoinfo(c); + free(c); + } + } + } - e = getenv("HOME"); if (e != NULL) { + if (c == NULL) + e = strdup(e); /* So we don't destroy env */ + if (e == NULL) + tic = NULL; + else { + tic = _ti_compile(e, TIC_WARNING | + TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA); + free(e); + } + if (tic != NULL && ticcmp(tic, name) == 0) { + len = _ti_flatten(&f, tic); + if (len != -1) { + r = _ti_readterm(term, (char *)f, (size_t)len, + flags); + free(f); + } + } + _ti_freetic(tic); + if (r == 1) { + if (c == NULL) + _ti_database = "$TERMINFO"; + else + _ti_database = "$TERMCAP"; + return r; + } + } + + if ((e = getenv("TERMINFO_DIRS")) != NULL) + return _ti_dbgettermp(term, e, name, flags); + + if ((e = getenv("HOME")) != NULL) { snprintf(h, sizeof(h), "%s/.terminfo", e); r = _ti_dbgetterm(term, h, name, flags); - if (r == 1) - return 1; } - - return _ti_dbgettermp(term, TERMINFO_DIRS, name, flags); + if (r != 1) + r = _ti_dbgettermp(term, _PATH_TERMINFO, name, flags); + + return r; } -void -_ti_freeterm(TERMINAL *term) +int +_ti_getterm(TERMINAL *term, const char *name, int flags) { + int r; + size_t i; + const struct compiled_term *t; - _DIAGASSERT(term != NULL); - - free(term->_area); - term->_area = NULL; - free(term->strs); - term->strs = NULL; - free(term->nums); - term->nums = NULL; - free(term->flags); - term->flags = NULL; - free(term->_userdefs); - term->_userdefs = NULL; + r = _ti_findterm(term, name, flags); + if (r == 1) + return r; + + for (i = 0; i < __arraycount(compiled_terms); i++) { + t = &compiled_terms[i]; + if (strcmp(name, t->name) == 0) { + r = _ti_readterm(term, t->cap, t->caplen, flags); + break; + } + } + + return r; }