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