[BACK]Return to term.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libterminfo

Annotation of src/lib/libterminfo/term.c, Revision 1.21.2.1

1.21.2.1! pgoyette    1: /* $NetBSD: term.c,v 1.22 2017/05/04 09:42:23 roy Exp $ */
1.1       roy         2:
                      3: /*
1.12      roy         4:  * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc.
1.1       roy         5:  *
                      6:  * This code is derived from software contributed to The NetBSD Foundation
                      7:  * by Roy Marples.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     27:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29:
                     30: #include <sys/cdefs.h>
1.21.2.1! pgoyette   31: __RCSID("$NetBSD: term.c,v 1.22 2017/05/04 09:42:23 roy Exp $");
1.1       roy        32:
                     33: #include <sys/stat.h>
                     34:
                     35: #include <assert.h>
1.15      joerg      36: #include <cdbr.h>
1.1       roy        37: #include <ctype.h>
                     38: #include <errno.h>
                     39: #include <fcntl.h>
                     40: #include <limits.h>
                     41: #include <stdio.h>
                     42: #include <stdlib.h>
                     43: #include <string.h>
                     44: #include <term_private.h>
                     45: #include <term.h>
                     46:
1.8       roy        47: #define _PATH_TERMINFO         "/usr/share/misc/terminfo"
1.1       roy        48:
                     49: static char database[PATH_MAX];
                     50: static char pathbuf[PATH_MAX];
                     51: const char *_ti_database;
                     52:
1.9       roy        53: /* Include a generated list of pre-compiled terminfo descriptions. */
                     54: #include "compiled_terms.c"
1.5       roy        55:
1.1       roy        56: static int
1.18      christos   57: allocset(void *pp, int init, size_t nelem, size_t elemsize)
                     58: {
                     59:        void **p = pp;
                     60:        if (*p) {
                     61:                memset(*p, init, nelem * elemsize);
                     62:                return 0;
                     63:        }
                     64:
                     65:        if ((*p = calloc(nelem, elemsize)) == NULL)
                     66:                return -1;
                     67:
                     68:        if (init != 0)
                     69:                memset(*p, init, nelem * elemsize);
                     70:        return 0;
                     71: }
                     72:
                     73: static int
