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 26 #ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.9 */ 27 /* EMACS_MODES: !fill, lnumb, !overwrite, !nodelete, !picture */ 28 29 #include "fcntl.h" 30 #include "errno.h" 31 #include "string.h" 32 #include "unistd.h" 33 #include "search.h" 34 #include "stdlib.h" 35 36 #include "lp.h" 37 38 #if defined(__STDC__) 39 typedef void ** A2; 40 typedef int (*A3)(const void *, const void *); 41 #else 42 typedef char ** A2; 43 typedef int (*A3)(); 44 #endif 45 46 /* 47 * Define the following if you want to do a stronger check: 48 * that a type names a valid entry in the Terminfo database. 49 * The stronger check reads the entry and verifies the magic 50 * number in the header. The weaker check is to see if we 51 * have read access to the file. The weaker check will be a 52 * tad faster. 53 */ 54 /* #define STRONG_CHECK 1 */ /* */ 55 56 /* 57 * Define the following if you want to cache hits and/or misses. 58 * One reason for NOT caching is to guard against crazies who try 59 * submitting print requests with goofball types, or every valid type 60 * under the sun. Since Terminfo is limited, the hit cache is effectively 61 * limited, so it shouldn't be a problem searching the cache (the search 62 * is binary) but the cache can become big. The miss cache, on the other 63 * hand, could cause a problem. This problem can become severe, so 64 * consider limiting the size of the cache (see below). 65 * Another reason for NOT caching is to pick up changes in the Terminfo 66 * database. The "terminfo" type is not likely to be an oft used feature, 67 * though, so this shouldn't be a big problem. 68 * The reason FOR caching is to limit the number of file system accesses. 69 * This routine is called OFTEN, so limiting the number of open() or 70 * access() calls is a good idea. 71 */ 72 #define CACHE_HITS 1 /* */ 73 #define CACHE_MISSES 1 /* */ 74 75 /* 76 * Define the following if you want to limit the sizes of the caches. 77 */ 78 #define HIT_CACHE_LIMIT 100 /* */ 79 #define MISS_CACHE_LIMIT 100 /* */ 80 81 #if defined(CACHE_HITS) 82 static char *hit_cache = 0; 83 84 # if defined(HIT_CACHE_LIMIT) 85 static int hit_cache_size = 0; 86 # endif 87 #endif 88 89 #if defined(CACHE_MISSES) 90 static char *miss_cache = 0; 91 92 # if defined(MISS_CACHE_LIMIT) 93 static int miss_cache_size = 0; 94 # endif 95 #endif 96 97 #if defined(__STDC__) 98 static int _isterminfo ( char * , char * ); 99 #else 100 static int _isterminfo(); 101 #endif 102 103 /** 104 ** isterminfo() - SEE IF TYPE IS IN TERMINFO DATABASE 105 **/ 106 107 int 108 #if defined(__STDC__) 109 isterminfo ( 110 char * type 111 ) 112 #else 113 isterminfo (type) 114 char *type; 115 #endif 116 { 117 register int ret; 118 119 static char *envTERMINFO = 0; 120 121 122 if (!type || !*type) 123 return (0); 124 125 #if defined(CACHE_HITS) 126 if (tfind(type, (A2)&hit_cache, (A3)strcmp)) 127 return (1); 128 #endif 129 130 #if defined(CACHE_MISSES) 131 if (tfind(type, (A2)&miss_cache, (A3)strcmp)) 132 return (0); 133 #endif 134 135 if (!envTERMINFO) 136 envTERMINFO = getenv("TERMNIFO"); 137 if ( 138 envTERMINFO 139 && _isterminfo(type, envTERMINFO) 140 #if defined(TERMINFO) 141 || _isterminfo(type, TERMINFO) 142 #endif 143 ) { 144 ret = 1; 145 146 #if defined(CACHE_HITS) 147 # if defined(HIT_CACHE_LIMIT) 148 if (hit_cache_size++ < HIT_CACHE_LIMIT) 149 # endif 150 (void)tsearch (Strdup(type), (A2)&hit_cache, (A3)strcmp); 151 #endif 152 153 } else { 154 ret = 0; 155 156 #if defined(CACHE_MISSES) 157 # if defined(MISS_CACHE_LIMIT) 158 if (miss_cache_size++ < MISS_CACHE_LIMIT) 159 # endif 160 (void)tsearch (Strdup(type), (A2)&miss_cache, (A3)strcmp); 161 #endif 162 } 163 return (ret); 164 } 165 166 /** 167 ** _isterminfo() 168 **/ 169 170 static int 171 #if defined(__STDC__) 172 _isterminfo ( 173 char * type, 174 char * parent 175 ) 176 #else 177 _isterminfo (type, parent) 178 char *type, 179 *parent; 180 #endif 181 { 182 char *path, 183 *type_letter = "X"; 184 185 int ret; 186 187 #if defined(STRONG_CHECK) 188 int fd; 189 #endif 190 191 192 type_letter[0] = type[0]; 193 if (!(path = makepath(parent, type_letter, type, (char *)0))) 194 return (0); 195 196 #if defined(STRONG_CHECK) 197 if (!(fd = Open(path, O_RDONLY))) { 198 199 /* 200 * If we can't open the TERMINFO file because we 201 * don't have any open channels left, let's err on 202 * the side of likelihood--if the file can be 203 * accessed, figure that it's okay. 204 */ 205 if (errno == EMFILE && Access(path, R_OK) == 0) 206 ret = 1; 207 else 208 ret = 0; 209 210 } else { 211 212 char buf[2]; 213 214 if (Read(fd, buf, 2) == 2 && buf[0] == 26 && buf[1] == 1) 215 ret = 1; 216 else 217 ret = 0; 218 219 Close (fd); 220 221 } 222 #else 223 ret = (Access(path, R_OK) == 0); 224 #endif 225 226 Free (path); 227 228 return (ret); 229 } 230