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

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