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

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