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