1.5       roy        74: _ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags)
1.1       roy        75: {
1.21.2.1! pgoyette   76:        char ver;
1.1       roy        77:        uint16_t ind, num;
                     78:        size_t len;
                     79:        TERMUSERDEF *ud;
                     80:
1.20      christos   81:        if (caplen == 0)
                     82:                goto out;
1.3       roy        83:        ver = *cap++;
1.20      christos   84:        caplen--;
1.15      joerg      85:        /* Only read version 1 structures */
1.20      christos   86:        if (ver != 1)
                     87:                goto out;
1.1       roy        88:
1.21      roy        89:        if (allocset(&term->flags, 0, TIFLAGMAX+1, sizeof(*term->flags)) == -1)
1.13      roy        90:                return -1;
1.18      christos   91:
1.21      roy        92:        if (allocset(&term->nums, -1, TINUMMAX+1, sizeof(*term->nums)) == -1)
1.13      roy        93:                return -1;
1.18      christos   94:
1.21      roy        95:        if (allocset(&term->strs, 0, TISTRMAX+1, sizeof(*term->strs)) == -1)
1.13      roy        96:                return -1;
1.18      christos   97:
                     98:        if (term->_arealen != caplen) {
                     99:                term->_arealen = caplen;
                    100:                term->_area = realloc(term->_area, term->_arealen);
                    101:                if (term->_area == NULL)
                    102:                        return -1;
                    103:        }
1.19      christos  104:        memcpy(term->_area, cap, term->_arealen);
1.1       roy       105:
                    106:        cap = term->_area;
                    107:        len = le16dec(cap);
                    108:        cap += sizeof(uint16_t);
                    109:        term->name = cap;
                    110:        cap += len;
1.15      joerg     111:        len = le16dec(cap);
                    112:        cap += sizeof(uint16_t);
                    113:        if (len == 0)
1.3       roy       114:                term->_alias = NULL;
                    115:        else {
1.15      joerg     116:                term->_alias = cap;
                    117:                cap += len;
1.3       roy       118:        }
1.1       roy       119:        len = le16dec(cap);
                    120:        cap += sizeof(uint16_t);
1.6       roy       121:        if (len == 0)
                    122:                term->desc = NULL;
                    123:        else {
                    124:                term->desc = cap;
                    125:                cap += len;
                    126:        }
1.1       roy       127:
                    128:        num = le16dec(cap);
                    129:        cap += sizeof(uint16_t);
                    130:        if (num != 0) {
                    131:                num = le16dec(cap);
                    132:                cap += sizeof(uint16_t);
                    133:                for (; num != 0; num--) {
                    134:                        ind = le16dec(cap);
                    135:                        cap += sizeof(uint16_t);
                    136:                        term->flags[ind] = *cap++;
                    137:                        if (flags == 0 && !VALID_BOOLEAN(term->flags[ind]))
                    138:                                term->flags[ind] = 0;
                    139:                }
                    140:        }
1.17      roy       141:
1.1       roy       142:        num = le16dec(cap);
                    143:        cap += sizeof(uint16_t);
                    144:        if (num != 0) {
                    145:                num = le16dec(cap);
                    146:                cap += sizeof(uint16_t);
                    147:                for (; num != 0; num--) {
                    148:                        ind = le16dec(cap);
                    149:                        cap += sizeof(uint16_t);
1.21.2.1! pgoyette  150:                        term->nums[ind] = (short)le16dec(cap);
1.1       roy       151:                        if (flags == 0 && !VALID_NUMERIC(term->nums[ind]))
                    152:                                term->nums[ind] = ABSENT_NUMERIC;
                    153:                        cap += sizeof(uint16_t);
                    154:                }
                    155:        }
1.17      roy       156:
1.1       roy       157:        num = le16dec(cap);
                    158:        cap += sizeof(uint16_t);
                    159:        if (num != 0) {
                    160:                num = le16dec(cap);
                    161:                cap += sizeof(uint16_t);
                    162:                for (; num != 0; num--) {
                    163:                        ind = le16dec(cap);
                    164:                        cap += sizeof(uint16_t);
                    165:                        len = le16dec(cap);
                    166:                        cap += sizeof(uint16_t);
                    167:                        if (len > 0)
                    168:                                term->strs[ind] = cap;
                    169:                        else if (flags == 0)
                    170:                                term->strs[ind] = ABSENT_STRING;
                    171:                        else
                    172:                                term->strs[ind] = CANCELLED_STRING;
                    173:                        cap += len;
                    174:                }
                    175:        }
1.17      roy       176:
1.1       roy       177:        num = le16dec(cap);
                    178:        cap += sizeof(uint16_t);
                    179:        if (num != 0) {
1.18      christos  180:                num = le16dec(cap);
1.1       roy       181:                cap += sizeof(uint16_t);
1.18      christos  182:                if (num != term->_nuserdefs) {
                    183:                        free(term->_userdefs);
                    184:                        term->_userdefs = NULL;
                    185:                        term->_nuserdefs = num;
                    186:                }
                    187:                if (allocset(&term->_userdefs, 0, term->_nuserdefs,
                    188:                    sizeof(*term->_userdefs)) == -1)
                    189:                        return -1;
1.1       roy       190:                for (num = 0; num < term->_nuserdefs; num++) {
                    191:                        ud = &term->_userdefs[num];
                    192:                        len = le16dec(cap);
                    193:                        cap += sizeof(uint16_t);
                    194:                        ud->id = cap;
                    195:                        cap += len;
                    196:                        ud->type = *cap++;
                    197:                        switch (ud->type) {
                    198:                        case 'f':
                    199:                                ud->flag = *cap++;
                    200:                                if (flags == 0 &&
                    201:                                    !VALID_BOOLEAN(ud->flag))
                    202:                                        ud->flag = 0;
                    203:                                ud->num = ABSENT_NUMERIC;
                    204:                                ud->str = ABSENT_STRING;
                    205:                                break;
                    206:                        case 'n':
                    207:                                ud->flag = ABSENT_BOOLEAN;
1.21.2.1! pgoyette  208:                                ud->num = (short)le16dec(cap);
1.1       roy       209:                                if (flags == 0 &&
                    210:                                    !VALID_NUMERIC(ud->num))
                    211:                                        ud->num = ABSENT_NUMERIC;
                    212:                                ud->str = ABSENT_STRING;
                    213:                                cap += sizeof(uint16_t);
                    214:                                break;
                    215:                        case 's':
                    216:                                ud->flag = ABSENT_BOOLEAN;
                    217:                                ud->num = ABSENT_NUMERIC;
                    218:                                len = le16dec(cap);
                    219:                                cap += sizeof(uint16_t);
                    220:                                if (len > 0)
                    221:                                        ud->str = cap;
                    222:                                else if (flags == 0)
                    223:                                        ud->str = ABSENT_STRING;
                    224:                                else
                    225:                                        ud->str = CANCELLED_STRING;
                    226:                                cap += len;
                    227:                                break;
                    228:                        default:
1.20      christos  229:                                goto out;
1.1       roy       230:                        }
                    231:                }
1.18      christos  232:        } else {
                    233:                term->_nuserdefs = 0;
                    234:                if (term->_userdefs) {
                    235:                        free(term->_userdefs);
                    236:                        term->_userdefs = NULL;
                    237:                }
1.1       roy       238:        }
1.18      christos  239:
1.1       roy       240:        return 1;
1.20      christos  241: out:
                    242:        errno = EINVAL;
                    243:        return -1;
1.1       roy       244: }
                    245:
                    246: static int
                    247: _ti_dbgetterm(TERMINAL *term, const char *path, const char *name, int flags)
                    248: {
1.15      joerg     249:        struct cdbr *db;
                    250:        const void *data;
                    251:        char *db_name;
                    252:        const uint8_t *data8;
                    253:        size_t len, klen;
1.1       roy       254:        int r;
                    255:
1.15      joerg     256:        if (asprintf(&db_name, "%s.cdb", path) < 0)
                    257:                return -1;
                    258:
                    259:        db = cdbr_open(db_name, CDBR_DEFAULT);
                    260:        free(db_name);
1.1       roy       261:        if (db == NULL)
                    262:                return -1;
1.15      joerg     263:
                    264:        klen = strlen(name) + 1;
                    265:        if (cdbr_find(db, name, klen, &data, &len) == -1)
                    266:                goto fail;
                    267:        data8 = data;
                    268:        if (len == 0)
                    269:                goto fail;
                    270:        /* Check for alias first, fall through to processing normal entries. */
                    271:        if (data8[0] == 2) {
1.16      joerg     272:                if (klen + 7 > len || le16dec(data8 + 5) != klen)
1.15      joerg     273:                        goto fail;
                    274:                if (memcmp(data8 + 7, name, klen))
                    275:                        goto fail;
                    276:                if (cdbr_get(db, le32dec(data8 + 1), &data, &len))
                    277:                        goto fail;
                    278:                data8 = data;
                    279:                if (data8[0] != 1)
                    280:                        goto fail;
1.17      roy       281:        } else if (data8[0] != 1)
1.15      joerg     282:                goto fail;
                    283:        else if (klen + 3 >= len || le16dec(data8 + 1) != klen)
                    284:                goto fail;
                    285:        else if (memcmp(data8 + 3, name, klen))
                    286:                goto fail;
                    287:
1.1       roy       288:        strlcpy(database, path, sizeof(database));
                    289:        _ti_database = database;
                    290:
1.15      joerg     291:        r = _ti_readterm(term, data, len, flags);
                    292:        cdbr_close(db);
1.1       roy       293:        return r;
1.15      joerg     294:
1.21      roy       295: fail:
1.15      joerg     296:        cdbr_close(db);
                    297:        return 0;
1.1       roy       298: }
                    299:
                    300: static int
                    301: _ti_dbgettermp(TERMINAL *term, const char *path, const char *name, int flags)
                    302: {
                    303:        const char *p;
                    304:        size_t l;
                    305:        int r, e;
                    306:
                    307:        e = -1;
                    308:        r = 0;
                    309:        do {
                    310:                for (p = path; *path != '\0' && *path != ':'; path++)
                    311:                        continue;
1.21.2.1! pgoyette  312:                l = (size_t)(path - p);
1.1       roy       313:                if (l != 0 && l + 1 < sizeof(pathbuf)) {
                    314:                        memcpy(pathbuf, p, l);
                    315:                        pathbuf[l] = '\0';
                    316:                        r = _ti_dbgetterm(term, pathbuf, name, flags);
                    317:                        if (r == 1)
                    318:                                return 1;
                    319:                        if (r == 0)
                    320:                                e = 0;
                    321:                }
                    322:        } while (*path++ == ':');
                    323:        return e;
                    324: }
                    325:
