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

Annotation of src/usr.bin/less/main.c, Revision 1.36

1.1       etheisen    1: /*
1.13      shadchin    2:  * Copyright (C) 1984-2012  Mark Nudelman
1.19      nicm        3:  * Modified for use with illumos by Garrett D'Amore.
                      4:  * Copyright 2014 Garrett D'Amore <garrett@damore.org>
1.1       etheisen    5:  *
1.7       millert     6:  * You may distribute under the terms of either the GNU General Public
                      7:  * License or the Less License, as specified in the README file.
1.1       etheisen    8:  *
1.13      shadchin    9:  * For more information, see the README file.
1.17      nicm       10:  */
1.1       etheisen   11:
                     12: /*
                     13:  * Entry point, initialization, miscellaneous routines.
                     14:  */
                     15:
1.33      mmcc       16: #include <sys/types.h>
                     17:
1.17      nicm       18: #include <libgen.h>
                     19: #include <stdarg.h>
1.33      mmcc       20:
1.1       etheisen   21: #include "less.h"
                     22:
1.17      nicm       23: char   *every_first_cmd = NULL;
                     24: int    new_file;
                     25: int    is_tty;
1.25      deraadt    26: IFILE  curr_ifile = NULL;
                     27: IFILE  old_ifile = NULL;
1.17      nicm       28: struct scrpos initial_scrpos;
                     29: int    any_display = FALSE;
                     30: off_t  start_attnpos = -1;
                     31: off_t  end_attnpos = -1;
                     32: int    wscroll;
                     33:
1.18      deraadt    34: static char    *progname;
1.17      nicm       35:
                     36: int    quitting;
                     37: int    secure;
                     38: int    dohelp;
                     39:
                     40: int logfile = -1;
                     41: int force_logfile = FALSE;
                     42: char *namelogfile = NULL;
                     43: char *editor;
                     44: char *editproto;
1.1       etheisen   45:
1.18      deraadt    46: extern char    *tags;
                     47: extern char    *tagoption;
1.17      nicm       48: extern int     jump_sline;
1.11      shadchin   49: extern int     less_is_more;
1.7       millert    50: extern int     missing_cap;
                     51: extern int     know_dumb;
1.17      nicm       52: extern int     quit_if_one_screen;
                     53: extern int     quit_at_eof;
1.11      shadchin   54: extern int     pr_type;
1.17      nicm       55: extern int     hilite_search;
                     56: extern int     use_lessopen;
                     57: extern int     no_init;
                     58: extern int     top_scroll;
                     59: extern int     errmsgs;
1.7       millert    60:
1.1       etheisen   61:
                     62: /*
                     63:  * Entry point.
                     64:  */
                     65: int
