[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.2

1.21.2.2! pgoyette    1: /* $NetBSD: term.c,v 1.28 2017/05/16 12:03:41 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.2! pgoyette   31: __RCSID("$NetBSD: term.c,v 1.28 2017/05/16 12:03:41 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:
1.21.2.2! pgoyette   49: static char __ti_database[PATH_MAX];
1.1       roy        50: const char *_ti_database;
                     51:
1.9       roy        52: /* Include a generated list of pre-compiled terminfo descriptions. */
                     53: #include "compiled_terms.c"
1.5       roy        54:
1.1       roy        55: static int
1.18      christos   56: allocset(void *pp, int init, size_t nelem, size_t elemsize)
                     57: {
                     58:        void **p = pp;
                     59:        if (*p) {
                     60:                memset(*p, init, nelem * elemsize);
                     61:                return 0;
                     62:        }
                     63:
                     64:        if ((*p = calloc(nelem, elemsize)) == NULL)
                     65:                return -1;
                     66:
                     67:        if (init != 0)
                     68:                memset(*p, init, nelem * elemsize);
                     69:        return 0;
                     70: }
                     71:
                     72: static int
1.5       roy        73: _ti_readterm(TERMINAL *term, const char *cap, size_t caplen, int flags)
1.1       roy        74: {
1.21.2.1  pgoyette   75:        char ver;
1.1       roy        76:        uint16_t ind, num;
                     77:        size_t len;
                     78:        TERMUSERDEF *ud;
                     79:
1.20      christos   80:        if (caplen == 0)
                     81:                goto out;
1.3       roy        82:        ver = *cap++;
1.20      christos   83:        caplen--;
1.15      joerg      84:        /* Only read version 1 structures */
1.20      christos   85:        if (ver != 1)
                     86:                goto out;
1.1       roy        87:
1.21      roy        88:        if (allocset(&term->flags, 0, TIFLAGMAX+1, sizeof(*term->flags)) == -1)
1.13      roy        89:                return -1;
1.18      christos   90:
1.21      roy        91:        if (allocset(&term->nums, -1, TINUMMAX+1, sizeof(*term->nums)) == -1)
1.13      roy        92:                return -1;
1.18      christos   93:
1.21      roy        94:        if (allocset(&term->strs, 0, TISTRMAX+1, sizeof(*term->strs)) == -1)
1.13      roy        95:                return -1;
1.18      christos   96:
                     97:        if (term->_arealen != caplen) {
                     98:                term->_arealen = caplen;
                     99:                term->_area = realloc(term->_area, term->_arealen);
                    100:                if (term->_area == NULL)
                    101:                        return -1;
                    102:        }
1.19      christos  103:        memcpy(term->_area, cap, term->_arealen);
1.1       roy       104:
                    105:        cap = term->_area;
                    106:        len = le16dec(cap);
                    107:        cap += sizeof(uint16_t);
                    108:        term->name = cap;
                    109:        cap += len;
1.15      joerg     110:        len = le16dec(cap);
                    111:        cap += sizeof(uint16_t);
                    112:        if (len == 0)
1.3       roy       113:                term->_alias = NULL;
                    114:        else {
1.15      joerg     115:                term->_alias = cap;
                    116:                cap += len;
1.3       roy       117:        }
1.1       roy       118:        len = le16dec(cap);
                    119:        cap += sizeof(uint16_t);
1.6       roy       120:        if (len == 0)
                    121:                term->desc = NULL;
                    122:        else {
                    123:                term->desc = cap;
                    124:                cap += len;
                    125:        }
1.1       roy       126:
                    127:        num = le16dec(cap);
                    128:        cap += sizeof(uint16_t);
                    129:        if (num != 0) {
                    130:                num = le16dec(cap);
                    131:                cap += sizeof(uint16_t);
                    132:                for (; num != 0; num--) {
                    133:                        ind = le16dec(cap);
                    134:                        cap += sizeof(uint16_t);
                    135:                        term->flags[ind] = *cap++;
                    136:                        if (flags == 0 && !VALID_BOOLEAN(term->flags[ind]))
                    137:                                term->flags[ind] = 0;
                    138:                }
                    139:        }
1.17      roy       140:
1.1       roy       141:        num = le16dec(cap);
                    142:        cap += sizeof(uint16_t);
                    143:        if (num != 0) {
                    144:                num = le16dec(cap);
                    145:                cap += sizeof(uint16_t);
                    146:                for (; num != 0; num--) {
                    147:                        ind = le16dec(cap);
                    148:                        cap += sizeof(uint16_t);
1.21.2.1  pgoyette  149:                        term->nums[ind] = (short)le16dec(cap);
1.1       roy       150:                        if (flags == 0 && !VALID_NUMERIC(term->nums[ind]))
                    151:                                term->nums[ind] = ABSENT_NUMERIC;
                    152:                        cap += sizeof(uint16_t);
                    153:                }
                    154:        }
1.17      roy       155:
1.1       roy       156:        num = le16dec(cap);
                    157:        cap += sizeof(uint16_t);
                    158:        if (num != 0) {
                    159:                num = le16dec(cap);
                    160:                cap += sizeof(uint16_t);
                    161:                for (; num != 0; num--) {
                    162:                        ind = le16dec(cap);
                    163:                        cap += sizeof(uint16_t);
                    164:                        len = le16dec(cap);
                    165:                        cap += sizeof(uint16_t);
                    166:                        if (len > 0)
                    167:                                term->strs[ind] = cap;
                    168:                        else if (flags == 0)
                    169:                                term->strs[ind] = ABSENT_STRING;
                    170:                        else
                    171:                                term->strs[ind] = CANCELLED_STRING;
                    172:                        cap += len;
                    173:                }
                    174:        }
1.17      roy       175:
1.1       roy       176:        num = le16dec(cap);
                    177:        cap += sizeof(uint16_t);
                    178:        if (num != 0) {
1.18      christos  179:                num = le16dec(cap);
1.1       roy       180:                cap += sizeof(uint16_t);
1.18      christos  181:                if (num != term->_nuserdefs) {
                    182:                        free(term->_userdefs);
                    183:                        term->_userdefs = NULL;
                    184:                        term->_nuserdefs = num;
                    185:                }
                    186:                if (allocset(&term->_userdefs, 0, term->_nuserdefs,
                    187:                    sizeof(*term->_userdefs)) == -1)
                    188:                        return -1;
1.1       roy       189:                for (num = 0; num < term->_nuserdefs; num++) {
                    190:                        ud = &term->_userdefs[num];
                    191:                        len = le16dec(cap);
                    192:                        cap += sizeof(uint16_t);
                    193:                        ud->id = cap;
                    194:                        cap += len;
                    195:                        ud->type = *cap++;
                    196:                        switch (ud->type) {
                    197:                        case 'f':
                    198:                                ud->flag = *cap++;
                    199:                                if (flags == 0 &&
                    200:                                    !VALID_BOOLEAN(ud->flag))
                    201:                                        ud->flag = 0;
                    202:                                ud->num = ABSENT_NUMERIC;
                    203:                                ud->str = ABSENT_STRING;
                    204:                                break;
                    205:                        case 'n':
                    206:                                ud->flag = ABSENT_BOOLEAN;
1.21.2.1  pgoyette  207:                                ud->num = (short)le16dec(cap);
1.1       roy       208:                                if (flags == 0 &&
                    209:                                    !VALID_NUMERIC(ud->num))
                    210:                                        ud->num = ABSENT_NUMERIC;
                    211:                                ud->str = ABSENT_STRING;
                    212:                                cap += sizeof(uint16_t);
                    213:                                break;
                    214:                        case 's':
                    215:                                ud->flag = ABSENT_BOOLEAN;
                    216:                                ud->num = ABSENT_NUMERIC;
                    217:                                len = le16dec(cap);
                    218:                                cap += sizeof(uint16_t);
                    219:                                if (len > 0)
                    220:                                        ud->str = cap;
                    221:                                else if (flags == 0)
                    222:                                        ud->str = ABSENT_STRING;
                    223:                                else
                    224:                                        ud->str = CANCELLED_STRING;
                    225:                                cap += len;
                    226:                                break;
                    227:                        default:
1.20      christos  228:                                goto out;
1.1       roy       229:                        }
                    230:                }
1.18      christos  231:        } else {
                    232:                term->_nuserdefs = 0;
                    233:                if (term->_userdefs) {
                    234:                        free(term->_userdefs);
                    235:                        term->_userdefs = NULL;
                    236:                }
1.1       roy       237:        }
1.18      christos  238:
1.1       roy       239:        return 1;
1.20      christos  240: out:
                    241:        errno = EINVAL;
                    242:        return -1;
1.1       roy       243: }
                    244:
                    245: static int
1.21.2.2! pgoyette  246: _ti_checkname(const char *name, const char *termname, const char *termalias)
        !           247: {
        !           248:        const char *alias, *s;
        !           249:        size_t len, l;
        !           250:
        !           251:        /* Check terminal name matches. */
        !           252:        if (strcmp(termname, name) == 0)
        !           253:                return 1;
        !           254:
        !           255:        /* Check terminal aliases match. */
        !           256:        if (termalias == NULL)
        !           257:                return 0;
        !           258:
        !           259:        len = strlen(name);
        !           260:        alias = termalias;
        !           261:        while (*alias != '\0') {
        !           262:                s = strchr(alias, '|');
        !           263:                if (s == NULL)
        !           264:                        l = strlen(alias);
        !           265:                else
        !           266:                        l = (size_t)(s - alias);
        !           267:                if (len == l && memcmp(alias, name, l) == 0)
        !           268:                        return 1;
        !           269:                if (s == NULL)
        !           270:                        break;
        !           271:                alias = s + 1;
        !           272:        }
        !           273:
        !           274:        /* No match. */
        !           275:        return 0;
        !           276: }
        !           277:
        !           278: static int
1.1       roy       279: _ti_dbgetterm(TERMINAL *term, const char *path, const char *name, int flags)
                    280: {
1.15      joerg     281:        struct cdbr *db;
                    282:        const void *data;
                    283:        const uint8_t *data8;
                    284:        size_t len, klen;
1.1       roy       285:        int r;
                    286:
1.21.2.2! pgoyette  287:        if (snprintf(__ti_database, sizeof(__ti_database), "%s.cdb", path) < 0)
1.15      joerg     288:                return -1;
1.21.2.2! pgoyette  289:        db = cdbr_open(__ti_database, CDBR_DEFAULT);
1.1       roy       290:        if (db == NULL)
                    291:                return -1;
1.15      joerg     292:
1.21.2.2! pgoyette  293:        r = 0;
1.15      joerg     294:        klen = strlen(name) + 1;
                    295:        if (cdbr_find(db, name, klen, &data, &len) == -1)
1.21.2.2! pgoyette  296:                goto out;
1.15      joerg     297:        data8 = data;
                    298:        if (len == 0)
1.21.2.2! pgoyette  299:                goto out;
        !           300:
        !           301:        /* If the entry is an alias, load the indexed terminfo description. */
1.15      joerg     302:        if (data8[0] == 2) {
                    303:                if (cdbr_get(db, le32dec(data8 + 1), &data, &len))
1.21.2.2! pgoyette  304:                        goto out;
1.15      joerg     305:                data8 = data;
1.21.2.2! pgoyette  306:        }
1.1       roy       307:
1.15      joerg     308:        r = _ti_readterm(term, data, len, flags);
1.21.2.2! pgoyette  309:        /* Ensure that this is the right terminfo description. */
        !           310:         if (r == 1)
        !           311:                 r = _ti_checkname(name, term->name, term->_alias);
        !           312:        /* Remember the database we read. */
        !           313:         if (r == 1)
        !           314:                 _ti_database = __ti_database;
1.15      joerg     315:
1.21.2.2! pgoyette  316: out:
1.15      joerg     317:        cdbr_close(db);
1.21.2.2! pgoyette  318:        return r;
1.1       roy       319: }
                    320:
                    321: static int
                    322: _ti_dbgettermp(TERMINAL *term, const char *path, const char *name, int flags)
                    323: {
                    324:        const char *p;
1.21.2.2! pgoyette  325:        char pathbuf[PATH_MAX];
1.1       roy       326:        size_t l;
                    327:        int r, e;
                    328:
                    329:        e = -1;
                    330:        r = 0;
                    331:        do {
                    332:                for (p = path; *path != '\0' && *path != ':'; path++)
                    333:                        continue;
1.21.2.1  pgoyette  334:                l = (size_t)(path - p);
1.1       roy       335:                if (l != 0 && l + 1 < sizeof(pathbuf)) {
                    336:                        memcpy(pathbuf, p, l);
                    337:                        pathbuf[l] = '\0';
                    338:                        r = _ti_dbgetterm(term, pathbuf, name, flags);
                    339:                        if (r == 1)
                    340:                                return 1;
                    341:                        if (r == 0)
                    342:                                e = 0;
                    343:                }
                    344:        } while (*path++ == ':');
                    345:        return e;
                    346: }
                    347:
1.8       roy       348: static int
                    349: _ti_findterm(TERMINAL *term, const char *name, int flags)
1.1       roy       350: {
                    351:        int r;
1.21.2.2! pgoyette  352:        char *c, *e;
1.1       roy       353:
                    354:        _DIAGASSERT(term != NULL);
                    355:        _DIAGASSERT(name != NULL);
                    356:
                    357:        _ti_database = NULL;
1.10      roy       358:        r = 0;
1.5       roy       359:
1.21      roy       360:        if ((e = getenv("TERMINFO")) != NULL && *e != '\0') {
1.8       roy       361:                if (e[0] == '/')
                    362:                        return _ti_dbgetterm(term, e, name, flags);
1.21      roy       363:        }
1.11      roy       364:
                    365:        c = NULL;
                    366:        if (e == NULL && (c = getenv("TERMCAP")) != NULL) {
                    367:                if (*c != '\0' && *c != '/') {
                    368:                        c = strdup(c);
                    369:                        if (c != NULL) {
                    370:                                e = captoinfo(c);
                    371:                                free(c);
                    372:                        }
                    373:                }
                    374:        }
                    375:
                    376:        if (e != NULL) {
1.21.2.2! pgoyette  377:                TIC *tic;
        !           378:
1.11      roy       379:                if (c == NULL)
                    380:                        e = strdup(e); /* So we don't destroy env */
1.18      christos  381:                if (e == NULL)
1.11      roy       382:                        tic = NULL;
1.18      christos  383:                else {
1.11      roy       384:                        tic = _ti_compile(e, TIC_WARNING |
                    385:                            TIC_ALIAS | TIC_DESCRIPTION | TIC_EXTRA);
                    386:                        free(e);
1.18      christos  387:                }
1.21.2.2! pgoyette  388:                if (tic != NULL &&
        !           389:                    _ti_checkname(name, tic->name, tic->alias) == 1)
        !           390:                {
        !           391:                        uint8_t *f;
        !           392:                        ssize_t len;
        !           393:
1.10      roy       394:                        len = _ti_flatten(&f, tic);
                    395:                        if (len != -1) {
1.12      roy       396:                                r = _ti_readterm(term, (char *)f, (size_t)len,
                    397:                                    flags);
1.10      roy       398:                                free(f);
                    399:                        }
                    400:                }
                    401:                _ti_freetic(tic);
                    402:                if (r == 1) {
1.11      roy       403:                        if (c == NULL)
                    404:                                _ti_database = "$TERMINFO";
                    405:                        else
                    406:                                _ti_database = "$TERMCAP";
1.10      roy       407:                        return r;
                    408:                }
1.8       roy       409:        }
1.1       roy       410:
1.8       roy       411:        if ((e = getenv("TERMINFO_DIRS")) != NULL)
                    412:                return _ti_dbgettermp(term, e, name, flags);
                    413:
                    414:        if ((e = getenv("HOME")) != NULL) {
1.21.2.2! pgoyette  415:                char homepath[PATH_MAX];
        !           416:
        !           417:                if (snprintf(homepath, sizeof(homepath), "%s/.terminfo", e) > 0)
        !           418:                        r = _ti_dbgetterm(term, homepath, name, flags);
1.1       roy       419:        }
1.8       roy       420:        if (r != 1)
                    421:                r = _ti_dbgettermp(term, _PATH_TERMINFO, name, flags);
1.4       roy       422:
1.8       roy       423:        return r;
                    424: }
                    425:
                    426: int
                    427: _ti_getterm(TERMINAL *term, const char *name, int flags)
                    428: {
                    429:        int r;
                    430:        size_t i;
                    431:        const struct compiled_term *t;
                    432:
                    433:        r = _ti_findterm(term, name, flags);
1.4       roy       434:        if (r == 1)
1.10      roy       435:                return r;
1.4       roy       436:
1.7       roy       437:        for (i = 0; i < __arraycount(compiled_terms); i++) {
                    438:                t = &compiled_terms[i];
                    439:                if (strcmp(name, t->name) == 0) {
                    440:                        r = _ti_readterm(term, t->cap, t->caplen, flags);
1.5       roy       441:                        break;
                    442:                }
1.7       roy       443:        }
1.5       roy       444:
1.4       roy       445:        return r;
1.1       roy       446: }

CVSweb <webmaster@jp.NetBSD.org>