1/*-
2 * Copyright (c) 1991, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#include <sys/cdefs.h>
31
32__FBSDID("$FreeBSD: releng/10.3/usr.bin/tset/term.c 241737 2012-10-19 14:49:42Z ed $");
33
34#ifndef lint
35static const char sccsid[] = "@(#)term.c	8.1 (Berkeley) 6/9/93";
36#endif
37
38#include <sys/types.h>
39#include <err.h>
40#include <errno.h>
41#include <stdio.h>
42#include <stdlib.h>
43#include <string.h>
44#include <termcap.h>
45#include <unistd.h>
46#include <ttyent.h>
47#include "extern.h"
48
49static char tbuf[1024];		/* Termcap entry. */
50
51const char *askuser(const char *);
52char	*ttys(char *);
53
54/*
55 * Figure out what kind of terminal we're dealing with, and then read in
56 * its termcap entry.
57 */
58const char *
59get_termcap_entry(char *userarg, char **tcapbufp)
60{
61	struct ttyent *t;
62	int rval;
63	char *p, *ttypath;
64	const char *ttype;
65
66	if (userarg) {
67		ttype = userarg;
68		goto found;
69	}
70
71	/* Try the environment. */
72	if ((ttype = getenv("TERM")))
73		goto map;
74
75	/* Try ttyname(3); check for dialup or other mapping. */
76	if ((ttypath = ttyname(STDERR_FILENO))) {
77		if ((p = strrchr(ttypath, '/')))
78			++p;
79		else
80			p = ttypath;
81		if ((t = getttynam(p))) {
82			ttype = t->ty_type;
83			goto map;
84		}
85	}
86
87	/* If still undefined, use "unknown". */
88	ttype = "unknown";
89
90map:	ttype = mapped(ttype);
91
92	/*
93	 * If not a path, remove TERMCAP from the environment so we get a
94	 * real entry from /etc/termcap.  This prevents us from being fooled
95	 * by out of date stuff in the environment.
96	 */
97found:	if ((p = getenv("TERMCAP")) != NULL && *p != '/')
98		unsetenv("TERMCAP");
99
100	/*
101	 * ttype now contains a pointer to the type of the terminal.
102	 * If the first character is '?', ask the user.
103	 */
104	if (ttype[0] == '?') {
105		if (ttype[1] != '\0')
106			ttype = askuser(ttype + 1);
107		else
108			ttype = askuser(NULL);
109	}
110
111	/* Find the termcap entry.  If it doesn't exist, ask the user. */
112	while ((rval = tgetent(tbuf, ttype)) == 0) {
113		warnx("terminal type %s is unknown", ttype);
114		ttype = askuser(NULL);
115	}
116	if (rval == -1)
117		errx(1, "termcap: %s", strerror(errno ? errno : ENOENT));
118	*tcapbufp = tbuf;
119	return (ttype);
120}
121
122/* Prompt the user for a terminal type. */
123const char *
124askuser(const char *dflt)
125{
126	static char answer[256];
127	char *p;
128
129	/* We can get recalled; if so, don't continue uselessly. */
130	if (feof(stdin) || ferror(stdin)) {
131		(void)fprintf(stderr, "\n");
132		exit(1);
133	}
134	for (;;) {
135		if (dflt)
136			(void)fprintf(stderr, "Terminal type? [%s] ", dflt);
137		else
138			(void)fprintf(stderr, "Terminal type? ");
139		(void)fflush(stderr);
140
141		if (fgets(answer, sizeof(answer), stdin) == NULL) {
142			if (dflt == NULL) {
143				(void)fprintf(stderr, "\n");
144				exit(1);
145			}
146			return (dflt);
147		}
148
149		if ((p = strchr(answer, '\n')))
150			*p = '\0';
151		if (answer[0])
152			return (answer);
153		if (dflt != NULL)
154			return (dflt);
155	}
156}
157