1 /* $OpenBSD: termcap.c,v 1.2 2015/11/15 07:12:50 deraadt Exp $ */
2 /* $NetBSD: termcap.c,v 1.7 1995/06/05 19:45:52 pk Exp $ */
3
4 /*
5 * Copyright (c) 1980, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #define PBUFSIZ 512 /* max length of filename path */
34 #define PVECSIZ 32 /* max number of names in path */
35
36 #include <stdio.h>
37 #include <ctype.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <limits.h>
42 #include <curses.h>
43 #include "pathnames.h"
44
45 /*
46 * termcap - routines for dealing with the terminal capability data base
47 *
48 * BUG: Should use a "last" pointer in tbuf, so that searching
49 * for capabilities alphabetically would not be a n**2/2
50 * process when large numbers of capabilities are given.
51 * Note: If we add a last pointer now we will screw up the
52 * tc capability. We really should compile termcap.
53 *
54 * Essentially all the work here is scanning and decoding escapes
55 * in string capabilities. We don't use stdio because the editor
56 * doesn't, and because living w/o it is not hard.
57 */
58
59 static char *tbuf; /* termcap buffer */
60
61 /*
62 * Get an entry for terminal name in buffer bp from the termcap file.
63 */
64 int
tgetent(char * bp,char * name)65 tgetent(char *bp, char *name)
66 {
67 char *p, *cp, *dummy, **fname, *home;
68 int i;
69 char pathbuf[PATH_MAX]; /* holds raw path of filenames */
70 char *pathvec[PVECSIZ]; /* to point to names in pathbuf */
71 char **pvec; /* holds usable tail of path vector */
72 char *termpath;
73
74 fname = pathvec;
75 pvec = pathvec;
76 tbuf = bp;
77
78 cp = issetugid() ? NULL : getenv("TERMCAP");
79 /*
80 * TERMCAP can have one of two things in it. It can be the name
81 * of a file to use instead of /usr/share/misc/termcap. In this
82 * case it better start with a "/". Or it can be an entry to use
83 * so we don't have to read the file. In this case it has to
84 * already have the newlines crunched out. If TERMCAP does not
85 * hold a file name then a path of names is searched instead.
86 * The path is found in the TERMPATH variable, or becomes
87 * "$HOME/.termcap /usr/share/misc/termcap" if no TERMPATH exists.
88 */
89 if (cp == NULL) {
90 strlcpy(pathbuf, _PATH_TERMCAP, sizeof(pathbuf));
91 } else if (!cp || *cp != '/') { /* TERMCAP holds an entry */
92 if ((termpath = getenv("TERMPATH")) != NULL)
93 strlcpy(pathbuf, termpath, sizeof(pathbuf));
94 else if ((home = getenv("HOME")) == NULL || *home == '\0' ||
95 snprintf(pathbuf, sizeof(pathbuf), "%s/%s", home,
96 _PATH_DEF) >= sizeof(pathbuf))
97 strlcpy(pathbuf, _PATH_DEF, sizeof(pathbuf));
98 } else { /* user-defined path in TERMCAP */
99 /* still can be tokenized */
100 strlcpy(pathbuf, cp, sizeof(pathbuf));
101 }
102 *fname++ = pathbuf; /* tokenize path into vector of names */
103
104 /* split pathbuf into a vector of paths */
105 p = pathbuf;
106 while (*++p)
107 if (*p == ' ' || *p == ':') {
108 *p = '\0';
109 while (*++p)
110 if (*p != ' ' && *p != ':')
111 break;
112 if (*p == '\0')
113 break;
114 *fname++ = p;
115 if (fname >= pathvec + PVECSIZ) {
116 fname--;
117 break;
118 }
119 }
120 *fname = (char *) 0; /* mark end of vector */
121 if (cp && *cp && *cp != '/')
122 if (cgetset(cp) < 0)
123 return (-2);
124
125 dummy = NULL;
126 i = cgetent(&dummy, pathvec, name);
127
128 if (i == 0 && bp != NULL) {
129 strlcpy(bp, dummy, 1024);
130 if ((cp = strrchr(bp, ':')) != NULL)
131 if (cp[1] != '\0')
132 cp[1] = '\0';
133 }
134 else if (i == 0 && bp == NULL)
135 tbuf = dummy;
136 else if (dummy != NULL)
137 free(dummy);
138
139 /* no tc reference loop return code in libterm XXX */
140 if (i == -3)
141 return (-1);
142 return (i + 1);
143 }
144
145 /*
146 * Return the (numeric) option id.
147 * Numeric options look like
148 * li#80
149 * i.e. the option string is separated from the numeric value by
150 * a # character. If the option is not found we return -1.
151 * Note that we handle octal numbers beginning with 0.
152 */
153 int
tgetnum(char * id)154 tgetnum(char *id)
155 {
156 long num;
157
158 if (cgetnum(tbuf, id, &num) == 0)
159 return (num);
160 else
161 return (-1);
162 }
163
164 /*
165 * Handle a flag option.
166 * Flag options are given "naked", i.e. followed by a : or the end
167 * of the buffer. Return 1 if we find the option, or 0 if it is
168 * not given.
169 */
170 int
tgetflag(char * id)171 tgetflag(char *id)
172 {
173 return (cgetcap(tbuf, id, ':') != NULL);
174 }
175
176 /*
177 * Get a string valued option.
178 * These are given as
179 * cl=^Z
180 * Much decoding is done on the strings, and the strings are
181 * placed in area, which is a ref parameter which is updated.
182 * No checking on area overflow.
183 */
184 char *
tgetstr(char * id,char ** area)185 tgetstr(char *id, char **area)
186 {
187 char ids[3];
188 char *s;
189 int i;
190
191 /*
192 * XXX
193 * This is for all the boneheaded programs that relied on tgetstr
194 * to look only at the first 2 characters of the string passed...
195 */
196 *ids = *id;
197 ids[1] = id[1];
198 ids[2] = '\0';
199
200 if ((i = cgetstr(tbuf, ids, &s)) < 0)
201 return NULL;
202
203 strlcpy(*area, s, 1024);
204 *area += i + 1;
205 return (s);
206 }
207