[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.26

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