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>