term.c revision 216370
1243750Srwatson/*-
2186545Srwatson * Copyright (c) 1991, 1993
3186545Srwatson *	The Regents of the University of California.  All rights reserved.
4243750Srwatson *
5243750Srwatson * Redistribution and use in source and binary forms, with or without
6186545Srwatson * modification, are permitted provided that the following conditions
7186545Srwatson * are met:
8186545Srwatson * 1. Redistributions of source code must retain the above copyright
9186545Srwatson *    notice, this list of conditions and the following disclaimer.
10186545Srwatson * 2. Redistributions in binary form must reproduce the above copyright
11186545Srwatson *    notice, this list of conditions and the following disclaimer in the
12186545Srwatson *    documentation and/or other materials provided with the distribution.
13186545Srwatson * 4. Neither the name of the University nor the names of its contributors
14186545Srwatson *    may be used to endorse or promote products derived from this software
15186545Srwatson *    without specific prior written permission.
16186545Srwatson *
17186545Srwatson * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18243750Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19243750Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20243750Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21243750Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22243750Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23243750Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24243750Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25243750Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26243750Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27243750Srwatson * SUCH DAMAGE.
28243750Srwatson */
29243750Srwatson
30243750Srwatson#include <sys/cdefs.h>
31243750Srwatson
32243750Srwatson__FBSDID("$FreeBSD: head/usr.bin/tset/term.c 216370 2010-12-11 08:32:16Z joel $");
33243750Srwatson
34243750Srwatson#ifndef lint
35186545Srwatsonstatic const char sccsid[] = "@(#)term.c	8.1 (Berkeley) 6/9/93";
36243750Srwatson#endif
37186545Srwatson
38243750Srwatson#include <sys/types.h>
39186545Srwatson#include <err.h>
40186545Srwatson#include <errno.h>
41186545Srwatson#include <stdio.h>
42186545Srwatson#include <stdlib.h>
43186545Srwatson#include <string.h>
44186545Srwatson#include <termcap.h>
45186545Srwatson#include <unistd.h>
46186545Srwatson#include <ttyent.h>
47186545Srwatson#include "extern.h"
48186545Srwatson
49186545Srwatsonchar    tbuf[1024];      		/* Termcap entry. */
50186545Srwatson
51186545Srwatsonconst char *askuser(const char *);
52186545Srwatsonchar	*ttys(char *);
53186545Srwatson
54243750Srwatson/*
55243750Srwatson * Figure out what kind of terminal we're dealing with, and then read in
56186545Srwatson * its termcap entry.
57186545Srwatson */
58186545Srwatsonconst char *
59186545Srwatsonget_termcap_entry(char *userarg, char **tcapbufp)
60186545Srwatson{
61186545Srwatson	struct ttyent *t;
62186545Srwatson	int rval;
63243750Srwatson	char *p, *ttypath;
64186545Srwatson	const char *ttype;
65186545Srwatson
66186545Srwatson	if (userarg) {
67186545Srwatson		ttype = userarg;
68186545Srwatson		goto found;
69243750Srwatson	}
70243750Srwatson
71243750Srwatson	/* Try the environment. */
72243750Srwatson	if ((ttype = getenv("TERM")))
73243750Srwatson		goto map;
74243750Srwatson
75243750Srwatson	/* Try ttyname(3); check for dialup or other mapping. */
76243750Srwatson	if ((ttypath = ttyname(STDERR_FILENO))) {
77243750Srwatson		if ((p = rindex(ttypath, '/')))
78243750Srwatson			++p;
79243750Srwatson		else
80243750Srwatson			p = ttypath;
81243750Srwatson		if ((t = getttynam(p))) {
82243750Srwatson			ttype = t->ty_type;
83243750Srwatson			goto map;
84243750Srwatson		}
85243750Srwatson	}
86243750Srwatson
87243750Srwatson	/* If still undefined, use "unknown". */
88243750Srwatson	ttype = "unknown";
89243750Srwatson
90243750Srwatsonmap:	ttype = mapped(ttype);
91187214Srwatson
92186545Srwatson	/*
93186545Srwatson	 * If not a path, remove TERMCAP from the environment so we get a
94186545Srwatson	 * real entry from /etc/termcap.  This prevents us from being fooled
95186545Srwatson	 * by out of date stuff in the environment.
96191273Srwatson	 */
97186545Srwatsonfound:	if ((p = getenv("TERMCAP")) != NULL && *p != '/')
98186545Srwatson		unsetenv("TERMCAP");
99243750Srwatson
100186545Srwatson	/*
101186545Srwatson	 * ttype now contains a pointer to the type of the terminal.
102186545Srwatson	 * If the first character is '?', ask the user.
103186545Srwatson	 */
104186545Srwatson	if (ttype[0] == '?') {
105186545Srwatson		if (ttype[1] != '\0')
106186545Srwatson			ttype = askuser(ttype + 1);
107186545Srwatson		else
108186545Srwatson			ttype = askuser(NULL);
109186545Srwatson	}
110186545Srwatson
111243750Srwatson	/* Find the termcap entry.  If it doesn't exist, ask the user. */
112243750Srwatson	while ((rval = tgetent(tbuf, ttype)) == 0) {
113243750Srwatson		warnx("terminal type %s is unknown", ttype);
114243750Srwatson		ttype = askuser(NULL);
115243750Srwatson	}
116187214Srwatson	if (rval == -1)
117187214Srwatson		errx(1, "termcap: %s", strerror(errno ? errno : ENOENT));
118187214Srwatson	*tcapbufp = tbuf;
119186545Srwatson	return (ttype);
120186545Srwatson}
121186545Srwatson
122186545Srwatson/* Prompt the user for a terminal type. */
123186545Srwatsonconst char *
124186545Srwatsonaskuser(const char *dflt)
125186545Srwatson{
126186545Srwatson	static char answer[256];
127186545Srwatson	char *p;
128186545Srwatson
129186545Srwatson	/* We can get recalled; if so, don't continue uselessly. */
130186545Srwatson	if (feof(stdin) || ferror(stdin)) {
131186545Srwatson		(void)fprintf(stderr, "\n");
132186545Srwatson		exit(1);
133186545Srwatson	}
134186545Srwatson	for (;;) {
135186545Srwatson		if (dflt)
136186545Srwatson			(void)fprintf(stderr, "Terminal type? [%s] ", dflt);
137243750Srwatson		else
138191273Srwatson			(void)fprintf(stderr, "Terminal type? ");
139243750Srwatson		(void)fflush(stderr);
140186545Srwatson
141186545Srwatson		if (fgets(answer, sizeof(answer), stdin) == NULL) {
142186545Srwatson			if (dflt == NULL) {
143186545Srwatson				(void)fprintf(stderr, "\n");
144186545Srwatson				exit(1);
145243750Srwatson			}
146186545Srwatson			return (dflt);
147186545Srwatson		}
148186545Srwatson
149186545Srwatson		if ((p = index(answer, '\n')))
150186545Srwatson			*p = '\0';
151186545Srwatson		if (answer[0])
152243750Srwatson			return (answer);
153186545Srwatson		if (dflt != NULL)
154243750Srwatson			return (dflt);
155243750Srwatson	}
156243750Srwatson}
157186545Srwatson