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__)
isterminfo(char * type)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__)
_isterminfo(char * type,char * parent)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