1.17      nicm       66: main(int argc, char *argv[])
1.1       etheisen   67: {
                     68:        IFILE ifile;
1.7       millert    69:        char *s;
1.1       etheisen   70:
1.17      nicm       71:        progname = basename(argv[0]);
                     72:        argv++;
                     73:        argc--;
1.1       etheisen   74:
1.17      nicm       75:        /*
                     76:         * If the name of the executable program is "more",
                     77:         * act like LESS_IS_MORE is set.  We have to set this as early
                     78:         * as possible for POSIX.
                     79:         */
1.26      deraadt    80:        if (strcmp(progname, "more") == 0)
1.17      nicm       81:                less_is_more = 1;
1.26      deraadt    82:        else {
1.17      nicm       83:                s = lgetenv("LESS_IS_MORE");
                     84:                if (s != NULL && *s != '\0')
                     85:                        less_is_more = 1;
                     86:        }
1.7       millert    87:
                     88:        secure = 0;
                     89:        s = lgetenv("LESSSECURE");
                     90:        if (s != NULL && *s != '\0')
                     91:                secure = 1;
                     92:
1.23      deraadt    93:        if (secure) {
1.28      deraadt    94:                if (pledge("stdio rpath wpath tty", NULL) == -1) {
1.27      deraadt    95:                        perror("pledge");
1.28      deraadt    96:                        exit(1);
                     97:                }
1.23      deraadt    98:        } else {
1.28      deraadt    99:                if (pledge("stdio rpath wpath cpath fattr proc exec tty", NULL) == -1) {
1.27      deraadt   100:                        perror("pledge");
1.28      deraadt   101:                        exit(1);
                    102:                }
1.23      deraadt   103:        }
                    104:
1.1       etheisen  105:        /*
                    106:         * Process command line arguments and LESS environment arguments.
                    107:         * Command line arguments override environment arguments.
                    108:         */
1.7       millert   109:        is_tty = isatty(1);
1.1       etheisen  110:        get_term();
                    111:        init_cmds();
                    112:        init_charset();
1.7       millert   113:        init_line();
1.11      shadchin  114:        init_cmdhist();
1.1       etheisen  115:        init_option();
1.11      shadchin  116:        init_search();
                    117:
                    118:
                    119:        init_prompt();
                    120:
1.17      nicm      121:        if (less_is_more) {
                    122:                /* this is specified by XPG */
                    123:                quit_at_eof = OPT_ON;
                    124:
                    125:                /* more users don't like the warning */
                    126:                know_dumb = OPT_ON;
                    127:
                    128:                /* default prompt is medium */
                    129:                pr_type = OPT_ON;
                    130:
                    131:                /* do not hilight search terms */
                    132:                hilite_search = OPT_OFF;
                    133:
                    134:                /* do not use LESSOPEN */
                    135:                use_lessopen = OPT_OFF;
                    136:
                    137:                /* do not set init strings to terminal */
                    138:                no_init = OPT_ON;
                    139:
                    140:                /* repaint from top of screen */
                    141:                top_scroll = OPT_OFF;
                    142:        }
1.34      nicm      143:
                    144:        s = lgetenv(less_is_more ? "MORE" : "LESS");
                    145:        if (s != NULL)
1.36    ! krw       146:                scan_option(estrdup(s), 1);
1.17      nicm      147:
1.7       millert   148: #define        isoptstring(s)  (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
1.17      nicm      149:        while (argc > 0 && (isoptstring(*argv) || isoptpending())) {
1.7       millert   150:                s = *argv++;
                    151:                argc--;
                    152:                if (strcmp(s, "--") == 0)
1.3       deraadt   153:                        break;
1.36    ! krw       154:                scan_option(s, 0);
1.3       deraadt   155:        }
1.1       etheisen  156: #undef isoptstring
                    157:
1.17      nicm      158:        if (isoptpending()) {
1.1       etheisen  159:                /*
                    160:                 * Last command line option was a flag requiring a
                    161:                 * following string, but there was no following string.
                    162:                 */
                    163:                nopendopt();
                    164:                quit(QUIT_OK);
                    165:        }
1.11      shadchin  166:
1.17      nicm      167:        if (errmsgs) {
                    168:                quit(QUIT_ERROR);
                    169:        }
                    170:        if (less_is_more && quit_at_eof == OPT_ONPLUS) {
                    171:                extern int no_init;
                    172:                no_init = OPT_ON;
                    173:        }
                    174:        if (less_is_more && pr_type == OPT_ONPLUS) {
                    175:                extern int quiet;
                    176:                quiet = VERY_QUIET;
                    177:        }
                    178:
1.7       millert   179:        editor = lgetenv("VISUAL");
1.17      nicm      180:        if (editor == NULL || *editor == '\0') {
1.7       millert   181:                editor = lgetenv("EDITOR");
1.1       etheisen  182:                if (editor == NULL || *editor == '\0')
                    183:                        editor = EDIT_PGM;
                    184:        }
1.7       millert   185:        editproto = lgetenv("LESSEDIT");
1.1       etheisen  186:        if (editproto == NULL || *editproto == '\0')
                    187:                editproto = "%E ?lm+%lm. %f";
                    188:
                    189:        /*
                    190:         * Call get_ifile with all the command line filenames
                    191:         * to "register" them with the ifile system.
                    192:         */
1.25      deraadt   193:        ifile = NULL;
1.11      shadchin  194:        if (dohelp)
1.15      schwarze  195:                ifile = get_ifile(helpfile(), ifile);
1.17      nicm      196:        while (argc-- > 0) {
1.7       millert   197:                char *filename;
                    198:                filename = shell_quote(*argv);
                    199:                if (filename == NULL)
                    200:                        filename = *argv;
                    201:                argv++;
                    202:                (void) get_ifile(filename, ifile);
1.25      deraadt   203:                ifile = prev_ifile(NULL);
1.13      shadchin  204:                free(filename);
1.1       etheisen  205:        }
                    206:        /*
                    207:         * Set up terminal, etc.
                    208:         */
1.17      nicm      209:        if (!is_tty) {
1.1       etheisen  210:                /*
                    211:                 * Output is not a tty.
                    212:                 * Just copy the input file(s) to output.
                    213:                 */
1.17      nicm      214:                if (nifile() == 0) {
1.1       etheisen  215:                        if (edit_stdin() == 0)
                    216:                                cat_file();
1.17      nicm      217:                } else if (edit_first() == 0) {
1.1       etheisen  218:                        do {
                    219:                                cat_file();
                    220:                        } while (edit_next(1) == 0);
                    221:                }
                    222:                quit(QUIT_OK);
                    223:        }
                    224:
1.17      nicm      225:        if (missing_cap && !know_dumb)
1.24      deraadt   226:                error("WARNING: terminal is not fully functional", NULL);
1.1       etheisen  227:        init_mark();
1.7       millert   228:        open_getchr();
1.23      deraadt   229:
                    230:        if (secure)
1.28      deraadt   231:                if (pledge("stdio rpath tty", NULL) == -1) {
1.27      deraadt   232:                        perror("pledge");
1.28      deraadt   233:                        exit(1);
                    234:                }
1.23      deraadt   235:
1.1       etheisen  236:        raw_mode(1);
                    237:        init_signals(1);
                    238:
                    239:        /*
                    240:         * Select the first file to examine.
                    241:         */
1.17      nicm      242:        if (tagoption != NULL || strcmp(tags, "-") == 0) {
1.1       etheisen  243:                /*
                    244:                 * A -t option was given.
                    245:                 * Verify that no filenames were also given.
                    246:                 * Edit the file selected by the "tags" search,
                    247:                 * and search for the proper line in the file.
                    248:                 */
1.17      nicm      249:                if (nifile() > 0) {
1.24      deraadt   250:                        error("No filenames allowed with -t option", NULL);
1.1       etheisen  251:                        quit(QUIT_ERROR);
                    252:                }
                    253:                findtag(tagoption);
1.7       millert   254:                if (edit_tagfile())  /* Edit file which contains the tag */
1.1       etheisen  255:                        quit(QUIT_ERROR);
                    256:                /*
                    257:                 * Search for the line which contains the tag.
                    258:                 * Set up initial_scrpos so we display that line.
                    259:                 */
                    260:                initial_scrpos.pos = tagsearch();
1.17      nicm      261:                if (initial_scrpos.pos == -1)
1.1       etheisen  262:                        quit(QUIT_ERROR);
                    263:                initial_scrpos.ln = jump_sline;
1.17      nicm      264:        } else if (nifile() == 0) {
1.1       etheisen  265:                if (edit_stdin())  /* Edit standard input */
                    266:                        quit(QUIT_ERROR);
1.17      nicm      267:        } else {
1.1       etheisen  268:                if (edit_first())  /* Edit first valid file in cmd line */
                    269:                        quit(QUIT_ERROR);
                    270:        }
                    271:
                    272:        init();
                    273:        commands();
                    274:        quit(QUIT_OK);
1.7       millert   275:        return (0);
1.1       etheisen  276: }
                    277:
                    278: /*
                    279:  * Allocate memory.
                    280:  * Like calloc(), but never returns an error (NULL).
                    281:  */
