xref: /illumos-gate/usr/src/cmd/lp/lib/lp/isterminfo.c (revision 268ffd3a)
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