Annotation of src/usr.bin/tput/tput.c, Revision 1.8
1.6 millert 1: /* $OpenBSD: tput.c,v 1.5 1997/06/24 02:40:15 dgregor 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.6 millert 72: static char rcsid[] = "$OpenBSD: tput.c,v 1.5 1997/06/24 02:40:15 dgregor 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.1 deraadt 92: static void usage __P((void));
1.8 ! millert 93:
! 94: extern char *__progname;
1.1 deraadt 95:
96: int
97: main(argc, argv)
98: int argc;
99: char **argv;
100: {
1.8 ! millert 101: int ch, exitval, n, Sflag;
! 102: size_t len;
! 103: char *p, *term, *str;
! 104: char **oargv;
1.1 deraadt 105:
1.8 ! millert 106: oargv = argv;
1.1 deraadt 107: term = NULL;
1.8 ! millert 108: Sflag = exitval = 0;
! 109: while ((ch = getopt(argc, argv, "ST:")) != -1)
1.1 deraadt 110: switch(ch) {
111: case 'T':
112: term = optarg;
113: break;
1.8 ! millert 114: case 'S':
! 115: Sflag = 1;
! 116: break;
1.1 deraadt 117: case '?':
118: default:
119: usage();
120: }
121: argc -= optind;
122: argv += optind;
123:
1.8 ! millert 124: if (Sflag && argc > 0)
! 125: usage();
1.4 gene 126:
1.1 deraadt 127: if (!term && !(term = getenv("TERM")))
1.8 ! millert 128: errx(2, "No value for $TERM and no -T specified");
! 129:
! 130: /*
! 131: * NOTE: tgetent() will call setupterm() and set ospeed for us
! 132: * (this is ncurses-specific behavior)
! 133: */
! 134: if (tgetent(NULL, term) != 1)
! 135: errx(3, "Unknown terminal type `%s'", term);
! 136:
! 137: if (strcmp(__progname, "clear") == 0) {
! 138: if (Sflag)
! 139: usage();
! 140: argv = oargv;
! 141: *argv = __progname;
1.4 gene 142: *(argv+1) = NULL;
143: }
1.8 ! millert 144: if (Sflag) {
! 145: char **av;
! 146:
! 147: /* Build new argv based on stdin */
! 148: argc = n = 0;
! 149: av = NULL;
! 150: while ((str = fgetln(stdin, &len)) != NULL) {
! 151: if (str[len-1] != '\n')
! 152: errx(1, "premature EOF");
! 153: str[len-1] = '\0';
! 154: /* grow av as needed */
! 155: if (argc + 1 >= n) {
! 156: n += 64;
! 157: av = (char **)realloc(av, sizeof(char *) * n);
! 158: if (av == NULL)
! 159: errx(1, "out of memory");
! 160: }
! 161: while ((p = strsep(&str, " \t")) != NULL) {
! 162: if (*p != '\0' &&
! 163: (av[argc++] = strdup(p)) == NULL)
! 164: errx(1, "out of memory");
! 165: }
! 166: }
! 167: if (argc > 0) {
! 168: av[argc] = NULL;
! 169: argv = av;
! 170: }
! 171: }
! 172: while ((p = *argv++)) {
1.1 deraadt 173: switch (*p) {
174: case 'i':
1.8 ! millert 175: if (!strcmp(p, "init")) {
! 176: init();
! 177: continue;
! 178: }
1.1 deraadt 179: break;
180: case 'l':
181: if (!strcmp(p, "longname")) {
1.8 ! millert 182: puts(longname());
1.1 deraadt 183: continue;
184: }
185: break;
186: case 'r':
1.8 ! millert 187: if (!strcmp(p, "reset")) {
! 188: reset();
! 189: continue;
! 190: }
1.1 deraadt 191: break;
192: }
1.8 ! millert 193:
! 194: /* First try as terminfo */
! 195: if ((str = tigetstr(p)) && str != (char *)-1)
! 196: argv = process(p, str, argv);
! 197: else if ((n = tigetnum(p)) != -2)
! 198: (void)printf("%d\n", n);
! 199: else if ((n = tigetflag(p)) != -1)
! 200: exitval = !n;
! 201: /* Then fall back on termcap */
! 202: else if ((str = tgetstr(p, NULL)))
! 203: argv = process(p, str, argv);
1.7 millert 204: else if ((n = tgetnum(p)) != -1)
1.1 deraadt 205: (void)printf("%d\n", n);
1.8 ! millert 206: else if ((exitval = tgetflag(p)) != 0)
! 207: exitval = !exitval;
! 208: else {
! 209: warnx("Unknown terminfo capability `%s'", p);
! 210: exitval = 4;
! 211: }
1.1 deraadt 212:
1.8 ! millert 213: if (*argv == NULL)
1.1 deraadt 214: break;
215: }
1.8 ! millert 216: exit(*argv ? exitval : 2);
1.1 deraadt 217: }
218:
219: static char **
220: process(cap, str, argv)
221: char *cap, *str, **argv;
222: {
1.8 ! millert 223: char *cp, *s, *nargv[9];
! 224: int arg_need, popcount, i;
1.1 deraadt 225:
226: /* Count how many values we need for this capability. */
1.8 ! millert 227: for (cp = str, arg_need = popcount = 0; *cp != '\0'; cp++) {
! 228: if (*cp == '%') {
! 229: switch (*++cp) {
! 230: case '%':
! 231: cp++;
! 232: break;
! 233: case 'i':
! 234: if (popcount < 2)
! 235: popcount = 2;
! 236: break;
! 237: case 'p':
! 238: cp++;
! 239: if (isdigit(cp[1]) && popcount < cp[1] - '0')
! 240: popcount = cp[1] - '0';
! 241: break;
! 242: case 'd':
! 243: case 's':
! 244: case '0':
! 245: case '1':
! 246: case '2':
! 247: case '3':
! 248: case '4':
! 249: case '5':
! 250: case '6':
! 251: case '7':
! 252: case '8':
! 253: case '9':
! 254: case '.':
! 255: case '+':
! 256: arg_need++;
! 257: break;
! 258: default:
! 259: break;
! 260: }
! 261: }
! 262: }
! 263: arg_need = MAX(arg_need, popcount);
! 264: if (arg_need > 9)
! 265: errx(2, "too many arguments (%d) for capability `%s'",
! 266: arg_need, cap);
! 267:
! 268: for (i = 0; i < arg_need; i++) {
! 269: long l;
! 270:
! 271: if (argv[i] == NULL)
! 272: errx(2, "not enough arguments (%d) for capability `%s'",
! 273: arg_need, cap);
! 274:
! 275: /* convert ascii representation of numbers to longs */
! 276: if (isdigit(argv[i][0]) && (l = strtol(argv[i], &cp, 10)) >= 0
! 277: && l < LONG_MAX && *cp == '\0')
! 278: nargv[i] = (char *)l;
! 279: else
! 280: nargv[i] = argv[i];
! 281: }
1.1 deraadt 282:
1.8 ! millert 283: s = tparm(str, nargv[0], nargv[1], nargv[2], nargv[3],
! 284: nargv[4], nargv[5], nargv[6], nargv[7], nargv[8]);
! 285: putp(s);
! 286: fflush(stdout);
1.1 deraadt 287:
1.8 ! millert 288: return (argv + arg_need);
1.1 deraadt 289: }
290:
291: static void
1.8 ! millert 292: init()
1.1 deraadt 293: {
1.8 ! millert 294: FILE *ifile;
! 295: size_t len;
! 296: char *buf;
! 297: int waitinfo;
1.1 deraadt 298:
1.8 ! millert 299: /* XXX - should we check for existence before exec()'ing? */
! 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:
! 311: wait(&waitinfo);
! 312: /* XXX - interpret waitinfo? */
! 313: break;
! 314: }
! 315: }
! 316: if (init_1string)
! 317: putp(init_1string);
! 318: if (init_2string)
! 319: putp(init_2string);
! 320: if (init_file && !issetugid() && (ifile = fopen(init_file, "r"))) {
! 321: while ((buf = fgetln(ifile, &len)) != NULL) {
! 322: if (buf[len-1] != '\n')
! 323: errx(1, "premature EOF reading %s", init_file);
! 324: buf[len-1] = '\0';
! 325: putp(buf);
! 326: }
! 327: fclose(ifile);
! 328: }
! 329: if (init_3string)
! 330: putp(init_3string);
! 331: /* XXX - do tabs and margins */
! 332: fflush(stdout);
1.1 deraadt 333: }
334:
335: static void
1.8 ! millert 336: reset()
1.7 millert 337: {
1.8 ! millert 338: FILE *rfile;
! 339: size_t len;
! 340: char *buf;
! 341:
! 342: if (reset_1string)
! 343: putp(reset_1string);
! 344: if (reset_2string)
! 345: putp(reset_2string);
! 346: /* XXX - cat reset_file */
! 347: if (reset_file && !issetugid() && (rfile = fopen(reset_file, "r"))) {
! 348: while ((buf = fgetln(rfile, &len)) != NULL) {
! 349: if (buf[len-1] != '\n')
! 350: errx(1, "premature EOF reading %s", reset_file);
! 351: buf[len-1] = '\0';
! 352: putp(buf);
! 353: }
! 354: fclose(rfile);
! 355: }
! 356: if (reset_3string)
! 357: putp(reset_3string);
! 358: /* XXX - do tabs and margins */
! 359: fflush(stdout);
1.7 millert 360: }
361:
362: static void
1.1 deraadt 363: usage()
364: {
1.8 ! millert 365:
! 366: if (strcmp(__progname, "clear") == 0)
! 367: (void)fprintf(stderr, "usage: %s [-T term]\n", __progname);
! 368: else
! 369: (void)fprintf(stderr,
! 370: "usage: %s [-T term] attribute [attribute-args] ...\n"
! 371: " %s [-T term] -S\n", __progname, __progname);
1.1 deraadt 372: exit(1);
373: }