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

Annotation of src/usr.bin/more/main.c, Revision 1.1.1.1

1.1       deraadt     1: /*
                      2:  * Copyright (c) 1988 Mark Nudleman
                      3:  * Copyright (c) 1988 Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  * 3. All advertising materials mentioning features or use of this software
                     15:  *    must display the following acknowledgement:
                     16:  *     This product includes software developed by the University of
                     17:  *     California, Berkeley and its contributors.
                     18:  * 4. Neither the name of the University nor the names of its contributors
                     19:  *    may be used to endorse or promote products derived from this software
                     20:  *    without specific prior written permission.
                     21:  *
                     22:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     23:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     24:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     25:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     26:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     28:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     29:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     30:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     31:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     32:  * SUCH DAMAGE.
                     33:  */
                     34:
                     35: #ifndef lint
                     36: char copyright[] =
                     37: "@(#) Copyright (c) 1988 Mark Nudleman.\n\
                     38: @(#) Copyright (c) 1988 Regents of the University of California.\n\
                     39:  All rights reserved.\n";
                     40: #endif /* not lint */
                     41:
                     42: #ifndef lint
                     43: /* from: static char sccsid[] = "@(#)main.c    5.13 (Berkeley) 6/1/90"; */
                     44: static char *rcsid = "$Id: main.c,v 1.3 1994/12/24 17:17:09 cgd Exp $";
                     45: #endif /* not lint */
                     46:
                     47: /*
                     48:  * Entry point, initialization, miscellaneous routines.
                     49:  */
                     50:
                     51: #include <sys/types.h>
                     52: #include <sys/file.h>
                     53: #include <stdio.h>
                     54: #include <string.h>
                     55: #include <less.h>
                     56:
                     57: int    ispipe;
                     58: int    new_file;
                     59: int    is_tty;
                     60: char   *current_file, *previous_file, *current_name, *next_name;
                     61: off_t  prev_pos;
                     62: int    any_display;
                     63: int    scroll;
                     64: int    ac;
                     65: char   **av;
                     66: int    curr_ac;
                     67: int    quitting;
                     68:
                     69: extern int     file;
                     70: extern int     cbufs;
                     71: extern int     errmsgs;
                     72:
                     73: extern char    *tagfile;
                     74: extern int     tagoption;
                     75:
                     76: /*
                     77:  * Edit a new file.
                     78:  * Filename "-" means standard input.
                     79:  * No filename means the "current" file, from the command line.
                     80:  */
                     81: edit(filename)
                     82:        register char *filename;
                     83: {
                     84:        extern int errno;
                     85:        register int f;
                     86:        register char *m;
                     87:        off_t initial_pos, position();
                     88:        static int didpipe;
                     89:        char message[100], *p;
                     90:        char *rindex(), *strerror(), *save(), *bad_file();
                     91:
                     92:        initial_pos = NULL_POSITION;
                     93:        if (filename == NULL || *filename == '\0') {
                     94:                if (curr_ac >= ac) {
                     95:                        error("No current file");
                     96:                        return(0);
                     97:                }
                     98:                filename = save(av[curr_ac]);
                     99:        }
                    100:        else if (strcmp(filename, "#") == 0) {
                    101:                if (*previous_file == '\0') {
                    102:                        error("no previous file");
                    103:                        return(0);
                    104:                }
                    105:                filename = save(previous_file);
                    106:                initial_pos = prev_pos;
                    107:        } else
                    108:                filename = save(filename);
                    109:
                    110:        /* use standard input. */
                    111:        if (!strcmp(filename, "-")) {
                    112:                if (didpipe) {
                    113:                        error("Can view standard input only once");
                    114:                        return(0);
                    115:                }
                    116:                f = 0;
                    117:        }
                    118:        else if ((m = bad_file(filename, message, sizeof(message))) != NULL) {
                    119:                error(m);
                    120:                free(filename);
                    121:                return(0);
                    122:        }
                    123:        else if ((f = open(filename, O_RDONLY, 0)) < 0) {
                    124:                (void)sprintf(message, "%s: %s", filename, strerror(errno));
                    125:                error(message);
                    126:                free(filename);
                    127:                return(0);
                    128:        }
                    129:
                    130:        if (isatty(f)) {
                    131:                /*
                    132:                 * Not really necessary to call this an error,
                    133:                 * but if the control terminal (for commands)
                    134:                 * and the input file (for data) are the same,
                    135:                 * we get weird results at best.
                    136:                 */
                    137:                error("Can't take input from a terminal");
                    138:                if (f > 0)
                    139:                        (void)close(f);
                    140:                (void)free(filename);
                    141:                return(0);
                    142:        }
                    143:
                    144:        /*
                    145:         * We are now committed to using the new file.
                    146:         * Close the current input file and set up to use the new one.
                    147:         */
                    148:        if (file > 0)
                    149:                (void)close(file);
                    150:        new_file = 1;
                    151:        if (previous_file != NULL)
                    152:                free(previous_file);
                    153:        previous_file = current_file;
                    154:        current_file = filename;
                    155:        pos_clear();
                    156:        prev_pos = position(TOP);
                    157:        ispipe = (f == 0);
                    158:        if (ispipe) {
                    159:                didpipe = 1;
                    160:                current_name = "stdin";
                    161:        } else
                    162:                current_name = (p = rindex(filename, '/')) ? p + 1 : filename;
                    163:        if (curr_ac >= ac)
                    164:                next_name = NULL;
                    165:        else
                    166:                next_name = av[curr_ac + 1];
                    167:        file = f;
                    168:        ch_init(cbufs, 0);
                    169:        init_mark();
                    170:
                    171:        if (is_tty) {
                    172:                int no_display = !any_display;
                    173:                any_display = 1;
                    174:                if (no_display && errmsgs > 0) {
                    175:                        /*
                    176:                         * We displayed some messages on error output
                    177:                         * (file descriptor 2; see error() function).
                    178:                         * Before erasing the screen contents,
                    179:                         * display the file name and wait for a keystroke.
                    180:                         */
                    181:                        error(filename);
                    182:                }
                    183:                /*
                    184:                 * Indicate there is nothing displayed yet.
                    185:                 */
                    186:                if (initial_pos != NULL_POSITION)
                    187:                        jump_loc(initial_pos);
                    188:                clr_linenum();
                    189:        }
                    190:        return(1);
                    191: }
                    192:
                    193: /*
                    194:  * Edit the next file in the command line list.
                    195:  */
                    196: next_file(n)
                    197:        int n;
                    198: {
                    199:        extern int quit_at_eof;
                    200:        off_t position();
                    201:
                    202:        if (curr_ac + n >= ac) {
                    203:                if (quit_at_eof || position(TOP) == NULL_POSITION)
                    204:                        quit();
                    205:                error("No (N-th) next file");
                    206:        }
                    207:        else
                    208:                (void)edit(av[curr_ac += n]);
                    209: }
                    210:
                    211: /*
                    212:  * Edit the previous file in the command line list.
                    213:  */
                    214: prev_file(n)
                    215:        int n;
                    216: {
                    217:        if (curr_ac - n < 0)
                    218:                error("No (N-th) previous file");
                    219:        else
                    220:                (void)edit(av[curr_ac -= n]);
                    221: }
                    222:
                    223: /*
                    224:  * copy a file directly to standard output; used if stdout is not a tty.
                    225:  * the only processing is to squeeze multiple blank input lines.
                    226:  */
                    227: static
                    228: cat_file()
                    229: {
                    230:        extern int squeeze;
                    231:        register int c, empty;
                    232:
                    233:        if (squeeze) {
                    234:                empty = 0;
                    235:                while ((c = ch_forw_get()) != EOI)
                    236:                        if (c != '\n') {
                    237:                                putchr(c);
                    238:                                empty = 0;
                    239:                        }
                    240:                        else if (empty < 2) {
                    241:                                putchr(c);
                    242:                                ++empty;
                    243:                        }
                    244:        }
                    245:        else while ((c = ch_forw_get()) != EOI)
                    246:                putchr(c);
                    247:        flush();
                    248: }
                    249:
                    250: main(argc, argv)
                    251:        int argc;
                    252:        char **argv;
                    253: {
                    254:        int envargc, argcnt;
                    255:        char *envargv[2], *getenv();
                    256:
                    257:        /*
                    258:         * Process command line arguments and MORE environment arguments.
                    259:         * Command line arguments override environment arguments.
                    260:         */
                    261:        if (envargv[1] = getenv("MORE")) {
                    262:                envargc = 2;
                    263:                envargv[0] = "more";
                    264:                envargv[2] = NULL;
                    265:                (void)option(envargc, envargv);
                    266:        }
                    267:        argcnt = option(argc, argv);
                    268:        argv += argcnt;
                    269:        argc -= argcnt;
                    270:
                    271:        /*
                    272:         * Set up list of files to be examined.
                    273:         */
                    274:        ac = argc;
                    275:        av = argv;
                    276:        curr_ac = 0;
                    277:
                    278:        /*
                    279:         * Set up terminal, etc.
                    280:         */
                    281:        is_tty = isatty(1);
                    282:        if (!is_tty) {
                    283:                /*
                    284:                 * Output is not a tty.
                    285:                 * Just copy the input file(s) to output.
                    286:                 */
                    287:                if (ac < 1) {
                    288:                        (void)edit("-");
                    289:                        cat_file();
                    290:                } else {
                    291:                        do {
                    292:                                (void)edit((char *)NULL);
                    293:                                if (file >= 0)
                    294:                                        cat_file();
                    295:                        } while (++curr_ac < ac);
                    296:                }
                    297:                exit(0);
                    298:        }
                    299:
                    300:        raw_mode(1);
                    301:        get_term();
                    302:        open_getchr();
                    303:        init();
                    304:        init_signals(1);
                    305:
                    306:        /* select the first file to examine. */
                    307:        if (tagoption) {
                    308:                /*
                    309:                 * A -t option was given; edit the file selected by the
                    310:                 * "tags" search, and search for the proper line in the file.
                    311:                 */
                    312:                if (!tagfile || !edit(tagfile) || tagsearch())
                    313:                        quit();
                    314:        }
                    315:        else if (ac < 1)
                    316:                (void)edit("-");        /* Standard input */
                    317:        else {
                    318:                /*
                    319:                 * Try all the files named as command arguments.
                    320:                 * We are simply looking for one which can be
                    321:                 * opened without error.
                    322:                 */
                    323:                do {
                    324:                        (void)edit((char *)NULL);
                    325:                } while (file < 0 && ++curr_ac < ac);
                    326:        }
                    327:
                    328:        if (file >= 0)
                    329:                commands();
                    330:        quit();
                    331:        /*NOTREACHED*/
                    332: }
                    333:
                    334: /*
                    335:  * Copy a string to a "safe" place
                    336:  * (that is, to a buffer allocated by malloc).
                    337:  */
                    338: char *
                    339: save(s)
                    340:        char *s;
                    341: {
                    342:        char *p, *strcpy(), *malloc();
                    343:
                    344:        p = malloc((u_int)strlen(s)+1);
                    345:        if (p == NULL)
                    346:        {
                    347:                error("cannot allocate memory");
                    348:                quit();
                    349:        }
                    350:        return(strcpy(p, s));
                    351: }
                    352:
                    353: /*
                    354:  * Exit the program.
                    355:  */
                    356: quit()
                    357: {
                    358:        /*
                    359:         * Put cursor at bottom left corner, clear the line,
                    360:         * reset the terminal modes, and exit.
                    361:         */
                    362:        quitting = 1;
                    363:        lower_left();
                    364:        clear_eol();
                    365:        deinit();
                    366:        flush();
                    367:        raw_mode(0);
                    368:        exit(0);
                    369: }