diff options
Diffstat (limited to 'usr.bin/more/main.c')
-rw-r--r-- | usr.bin/more/main.c | 367 |
1 files changed, 367 insertions, 0 deletions
diff --git a/usr.bin/more/main.c b/usr.bin/more/main.c new file mode 100644 index 0000000..f019bdc --- /dev/null +++ b/usr.bin/more/main.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 1988 Mark Nudleman + * Copyright (c) 1988, 1993 + * Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1988 Mark Nudleman.\n\ +@(#) Copyright (c) 1988, 1993 + Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/7/93"; +#endif /* not lint */ + +/* + * Entry point, initialization, miscellaneous routines. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <stdio.h> +#include <less.h> + +int ispipe; +int new_file; +int is_tty; +char *current_file, *previous_file, *current_name, *next_name; +off_t prev_pos; +int any_display; +int scroll; +int ac; +char **av; +int curr_ac; +int quitting; + +extern int file; +extern int cbufs; +extern int errmsgs; + +extern char *tagfile; +extern int tagoption; + +/* + * Edit a new file. + * Filename "-" means standard input. + * No filename means the "current" file, from the command line. + */ +edit(filename) + register char *filename; +{ + extern int errno; + register int f; + register char *m; + off_t initial_pos, position(); + static int didpipe; + char message[100], *p; + char *rindex(), *strerror(), *save(), *bad_file(); + + initial_pos = NULL_POSITION; + if (filename == NULL || *filename == '\0') { + if (curr_ac >= ac) { + error("No current file"); + return(0); + } + filename = save(av[curr_ac]); + } + else if (strcmp(filename, "#") == 0) { + if (*previous_file == '\0') { + error("no previous file"); + return(0); + } + filename = save(previous_file); + initial_pos = prev_pos; + } else + filename = save(filename); + + /* use standard input. */ + if (!strcmp(filename, "-")) { + if (didpipe) { + error("Can view standard input only once"); + return(0); + } + f = 0; + } + else if ((m = bad_file(filename, message, sizeof(message))) != NULL) { + error(m); + free(filename); + return(0); + } + else if ((f = open(filename, O_RDONLY, 0)) < 0) { + (void)sprintf(message, "%s: %s", filename, strerror(errno)); + error(message); + free(filename); + return(0); + } + + if (isatty(f)) { + /* + * Not really necessary to call this an error, + * but if the control terminal (for commands) + * and the input file (for data) are the same, + * we get weird results at best. + */ + error("Can't take input from a terminal"); + if (f > 0) + (void)close(f); + (void)free(filename); + return(0); + } + + /* + * We are now committed to using the new file. + * Close the current input file and set up to use the new one. + */ + if (file > 0) + (void)close(file); + new_file = 1; + if (previous_file != NULL) + free(previous_file); + previous_file = current_file; + current_file = filename; + pos_clear(); + prev_pos = position(TOP); + ispipe = (f == 0); + if (ispipe) { + didpipe = 1; + current_name = "stdin"; + } else + current_name = (p = rindex(filename, '/')) ? p + 1 : filename; + if (curr_ac >= ac) + next_name = NULL; + else + next_name = av[curr_ac + 1]; + file = f; + ch_init(cbufs, 0); + init_mark(); + + if (is_tty) { + int no_display = !any_display; + any_display = 1; + if (no_display && errmsgs > 0) { + /* + * We displayed some messages on error output + * (file descriptor 2; see error() function). + * Before erasing the screen contents, + * display the file name and wait for a keystroke. + */ + error(filename); + } + /* + * Indicate there is nothing displayed yet. + */ + if (initial_pos != NULL_POSITION) + jump_loc(initial_pos); + clr_linenum(); + } + return(1); +} + +/* + * Edit the next file in the command line list. + */ +next_file(n) + int n; +{ + extern int quit_at_eof; + off_t position(); + + if (curr_ac + n >= ac) { + if (quit_at_eof || position(TOP) == NULL_POSITION) + quit(); + error("No (N-th) next file"); + } + else + (void)edit(av[curr_ac += n]); +} + +/* + * Edit the previous file in the command line list. + */ +prev_file(n) + int n; +{ + if (curr_ac - n < 0) + error("No (N-th) previous file"); + else + (void)edit(av[curr_ac -= n]); +} + +/* + * copy a file directly to standard output; used if stdout is not a tty. + * the only processing is to squeeze multiple blank input lines. + */ +static +cat_file() +{ + extern int squeeze; + register int c, empty; + + if (squeeze) { + empty = 0; + while ((c = ch_forw_get()) != EOI) + if (c != '\n') { + putchr(c); + empty = 0; + } + else if (empty < 2) { + putchr(c); + ++empty; + } + } + else while ((c = ch_forw_get()) != EOI) + putchr(c); + flush(); +} + +main(argc, argv) + int argc; + char **argv; +{ + int envargc, argcnt; + char *envargv[2], *getenv(); + + /* + * Process command line arguments and MORE environment arguments. + * Command line arguments override environment arguments. + */ + if (envargv[1] = getenv("MORE")) { + envargc = 2; + envargv[0] = "more"; + envargv[2] = NULL; + (void)option(envargc, envargv); + } + argcnt = option(argc, argv); + argv += argcnt; + argc -= argcnt; + + /* + * Set up list of files to be examined. + */ + ac = argc; + av = argv; + curr_ac = 0; + + /* + * Set up terminal, etc. + */ + is_tty = isatty(1); + if (!is_tty) { + /* + * Output is not a tty. + * Just copy the input file(s) to output. + */ + if (ac < 1) { + (void)edit("-"); + cat_file(); + } else { + do { + (void)edit((char *)NULL); + if (file >= 0) + cat_file(); + } while (++curr_ac < ac); + } + exit(0); + } + + raw_mode(1); + get_term(); + open_getchr(); + init(); + init_signals(1); + + /* select the first file to examine. */ + if (tagoption) { + /* + * A -t option was given; edit the file selected by the + * "tags" search, and search for the proper line in the file. + */ + if (!tagfile || !edit(tagfile) || tagsearch()) + quit(); + } + else if (ac < 1) + (void)edit("-"); /* Standard input */ + else { + /* + * Try all the files named as command arguments. + * We are simply looking for one which can be + * opened without error. + */ + do { + (void)edit((char *)NULL); + } while (file < 0 && ++curr_ac < ac); + } + + if (file >= 0) + commands(); + quit(); + /*NOTREACHED*/ +} + +/* + * Copy a string to a "safe" place + * (that is, to a buffer allocated by malloc). + */ +char * +save(s) + char *s; +{ + char *p, *strcpy(), *malloc(); + + p = malloc((u_int)strlen(s)+1); + if (p == NULL) + { + error("cannot allocate memory"); + quit(); + } + return(strcpy(p, s)); +} + +/* + * Exit the program. + */ +quit() +{ + /* + * Put cursor at bottom left corner, clear the line, + * reset the terminal modes, and exit. + */ + quitting = 1; + lower_left(); + clear_eol(); + deinit(); + flush(); + raw_mode(0); + exit(0); +} |