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

1.19.2.1! pgoyette    1: /* $NetBSD: term.c,v 1.20 2016/11/24 17:09:55 christos 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.19.2.1! pgoyette   31: __RCSID("$NetBSD: term.c,v 1.20 2016/11/24 17:09:55 christos 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.3       roy        76:        uint8_t ver;
1.1       roy        77:        uint16_t ind, num;
                     78:        size_t len;
                     79:        TERMUSERDEF *ud;
                     80:
1.19.2.1! pgoyette   81:        if (caplen == 0)
        !            82:                goto out;
1.3       roy        83:        ver = *cap++;
1.19.2.1! pgoyette   84:        caplen--;
1.15      joerg      85:        /* Only read version 1 structures */
1.19.2.1! pgoyette   86:        if (ver != 1)
        !            87:                goto out;
1.1       roy        88:
1.18      christos   89:
                     90:        if (allocset(&term->flags, 0, TIFLAGMAX + 1, sizeof(*term->flags)) == -1)
1.13      roy        91:                return -1;
1.18      christos   92:
                     93:        if (allocset(&term->nums, -1, TINUMMAX + 1, sizeof(*term->nums)) == -1)
1.13      roy        94:                return -1;
1.18      christos   95:
                     96:        if (allocset(&term->strs, 0, TISTRMAX + 1, sizeof(*term->strs)) == -1)
1.13      roy        97:                return -1;
1.18      christos   98:
                     99:        if (term->_arealen != caplen) {
                    100:                term->_arealen = caplen;
                    101:                term->_area = realloc(term->_area, term->_arealen);
                    102:                if (term->_area == NULL)
                    103:                        return -1;
                    104:        }
1.19      christos  105:        memcpy(term->_area, cap, term->_arealen);
1.1       roy       106:
                    107:        cap = term->_area;
                    108:        len = le16dec(cap);
                    109:        cap += sizeof(uint16_t);
                    110:        term->name = cap;
                    111:        cap += len;
1.15      joerg     112:        len = le16dec(cap);
                    113:        cap += sizeof(uint16_t);
                    114:        if (len == 0)
1.3       roy       115:                term->_alias = NULL;
                    116:        else {
1.15      joerg     117:                term->_alias = cap;
                    118:                cap += len;
1.3       roy       119:        }
1.1       roy       120:        len = le16dec(cap);
                    121:        cap += sizeof(uint16_t);
1.6       roy       122:        if (len == 0)
                    123:                term->desc = NULL;
                    124:        else {
                    125:                term->desc = cap;
                    126:                cap += len;
                    127:        }
1.1       roy       128:
                    129:        num = le16dec(cap);
                    130:        cap += sizeof(uint16_t);
                    131:        if (num != 0) {
                    132:                num = le16dec(cap);
                    133:                cap += sizeof(uint16_t);
                    134:                for (; num != 0; num--) {
                    135:                        ind = le16dec(cap);
                    136:                        cap += sizeof(uint16_t);
                    137:                        term->flags[ind] = *cap++;
                    138:                        if (flags == 0 && !VALID_BOOLEAN(term->flags[ind]))
                    139:                                term->flags[ind] = 0;
                    140:                }
                    141:        }
1.17      roy       142:
1.1       roy       143:        num = le16dec(cap);
                    144:        cap += sizeof(uint16_t);
                    145:        if (num != 0) {
                    146:                num = le16dec(cap);
                    147:                cap += sizeof(uint16_t);
                    148:                for (; num != 0; num--) {
                    149:                        ind = le16dec(cap);
                    150:                        cap += sizeof(uint16_t);
                    151:                        term->nums[ind] = le16dec(cap);
                    152:                        if (flags == 0 && !VALID_NUMERIC(term->nums[ind]))
                    153:                                term->nums[ind] = ABSENT_NUMERIC;
                    154:                        cap += sizeof(uint16_t);
                    155:                }
                    156:        }
1.17      roy       157:
1.1       roy       158:        num = le16dec(cap);
                    159:        cap += sizeof(uint16_t);
                    160:        if (num != 0) {
                    161:                num = le16dec(cap);
                    162:                cap += sizeof(uint16_t);
                    163:                for (; num != 0; num--) {
                    164:                        ind = le16dec(cap);
                    165:                        cap += sizeof(uint16_t);
                    166:                        len = le16dec(cap);
                    167:                        cap += sizeof(uint16_t);
                    168:                        if (len > 0)
                    169:                                term->strs[ind] = cap;
                    170:                        else if (flags == 0)
                    171:                                term->strs[ind] = ABSENT_STRING;
                    172:                        else
                    173:                                term->strs[ind] = CANCELLED_STRING;
                    174:                        cap += len;
                    175:                }
                    176:        }
