[BACK]Return to tput.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tput

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: }