Annotation of src/usr.bin/less/main.c, Revision 1.1
1.1 ! etheisen 1: /*
! 2: * Copyright (c) 1984,1985,1989,1994,1995 Mark Nudelman
! 3: * All rights reserved.
! 4: *
! 5: * Redistribution and use in source and binary forms, with or without
! 6: * modification, are permitted provided that the following conditions
! 7: * are met:
! 8: * 1. Redistributions of source code must retain the above copyright
! 9: * notice, this list of conditions and the following disclaimer.
! 10: * 2. Redistributions in binary form must reproduce the above copyright
! 11: * notice in the documentation and/or other materials provided with
! 12: * the distribution.
! 13: *
! 14: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
! 15: * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 16: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 17: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
! 18: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
! 20: * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
! 21: * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
! 22: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
! 23: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
! 24: * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 25: */
! 26:
! 27:
! 28: /*
! 29: * Entry point, initialization, miscellaneous routines.
! 30: */
! 31:
! 32: #include "less.h"
! 33: #include "position.h"
! 34:
! 35: public char * every_first_cmd = NULL;
! 36: public int new_file;
! 37: public int is_tty;
! 38: public IFILE curr_ifile = NULL_IFILE;
! 39: public IFILE old_ifile = NULL_IFILE;
! 40: public struct scrpos initial_scrpos;
! 41: public int any_display = FALSE;
! 42: public int wscroll;
! 43: public char * progname;
! 44: public int quitting;
! 45:
! 46: extern int quit_at_eof;
! 47: extern int cbufs;
! 48: extern int errmsgs;
! 49: extern int screen_trashed;
! 50: extern int force_open;
! 51:
! 52: #if LOGFILE
! 53: public int logfile = -1;
! 54: public int force_logfile = FALSE;
! 55: public char * namelogfile = NULL;
! 56: #endif
! 57:
! 58: #if EDITOR
! 59: public char * editor;
! 60: public char * editproto;
! 61: #endif
! 62:
! 63: #if TAGS
! 64: extern char * tagfile;
! 65: extern char * tagoption;
! 66: extern int jump_sline;
! 67: #endif
! 68:
! 69:
! 70:
! 71: /*
! 72: * Entry point.
! 73: */
! 74: int
! 75: main(argc, argv)
! 76: int argc;
! 77: char *argv[];
! 78: {
! 79: IFILE ifile;
! 80:
! 81: #ifdef __EMX__
! 82: _response(&argc, &argv);
! 83: _wildcard(&argc, &argv);
! 84: #endif
! 85:
! 86: progname = *argv++;
! 87:
! 88: /*
! 89: * Process command line arguments and LESS environment arguments.
! 90: * Command line arguments override environment arguments.
! 91: */
! 92: get_term();
! 93: init_cmds();
! 94: init_prompt();
! 95: init_charset();
! 96: init_option();
! 97: scan_option(getenv("LESS"));
! 98:
! 99: #if GNU_OPTIONS
! 100: /*
! 101: * Special case for "less --help" and "less --version".
! 102: */
! 103: if (argc == 2)
! 104: {
! 105: if (strcmp(argv[0], "--help") == 0)
! 106: scan_option("-?");
! 107: if (strcmp(argv[0], "--version") == 0)
! 108: scan_option("-V");
! 109: }
! 110: #endif
! 111: #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
! 112: while (--argc > 0 && (isoptstring(argv[0]) || isoptpending()))
! 113: scan_option(*argv++);
! 114: #undef isoptstring
! 115:
! 116: if (isoptpending())
! 117: {
! 118: /*
! 119: * Last command line option was a flag requiring a
! 120: * following string, but there was no following string.
! 121: */
! 122: nopendopt();
! 123: quit(QUIT_OK);
! 124: }
! 125:
! 126: #if EDITOR
! 127: editor = getenv("VISUAL");
! 128: if (editor == NULL || *editor == '\0')
! 129: {
! 130: editor = getenv("EDITOR");
! 131: if (editor == NULL || *editor == '\0')
! 132: editor = EDIT_PGM;
! 133: }
! 134: editproto = getenv("LESSEDIT");
! 135: if (editproto == NULL || *editproto == '\0')
! 136: editproto = "%E ?lm+%lm. %f";
! 137: #endif
! 138:
! 139: /*
! 140: * Call get_ifile with all the command line filenames
! 141: * to "register" them with the ifile system.
! 142: */
! 143: ifile = NULL_IFILE;
! 144: while (--argc >= 0)
! 145: {
! 146: #if MSOFTC || OS2
! 147: /*
! 148: * Because the "shell" doesn't expand filename patterns,
! 149: * treat each argument as a filename pattern rather than
! 150: * a single filename.
! 151: * Expand the pattern and iterate over the expanded list.
! 152: */
! 153: struct textlist tlist;
! 154: char *gfilename;
! 155: char *filename;
! 156:
! 157: gfilename = glob(*argv++);
! 158: init_textlist(&tlist, gfilename);
! 159: filename = NULL;
! 160: while ((filename = forw_textlist(&tlist, filename)) != NULL)
! 161: ifile = get_ifile(filename, ifile);
! 162: free(gfilename);
! 163: #else
! 164: ifile = get_ifile(*argv++, ifile);
! 165: #endif
! 166: }
! 167: /*
! 168: * Set up terminal, etc.
! 169: */
! 170: is_tty = isatty(1);
! 171: if (!is_tty)
! 172: {
! 173: /*
! 174: * Output is not a tty.
! 175: * Just copy the input file(s) to output.
! 176: */
! 177: if (nifile() == 0)
! 178: {
! 179: if (edit_stdin() == 0)
! 180: cat_file();
! 181: } else if (edit_first() == 0)
! 182: {
! 183: do {
! 184: cat_file();
! 185: } while (edit_next(1) == 0);
! 186: }
! 187: quit(QUIT_OK);
! 188: }
! 189:
! 190: init_mark();
! 191: raw_mode(1);
! 192: open_getchr();
! 193: init_signals(1);
! 194:
! 195: /*
! 196: * Select the first file to examine.
! 197: */
! 198: #if TAGS
! 199: if (tagoption != NULL)
! 200: {
! 201: /*
! 202: * A -t option was given.
! 203: * Verify that no filenames were also given.
! 204: * Edit the file selected by the "tags" search,
! 205: * and search for the proper line in the file.
! 206: */
! 207: if (nifile() > 0)
! 208: {
! 209: error("No filenames allowed with -t option", NULL_PARG);
! 210: quit(QUIT_ERROR);
! 211: }
! 212: findtag(tagoption);
! 213: if (tagfile == NULL)
! 214: quit(QUIT_ERROR);
! 215: if (edit(tagfile)) /* Edit file which contains the tag */
! 216: quit(QUIT_ERROR);
! 217: /*
! 218: * Search for the line which contains the tag.
! 219: * Set up initial_scrpos so we display that line.
! 220: */
! 221: initial_scrpos.pos = tagsearch();
! 222: if (initial_scrpos.pos == NULL_POSITION)
! 223: quit(QUIT_ERROR);
! 224: initial_scrpos.ln = jump_sline;
! 225: } else
! 226: #endif
! 227: if (nifile() == 0)
! 228: {
! 229: if (edit_stdin()) /* Edit standard input */
! 230: quit(QUIT_ERROR);
! 231: } else
! 232: {
! 233: if (edit_first()) /* Edit first valid file in cmd line */
! 234: quit(QUIT_ERROR);
! 235: }
! 236:
! 237: init();
! 238: commands();
! 239: quit(QUIT_OK);
! 240: /*NOTREACHED*/
! 241: }
! 242:
! 243: /*
! 244: * Copy a string, truncating to the specified length if necessary.
! 245: * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
! 246: */
! 247: public void
! 248: strtcpy(to, from, len)
! 249: char *to;
! 250: char *from;
! 251: unsigned int len;
! 252: {
! 253: strncpy(to, from, len);
! 254: to[len-1] = '\0';
! 255: }
! 256:
! 257: /*
! 258: * Copy a string to a "safe" place
! 259: * (that is, to a buffer allocated by calloc).
! 260: */
! 261: public char *
! 262: save(s)
! 263: char *s;
! 264: {
! 265: register char *p;
! 266:
! 267: p = (char *) ecalloc(strlen(s)+1, sizeof(char));
! 268: strcpy(p, s);
! 269: return (p);
! 270: }
! 271:
! 272: /*
! 273: * Allocate memory.
! 274: * Like calloc(), but never returns an error (NULL).
! 275: */
! 276: public VOID_POINTER
! 277: ecalloc(count, size)
! 278: int count;
! 279: unsigned int size;
! 280: {
! 281: register VOID_POINTER p;
! 282:
! 283: p = (VOID_POINTER) calloc(count, size);
! 284: if (p != NULL)
! 285: return (p);
! 286: error("Cannot allocate memory", NULL_PARG);
! 287: quit(QUIT_ERROR);
! 288: /*NOTREACHED*/
! 289: }
! 290:
! 291: /*
! 292: * Skip leading spaces in a string.
! 293: */
! 294: public char *
! 295: skipsp(s)
! 296: register char *s;
! 297: {
! 298: while (*s == ' ' || *s == '\t')
! 299: s++;
! 300: return (s);
! 301: }
! 302:
! 303: /*
! 304: * Exit the program.
! 305: */
! 306: public void
! 307: quit(status)
! 308: int status;
! 309: {
! 310: static int save_status;
! 311:
! 312: /*
! 313: * Put cursor at bottom left corner, clear the line,
! 314: * reset the terminal modes, and exit.
! 315: */
! 316: if (status < 0)
! 317: status = save_status;
! 318: else
! 319: save_status = status;
! 320: quitting = 1;
! 321: edit((char*)NULL);
! 322: if (any_display)
! 323: clear_bot();
! 324: deinit();
! 325: flush();
! 326: raw_mode(0);
! 327: #if MSOFTC
! 328: /*
! 329: * If we don't close 2, we get some garbage from
! 330: * 2's buffer when it flushes automatically.
! 331: * I cannot track this one down RB
! 332: * The same bug shows up if we use ^C^C to abort.
! 333: */
! 334: close(2);
! 335: #endif
! 336: exit(status);
! 337: }