Annotation of src/usr.bin/less/main.c, Revision 1.1.1.2
1.1 etheisen 1: /*
1.1.1.2 ! millert 2: * Copyright (C) 1984-2002 Mark Nudelman
1.1 etheisen 3: *
1.1.1.2 ! 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.1.1.2 ! millert 7: * For more information about less, or for information on how to
! 8: * contact the author, see the README file.
1.1 etheisen 9: */
10:
11:
12: /*
13: * Entry point, initialization, miscellaneous routines.
14: */
15:
16: #include "less.h"
1.1.1.2 ! millert 17: #if MSDOS_COMPILER==WIN32C
! 18: #include <windows.h>
! 19: #endif
1.1 etheisen 20:
21: public char * every_first_cmd = NULL;
22: public int new_file;
23: public int is_tty;
24: public IFILE curr_ifile = NULL_IFILE;
25: public IFILE old_ifile = NULL_IFILE;
26: public struct scrpos initial_scrpos;
27: public int any_display = FALSE;
1.1.1.2 ! millert 28: public POSITION start_attnpos = NULL_POSITION;
! 29: public POSITION end_attnpos = NULL_POSITION;
1.1 etheisen 30: public int wscroll;
31: public char * progname;
32: public int quitting;
1.1.1.2 ! millert 33: public int secure;
! 34: public int dohelp;
1.1 etheisen 35:
36: #if LOGFILE
37: public int logfile = -1;
38: public int force_logfile = FALSE;
39: public char * namelogfile = NULL;
40: #endif
41:
42: #if EDITOR
43: public char * editor;
44: public char * editproto;
45: #endif
46:
47: #if TAGS
1.1.1.2 ! millert 48: extern char * tags;
1.1 etheisen 49: extern char * tagoption;
50: extern int jump_sline;
51: #endif
52:
1.1.1.2 ! millert 53: #ifdef WIN32
! 54: static char consoleTitle[256];
! 55: #endif
! 56:
! 57: extern int missing_cap;
! 58: extern int know_dumb;
1.1 etheisen 59:
60:
61: /*
62: * Entry point.
63: */
64: int
65: main(argc, argv)
66: int argc;
67: char *argv[];
68: {
69: IFILE ifile;
1.1.1.2 ! millert 70: char *s;
1.1 etheisen 71:
72: #ifdef __EMX__
73: _response(&argc, &argv);
74: _wildcard(&argc, &argv);
75: #endif
76:
77: progname = *argv++;
1.1.1.2 ! millert 78: argc--;
! 79:
! 80: secure = 0;
! 81: s = lgetenv("LESSSECURE");
! 82: if (s != NULL && *s != '\0')
! 83: secure = 1;
! 84:
! 85: #ifdef WIN32
! 86: if (getenv("HOME") == NULL)
! 87: {
! 88: /*
! 89: * If there is no HOME environment variable,
! 90: * try the concatenation of HOMEDRIVE + HOMEPATH.
! 91: */
! 92: char *drive = getenv("HOMEDRIVE");
! 93: char *path = getenv("HOMEPATH");
! 94: if (drive != NULL && path != NULL)
! 95: {
! 96: char *env = (char *) ecalloc(strlen(drive) +
! 97: strlen(path) + 6, sizeof(char));
! 98: strcpy(env, "HOME=");
! 99: strcat(env, drive);
! 100: strcat(env, path);
! 101: putenv(env);
! 102: }
! 103: }
! 104: GetConsoleTitle(consoleTitle, sizeof(consoleTitle)/sizeof(char));
! 105: #endif /* WIN32 */
1.1 etheisen 106:
107: /*
108: * Process command line arguments and LESS environment arguments.
109: * Command line arguments override environment arguments.
110: */
1.1.1.2 ! millert 111: is_tty = isatty(1);
1.1 etheisen 112: get_term();
113: init_cmds();
114: init_prompt();
115: init_charset();
1.1.1.2 ! millert 116: init_line();
1.1 etheisen 117: init_option();
1.1.1.2 ! millert 118: s = lgetenv("LESS");
! 119: if (s != NULL)
! 120: scan_option(save(s));
1.1 etheisen 121:
1.1.1.2 ! millert 122: #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
! 123: while (argc > 0 && (isoptstring(*argv) || isoptpending()))
1.1 etheisen 124: {
1.1.1.2 ! millert 125: s = *argv++;
! 126: argc--;
! 127: if (strcmp(s, "--") == 0)
! 128: break;
! 129: scan_option(s);
1.1 etheisen 130: }
131: #undef isoptstring
132:
133: if (isoptpending())
134: {
135: /*
136: * Last command line option was a flag requiring a
137: * following string, but there was no following string.
138: */
139: nopendopt();
140: quit(QUIT_OK);
141: }
142:
143: #if EDITOR
1.1.1.2 ! millert 144: editor = lgetenv("VISUAL");
1.1 etheisen 145: if (editor == NULL || *editor == '\0')
146: {
1.1.1.2 ! millert 147: editor = lgetenv("EDITOR");
1.1 etheisen 148: if (editor == NULL || *editor == '\0')
149: editor = EDIT_PGM;
150: }
1.1.1.2 ! millert 151: editproto = lgetenv("LESSEDIT");
1.1 etheisen 152: if (editproto == NULL || *editproto == '\0')
153: editproto = "%E ?lm+%lm. %f";
154: #endif
155:
156: /*
157: * Call get_ifile with all the command line filenames
158: * to "register" them with the ifile system.
159: */
160: ifile = NULL_IFILE;
1.1.1.2 ! millert 161: if (dohelp)
! 162: ifile = get_ifile(FAKE_HELPFILE, ifile);
! 163: while (argc-- > 0)
1.1 etheisen 164: {
1.1.1.2 ! millert 165: char *filename;
! 166: #if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
1.1 etheisen 167: /*
168: * Because the "shell" doesn't expand filename patterns,
169: * treat each argument as a filename pattern rather than
170: * a single filename.
171: * Expand the pattern and iterate over the expanded list.
172: */
173: struct textlist tlist;
174: char *gfilename;
175:
1.1.1.2 ! millert 176: gfilename = lglob(*argv++);
1.1 etheisen 177: init_textlist(&tlist, gfilename);
178: filename = NULL;
179: while ((filename = forw_textlist(&tlist, filename)) != NULL)
1.1.1.2 ! millert 180: {
! 181: (void) get_ifile(filename, ifile);
! 182: ifile = prev_ifile(NULL_IFILE);
! 183: }
1.1 etheisen 184: free(gfilename);
185: #else
1.1.1.2 ! millert 186: filename = shell_quote(*argv);
! 187: if (filename == NULL)
! 188: filename = *argv;
! 189: argv++;
! 190: (void) get_ifile(filename, ifile);
! 191: ifile = prev_ifile(NULL_IFILE);
1.1 etheisen 192: #endif
193: }
194: /*
195: * Set up terminal, etc.
196: */
197: if (!is_tty)
198: {
199: /*
200: * Output is not a tty.
201: * Just copy the input file(s) to output.
202: */
1.1.1.2 ! millert 203: SET_BINARY(1);
1.1 etheisen 204: if (nifile() == 0)
205: {
206: if (edit_stdin() == 0)
207: cat_file();
208: } else if (edit_first() == 0)
209: {
210: do {
211: cat_file();
212: } while (edit_next(1) == 0);
213: }
214: quit(QUIT_OK);
215: }
216:
1.1.1.2 ! millert 217: if (missing_cap && !know_dumb)
! 218: error("WARNING: terminal is not fully functional", NULL_PARG);
1.1 etheisen 219: init_mark();
220: open_getchr();
1.1.1.2 ! millert 221: raw_mode(1);
1.1 etheisen 222: init_signals(1);
223:
224: /*
225: * Select the first file to examine.
226: */
227: #if TAGS
1.1.1.2 ! millert 228: if (tagoption != NULL || strcmp(tags, "-") == 0)
1.1 etheisen 229: {
230: /*
231: * A -t option was given.
232: * Verify that no filenames were also given.
233: * Edit the file selected by the "tags" search,
234: * and search for the proper line in the file.
235: */
236: if (nifile() > 0)
237: {
238: error("No filenames allowed with -t option", NULL_PARG);
239: quit(QUIT_ERROR);
240: }
241: findtag(tagoption);
1.1.1.2 ! millert 242: if (edit_tagfile()) /* Edit file which contains the tag */
1.1 etheisen 243: quit(QUIT_ERROR);
244: /*
245: * Search for the line which contains the tag.
246: * Set up initial_scrpos so we display that line.
247: */
248: initial_scrpos.pos = tagsearch();
249: if (initial_scrpos.pos == NULL_POSITION)
250: quit(QUIT_ERROR);
251: initial_scrpos.ln = jump_sline;
252: } else
253: #endif
254: if (nifile() == 0)
255: {
256: if (edit_stdin()) /* Edit standard input */
257: quit(QUIT_ERROR);
258: } else
259: {
260: if (edit_first()) /* Edit first valid file in cmd line */
261: quit(QUIT_ERROR);
262: }
263:
264: init();
265: commands();
266: quit(QUIT_OK);
267: /*NOTREACHED*/
1.1.1.2 ! millert 268: return (0);
1.1 etheisen 269: }
270:
271: /*
272: * Copy a string to a "safe" place
273: * (that is, to a buffer allocated by calloc).
274: */
275: public char *
276: save(s)
277: char *s;
278: {
279: register char *p;
280:
281: p = (char *) ecalloc(strlen(s)+1, sizeof(char));
282: strcpy(p, s);
283: return (p);
284: }
285:
286: /*
287: * Allocate memory.
288: * Like calloc(), but never returns an error (NULL).
289: */
290: public VOID_POINTER
291: ecalloc(count, size)
292: int count;
293: unsigned int size;
294: {
295: register VOID_POINTER p;
296:
297: p = (VOID_POINTER) calloc(count, size);
298: if (p != NULL)
299: return (p);
300: error("Cannot allocate memory", NULL_PARG);
301: quit(QUIT_ERROR);
302: /*NOTREACHED*/
1.1.1.2 ! millert 303: return (NULL);
1.1 etheisen 304: }
305:
306: /*
307: * Skip leading spaces in a string.
308: */
309: public char *
310: skipsp(s)
311: register char *s;
312: {
313: while (*s == ' ' || *s == '\t')
314: s++;
315: return (s);
316: }
317:
318: /*
1.1.1.2 ! millert 319: * See how many characters of two strings are identical.
! 320: * If uppercase is true, the first string must begin with an uppercase
! 321: * character; the remainder of the first string may be either case.
! 322: */
! 323: public int
! 324: sprefix(ps, s, uppercase)
! 325: char *ps;
! 326: char *s;
! 327: int uppercase;
! 328: {
! 329: register int c;
! 330: register int sc;
! 331: register int len = 0;
! 332:
! 333: for ( ; *s != '\0'; s++, ps++)
! 334: {
! 335: c = *ps;
! 336: if (uppercase)
! 337: {
! 338: if (len == 0 && SIMPLE_IS_LOWER(c))
! 339: return (-1);
! 340: if (SIMPLE_IS_UPPER(c))
! 341: c = SIMPLE_TO_LOWER(c);
! 342: }
! 343: sc = *s;
! 344: if (len > 0 && SIMPLE_IS_UPPER(sc))
! 345: sc = SIMPLE_TO_LOWER(sc);
! 346: if (c != sc)
! 347: break;
! 348: len++;
! 349: }
! 350: return (len);
! 351: }
! 352:
! 353: /*
1.1 etheisen 354: * Exit the program.
355: */
356: public void
357: quit(status)
358: int status;
359: {
360: static int save_status;
361:
362: /*
363: * Put cursor at bottom left corner, clear the line,
364: * reset the terminal modes, and exit.
365: */
366: if (status < 0)
367: status = save_status;
368: else
369: save_status = status;
370: quitting = 1;
371: edit((char*)NULL);
1.1.1.2 ! millert 372: if (any_display && is_tty)
1.1 etheisen 373: clear_bot();
374: deinit();
375: flush();
376: raw_mode(0);
1.1.1.2 ! millert 377: #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
1.1 etheisen 378: /*
379: * If we don't close 2, we get some garbage from
380: * 2's buffer when it flushes automatically.
381: * I cannot track this one down RB
382: * The same bug shows up if we use ^C^C to abort.
383: */
384: close(2);
385: #endif
1.1.1.2 ! millert 386: #if WIN32
! 387: SetConsoleTitle(consoleTitle);
! 388: #endif
! 389: close_getchr();
1.1 etheisen 390: exit(status);
391: }