1.17      nicm      282: void *
                    283: ecalloc(int count, unsigned int size)
1.1       etheisen  284: {
1.17      nicm      285:        void *p;
1.1       etheisen  286:
1.17      nicm      287:        p = calloc(count, size);
1.1       etheisen  288:        if (p != NULL)
                    289:                return (p);
1.24      deraadt   290:        error("Cannot allocate memory", NULL);
1.1       etheisen  291:        quit(QUIT_ERROR);
1.7       millert   292:        return (NULL);
1.1       etheisen  293: }
                    294:
1.17      nicm      295: char *
                    296: easprintf(const char *fmt, ...)
                    297: {
                    298:        char *p = NULL;
                    299:        int rv;
                    300:        va_list ap;
                    301:
                    302:        va_start(ap, fmt);
                    303:        rv = vasprintf(&p, fmt, ap);
                    304:        va_end(ap);
                    305:
                    306:        if (p == NULL || rv < 0) {
1.24      deraadt   307:                error("Cannot allocate memory", NULL);
1.17      nicm      308:                quit(QUIT_ERROR);
                    309:        }
                    310:        return (p);
                    311: }
                    312:
                    313: char *
                    314: estrdup(const char *str)
                    315: {
1.20      tedu      316:        char *n;
1.31      deraadt   317:
1.20      tedu      318:        n = strdup(str);
                    319:        if (n == NULL) {
1.24      deraadt   320:                error("Cannot allocate memory", NULL);
1.20      tedu      321:                quit(QUIT_ERROR);
1.17      nicm      322:        }
                    323:        return (n);
                    324: }
                    325:
