summaryrefslogtreecommitdiffstats
path: root/usr.bin/more/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/more/main.c')
-rw-r--r--usr.bin/more/main.c367
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);
+}
OpenPOWER on IntegriCloud