Annotation of src/usr.bin/tput/tput.c, Revision 1.12
1.12 ! millert 1: /* $OpenBSD: tput.c,v 1.11 2001/07/09 07:04:56 deraadt 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.12 ! millert 72: static char rcsid[] = "$OpenBSD: tput.c,v 1.11 2001/07/09 07:04:56 deraadt 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:
1.12 ! millert 89: static void init(void);
! 90: static char **process(char *, char *, char **);
! 91: static void reset(void);
! 92: static void set_margins(void);
! 93: static void usage(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.10 millert 214: exit(exitval);
1.1 deraadt 215: }
216:
217: static char **
218: process(cap, str, argv)
219: char *cap, *str, **argv;
220: {
1.8 millert 221: char *cp, *s, *nargv[9];
222: int arg_need, popcount, i;
1.1 deraadt 223:
224: /* Count how many values we need for this capability. */
1.8 millert 225: for (cp = str, arg_need = popcount = 0; *cp != '\0'; cp++) {
226: if (*cp == '%') {
227: switch (*++cp) {
228: case '%':
229: cp++;
230: break;
231: case 'i':
232: if (popcount < 2)
233: popcount = 2;
234: break;
235: case 'p':
236: cp++;
237: if (isdigit(cp[1]) && popcount < cp[1] - '0')
238: popcount = cp[1] - '0';
239: break;
240: case 'd':
241: case 's':
242: case '0':
243: case '1':
244: case '2':
245: case '3':
246: case '4':
247: case '5':
248: case '6':
249: case '7':
250: case '8':
251: case '9':
252: case '.':
253: case '+':
254: arg_need++;
255: break;
256: default:
257: break;
258: }
259: }
260: }
261: arg_need = MAX(arg_need, popcount);
262: if (arg_need > 9)
263: errx(2, "too many arguments (%d) for capability `%s'",
264: arg_need, cap);
265:
266: for (i = 0; i < arg_need; i++) {
267: long l;
268:
269: if (argv[i] == NULL)
270: errx(2, "not enough arguments (%d) for capability `%s'",
271: arg_need, cap);
272:
273: /* convert ascii representation of numbers to longs */
274: if (isdigit(argv[i][0]) && (l = strtol(argv[i], &cp, 10)) >= 0
275: && l < LONG_MAX && *cp == '\0')
276: nargv[i] = (char *)l;
277: else
278: nargv[i] = argv[i];
279: }
1.1 deraadt 280:
1.8 millert 281: s = tparm(str, nargv[0], nargv[1], nargv[2], nargv[3],
282: nargv[4], nargv[5], nargv[6], nargv[7], nargv[8]);
283: putp(s);
284: fflush(stdout);
1.1 deraadt 285:
1.8 millert 286: return (argv + arg_need);
1.1 deraadt 287: }
288:
289: static void
1.8 millert 290: init()
1.1 deraadt 291: {
1.8 millert 292: FILE *ifile;
293: size_t len;
294: char *buf;
1.9 millert 295: int wstatus;
1.1 deraadt 296:
1.8 millert 297: if (init_prog && !issetugid()) {
298: switch (vfork()) {
299: case -1:
300: err(4, "vfork");
301: break;
302: case 0:
303: /* child */
1.11 deraadt 304: execl(init_prog, init_prog, (char *)NULL);
1.8 millert 305: _exit(127);
306: break;
307: default:
1.9 millert 308: wait(&wstatus);
309: /* parent */
1.8 millert 310: break;
311: }
312: }
313: if (init_1string)
314: putp(init_1string);
315: if (init_2string)
316: putp(init_2string);
1.9 millert 317: set_margins();
318: /* always use 8 space tabs */
319: if (init_tabs != 8 && clear_all_tabs && set_tab) {
320: int i;
321:
322: putp(clear_all_tabs);
323: for (i = 0; i < (columns - 1) / 8; i++) {
324: if (parm_right_cursor)
325: putp(tparm(parm_right_cursor, 8));
326: else
327: fputs(" ", stdout);
328: putp(set_tab);
329: }
330: }
1.8 millert 331: if (init_file && !issetugid() && (ifile = fopen(init_file, "r"))) {
332: while ((buf = fgetln(ifile, &len)) != NULL) {
333: if (buf[len-1] != '\n')
334: errx(1, "premature EOF reading %s", init_file);
335: buf[len-1] = '\0';
336: putp(buf);
337: }
338: fclose(ifile);
339: }
340: if (init_3string)
341: putp(init_3string);
342: fflush(stdout);
1.1 deraadt 343: }
344:
345: static void
1.8 millert 346: reset()
1.7 millert 347: {
1.8 millert 348: FILE *rfile;
349: size_t len;
350: char *buf;
351:
352: if (reset_1string)
353: putp(reset_1string);
354: if (reset_2string)
355: putp(reset_2string);
1.9 millert 356: set_margins();
1.8 millert 357: if (reset_file && !issetugid() && (rfile = fopen(reset_file, "r"))) {
358: while ((buf = fgetln(rfile, &len)) != NULL) {
359: if (buf[len-1] != '\n')
360: errx(1, "premature EOF reading %s", reset_file);
361: buf[len-1] = '\0';
362: putp(buf);
363: }
364: fclose(rfile);
365: }
366: if (reset_3string)
367: putp(reset_3string);
1.9 millert 368: fflush(stdout);
369: }
370:
371: static void
372: set_margins()
373: {
374:
375: /*
376: * Four possibilities:
377: * 1) we have set_lr_margin and can set things with one call
378: * 2) we have set_{left,right}_margin_parm, use two calls
379: * 3) we have set_{left,right}_margin, set based on position
380: * 4) none of the above, leave things the way they are
381: */
382: if (set_lr_margin) {
383: putp(tparm(set_lr_margin, 0, columns - 1));
384: } else if (set_left_margin_parm && set_right_margin_parm) {
385: putp(tparm(set_left_margin_parm, 0));
386: putp(tparm(set_right_margin_parm, columns - 1));
387: } else if (set_left_margin && set_right_margin && clear_margins) {
388: putp(clear_margins);
389:
390: /* go to column 0 and set the left margin */
391: putp(carriage_return ? carriage_return : "\r");
392: putp(set_left_margin);
393:
394: /* go to last column and set the right margin */
395: if (parm_right_cursor)
396: putp(tparm(parm_right_cursor, columns - 1));
397: else
398: printf("%*s", columns - 1, " ");
399: putp(set_right_margin);
400: putp(carriage_return ? carriage_return : "\r");
401: }
1.8 millert 402: fflush(stdout);
1.7 millert 403: }
404:
405: static void
1.1 deraadt 406: usage()
407: {
1.8 millert 408:
409: if (strcmp(__progname, "clear") == 0)
410: (void)fprintf(stderr, "usage: %s [-T term]\n", __progname);
411: else
412: (void)fprintf(stderr,
413: "usage: %s [-T term] attribute [attribute-args] ...\n"
414: " %s [-T term] -S\n", __progname, __progname);
1.1 deraadt 415: exit(1);
416: }