1.1       etheisen  326: /*
                    327:  * Skip leading spaces in a string.
                    328:  */
1.17      nicm      329: char *
                    330: skipsp(char *s)
1.1       etheisen  331: {
1.17      nicm      332:        while (*s == ' ' || *s == '\t')
1.1       etheisen  333:                s++;
                    334:        return (s);
                    335: }
                    336:
                    337: /*
1.7       millert   338:  * See how many characters of two strings are identical.
                    339:  * If uppercase is true, the first string must begin with an uppercase
                    340:  * character; the remainder of the first string may be either case.
                    341:  */
1.17      nicm      342: int
                    343: sprefix(char *ps, char *s, int uppercase)
1.7       millert   344: {
1.17      nicm      345:        int c;
                    346:        int sc;
                    347:        int len = 0;
1.7       millert   348:
1.35      deraadt   349:        for (; *s != '\0'; s++, ps++) {
1.7       millert   350:                c = *ps;
1.17      nicm      351:                if (uppercase) {
1.30      guenther  352:                        if (len == 0 && islower(c))
1.7       millert   353:                                return (-1);
1.30      guenther  354:                        c = tolower(c);
1.7       millert   355:                }
                    356:                sc = *s;
1.30      guenther  357:                if (len > 0)
1.17      nicm      358:                        sc = tolower(sc);
1.7       millert   359:                if (c != sc)
                    360:                        break;
                    361:                len++;
                    362:        }
                    363:        return (len);
                    364: }
                    365:
                    366: /*
1.1       etheisen  367:  * Exit the program.
                    368:  */
1.17      nicm      369: void
                    370: quit(int status)
1.1       etheisen  371: {
                    372:        static int save_status;
                    373:
                    374:        /*
                    375:         * Put cursor at bottom left corner, clear the line,
                    376:         * reset the terminal modes, and exit.
                    377:         */
                    378:        if (status < 0)
                    379:                status = save_status;
                    380:        else
                    381:                save_status = status;
                    382:        quitting = 1;
1.17      nicm      383:        edit(NULL);
1.22      deraadt   384:        if (!secure)
                    385:                save_cmdhist();
1.7       millert   386:        if (any_display && is_tty)
1.1       etheisen  387:                clear_bot();
                    388:        deinit();
1.29      nicm      389:        flush(1);
1.1       etheisen  390:        raw_mode(0);
                    391:        exit(status);
1.15      schwarze  392: }
                    393:
1.17      nicm      394: char *
1.15      schwarze  395: helpfile(void)
                    396: {
                    397:        return (less_is_more ? HELPDIR "/more.help" : HELPDIR "/less.help");
1.1       etheisen  398: }