1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1996, by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 /*
28 * tput.c
29 *
30 * Copyright 1990, 1994 by Mortice Kern Systems Inc. All rights reserved.
31 *
32 * PORTABILITY:
33 * SVID 3 - fully
34 * POSIX.2a UPE - needs clarification between SVID 3 exit statues.
35 * In particular exit 1 and 4 for string capnames.
36 * not in XPG 3
37 *
38 * SYNOPSIS:
39 * tput [-T<term>] capname [parm1..parm9]
40 * tput [-T<term>] -S
41 *
42 * DESCRIPTION:
43 * tput lets you change your terminal's characteristics. The capname
44 * argument indicates how you want to change the characteristics.
45 * Some special capnames are:
46 *
47 * clear clear the screen
48 * init initialize terminal in an implemenation-defined way
49 * reset reset terminal in an implemenation-defined way
50 * longname print the full name of the ternminal (SVID)
51 *
52 * Other capnames are supported and may take from 0 to 9 parameters. A
53 * list of them can be found in the SVID 3, vol 3. (SVID)
54 *
55 * tput does its work by outputting approriate character sequences to the
56 * standard output. These character sequences are terminal-specific. If
57 * you specify -T <type>, tput assumes that your terminal has the
58 * specified type and will issue sequences appropriate to that terminal.
59 *
60 * If you do not specify -T, tput looks for an environment variable
61 * named TERM. If TERM exists, its value is assumed to give the terminal
62 * type. If TERM does not exist, tput assumes a default terminal type.
63 *
64 * The -S option allows more than one capability per invocation of tput.
65 * The capabilities must be passed to tput from the standard input instead
66 * of the comamnd line. Only one capname is allowed per line.
67 *
68 * EXIT STATUS
69 * tput may return the following status values:
70 *
71 * 0 Either a boolean capname is set true or a string capname was
72 * successfully written to the terminal.
73 *
74 * 1 No error message is printed. Returned if a boolean capname is
75 * false or a string capname is not defined for the terminal.(SVID)
76 *
77 * 2 Usage error.
78 *
79 * 3 Unknown terminal <term> or no terminfo database.
80 *
81 * 4 Unknown terminfo capability <capname>.
82 *
83 * >4 An error occured.
84 *
85 *
86 * NOTE 1: If the Caps file that describes the terminfo database changes
87 * then a new term.h will be required. See CURSES/tic related tools.
88 *
89 * NOTE 2: tput has knowledge about the TERMINAL structure.
90 */
91 #ifdef M_RCSID
92 #ifndef lint
93 static char rcsID[] = "$Id: tput.c 1.28 1995/04/12 09:28:05 ross Exp $";
94 #endif
95 #endif
96
97 #include <mks.h>
98 #include <curses.h>
99 #include <term.h>
100 #include <ctype.h>
101 #include <limits.h>
102 #include <stdarg.h>
103 #include <stdio.h>
104 #include <stdlib.h>
105 #include <string.h>
106
107 extern char *_cmdname;
108
109
110 /* Exit Status */
111 #define SUCCESS 0
112 #define NOT_DEFINED 1
113 #define USAGE 2
114 #define BAD_TERMINAL 3
115 #define NOT_VALID 4
116 #define ERROR 5
117
118 static int S_flag = 0;
119 static char *term_name;
120 static char dumb_term[] = "dumb";
121 static char usage_msg[] = m_textstr(4931, "\
122 Usage: tput [-W] [-Tterm] capname [parm1..parm9]\n\
123 tput [-W] [-Tterm] -S\n", "U");
124
125 STATREF void build_argv ANSI((int *ac, char ***av));
126 STATREF int do_tput ANSI((int _argc, char **_argv));
127 STATREF void init ANSI((void));
128 STATREF void reset ANSI((void));
129 STATREF int usage ANSI((void));
130 STATREF void err_msg ANSI((char *fmt, ...)); /* GENTEXT: err_msg */
131 STATREF void cat ANSI((char *_Fn));
132
133 /*f
134 * mainline for tput
135 */
136 int
main(argc,argv)137 main(argc, argv)
138 int argc;
139 char **argv;
140 {
141 int opt;
142 int err_code;
143 setlocale(LC_ALL, "");
144 _cmdname = m_cmdname(*argv);
145 if ((term_name = getenv("TERM")) == NULL) {
146 term_name = dumb_term;
147 } else {
148 term_name = m_strdup(term_name);
149 }
150
151 /* Default uses the terminfo database without modification. */
152 use_env(0);
153
154 while ((opt = getopt(argc, argv, "ST:W")) != -1) {
155 switch (opt) {
156 case 'W':
157 /* Environment/window size are consulted and may
158 * alter the database entries for lines and columns.
159 */
160 use_env(1);
161 break;
162 case 'S':
163 S_flag = 1;
164 break;
165
166 case 'T':
167 term_name = optarg;
168 break;
169
170 default:
171 return (usage());
172 }
173 }
174
175 argc -= optind;
176 argv += optind;
177
178 if ((S_flag ^ (argc <= 0)) == 1)
179 return (usage());
180 (void) setupterm(term_name, fileno(stdout), &err_code);
181 switch (err_code) {
182 case 1:
183 break;
184 case 0:
185 err_msg(m_textstr(202, "Unknown terminal \"%s\".\n", "E term"), term_name);
186 return (BAD_TERMINAL);
187 case -1:
188 err_msg(m_textstr(203, "No terminfo database.\n", "E"));
189 return (BAD_TERMINAL);
190 }
191 do {
192 if (S_flag) {
193 build_argv(&argc, &argv);
194 if (argc <= 0)
195 break;
196 }
197 err_code = do_tput(argc, argv);
198 } while (S_flag && err_code == SUCCESS);
199 return (err_code);
200 }
201
202 /*f
203 * Get an input line from stdin and then break it up into an argv array.
204 * If EOF is reached then S_flag is set to 0. Only the first 10 strings
205 * are of any interest. Any extra are ignored.
206 */
207 STATIC void
build_argv(ac,av)208 build_argv(ac, av)
209 int *ac;
210 char ***av;
211 {
212 int i = 0;
213 char *p;
214 static char *v[10+1];
215 static char buf[LINE_MAX];
216 if ((*v = fgets(buf, LINE_MAX, stdin)) == NULL) {
217 /* End of file or input error */
218 S_flag = 0;
219 } else {
220 if ((p = strchr(buf, '\n')) != NULL)
221 *p = '\0';
222 for (p = buf; i < 10;) {
223 while (isspace(*(unsigned char*) p))
224 ++p;
225 if (*p == '\0')
226 break;
227 v[i++] = p;
228 while (!isspace(*(unsigned char*) p) && *p != '\0')
229 ++p;
230 if (*p == '\0')
231 break;
232 *p++ = '\0';
233 }
234 }
235 v[i] = NULL;
236 *ac = i;
237 *av = v;
238 }
239
240 /*f
241 *
242 */
243 STATIC int
do_tput(_argc,_argv)244 do_tput(_argc, _argv)
245 int _argc;
246 char **_argv;
247 {
248 int i;
249 long q[9];
250 const char *p;
251 char *end_num;
252
253 if (strcmp(*_argv, "init") == 0)
254 init();
255 else if (strcmp(*_argv, "reset") == 0)
256 reset();
257 else if (strcmp(*_argv, "longname") == 0)
258 (void) printf("%s\n", longname());
259 else if ((i = tigetflag(*_argv)) != -1)
260 return (!i);
261 else if ((i = tigetnum(*_argv)) != -2)
262 (void) printf("%d\n", i);
263 else if ((p = tigetstr(*_argv)) != (char*) -1) {
264 if (p == NULL)
265 return (NOT_DEFINED);
266 for (i = 0; i < 9; ++i) {
267 if (1 < _argc) {
268 --_argc;
269 q[i] = strtol(*++_argv, &end_num, 0);
270 if (*end_num != '\0') {
271 /* The parameter must be a string
272 * so we save the pointer instead.
273 */
274 q[i] = (long) *_argv;
275 }
276 } else {
277 q[i] = 0L;
278 }
279 }
280 (void) putp(tparm(p, q[0], q[1], q[2], q[3],
281 q[4], q[5], q[6], q[7], q[8]
282 ));
283 fflush(stdout);
284 } else {
285 err_msg(m_textstr(1864, "Unknown terminfo capability \"%s\".\n", "E action"), *_argv);
286 return (NOT_VALID);
287 }
288 return (SUCCESS);
289 }
290
291 /*f
292 *
293 */
294 STATIC void
init()295 init()
296 {
297 if (init_prog != NULL)
298 (void) system(init_prog);
299 if (init_1string != NULL)
300 putp(init_1string);
301 if (init_2string != NULL)
302 putp(init_2string);
303 #if 0 /* currently not supported by our terminfo database */
304 if (clear_margins != NULL)
305 putp(clear_margins);
306 if (set_left_margin != NULL)
307 putp(set_left_margin);
308 if (set_right_margin != NULL)
309 putp(set_right_margin);
310 #endif
311 /* TODO: setting of tabs using clear_all_tabs & set_tab. */
312 if (init_file != NULL)
313 cat(init_file);
314 if (init_3string != NULL)
315 putp(init_3string);
316 }
317
318 /*f
319 *
320 */
321 STATIC void
reset()322 reset()
323 {
324 if (reset_1string != NULL)
325 putp(reset_1string);
326 if (reset_2string != NULL)
327 putp(reset_2string);
328 if (reset_file != NULL)
329 cat(reset_file);
330 if (reset_3string != NULL)
331 putp(reset_3string);
332 }
333
334 /*f
335 * usage message for tput
336 */
337 STATIC int
usage()338 usage()
339 {
340 (void) fprintf(stderr, m_strmsg(usage_msg));
341 return (USAGE);
342 }
343
344 /*f
345 * display error message
346 */
347 STATIC void
VARARG1(char *,fmt)348 err_msg VARARG1(char*, fmt)
349 {
350 va_list ap;
351 (void) fprintf(stderr, "%s: ", _cmdname);
352 va_start(ap, fmt);
353 (void) vfprintf(stderr, m_strmsg(fmt), ap);
354 va_end(ap);
355 }
356
357 /*
358 * Print a file via putp().
359 */
360 STATIC void
cat(fn)361 cat(fn)
362 char *fn;
363 {
364 FILE *fp;
365 char buf[LINE_MAX+1];
366 if ((fp = fopen(fn, "rb")) == NULL)
367 return;
368 while (fgets(buf, LINE_MAX, fp) != NULL)
369 putp(buf);
370 (void) fclose(fp);
371 }
372