1.17      roy       177:
1.1       roy       178:        num = le16dec(cap);
                    179:        cap += sizeof(uint16_t);
                    180:        if (num != 0) {
1.18      christos  181:                num = le16dec(cap);
1.1       roy       182:                cap += sizeof(uint16_t);
1.18      christos  183:                if (num != term->_nuserdefs) {
                    184:                        free(term->_userdefs);
                    185:                        term->_userdefs = NULL;
                    186:                        term->_nuserdefs = num;
                    187:                }
                    188:                if (allocset(&term->_userdefs, 0, term->_nuserdefs,
                    189:                    sizeof(*term->_userdefs)) == -1)
                    190:                        return -1;
1.1       roy       191:                for (num = 0; num < term->_nuserdefs; num++) {
                    192:                        ud = &term->_userdefs[num];
                    193:                        len = le16dec(cap);
                    194:                        cap += sizeof(uint16_t);
                    195:                        ud->id = cap;
                    196:                        cap += len;
                    197:                        ud->type = *cap++;
                    198:                        switch (ud->type) {
                    199:                        case 'f':
                    200:                                ud->flag = *cap++;
                    201:                                if (flags == 0 &&
                    202:                                    !VALID_BOOLEAN(ud->flag))
                    203:                                        ud->flag = 0;
                    204:                                ud->num = ABSENT_NUMERIC;
                    205:                                ud->str = ABSENT_STRING;
                    206:                                break;
                    207:                        case 'n':
                    208:                                ud->flag = ABSENT_BOOLEAN;
                    209:                                ud->num = le16dec(cap);
                    210:                                if (flags == 0 &&
                    211:                                    !VALID_NUMERIC(ud->num))
                    212:                                        ud->num = ABSENT_NUMERIC;
                    213:                                ud->str = ABSENT_STRING;
                    214:                                cap += sizeof(uint16_t);
                    215:                                break;
                    216:                        case 's':
                    217:                                ud->flag = ABSENT_BOOLEAN;
                    218:                                ud->num = ABSENT_NUMERIC;
                    219:                                len = le16dec(cap);
                    220:                                cap += sizeof(uint16_t);
                    221:                                if (len > 0)
                    222:                                        ud->str = cap;
                    223:                                else if (flags == 0)
                    224:                                        ud->str = ABSENT_STRING;
                    225:                                else
                    226:                                        ud->str = CANCELLED_STRING;
                    227:                                cap += len;
                    228:                                break;
                    229:                        default:
1.19.2.1! pgoyette  230:                                goto out;
1.1       roy       231:                        }
                    232:                }
1.18      christos  233:        } else {
                    234:                term->_nuserdefs = 0;
                    235:                if (term->_userdefs) {
                    236:                        free(term->_userdefs);
                    237:                        term->_userdefs = NULL;
                    238:                }
1.1       roy       239:        }
1.18      christos  240:
1.1       roy       241:        return 1;
1.19.2.1! pgoyette  242: out:
        !           243:        errno = EINVAL;
        !           244:        return -1;
