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

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

CVSweb <webmaster@jp.NetBSD.org>