1 /* $OpenBSD: read_bsd_terminfo.c,v 1.14 2003/06/17 21:56:24 millert Exp $ */
2
3 /*
4 * Copyright (c) 2006, 2009 Thorsten Glaser <tg@mirbsd.org>
5 * Copyright (c) 1998, 1999, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 *
19 * The following disclaimer must also be retained in all copies:
20 *
21 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
22 * the utmost extent permitted by applicable law, neither express nor
23 * implied; without malicious intent or gross negligence. In no event
24 * may a licensor, author or contributor be held liable for indirect,
25 * direct, other damage, loss, or other issues arising in any way out
26 * of dealing in the work, even if advised of the possibility of such
27 * damage or existence of a defect, except proven that it results out
28 * of said person's immediate fault when using the work as intended.
29 */
30
31 #include <curses.priv.h>
32 #include <tic.h>
33 #include <term.h> /* lines, columns, cur_term */
34 #include <term_entry.h>
35
36 __RCSID("$MirOS: src/lib/libncurses/src/ncurses/tinfo/read_bsd_terminfo.c,v 1.6 2009/09/06 12:46:46 tg Exp $");
37
38 #ifndef _PATH_TERMINFO
39 #define _PATH_TERMINFO "/usr/share/misc/terminfo"
40 #endif /* ! _PATH_TERMINFO */
41
42 static char _path_terminfo[] = _PATH_TERMINFO;
43
44 /* Function prototypes for private functions, */
45 static int _nc_lookup_bsd_terminfo_entry(char *, char *, TERMTYPE * const);
46
47 /*
48 * Look up ``tn'' in the BSD terminfo.db file and fill in ``tp''
49 * with the info we find there.
50 * Returns 1 on success, 0 on failure.
51 */
52 int
_nc_read_bsd_terminfo_entry(const char * const tn_,char * const filename,TERMTYPE * const tp)53 _nc_read_bsd_terminfo_entry(const char * const tn_, char * const filename,
54 TERMTYPE * const tp)
55 {
56 char **fname, *p;
57 char envterm[PATH_MAX]; /* local copy of $TERMINFO */
58 char hometerm[PATH_MAX]; /* local copy of $HOME/.terminfo */
59 char *pathvec[4]; /* list of possible terminfo files */
60 char *tn;
61 size_t len;
62
63 if ((tn = strdup(tn_)) == NULL)
64 return (0);
65
66 fname = pathvec;
67 /* $TERMINFO may hold a path to a terminfo file */
68 if (use_terminfo_vars() && (p = getenv("TERMINFO")) != NULL) {
69 len = strlcpy(envterm, p, sizeof(envterm));
70 if (len < sizeof(envterm))
71 *fname++ = envterm;
72 }
73
74 /* Also check $HOME/.terminfo if it exists */
75 if (use_terminfo_vars() && (p = getenv("HOME")) != NULL && *p != '\0') {
76 len = snprintf(hometerm, sizeof(hometerm), "%s/.terminfo", p);
77 if (len > 0 && len < sizeof(hometerm))
78 *fname++ = hometerm;
79 }
80
81 /* Finally we check the system terminfo file */
82 *fname++ = _path_terminfo;
83 *fname = NULL;
84
85 /*
86 * Lookup ``tn'' in each possible terminfo file until
87 * we find it or reach the end.
88 */
89 for (fname = pathvec; *fname; fname++) {
90 if (_nc_lookup_bsd_terminfo_entry(tn, *fname, tp) == 1) {
91 /* Set copyout parameter and return */
92 (void)strlcpy(filename, *fname, PATH_MAX);
93 free(tn);
94 return (1);
95 }
96 }
97 free(tn);
98 return (0);
99 }
100
101 /*
102 * Given a path /path/to/terminfo/X/termname, look up termname
103 * /path/to/terminfo.db and fill in ``tp'' with the info we find there.
104 * Returns 1 on success, 0 on failure.
105 */
106 int
_nc_read_bsd_terminfo_file(const char * const filename,TERMTYPE * const tp)107 _nc_read_bsd_terminfo_file(const char * const filename, TERMTYPE * const tp)
108 {
109 char path[PATH_MAX]; /* path to terminfo.db */
110 char *tname; /* name of terminal to look up */
111 char *p;
112
113 (void)strlcpy(path, filename, sizeof(path));
114
115 /* Split filename into path and term name components. */
116 if ((tname = strrchr(path, '/')) == NULL)
117 return (0);
118 *tname++ = '\0';
119 if ((p = strrchr(path, '/')) == NULL)
120 return (0);
121 *p = '\0';
122
123 return (_nc_lookup_bsd_terminfo_entry(tname, path, tp));
124 }
125
126 /*
127 * Look up ``tn'' in the BSD terminfo file ``filename'' and fill in
128 * ``tp'' with the info we find there.
129 * Returns 1 on success, 0 on failure.
130 */
131 static int
_nc_lookup_bsd_terminfo_entry(char * tn,char * filename,TERMTYPE * const tp)132 _nc_lookup_bsd_terminfo_entry(char *tn, char *filename, TERMTYPE * const tp)
133 {
134 char *pathvec[2], *sfn;
135 char *capbuf, *cptr, *infobuf, *iptr;
136 int error;
137 size_t len;
138 ENTRY thisentry;
139
140 if (asprintf(&sfn, "getcap(%s)", filename) == -1)
141 sfn = filename;
142
143 pathvec[0] = filename;
144 pathvec[1] = NULL;
145 capbuf = NULL;
146 infobuf = NULL;
147
148 _nc_set_source(sfn); /* For useful error messages */
149
150 /* Don't prepend any hardcoded entries. */
151 (void) cgetset(NULL);
152
153 /* Lookup tn in 'filename' */
154 error = cgetent(&capbuf, pathvec, tn);
155 if (error == 0) {
156 /*
157 * To make the terminfo parser happy we need to, as a minimum,
158 * 1) convert ':' separators to ','
159 * 2) add a newline after the name field
160 * 3) add a newline at the end of the entry
161 */
162
163 /* Add space for 2 extra newlines and the final NUL */
164 infobuf = malloc(strlen(capbuf) + 3);
165 if (infobuf == NULL) {
166 error = TRUE;
167 goto done;
168 }
169
170 /* Copy name and aliases, adding a newline. */
171 cptr = strchr(capbuf, ':');
172 if (cptr == NULL) {
173 error = TRUE;
174 goto done;
175 }
176 len = cptr - capbuf;
177 memcpy(infobuf, capbuf, len);
178 iptr = infobuf + len;
179 *iptr++ = ',';
180 *iptr++ = '\n';
181
182 /* Copy the rest of capbuf, converting ':' -> ',' */
183 for (++cptr; *cptr; ++cptr)
184 if ((*cptr == '\\') || (*cptr == '^')) {
185 *iptr++ = *cptr++;
186 if (!*cptr)
187 break;
188 *iptr++ = *cptr;
189 } else if (*cptr == ':')
190 *iptr++ = ',';
191 else
192 *iptr++ = *cptr;
193 *iptr++ = '\n';
194 *iptr = '\0';
195
196 _nc_reset_input(NULL, infobuf);
197 memset(&thisentry, 0, sizeof (thisentry));
198 if (_nc_parse_entry(&thisentry, FALSE, FALSE) == ERR) {
199 error = TRUE;
200 goto done;
201 }
202 *tp = thisentry.tterm;
203 }
204
205 done:
206 if (capbuf)
207 free(capbuf);
208 if (infobuf)
209 free(infobuf);
210 cgetclose();
211
212 _nc_set_source("");
213 if (sfn != filename)
214 free(sfn);
215
216 return ((error == 0));
217 }
218