1.1       roy       245: }
                    246:
                    247: static int
                    248: _ti_dbgetterm(TERMINAL *term, const char *path, const char *name, int flags)
                    249: {
1.15      joerg     250:        struct cdbr *db;
                    251:        const void *data;
                    252:        char *db_name;
                    253:        const uint8_t *data8;
                    254:        size_t len, klen;
1.1       roy       255:        int r;
                    256:
1.15      joerg     257:        if (asprintf(&db_name, "%s.cdb", path) < 0)
                    258:                return -1;
                    259:
                    260:        db = cdbr_open(db_name, CDBR_DEFAULT);
                    261:        free(db_name);
1.1       roy       262:        if (db == NULL)
                    263:                return -1;
1.15      joerg     264:
                    265:        klen = strlen(name) + 1;
                    266:        if (cdbr_find(db, name, klen, &data, &len) == -1)
                    267:                goto fail;
                    268:        data8 = data;
                    269:        if (len == 0)
                    270:                goto fail;
                    271:        /* Check for alias first, fall through to processing normal entries. */
                    272:        if (data8[0] == 2) {
1.16      joerg     273:                if (klen + 7 > len || le16dec(data8 + 5) != klen)
1.15      joerg     274:                        goto fail;
                    275:                if (memcmp(data8 + 7, name, klen))
                    276:                        goto fail;
                    277:                if (cdbr_get(db, le32dec(data8 + 1), &data, &len))
                    278:                        goto fail;
                    279:                data8 = data;
                    280:                if (data8[0] != 1)
                    281:                        goto fail;
1.17      roy       282:        } else if (data8[0] != 1)
1.15      joerg     283:                goto fail;
                    284:        else if (klen + 3 >= len || le16dec(data8 + 1) != klen)
                    285:                goto fail;
                    286:        else if (memcmp(data8 + 3, name, klen))
                    287:                goto fail;
                    288:
1.1       roy       289:        strlcpy(database, path, sizeof(database));
                    290:        _ti_database = database;
                    291:
1.15      joerg     292:        r = _ti_readterm(term, data, len, flags);
                    293:        cdbr_close(db);
1.1       roy       294:        return r;
1.15      joerg     295:
                    296:  fail:
                    297:        cdbr_close(db);
                    298:        return 0;
1.1       roy       299: }
                    300:
                    301: static int
                    302: _ti_dbgettermp(TERMINAL *term, const char *path, const char *name, int flags)
                    303: {
                    304:        const char *p;
                    305:        size_t l;
                    306:        int r, e;
                    307:
                    308:        e = -1;
                    309:        r = 0;
                    310:        do {
                    311:                for (p = path; *path != '\0' && *path != ':'; path++)
                    312:                        continue;
                    313:                l = path - p;
                    314:                if (l != 0 && l + 1 < sizeof(pathbuf)) {
                    315:                        memcpy(pathbuf, p, l);
                    316:                        pathbuf[l] = '\0';
                    317:                        r = _ti_dbgetterm(term, pathbuf, name, flags);
                    318:                        if (r == 1)
                    319:                                return 1;
                    320:                        if (r == 0)
                    321:                                e = 0;
                    322:                }
                    323:        } while (*path++ == ':');
                    324:        return e;
                    325: }
                    326:
1.8       roy       327: static int
1.11      roy       328: ticcmp(const TIC *tic, const char *name)
                    329: {
                    330:        char *alias, *s;
                    331:        size_t len, l;
                    332:
                    333:        if (strcmp(tic->name, name) == 0)
                    334:                return 0;
                    335:        if (tic->alias == NULL)
                    336:                return -1;
                    337:
                    338:        len = strlen(name);
                    339:        alias = tic->alias;
                    340:        while (*alias != '\0') {
                    341:                s = strchr(alias, '|');
                    342:                if (s == NULL)
                    343:                        l = strlen(alias);
                    344:                else
                    345:                        l = s - alias;
1.14      joerg     346:                if (len == l && memcmp(alias, name, l) == 0)
1.11      roy       347:                        return 0;
                    348:                if (s == NULL)
                    349:                        break;
                    350:                alias = s + 1;
                    351:        }
                    352:        return 1;
                    353: }
                    354:
                    355: static int
1.8       roy       356: _ti_findterm(TERMINAL *term, const char *name, int flags)
1.1       roy       357: {
                    358:        int r;
1.10      roy       359:        char *c, *e, h[PATH_MAX];
                    360:        TIC *tic;
                    361:        uint8_t *f;
                    362:        ssize_t len;
1.1       roy       363:
                    364:        _DIAGASSERT(term != NULL);
                    365:        _DIAGASSERT(name != NULL);
                    366:
1.4       roy       367:        database[0] = '\0';
1.1       roy       368:        _ti_database = NULL;
1.10      roy       369:        r = 0;
1.5       roy       370:
1.11      roy       371:        if ((e = getenv("TERMINFO")) != NULL && *e != '\0')
1.8       roy       372:                if (e[0] == '/')
                    373:                        return _ti_dbgetterm(term, e, name, flags);
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:
                    428: int
                    429: _ti_getterm(TERMINAL *term, const char *name, int flags)
                    430: {
                    431:        int r;
                    432:        size_t i;
                    433:        const struct compiled_term *t;
                    434:
                    435:        r = _ti_findterm(term, name, flags);
1.4       roy       436:        if (r == 1)
1.10      roy       437:                return r;
1.4       roy       438:
1.7       roy       439:        for (i = 0; i < __arraycount(compiled_terms); i++) {
                    440:                t = &compiled_terms[i];
                    441:                if (strcmp(name, t->name) == 0) {
                    442:                        r = _ti_readterm(term, t->cap, t->caplen, flags);
1.5       roy       443:                        break;
                    444:                }
1.7       roy       445:        }
1.5       roy       446:
1.4       roy       447:        return r;
1.1       roy       448: }

CVSweb <webmaster@jp.NetBSD.org>