GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/tput/tput.c Lines: 0 156 0.0 %
Date: 2016-12-06 Branches: 0 161 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: tput.c,v 1.22 2015/11/16 03:03:28 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
5
 *
6
 * Permission to use, copy, modify, and distribute this software for any
7
 * purpose with or without fee is hereby granted, provided that the above
8
 * copyright notice and this permission notice appear in all copies.
9
 *
10
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 */
18
/*-
19
 * Copyright (c) 1980, 1988, 1993
20
 *	The Regents of the University of California.  All rights reserved.
21
 *
22
 * Redistribution and use in source and binary forms, with or without
23
 * modification, are permitted provided that the following conditions
24
 * are met:
25
 * 1. Redistributions of source code must retain the above copyright
26
 *    notice, this list of conditions and the following disclaimer.
27
 * 2. Redistributions in binary form must reproduce the above copyright
28
 *    notice, this list of conditions and the following disclaimer in the
29
 *    documentation and/or other materials provided with the distribution.
30
 * 3. Neither the name of the University nor the names of its contributors
31
 *    may be used to endorse or promote products derived from this software
32
 *    without specific prior written permission.
33
 *
34
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
35
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44
 * SUCH DAMAGE.
45
 */
46
47
#include <ctype.h>
48
#include <err.h>
49
#include <curses.h>
50
#include <term.h>
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <termios.h>
54
#include <unistd.h>
55
#include <limits.h>
56
#include <string.h>
57
58
#define MAXIMUM(a, b)	(((a) > (b)) ? (a) : (b))
59
60
#include <sys/wait.h>
61
62
static void   init(void);
63
static char **process(char *, char *, char **);
64
static void   reset(void);
65
static void   set_margins(void);
66
static void   usage(void);
67
68
extern char  *__progname;
69
70
int
71
main(int argc, char *argv[])
72
{
73
	int ch, exitval, n, Sflag;
74
	size_t len;
75
	char *p, *term, *str;
76
	char **oargv;
77
78
	if (pledge("stdio rpath wpath tty cpath", NULL) == -1)
79
		err(1, "pledge");
80
81
	oargv = argv;
82
	term = NULL;
83
	Sflag = exitval = 0;
84
	while ((ch = getopt(argc, argv, "ST:")) != -1)
85
		switch(ch) {
86
		case 'T':
87
			term = optarg;
88
			break;
89
		case 'S':
90
			Sflag = 1;
91
			break;
92
		case '?':
93
		default:
94
			usage();
95
		}
96
	argc -= optind;
97
	argv += optind;
98
99
	if (Sflag && argc > 0)
100
		usage();
101
102
	if (!term && !(term = getenv("TERM")))
103
		errx(2, "No value for $TERM and no -T specified");
104
105
	/*
106
	 * NOTE: tgetent() will call setupterm() and set ospeed for us
107
	 * (this is ncurses-specific behavior)
108
	 */
109
	if (tgetent(NULL, term) != 1)
110
		errx(3, "Unknown terminal type `%s'", term);
111
112
	if (strcmp(__progname, "clear") == 0) {
113
		if (Sflag)
114
			usage();
115
		argv = oargv;
116
		*argv = __progname;
117
		*(argv+1) = NULL;
118
	}
119
	if (Sflag) {
120
		char **av;
121
122
		/* Build new argv based on stdin */
123
		argc = n = 0;
124
		av = NULL;
125
		while ((str = fgetln(stdin, &len)) != NULL) {
126
			if (str[len-1] != '\n')
127
				errx(1, "premature EOF");
128
			str[len-1] = '\0';
129
			while ((p = strsep(&str, " \t")) != NULL) {
130
				/* grow av as needed */
131
				if (argc + 1 >= n) {
132
					n += 64;
133
					av = reallocarray(av, n,
134
					    sizeof(char *));
135
					if (av == NULL)
136
						errx(1, "out of memory");
137
				}
138
				if (*p != '\0' &&
139
				    (av[argc++] = strdup(p)) == NULL)
140
					errx(1, "out of memory");
141
			}
142
		}
143
		if (argc > 0) {
144
			av[argc] = NULL;
145
			argv = av;
146
		}
147
	}
148
	while ((p = *argv++)) {
149
		switch (*p) {
150
		case 'i':
151
			if (!strcmp(p, "init")) {
152
				init();
153
				continue;
154
			}
155
			break;
156
		case 'l':
157
			if (!strcmp(p, "longname")) {
158
				puts(longname());
159
				continue;
160
			}
161
			break;
162
		case 'r':
163
			if (!strcmp(p, "reset")) {
164
				reset();
165
				continue;
166
			}
167
			break;
168
		}
169
170
		/* First try as terminfo */
171
		if ((str = tigetstr(p)) && str != (char *)-1)
172
			argv = process(p, str, argv);
173
		else if ((n = tigetnum(p)) != -2)
174
			(void)printf("%d\n", n);
175
		else if ((n = tigetflag(p)) != -1)
176
			exitval = !n;
177
		/* Then fall back on termcap */
178
		else if ((str = tgetstr(p, NULL)))
179
			argv = process(p, str, argv);
180
		else if ((n = tgetnum(p)) != -1)
181
			(void)printf("%d\n", n);
182
		else if ((exitval = tgetflag(p)) != 0)
183
			exitval = !exitval;
184
		else {
185
			warnx("Unknown terminfo capability `%s'", p);
186
			exitval = 4;
187
		}
188
	}
189
	exit(exitval);
190
}
191
192
static char **
193
process(char *cap, char *str, char **argv)
194
{
195
	char *cp, *s, *nargv[9];
196
	int arg_need, popcount, i;
197
198
	/* Count how many values we need for this capability. */
199
	for (cp = str, arg_need = popcount = 0; *cp != '\0'; cp++) {
200
		if (*cp == '%') {
201
			switch (*++cp) {
202
			case '%':
203
			   	cp++;
204
				break;
205
			case 'i':
206
				if (popcount < 2)
207
					popcount = 2;
208
				break;
209
			case 'p':
210
				cp++;
211
				if (isdigit((unsigned char)cp[1]) &&
212
				    popcount < cp[1] - '0')
213
					popcount = cp[1] - '0';
214
				break;
215
			case 'd':
216
			case 's':
217
			case '0':
218
			case '1':
219
			case '2':
220
			case '3':
221
			case '4':
222
			case '5':
223
			case '6':
224
			case '7':
225
			case '8':
226
			case '9':
227
			case '.':
228
			case '+':
229
				arg_need++;
230
				break;
231
			default:
232
				break;
233
			}
234
		}
235
	}
236
	arg_need = MAXIMUM(arg_need, popcount);
237
	if (arg_need > 9)
238
		errx(2, "too many arguments (%d) for capability `%s'",
239
		    arg_need, cap);
240
241
	for (i = 0; i < arg_need; i++) {
242
		long l;
243
244
		if (argv[i] == NULL)
245
			errx(2, "not enough arguments (%d) for capability `%s'",
246
			    arg_need, cap);
247
248
		/* convert ascii representation of numbers to longs */
249
		if (isdigit((unsigned char)argv[i][0])
250
		    && (l = strtol(argv[i], &cp, 10)) >= 0
251
		    && l < LONG_MAX && *cp == '\0')
252
			nargv[i] = (char *)l;
253
		else
254
			nargv[i] = argv[i];
255
	}
256
257
	s = tparm(str, nargv[0], nargv[1], nargv[2], nargv[3],
258
	    nargv[4], nargv[5], nargv[6], nargv[7], nargv[8]);
259
	putp(s);
260
	fflush(stdout);
261
262
	return (argv + arg_need);
263
}
264
265
static void
266
init(void)
267
{
268
	FILE *ifile;
269
	size_t len;
270
	char *buf;
271
	int wstatus;
272
273
	if (init_prog && !issetugid()) {
274
		switch (vfork()) {
275
		case -1:
276
			err(4, "vfork");
277
			break;
278
		case 0:
279
			/* child */
280
			execl(init_prog, init_prog, (char *)NULL);
281
			_exit(127);
282
			break;
283
		default:
284
			wait(&wstatus);
285
			/* parent */
286
			break;
287
		}
288
	}
289
	if (init_1string)
290
		putp(init_1string);
291
	if (init_2string)
292
		putp(init_2string);
293
	set_margins();
294
	/* always use 8 space tabs */
295
	if (init_tabs != 8 && clear_all_tabs && set_tab) {
296
		int i;
297
298
		putp(clear_all_tabs);
299
		for (i = 0; i < (columns - 1) / 8; i++) {
300
			if (parm_right_cursor)
301
				putp(tparm(parm_right_cursor, 8));
302
			else
303
				fputs("        ", stdout);
304
			putp(set_tab);
305
		}
306
	}
307
	if (init_file && !issetugid() && (ifile = fopen(init_file, "r"))) {
308
		while ((buf = fgetln(ifile, &len)) != NULL) {
309
			if (buf[len-1] != '\n')
310
				errx(1, "premature EOF reading %s", init_file);
311
			buf[len-1] = '\0';
312
			putp(buf);
313
		}
314
		fclose(ifile);
315
	}
316
	if (init_3string)
317
		putp(init_3string);
318
	fflush(stdout);
319
}
320
321
static void
322
reset(void)
323
{
324
	FILE *rfile;
325
	size_t len;
326
	char *buf;
327
328
	if (reset_1string)
329
		putp(reset_1string);
330
	if (reset_2string)
331
		putp(reset_2string);
332
	set_margins();
333
	if (reset_file && !issetugid() && (rfile = fopen(reset_file, "r"))) {
334
		while ((buf = fgetln(rfile, &len)) != NULL) {
335
			if (buf[len-1] != '\n')
336
				errx(1, "premature EOF reading %s", reset_file);
337
			buf[len-1] = '\0';
338
			putp(buf);
339
		}
340
		fclose(rfile);
341
	}
342
	if (reset_3string)
343
		putp(reset_3string);
344
	fflush(stdout);
345
}
346
347
static void
348
set_margins(void)
349
{
350
351
	/*
352
	 * Four possibilities:
353
	 *	1) we have set_lr_margin and can set things with one call
354
	 *	2) we have set_{left,right}_margin_parm, use two calls
355
	 *	3) we have set_{left,right}_margin, set based on position
356
	 *	4) none of the above, leave things the way they are
357
	 */
358
	if (set_lr_margin) {
359
		putp(tparm(set_lr_margin, 0, columns - 1));
360
	} else if (set_left_margin_parm && set_right_margin_parm) {
361
		putp(tparm(set_left_margin_parm, 0));
362
		putp(tparm(set_right_margin_parm, columns - 1));
363
	} else if (set_left_margin && set_right_margin && clear_margins) {
364
		putp(clear_margins);
365
366
		/* go to column 0 and set the left margin */
367
		putp(carriage_return ? carriage_return : "\r");
368
		putp(set_left_margin);
369
370
		/* go to last column and set the right margin */
371
		if (parm_right_cursor)
372
			putp(tparm(parm_right_cursor, columns - 1));
373
		else
374
			printf("%*s", columns - 1, " ");
375
		putp(set_right_margin);
376
		putp(carriage_return ? carriage_return : "\r");
377
	}
378
	fflush(stdout);
379
}
380
381
static void
382
usage(void)
383
{
384
385
	if (strcmp(__progname, "clear") == 0)
386
		(void)fprintf(stderr, "usage: %s [-T term]\n", __progname);
387
	else
388
		(void)fprintf(stderr,
389
		    "usage: %s [-T term] attribute [attribute-args] ...\n"
390
		    "       %s [-T term] -S\n", __progname, __progname);
391
	exit(1);
392
}