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 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 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 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 * 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