1.8       roy       326: static int
1.11      roy       327: ticcmp(const TIC *tic, const char *name)
                    328: {
                    329:        char *alias, *s;
                    330:        size_t len, l;
                    331:
                    332:        if (strcmp(tic->name, name) == 0)
                    333:                return 0;
                    334:        if (tic->alias == NULL)
                    335:                return -1;
                    336:
                    337:        len = strlen(name);
                    338:        alias = tic->alias;
                    339:        while (*alias != '\0') {
                    340:                s = strchr(alias, '|');
                    341:                if (s == NULL)
                    342:                        l = strlen(alias);
                    343:                else
1.21.2.1! pgoyette  344:                        l = (size_t)(s - alias);
1.14      joerg     345:                if (len == l && memcmp(alias, name, l) == 0)
1.11      roy       346:                        return 0;
                    347:                if (s == NULL)
                    348:                        break;
                    349:                alias = s + 1;
                    350:        }
                    351:        return 1;
                    352: }
                    353:
                    354: static int
1.8       roy       355: _ti_findterm(TERMINAL *term, const char *name, int flags)
1.1       roy       356: {
                    357:        int r;
1.10      roy       358:        char *c, *e, h[PATH_MAX];
                    359:        TIC *tic;
                    360:        uint8_t *f;
                    361:        ssize_t len;
1.1       roy       362:
                    363:        _DIAGASSERT(term != NULL);
                    364:        _DIAGASSERT(name != NULL);
                    365:
1.4       roy       366:        database[0] = '\0';
1.1       roy       367:        _ti_database = NULL;
1.10      roy       368:        r = 0;
1.5       roy       369:
1.21      roy       370:        if ((e = getenv("TERMINFO")) != NULL && *e != '\0') {
1.8       roy       371:                if (e[0] == '/')
                    372:                        return _ti_dbgetterm(term, e, name, flags);
1.21      roy       373:        }
1.11      roy       374:
                    375:        c = NULL;
                    376:        if (e == NULL && (c = getenv("TERMCAP")) != NULL) {
                    377:                if (*c != '\0' && *c != '/') {
                    378:                        c = strdup(c);
                    379:                        if (c != NULL) {
                    380:                                e = captoinfo(c);
                    381:                                free(c);
                    382:                        }
                    383:                }
                    384:        }
                    385:
                    386:        if (e != NULL) {
                    387:                if (c == NULL)
                    388:                        e = strdup(e); /* So we don't destroy env */
1.18      christos  389:                if (e == NULL)
1.11      roy       390:                        tic = NULL;
1.18      christos  391:                else {
1.11      roy       392:                        tic = _ti_compile(e, TIC_WARNING |
                    393:                            TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA);
                    394:                        free(e);
1.18      christos  395:                }
1.11      roy       396:                if (tic != NULL && ticcmp(tic, name) == 0) {
1.10      roy       397:                        len = _ti_flatten(&f, tic);
                    398:                        if (len != -1) {
1.12      roy       399:                                r = _ti_readterm(term, (char *)f, (size_t)len,
                    400:                                    flags);
1.10      roy       401:                                free(f);
                    402:                        }
                    403:                }
                    404:                _ti_freetic(tic);
                    405:                if (r == 1) {
1.11      roy       406:                        if (c == NULL)
                    407:                                _ti_database = "$TERMINFO";
                    408:                        else
                    409:                                _ti_database = "$TERMCAP";
1.10      roy       410:                        return r;
                    411:                }
1.8       roy       412:        }
1.1       roy       413:
1.8       roy       414:        if ((e = getenv("TERMINFO_DIRS")) != NULL)
                    415:                return _ti_dbgettermp(term, e, name, flags);
                    416:
                    417:        if ((e = getenv("HOME")) != NULL) {
1.1       roy       418:                snprintf(h, sizeof(h), "%s/.terminfo", e);
                    419:                r = _ti_dbgetterm(term, h, name, flags);
                    420:        }
1.8       roy       421:        if (r != 1)
                    422:                r = _ti_dbgettermp(term, _PATH_TERMINFO, name, flags);
1.4       roy       423:
1.8       roy       424:        return r;
                    425: }
                    426:
                    427: int
                    428: _ti_getterm(TERMINAL *term, const char *name, int flags)
                    429: {
                    430:        int r;
                    431:        size_t i;
                    432:        const struct compiled_term *t;
                    433:
                    434:        r = _ti_findterm(term, name, flags);
1.4       roy       435:        if (r == 1)
1.10      roy       436:                return r;
1.4       roy       437:
1.7       roy       438:        for (i = 0; i < __arraycount(compiled_terms); i++) {
                    439:                t = &compiled_terms[i];
                    440:                if (strcmp(name, t->name) == 0) {
                    441:                        r = _ti_readterm(term, t->cap, t->caplen, flags);
1.5       roy       442:                        break;
                    443:                }
1.7       roy       444:        }
1.5       roy       445:
1.4       roy       446:        return r;
1.1       roy       447: }

CVSweb <webmaster@jp.NetBSD.org>