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