1 /* $NetBSD: term.c,v 1.11 2010/02/26 00:09:00 roy Exp $ */
4 * Copyright (c) 2009, 2010 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.11 2010/02/26 00:09:00 roy 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 and 2 structures */
70 if (ver
!= 1 && ver
!= 2) {
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);
100 cap
+= sizeof(uint16_t);
109 cap
+= sizeof(uint16_t);
118 cap
+= sizeof(uint16_t);
121 cap
+= sizeof(uint16_t);
122 for (; num
!= 0; num
--) {
124 cap
+= sizeof(uint16_t);
125 term
->flags
[ind
] = *cap
++;
126 if (flags
== 0 && !VALID_BOOLEAN(term
->flags
[ind
]))
127 term
->flags
[ind
] = 0;
132 cap
+= sizeof(uint16_t);
135 cap
+= sizeof(uint16_t);
136 for (; num
!= 0; num
--) {
138 cap
+= sizeof(uint16_t);
139 term
->nums
[ind
] = le16dec(cap
);
140 if (flags
== 0 && !VALID_NUMERIC(term
->nums
[ind
]))
141 term
->nums
[ind
] = ABSENT_NUMERIC
;
142 cap
+= sizeof(uint16_t);
147 cap
+= sizeof(uint16_t);
150 cap
+= sizeof(uint16_t);
151 for (; num
!= 0; num
--) {
153 cap
+= sizeof(uint16_t);
155 cap
+= sizeof(uint16_t);
157 term
->strs
[ind
] = cap
;
159 term
->strs
[ind
] = ABSENT_STRING
;
161 term
->strs
[ind
] = CANCELLED_STRING
;
167 cap
+= sizeof(uint16_t);
169 term
->_nuserdefs
= le16dec(cap
);
170 term
->_userdefs
= malloc(sizeof(*term
->_userdefs
) * num
);
171 cap
+= sizeof(uint16_t);
172 for (num
= 0; num
< term
->_nuserdefs
; num
++) {
173 ud
= &term
->_userdefs
[num
];
175 cap
+= sizeof(uint16_t);
183 !VALID_BOOLEAN(ud
->flag
))
185 ud
->num
= ABSENT_NUMERIC
;
186 ud
->str
= ABSENT_STRING
;
189 ud
->flag
= ABSENT_BOOLEAN
;
190 ud
->num
= le16dec(cap
);
192 !VALID_NUMERIC(ud
->num
))
193 ud
->num
= ABSENT_NUMERIC
;
194 ud
->str
= ABSENT_STRING
;
195 cap
+= sizeof(uint16_t);
198 ud
->flag
= ABSENT_BOOLEAN
;
199 ud
->num
= ABSENT_NUMERIC
;
201 cap
+= sizeof(uint16_t);
205 ud
->str
= ABSENT_STRING
;
207 ud
->str
= CANCELLED_STRING
;
224 _ti_dbgetterm(TERMINAL
*term
, const char *path
, const char *name
, int flags
)
231 db
= dbm_open(path
, O_RDONLY
, 0644);
234 strlcpy(database
, path
, sizeof(database
));
235 _ti_database
= database
;
236 dt
.dptr
= (void *)__UNCONST(name
);
237 dt
.dsize
= strlen(name
);
238 dt
= dbm_fetch(db
, dt
);
239 if (dt
.dptr
== NULL
) {
246 if (*p
++ != 0) /* not alias */
248 dt
.dsize
= le16dec(p
) - 1;
249 p
+= sizeof(uint16_t);
251 dt
= dbm_fetch(db
, dt
);
252 if (dt
.dptr
== NULL
) {
258 r
= _ti_readterm(term
, (char *)dt
.dptr
, dt
.dsize
, flags
);
264 _ti_dbgettermp(TERMINAL
*term
, const char *path
, const char *name
, int flags
)
273 for (p
= path
; *path
!= '\0' && *path
!= ':'; path
++)
276 if (l
!= 0 && l
+ 1 < sizeof(pathbuf
)) {
277 memcpy(pathbuf
, p
, l
);
279 r
= _ti_dbgetterm(term
, pathbuf
, name
, flags
);
285 } while (*path
++ == ':');
290 ticcmp(const TIC
*tic
, const char *name
)
295 if (strcmp(tic
->name
, name
) == 0)
297 if (tic
->alias
== NULL
)
302 while (*alias
!= '\0') {
303 s
= strchr(alias
, '|');
308 if (len
== l
&& strncmp(alias
, name
, l
) == 0)
318 _ti_findterm(TERMINAL
*term
, const char *name
, int flags
)
321 char *c
, *e
, h
[PATH_MAX
];
326 _DIAGASSERT(term
!= NULL
);
327 _DIAGASSERT(name
!= NULL
);
333 if ((e
= getenv("TERMINFO")) != NULL
&& *e
!= '\0')
335 return _ti_dbgetterm(term
, e
, name
, flags
);
338 if (e
== NULL
&& (c
= getenv("TERMCAP")) != NULL
) {
339 if (*c
!= '\0' && *c
!= '/') {
350 e
= strdup(e
); /* So we don't destroy env */
354 tic
= _ti_compile(e
, TIC_WARNING
|
355 TIC_ALIAS
| TIC_DESCRIPTION
| TIC_EXTRA
);
356 if (c
== NULL
&& e
!= NULL
)
358 if (tic
!= NULL
&& ticcmp(tic
, name
) == 0) {
359 len
= _ti_flatten(&f
, tic
);
361 r
= _ti_readterm(term
, (char *)f
, len
, flags
);
368 _ti_database
= "$TERMINFO";
370 _ti_database
= "$TERMCAP";
375 if ((e
= getenv("TERMINFO_DIRS")) != NULL
)
376 return _ti_dbgettermp(term
, e
, name
, flags
);
378 if ((e
= getenv("HOME")) != NULL
) {
379 snprintf(h
, sizeof(h
), "%s/.terminfo", e
);
380 r
= _ti_dbgetterm(term
, h
, name
, flags
);
383 r
= _ti_dbgettermp(term
, _PATH_TERMINFO
, name
, flags
);
390 _ti_getterm(TERMINAL
*term
, const char *name
, int flags
)
394 const struct compiled_term
*t
;
396 r
= _ti_findterm(term
, name
, flags
);
400 for (i
= 0; i
< __arraycount(compiled_terms
); i
++) {
401 t
= &compiled_terms
[i
];
402 if (strcmp(name
, t
->name
) == 0) {
403 r
= _ti_readterm(term
, t
->cap
, t
->caplen
, flags
);
412 _ti_freeterm(TERMINAL
*term
)
420 free(term
->_userdefs
);