1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 #include "fcntl.h" 26 #include "errno.h" 27 #include "string.h" 28 #include "unistd.h" 29 #include "search.h" 30 #include "stdlib.h" 31 32 #include "lp.h" 33 34 #if defined(__STDC__) 35 typedef void ** A2; 36 typedef int (*A3)(const void *, const void *); 37 #else 38 typedef char ** A2; 39 typedef int (*A3)(); 40 #endif 41 42 /* 43 * Define the following if you want to do a stronger check: 44 * that a type names a valid entry in the Terminfo database. 45 * The stronger check reads the entry and verifies the magic 46 * number in the header. The weaker check is to see if we 47 * have read access to the file. The weaker check will be a 48 * tad faster. 49 */ 50 /* #define STRONG_CHECK 1 */ /* */ 51 52 /* 53 * Define the following if you want to cache hits and/or misses. 54 * One reason for NOT caching is to guard against crazies who try 55 * submitting print requests with goofball types, or every valid type 56 * under the sun. Since Terminfo is limited, the hit cache is effectively 57 * limited, so it shouldn't be a problem searching the cache (the search 58 * is binary) but the cache can become big. The miss cache, on the other 59 * hand, could cause a problem. This problem can become severe, so 60 * consider limiting the size of the cache (see below). 61 * Another reason for NOT caching is to pick up changes in the Terminfo 62 * database. The "terminfo" type is not likely to be an oft used feature, 63 * though, so this shouldn't be a big problem. 64 * The reason FOR caching is to limit the number of file system accesses. 65 * This routine is called OFTEN, so limiting the number of open() or 66 * access() calls is a good idea. 67 */ 68 #define CACHE_HITS 1 /* */ 69 #define CACHE_MISSES 1 /* */ 70 71 /* 72 * Define the following if you want to limit the sizes of the caches. 73 */ 74 #define HIT_CACHE_LIMIT 100 /* */ 75 #define MISS_CACHE_LIMIT 100 /* */ 76 77 #if defined(CACHE_HITS) 78 static char *hit_cache = 0; 79 80 # if defined(HIT_CACHE_LIMIT) 81 static int hit_cache_size = 0; 82 # endif 83 #endif 84 85 #if defined(CACHE_MISSES) 86 static char *miss_cache = 0; 87 88 # if defined(MISS_CACHE_LIMIT) 89 static int miss_cache_size = 0; 90 # endif 91 #endif 92 93 #if defined(__STDC__) 94 static int _isterminfo ( char * , char * ); 95 #else 96 static int _isterminfo(); 97 #endif 98 99 /** 100 ** isterminfo() - SEE IF TYPE IS IN TERMINFO DATABASE 101 **/ 102 103 int 104 #if defined(__STDC__) 105 isterminfo ( 106 char * type 107 ) 108 #else 109 isterminfo (type) 110 char *type; 111 #endif 112 { 113 register int ret; 114 115 static char *envTERMINFO = 0; 116 117 118 if (!type || !*type) 119 return (0); 120 121 #if defined(CACHE_HITS) 122 if (tfind(type, (A2)&hit_cache, (A3)strcmp)) 123 return (1); 124 #endif 125 126 #if defined(CACHE_MISSES) 127 if (tfind(type, (A2)&miss_cache, (A3)strcmp)) 128 return (0); 129 #endif 130 131 if (!envTERMINFO) 132 envTERMINFO = getenv("TERMNIFO"); 133 if ( 134 envTERMINFO 135 && _isterminfo(type, envTERMINFO) 136 #if defined(TERMINFO) 137 || _isterminfo(type, TERMINFO) 138 #endif 139 ) { 140 ret = 1; 141 142 #if defined(CACHE_HITS) 143 # if defined(HIT_CACHE_LIMIT) 144 if (hit_cache_size++ < HIT_CACHE_LIMIT) 145 # endif 146 (void)tsearch (Strdup(type), (A2)&hit_cache, (A3)strcmp); 147 #endif 148 149 } else { 150 ret = 0; 151 152 #if defined(CACHE_MISSES) 153 # if defined(MISS_CACHE_LIMIT) 154 if (miss_cache_size++ < MISS_CACHE_LIMIT) 155 # endif 156 (void)tsearch (Strdup(type), (A2)&miss_cache, (A3)strcmp); 157 #endif 158 } 159 return (ret); 160 } 161 162 /** 163 ** _isterminfo() 164 **/ 165 166 static int 167 #if defined(__STDC__) 168 _isterminfo ( 169 char * type, 170 char * parent 171 ) 172 #else 173 _isterminfo (type, parent) 174 char *type, 175 *parent; 176 #endif 177 { 178 char *path, 179 type_letter[] = "X"; 180 181 int ret; 182 183 #if defined(STRONG_CHECK) 184 int fd; 185 #endif 186 187 188 type_letter[0] = type[0]; 189 if (!(path = makepath(parent, type_letter, type, (char *)0))) 190 return (0); 191 192 #if defined(STRONG_CHECK) 193 if (!(fd = Open(path, O_RDONLY))) { 194 195 /* 196 * If we can't open the TERMINFO file because we 197 * don't have any open channels left, let's err on 198 * the side of likelihood--if the file can be 199 * accessed, figure that it's okay. 200 */ 201 if (errno == EMFILE && Access(path, R_OK) == 0) 202 ret = 1; 203 else 204 ret = 0; 205 206 } else { 207 208 char buf[2]; 209 210 if (Read(fd, buf, 2) == 2 && buf[0] == 26 && buf[1] == 1) 211 ret = 1; 212 else 213 ret = 0; 214 215 Close (fd); 216 217 } 218 #else 219 ret = (Access(path, R_OK) == 0); 220 #endif 221 222 Free (path); 223 224 return (ret); 225 } 226