/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include "fcntl.h"
#include "errno.h"
#include "string.h"
#include "unistd.h"
#include "search.h"
#include "stdlib.h"
#include "lp.h"
#if defined(__STDC__)
typedef void ** A2;
typedef int (*A3)(const void *, const void *);
#else
typedef char ** A2;
typedef int (*A3)();
#endif
/*
* Define the following if you want to do a stronger check:
* that a type names a valid entry in the Terminfo database.
* The stronger check reads the entry and verifies the magic
* number in the header. The weaker check is to see if we
* have read access to the file. The weaker check will be a
* tad faster.
*/
/* #define STRONG_CHECK 1 */ /* */
/*
* Define the following if you want to cache hits and/or misses.
* One reason for NOT caching is to guard against crazies who try
* submitting print requests with goofball types, or every valid type
* under the sun. Since Terminfo is limited, the hit cache is effectively
* limited, so it shouldn't be a problem searching the cache (the search
* is binary) but the cache can become big. The miss cache, on the other
* hand, could cause a problem. This problem can become severe, so
* consider limiting the size of the cache (see below).
* Another reason for NOT caching is to pick up changes in the Terminfo
* database. The "terminfo" type is not likely to be an oft used feature,
* though, so this shouldn't be a big problem.
* The reason FOR caching is to limit the number of file system accesses.
* This routine is called OFTEN, so limiting the number of open() or
* access() calls is a good idea.
*/
#define CACHE_HITS 1 /* */
#define CACHE_MISSES 1 /* */
/*
* Define the following if you want to limit the sizes of the caches.
*/
#define HIT_CACHE_LIMIT 100 /* */
#define MISS_CACHE_LIMIT 100 /* */
#if defined(CACHE_HITS)
static char *hit_cache = 0;
# if defined(HIT_CACHE_LIMIT)
static int hit_cache_size = 0;
# endif
#endif
#if defined(CACHE_MISSES)
static char *miss_cache = 0;
# if defined(MISS_CACHE_LIMIT)
static int miss_cache_size = 0;
# endif
#endif
#if defined(__STDC__)
static int _isterminfo ( char * , char * );
#else
static int _isterminfo();
#endif
/**
** isterminfo() - SEE IF TYPE IS IN TERMINFO DATABASE
**/
int
#if defined(__STDC__)
isterminfo (
char * type
)
#else
isterminfo (type)
char *type;
#endif
{
register int ret;
static char *envTERMINFO = 0;
if (!type || !*type)
return (0);
#if defined(CACHE_HITS)
if (tfind(type, (A2)&hit_cache, (A3)strcmp))
return (1);
#endif
#if defined(CACHE_MISSES)
if (tfind(type, (A2)&miss_cache, (A3)strcmp))
return (0);
#endif
if (!envTERMINFO)
envTERMINFO = getenv("TERMNIFO");
if (
envTERMINFO
&& _isterminfo(type, envTERMINFO)
#if defined(TERMINFO)
|| _isterminfo(type, TERMINFO)
#endif
) {
ret = 1;
#if defined(CACHE_HITS)
# if defined(HIT_CACHE_LIMIT)
if (hit_cache_size++ < HIT_CACHE_LIMIT)
# endif
(void)tsearch (Strdup(type), (A2)&hit_cache, (A3)strcmp);
#endif
} else {
ret = 0;
#if defined(CACHE_MISSES)
# if defined(MISS_CACHE_LIMIT)
if (miss_cache_size++ < MISS_CACHE_LIMIT)
# endif
(void)tsearch (Strdup(type), (A2)&miss_cache, (A3)strcmp);
#endif
}
return (ret);
}
/**
** _isterminfo()
**/
static int
#if defined(__STDC__)
_isterminfo (
char * type,
char * parent
)
#else
_isterminfo (type, parent)
char *type,
*parent;
#endif
{
char *path,
type_letter[] = "X";
int ret;
#if defined(STRONG_CHECK)
int fd;
#endif
type_letter[0] = type[0];
if (!(path = makepath(parent, type_letter, type, (char *)0)))
return (0);
#if defined(STRONG_CHECK)
if (!(fd = Open(path, O_RDONLY))) {
/*
* If we can't open the TERMINFO file because we
* don't have any open channels left, let's err on
* the side of likelihood--if the file can be
* accessed, figure that it's okay.
*/
if (errno == EMFILE && Access(path, R_OK) == 0)
ret = 1;
else
ret = 0;
} else {
char buf[2];
if (Read(fd, buf, 2) == 2 && buf[0] == 26 && buf[1] == 1)
ret = 1;
else
ret = 0;
Close (fd);
}
#else
ret = (Access(path, R_OK) == 0);
#endif
Free (path);
return (ret);
}