150624Speter/* A portion of this file is from ncurses: */
250624Speter/***************************************************************************
350624Speter*                            COPYRIGHT NOTICE                              *
450624Speter****************************************************************************
550624Speter*                ncurses is copyright (C) 1992-1995                        *
650624Speter*                          Zeyd M. Ben-Halim                               *
750624Speter*                          zmbenhal@netcom.com                             *
850624Speter*                          Eric S. Raymond                                 *
950624Speter*                          esr@snark.thyrsus.com                           *
1050624Speter*                                                                          *
1150624Speter*        Permission is hereby granted to reproduce and distribute ncurses  *
1250624Speter*        by any means and for any fee, whether alone or as part of a       *
1350624Speter*        larger distribution, in source or in binary form, PROVIDED        *
1450624Speter*        this notice is included with any such distribution, and is not    *
1550624Speter*        removed from any of its header files. Mention of ncurses in any   *
1650624Speter*        applications linked with it is highly appreciated.                *
1750624Speter*                                                                          *
1850624Speter*        ncurses comes AS IS with no warranty, implied or expressed.       *
1950624Speter*                                                                          *
2050624Speter***************************************************************************/
2150624Speter
2250624Speter#include <curses.priv.h>
2350624Speter
2450624Speter#include <string.h>
2550624Speter#include <term.h>
2650624Speter#include <tic.h>
2750624Speter#include <term_entry.h>
2850624Speter
2950624Speter/* The rest is from BSD */
3050624Speter/*
3150624Speter * Copyright (c) 1980, 1993
3250624Speter *	The Regents of the University of California.  All rights reserved.
3350624Speter *
3450624Speter * Redistribution and use in source and binary forms, with or without
3550624Speter * modification, are permitted provided that the following conditions
3650624Speter * are met:
3750624Speter * 1. Redistributions of source code must retain the above copyright
3850624Speter *    notice, this list of conditions and the following disclaimer.
3950624Speter * 2. Redistributions in binary form must reproduce the above copyright
4050624Speter *    notice, this list of conditions and the following disclaimer in the
4150624Speter *    documentation and/or other materials provided with the distribution.
4250624Speter * 4. Neither the name of the University nor the names of its contributors
4350624Speter *    may be used to endorse or promote products derived from this software
4450624Speter *    without specific prior written permission.
4550624Speter *
4650624Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
4750624Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
4850624Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
4950624Speter * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5050624Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5150624Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5250624Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5350624Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5450624Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5550624Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5650624Speter * SUCH DAMAGE.
5750624Speter */
5850624Speter
5984214Sdillon#include <sys/cdefs.h>
6084214Sdillon__FBSDID("$FreeBSD$");
6184214Sdillon
6250624Speter#ifndef lint
6350624Speterstatic const char sccsid[] = "@(#)termcap.c	8.1 (Berkeley) 6/4/93";
6450624Speter#endif /* not lint */
6550624Speter
6650624Speter#include <stdio.h>
6750624Speter#include <ctype.h>
6850624Speter#include <stdlib.h>
6950624Speter#include <string.h>
7050624Speter#include <unistd.h>
7150624Speter#include <sys/param.h>
7250624Speter#include "pathnames.h"
7350624Speter
7450624Speter#define	PBUFSIZ	MAXPATHLEN	/* max length of filename path */
7550624Speter#define	PVECSIZ	32		/* max number of names in path */
7650624Speter#define	TBUFSIZ 1024		/* max length of _nc_tgetent buffer */
7750624Speter
7850624Speterchar _nc_termcap[TBUFSIZ + 1]; /* Last getcap, provided to tgetent() emul */
7950624Speter
8050624Speter/*
8150624Speter * termcap - routines for dealing with the terminal capability data base
8250624Speter *
8350624Speter * BUG:		Should use a "last" pointer in tbuf, so that searching
8450624Speter *		for capabilities alphabetically would not be a n**2/2
8550624Speter *		process when large numbers of capabilities are given.
8650624Speter * Note:	If we add a last pointer now we will screw up the
8750624Speter *		tc capability. We really should compile termcap.
8850624Speter *
8950624Speter * Essentially all the work here is scanning and decoding escapes
9050624Speter * in string capabilities.  We don't use stdio because the editor
9150624Speter * doesn't, and because living w/o it is not hard.
9250624Speter */
9350624Speter
9450624Speter/*
9550624Speter * Get an entry for terminal name in buffer _nc_termcap from the termcap
9650624Speter * file.
9750624Speter */
9850624Speterint
9950624Speter_nc_read_termcap_entry(const char *const name, TERMTYPE *const tp)
10050624Speter{
10150624Speter	ENTRY	*ep;
10292913Sobrien	char *p;
10392913Sobrien	char *cp;
10450624Speter	char  *dummy;
10550624Speter	char **fname;
10650624Speter	char  *home;
10750624Speter	int    i;
10850624Speter	char   pathbuf[PBUFSIZ];	/* holds raw path of filenames */
10950624Speter	char  *pathvec[PVECSIZ];	/* to point to names in pathbuf */
11050624Speter	char **pvec;			/* holds usable tail of path vector */
11150624Speter	char  *termpath;
11250624Speter
11350624Speter	_nc_termcap[0] = '\0';		/* in case */
11450624Speter	dummy = NULL;
11550624Speter	fname = pathvec;
11650624Speter	pvec = pathvec;
11750624Speter	p = pathbuf;
11850624Speter	cp = getenv("TERMCAP");
11950624Speter	/*
12050624Speter	 * TERMCAP can have one of two things in it. It can be the
12150624Speter	 * name of a file to use instead of /etc/termcap. In this
12250624Speter	 * case it better start with a "/". Or it can be an entry to
12350624Speter	 * use so we don't have to read the file. In this case it
12450624Speter	 * has to already have the newlines crunched out.  If TERMCAP
12550624Speter	 * does not hold a file name then a path of names is searched
12650624Speter	 * instead.  The path is found in the TERMPATH variable, or
12750624Speter	 * becomes "$HOME/.termcap /etc/termcap" if no TERMPATH exists.
12850624Speter	 */
12950624Speter	if (!cp || *cp != '/') {	/* no TERMCAP or it holds an entry */
13050624Speter		if ( (termpath = getenv("TERMPATH")) )
13150624Speter			strncpy(pathbuf, termpath, PBUFSIZ);
13250624Speter		else {
13350624Speter			if ( (home = getenv("HOME")) ) {/* set up default */
13450624Speter				strncpy(pathbuf, home, PBUFSIZ - 1); /* $HOME first */
13550624Speter				pathbuf[PBUFSIZ - 2] = '\0'; /* -2 because we add a slash */
13650624Speter				p += strlen(pathbuf);	/* path, looking in */
13750624Speter				*p++ = '/';
13850624Speter			}	/* if no $HOME look in current directory */
13950624Speter			strncpy(p, _PATH_DEF, PBUFSIZ - (p - pathbuf));
14050624Speter		}
14150624Speter	}
14250624Speter	else				/* user-defined name in TERMCAP */
14350624Speter		strncpy(pathbuf, cp, PBUFSIZ);	/* still can be tokenized */
14450624Speter
14550624Speter	/* For safety */
14650624Speter	if (issetugid())
14750624Speter		strcpy(pathbuf, _PATH_DEF_SEC);
14850624Speter
14950624Speter	pathbuf[PBUFSIZ - 1] = '\0';
15050624Speter
15150624Speter	*fname++ = pathbuf;	/* tokenize path into vector of names */
15250624Speter	while (*++p)
15350624Speter		if (*p == ' ' || *p == ':') {
15450624Speter			*p = '\0';
15550624Speter			while (*++p)
15650624Speter				if (*p != ' ' && *p != ':')
15750624Speter					break;
15850624Speter			if (*p == '\0')
15950624Speter				break;
16050624Speter			*fname++ = p;
16150624Speter			if (fname >= pathvec + PVECSIZ) {
16250624Speter				fname--;
16350624Speter				break;
16450624Speter			}
16550624Speter		}
16650624Speter	*fname = (char *) 0;			/* mark end of vector */
16750624Speter	if (cp && *cp && *cp != '/')
16850624Speter		if (cgetset(cp) < 0)
16950624Speter			return(-2);
17050624Speter
17150624Speter	i = cgetent(&dummy, pathvec, (char *)name);
17250624Speter
17350624Speter	if (i == 0) {
17450624Speter		char *pd, *ps, *tok, *s, *tcs;
17550624Speter		size_t len;
17650624Speter
17750624Speter		pd = _nc_termcap;
17850624Speter		ps = dummy;
17950624Speter		if ((tok = strchr(ps, ':')) == NULL) {
18050624Speter			len = strlen(ps);
18150624Speter			if (len >= TBUFSIZ)
18250624Speter				i = -1;
18350624Speter			else
18450624Speter				strcpy(pd, ps);
18550624Speter			goto done;
18650624Speter		}
18750624Speter		len = tok - ps + 1;
18850624Speter		if (pd + len + 1 - _nc_termcap >= TBUFSIZ) {
18950624Speter			i = -1;
19050624Speter			goto done;
19150624Speter		}
19250624Speter		memcpy(pd, ps, len);
19350624Speter		ps += len;
19450624Speter		pd += len;
19550624Speter		*pd = '\0';
19650624Speter		tcs = pd - 1;
19750624Speter		for (;;) {
19850624Speter			while ((tok = strsep(&ps, ":")) != NULL &&
199101752Sru			       *(tok - 2) != '\\' &&
200166130Srafan			       (*tok == '\0' || *tok == '\\' || !isgraph(UChar(*tok))))
20150624Speter				;
20250624Speter			if (tok == NULL)
20350624Speter				break;
20450624Speter			for (s = tcs; s != NULL && s[1] != '\0';
20550624Speter			     s = strchr(s, ':')) {
20650624Speter				s++;
20750624Speter				if (s[0] == tok[0] && s[1] == tok[1])
20850624Speter					goto skip_it;
20950624Speter			}
21050624Speter			len = strlen(tok);
21150624Speter			if (pd + len + 1 - _nc_termcap >= TBUFSIZ) {
21250624Speter				i = -1;
21350624Speter				break;
21450624Speter			}
21550624Speter			memcpy(pd, tok, len);
21650624Speter			pd += len;
21750624Speter			*pd++ = ':';
21850624Speter			*pd = '\0';
21950624Speter		skip_it: ;
22050624Speter		}
22150624Speter	}
22250624Speterdone:
22350624Speter	if (dummy)
22450624Speter		free(dummy);
22550624Speter
22650624Speter
22750624Speter/*
22850624Speter * From here on is ncurses-specific glue code
22950624Speter */
23050624Speter
23150624Speter	if (i < 0)
232166130Srafan		return(TGETENT_ERR);
23350624Speter
23450624Speter	_nc_set_source("TERMCAP");
23553252Speter	_nc_read_entry_source((FILE *)NULL, _nc_termcap, FALSE, TRUE, NULLHOOK);
23650624Speter
23750624Speter	if (_nc_head == (ENTRY *)NULL)
238166130Srafan		return(TGETENT_ERR);
23950624Speter
24050624Speter	/* resolve all use references */
241166130Srafan	_nc_resolve_uses2(TRUE, FALSE);
24250624Speter
24350624Speter	for_entry_list(ep)
24450624Speter		if (_nc_name_match(ep->tterm.term_names, name, "|:"))
24550624Speter		{
24650624Speter			/*
247166130Srafan			 * Make a local copy of the terminal capabilities, delinked
248166130Srafan			 * from the list.
24950624Speter			 */
25050624Speter			memcpy(tp, &ep->tterm, sizeof(TERMTYPE));
251166130Srafan			_nc_delink_entry(_nc_head, &(ep->tterm));
252166130Srafan			free(ep);
25350624Speter			_nc_free_entries(_nc_head);
25450624Speter			_nc_head = _nc_tail = NULL;	/* do not reuse! */
25550624Speter
256166130Srafan			return TGETENT_YES;	/* OK */
25750624Speter		}
25850624Speter
25950624Speter	_nc_free_entries(_nc_head);
26050624Speter	_nc_head = _nc_tail = NULL;	/* do not reuse! */
261166130Srafan	return(TGETENT_NO);	/* not found */
26250624Speter}
263