1 /* $NetBSD: term.c,v 1.16 2012/06/06 13:36:58 joerg Exp $ */
4 * Copyright (c) 2009, 2010, 2011 The NetBSD Foundation, Inc.
6 * This code is derived from software contributed to The NetBSD Foundation
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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.
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.
30 #include <sys/cdefs.h>
31 __RCSID("$NetBSD: term.c,v 1.16 2012/06/06 13:36:58 joerg Exp $");
44 #include <term_private.h>
48 #define _PATH_TERMINFO "/usr/share/misc/terminfo"
50 #define _PATH_TERMINFO "/usr/share/terminfo/terminfo"
53 static char database
[PATH_MAX
];
54 static char pathbuf
[PATH_MAX
];
55 const char *_ti_database
;
57 /* Include a generated list of pre-compiled terminfo descriptions. */
58 #include "compiled_terms.c"
61 _ti_readterm(TERMINAL
*term
, const char *cap
, size_t caplen
, int flags
)
69 /* Only read version 1 structures */
75 term
->flags
= calloc(TIFLAGMAX
+ 1, sizeof(char));
76 if (term
->flags
== NULL
)
78 term
->nums
= malloc((TINUMMAX
+ 1) * sizeof(short));
79 if (term
->nums
== NULL
)
81 memset(term
->nums
, (short)-1, (TINUMMAX
+ 1) * sizeof(short));
82 term
->strs
= calloc(TISTRMAX
+ 1, sizeof(char *));
83 if (term
->strs
== NULL
)
85 term
->_arealen
= caplen
;
86 term
->_area
= malloc(term
->_arealen
);
87 if (term
->_area
== NULL
)
89 memcpy(term
->_area
, cap
, term
->_arealen
);
93 cap
+= sizeof(uint16_t);
97 cap
+= sizeof(uint16_t);
105 cap
+= sizeof(uint16_t);
114 cap
+= sizeof(uint16_t);
117 cap
+= sizeof(uint16_t);
118 for (; num
!= 0; num
--) {
120 cap
+= sizeof(uint16_t);
121 term
->flags
[ind
] = *cap
++;
122 if (flags
== 0 && !VALID_BOOLEAN(term
->flags
[ind
]))
123 term
->flags
[ind
] = 0;
128 cap
+= sizeof(uint16_t);
131 cap
+= sizeof(uint16_t);
132 for (; num
!= 0; num
--) {
134 cap
+= sizeof(uint16_t);
135 term
->nums
[ind
] = le16dec(cap
);
136 if (flags
== 0 && !VALID_NUMERIC(term
->nums
[ind
]))
137 term
->nums
[ind
] = ABSENT_NUMERIC
;
138 cap
+= sizeof(uint16_t);
143 cap
+= sizeof(uint16_t);
146 cap
+= sizeof(uint16_t);
147 for (; num
!= 0; num
--) {
149 cap
+= sizeof(uint16_t);
151 cap
+= sizeof(uint16_t);
153 term
->strs
[ind
] = cap
;
155 term
->strs
[ind
] = ABSENT_STRING
;
157 term
->strs
[ind
] = CANCELLED_STRING
;
163 cap
+= sizeof(uint16_t);
165 term
->_nuserdefs
= le16dec(cap
);
166 term
->_userdefs
= malloc(sizeof(*term
->_userdefs
) * num
);
167 cap
+= sizeof(uint16_t);
168 for (num
= 0; num
< term
->_nuserdefs
; num
++) {
169 ud
= &term
->_userdefs
[num
];
171 cap
+= sizeof(uint16_t);
179 !VALID_BOOLEAN(ud
->flag
))
181 ud
->num
= ABSENT_NUMERIC
;
182 ud
->str
= ABSENT_STRING
;
185 ud
->flag
= ABSENT_BOOLEAN
;
186 ud
->num
= le16dec(cap
);
188 !VALID_NUMERIC(ud
->num
))
189 ud
->num
= ABSENT_NUMERIC
;
190 ud
->str
= ABSENT_STRING
;
191 cap
+= sizeof(uint16_t);
194 ud
->flag
= ABSENT_BOOLEAN
;
195 ud
->num
= ABSENT_NUMERIC
;
197 cap
+= sizeof(uint16_t);
201 ud
->str
= ABSENT_STRING
;
203 ud
->str
= CANCELLED_STRING
;
216 _ti_dbgetterm(TERMINAL
*term
, const char *path
, const char *name
, int flags
)
221 const uint8_t *data8
;
225 if (asprintf(&db_name
, "%s.cdb", path
) < 0)
228 db
= cdbr_open(db_name
, CDBR_DEFAULT
);
233 klen
= strlen(name
) + 1;
234 if (cdbr_find(db
, name
, klen
, &data
, &len
) == -1)
239 /* Check for alias first, fall through to processing normal entries. */
241 if (klen
+ 7 > len
|| le16dec(data8
+ 5) != klen
)
243 if (memcmp(data8
+ 7, name
, klen
))
245 if (cdbr_get(db
, le32dec(data8
+ 1), &data
, &len
))
250 } else if (data8
[0] != 1)
252 else if (klen
+ 3 >= len
|| le16dec(data8
+ 1) != klen
)
254 else if (memcmp(data8
+ 3, name
, klen
))
257 strlcpy(database
, path
, sizeof(database
));
258 _ti_database
= database
;
260 r
= _ti_readterm(term
, data
, len
, flags
);
270 _ti_dbgettermp(TERMINAL
*term
, const char *path
, const char *name
, int flags
)
279 for (p
= path
; *path
!= '\0' && *path
!= ':'; path
++)
282 if (l
!= 0 && l
+ 1 < sizeof(pathbuf
)) {
283 memcpy(pathbuf
, p
, l
);
285 r
= _ti_dbgetterm(term
, pathbuf
, name
, flags
);
291 } while (*path
++ == ':');
296 ticcmp(const TIC
*tic
, const char *name
)
301 if (strcmp(tic
->name
, name
) == 0)
303 if (tic
->alias
== NULL
)
308 while (*alias
!= '\0') {
309 s
= strchr(alias
, '|');
314 if (len
== l
&& memcmp(alias
, name
, l
) == 0)
324 _ti_findterm(TERMINAL
*term
, const char *name
, int flags
)
327 char *c
, *e
, h
[PATH_MAX
];
332 _DIAGASSERT(term
!= NULL
);
333 _DIAGASSERT(name
!= NULL
);
339 if ((e
= getenv("TERMINFO")) != NULL
&& *e
!= '\0')
341 return _ti_dbgetterm(term
, e
, name
, flags
);
344 if (e
== NULL
&& (c
= getenv("TERMCAP")) != NULL
) {
345 if (*c
!= '\0' && *c
!= '/') {
356 e
= strdup(e
); /* So we don't destroy env */
360 tic
= _ti_compile(e
, TIC_WARNING
|
361 TIC_ALIAS
| TIC_DESCRIPTION
| TIC_EXTRA
);
362 if (c
== NULL
&& e
!= NULL
)
364 if (tic
!= NULL
&& ticcmp(tic
, name
) == 0) {
365 len
= _ti_flatten(&f
, tic
);
367 r
= _ti_readterm(term
, (char *)f
, (size_t)len
,
375 _ti_database
= "$TERMINFO";
377 _ti_database
= "$TERMCAP";
382 if ((e
= getenv("TERMINFO_DIRS")) != NULL
)
383 return _ti_dbgettermp(term
, e
, name
, flags
);
385 if ((e
= getenv("HOME")) != NULL
) {
386 snprintf(h
, sizeof(h
), "%s/.terminfo", e
);
387 r
= _ti_dbgetterm(term
, h
, name
, flags
);
390 r
= _ti_dbgettermp(term
, _PATH_TERMINFO
, name
, flags
);
397 _ti_getterm(TERMINAL
*term
, const char *name
, int flags
)
401 const struct compiled_term
*t
;
403 r
= _ti_findterm(term
, name
, flags
);
407 for (i
= 0; i
< __arraycount(compiled_terms
); i
++) {
408 t
= &compiled_terms
[i
];
409 if (strcmp(name
, t
->name
) == 0) {
410 r
= _ti_readterm(term
, t
->cap
, t
->caplen
, flags
);