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