xref: /openbsd/usr.bin/tput/tput.c (revision f2dfb0a4)
1 /*	$OpenBSD: tput.c,v 1.5 1997/06/24 02:40:15 dgregor Exp $	*/
2 /*	$NetBSD: tput.c,v 1.8 1995/08/31 22:11:37 jtc Exp $	*/
3 
4 /*-
5  * Copyright (c) 1980, 1988, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 static char copyright[] =
39 "@(#) Copyright (c) 1980, 1988, 1993\n\
40 	The Regents of the University of California.  All rights reserved.\n";
41 #endif /* not lint */
42 
43 #ifndef lint
44 #if 0
45 static char sccsid[] = "@(#)tput.c	8.3 (Berkeley) 4/28/95";
46 #endif
47 static char rcsid[] = "$OpenBSD: tput.c,v 1.5 1997/06/24 02:40:15 dgregor Exp $";
48 #endif /* not lint */
49 
50 #include <termios.h>
51 
52 #include <err.h>
53 #include <curses.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <unistd.h>
57 #include <string.h>
58 
59 static void   prlongname __P((char *));
60 static void   setospeed __P((void));
61 static void   outc __P((int));
62 static void   usage __P((void));
63 static char **process __P((char *, char *, char **));
64 
65 int
66 main(argc, argv)
67 	int argc;
68 	char **argv;
69 {
70 	extern char *optarg;
71 	extern int optind;
72 	int ch, exitval, n;
73 	char *argv0, *cptr, *p, *term, buf[1024], tbuf[1024];
74 
75 	term = NULL;
76 	while ((ch = getopt(argc, argv, "T:")) != -1)
77 		switch(ch) {
78 		case 'T':
79 			term = optarg;
80 			break;
81 		case '?':
82 		default:
83 			usage();
84 		}
85 	if ((argv0 = (char *)strrchr(argv[0], '/')) != NULL)
86 		argv0++;
87 	else
88 		argv0 = argv[0];
89 	argc -= optind;
90 	argv += optind;
91 
92 
93 	if (!term && !(term = getenv("TERM")))
94 errx(2, "no terminal type specified and no TERM environmental variable.");
95 	if (tgetent(tbuf, term) != 1)
96 		err(2, "tgetent failure");
97 	setospeed();
98 	if (strcmp(argv0, "clear") == 0) {
99 		*argv = "clear";
100 		*(argv+1) = NULL;
101 	}
102 	for (exitval = 0; (p = *argv) != NULL; ++argv) {
103 		switch (*p) {
104 		case 'c':
105 			if (!strcmp(p, "clear"))
106 				p = "cl";
107 			break;
108 		case 'i':
109 			if (!strcmp(p, "init"))
110 				p = "is";
111 			break;
112 		case 'l':
113 			if (!strcmp(p, "longname")) {
114 				prlongname(tbuf);
115 				continue;
116 			}
117 			break;
118 		case 'r':
119 			if (!strcmp(p, "reset"))
120 				p = "rs";
121 			break;
122 		}
123 		cptr = buf;
124 		if (tgetstr(p, &cptr))
125 			argv = process(p, buf, argv);
126 		else if ((n = tgetnum(p)) != -1)
127 			(void)printf("%d\n", n);
128 		else
129 			exitval = !tgetflag(p);
130 
131 		if (argv == NULL)
132 			break;
133 	}
134 	exit(argv ? exitval : 2);
135 }
136 
137 static void
138 prlongname(buf)
139 	char *buf;
140 {
141 	int savech;
142 	char *p, *savep;
143 
144 	for (p = buf; *p && *p != ':'; ++p)
145 		continue;
146 	savech = *(savep = p);
147 	for (*p = '\0'; p >= buf && *p != '|'; --p)
148 		continue;
149 	(void)printf("%s\n", p + 1);
150 	*savep = savech;
151 }
152 
153 static char **
154 process(cap, str, argv)
155 	char *cap, *str, **argv;
156 {
157 	static char errfew[] =
158 	    "not enough arguments (%d) for capability `%s'";
159 	static char errmany[] =
160 	    "too many arguments (%d) for capability `%s'";
161 	static char erresc[] =
162 	    "unknown %% escape `%c' for capability `%s'";
163 	char *cp;
164 	int arg_need, arg_rows, arg_cols;
165 
166 	/* Count how many values we need for this capability. */
167 	for (cp = str, arg_need = 0; *cp != '\0'; cp++)
168 		if (*cp == '%')
169 			    switch (*++cp) {
170 			    case 'd':
171 			    case '2':
172 			    case '3':
173 			    case '.':
174 			    case '+':
175 				    arg_need++;
176 				    break;
177 			    case '%':
178 			    case '>':
179 			    case 'i':
180 			    case 'r':
181 			    case 'n':
182 			    case 'B':
183 			    case 'D':
184 				    break;
185 			    default:
186 				/*
187 				 * hpux has lot's of them, but we complain
188 				 */
189 				 errx(2, erresc, *cp, cap);
190 			    }
191 
192 	/* And print them. */
193 	switch (arg_need) {
194 	case 0:
195 		(void)tputs(str, 1, outc);
196 		break;
197 	case 1:
198 		arg_cols = 0;
199 
200 		if (*++argv == NULL || *argv[0] == '\0')
201 			errx(2, errfew, 1, cap);
202 		arg_rows = atoi(*argv);
203 
204 		(void)tputs(tgoto(str, arg_cols, arg_rows), 1, outc);
205 		break;
206 	case 2:
207 		if (*++argv == NULL || *argv[0] == '\0')
208 			errx(2, errfew, 2, cap);
209 		arg_rows = atoi(*argv);
210 
211 		if (*++argv == NULL || *argv[0] == '\0')
212 			errx(2, errfew, 2, cap);
213 		arg_cols = atoi(*argv);
214 
215 		(void) tputs(tgoto(str, arg_cols, arg_rows), arg_rows, outc);
216 		break;
217 
218 	default:
219 		errx(2, errmany, arg_need, cap);
220 	}
221 	return (argv);
222 }
223 
224 static void
225 setospeed()
226 {
227 #undef ospeed
228 	extern short ospeed;
229 	struct termios t;
230 
231 	if (tcgetattr(STDOUT_FILENO, &t) != -1)
232 		ospeed = 0;
233 	else
234 		ospeed = cfgetospeed(&t);
235 }
236 
237 static void
238 outc(c)
239 	int c;
240 {
241 	(void)putchar(c);
242 }
243 
244 static void
245 usage()
246 {
247 	(void)fprintf(stderr, "usage: tput [-T term] attribute ...\n");
248 	exit(1);
249 }
250