Annotation of src/usr.bin/less/main.c, Revision 1.23
1.1 etheisen 1: /*
1.13 shadchin 2: * Copyright (C) 1984-2012 Mark Nudelman
1.19 nicm 3: * Modified for use with illumos by Garrett D'Amore.
4: * Copyright 2014 Garrett D'Amore <garrett@damore.org>
1.1 etheisen 5: *
1.7 millert 6: * You may distribute under the terms of either the GNU General Public
7: * License or the Less License, as specified in the README file.
1.1 etheisen 8: *
1.13 shadchin 9: * For more information, see the README file.
1.17 nicm 10: */
1.1 etheisen 11:
12: /*
13: * Entry point, initialization, miscellaneous routines.
14: */
15:
1.17 nicm 16: #include <libgen.h>
17: #include <stdarg.h>
18: #include <sys/types.h>
1.1 etheisen 19: #include "less.h"
20:
1.17 nicm 21: char *every_first_cmd = NULL;
22: int new_file;
23: int is_tty;
24: IFILE curr_ifile = NULL_IFILE;
25: IFILE old_ifile = NULL_IFILE;
26: struct scrpos initial_scrpos;
27: int any_display = FALSE;
28: off_t start_attnpos = -1;
29: off_t end_attnpos = -1;
30: int wscroll;
31:
1.18 deraadt 32: static char *progname;
1.17 nicm 33:
34: int quitting;
35: int secure;
36: int dohelp;
37:
38: int logfile = -1;
39: int force_logfile = FALSE;
40: char *namelogfile = NULL;
41: char *editor;
42: char *editproto;
1.1 etheisen 43:
1.18 deraadt 44: extern char *tags;
45: extern char *tagoption;
1.17 nicm 46: extern int jump_sline;
1.11 shadchin 47: extern int less_is_more;
1.7 millert 48: extern int missing_cap;
49: extern int know_dumb;
1.17 nicm 50: extern int quit_if_one_screen;
51: extern int quit_at_eof;
1.11 shadchin 52: extern int pr_type;
1.17 nicm 53: extern int hilite_search;
54: extern int use_lessopen;
55: extern int no_init;
56: extern int top_scroll;
57: extern int errmsgs;
1.7 millert 58:
1.1 etheisen 59:
60: /*
61: * Entry point.
62: */
63: int
1.17 nicm 64: main(int argc, char *argv[])
1.1 etheisen 65: {
66: IFILE ifile;
1.7 millert 67: char *s;
1.1 etheisen 68:
1.17 nicm 69: progname = basename(argv[0]);
70: argv++;
71: argc--;
1.1 etheisen 72:
1.17 nicm 73: /*
74: * If the name of the executable program is "more",
75: * act like LESS_IS_MORE is set. We have to set this as early
76: * as possible for POSIX.
77: */
78: if ((strcmp(progname, "more") == 0) ||
79: (strcmp(progname, "page") == 0)) {
80: less_is_more = 1;
81: } else {
82: s = lgetenv("LESS_IS_MORE");
83: if (s != NULL && *s != '\0')
84: less_is_more = 1;
85: }
1.7 millert 86:
87: secure = 0;
88: s = lgetenv("LESSSECURE");
89: if (s != NULL && *s != '\0')
90: secure = 1;
91:
1.23 ! deraadt 92: if (secure) {
! 93: if (pledge("stdio rpath wpath tty", NULL) == -1)
! 94: err(1, "pledge");
! 95: } else {
! 96: if (pledge("stdio rpath wpath cpath fattr proc exec tty", NULL) == -1)
! 97: err(1, "pledge");
! 98: }
! 99:
1.1 etheisen 100: /*
101: * Process command line arguments and LESS environment arguments.
102: * Command line arguments override environment arguments.
103: */
1.7 millert 104: is_tty = isatty(1);
1.1 etheisen 105: get_term();
106: init_cmds();
107: init_charset();
1.7 millert 108: init_line();
1.11 shadchin 109: init_cmdhist();
1.1 etheisen 110: init_option();
1.11 shadchin 111: init_search();
112:
113:
114: init_prompt();
115:
116: s = lgetenv(less_is_more ? "MORE" : "LESS");
1.7 millert 117: if (s != NULL)
1.20 tedu 118: scan_option(estrdup(s));
1.1 etheisen 119:
1.17 nicm 120: if (less_is_more) {
121: /* this is specified by XPG */
122: quit_at_eof = OPT_ON;
123:
124: /* more users don't like the warning */
125: know_dumb = OPT_ON;
126:
127: /* default prompt is medium */
128: pr_type = OPT_ON;
129:
130: /* do not hilight search terms */
131: hilite_search = OPT_OFF;
132:
133: /* do not use LESSOPEN */
134: use_lessopen = OPT_OFF;
135:
136: /* do not set init strings to terminal */
137: no_init = OPT_ON;
138:
139: /* repaint from top of screen */
140: top_scroll = OPT_OFF;
141: }
142:
1.7 millert 143: #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
1.17 nicm 144: while (argc > 0 && (isoptstring(*argv) || isoptpending())) {
1.7 millert 145: s = *argv++;
146: argc--;
147: if (strcmp(s, "--") == 0)
1.3 deraadt 148: break;
1.7 millert 149: scan_option(s);
1.3 deraadt 150: }
1.1 etheisen 151: #undef isoptstring
152:
1.17 nicm 153: if (isoptpending()) {
1.1 etheisen 154: /*
155: * Last command line option was a flag requiring a
156: * following string, but there was no following string.
157: */
158: nopendopt();
159: quit(QUIT_OK);
160: }
1.11 shadchin 161:
1.17 nicm 162: if (errmsgs) {
163: quit(QUIT_ERROR);
164: }
165: if (less_is_more && quit_at_eof == OPT_ONPLUS) {
166: extern int no_init;
167: no_init = OPT_ON;
168: }
169: if (less_is_more && pr_type == OPT_ONPLUS) {
170: extern int quiet;
171: quiet = VERY_QUIET;
172: }
173:
1.7 millert 174: editor = lgetenv("VISUAL");
1.17 nicm 175: if (editor == NULL || *editor == '\0') {
1.7 millert 176: editor = lgetenv("EDITOR");
1.1 etheisen 177: if (editor == NULL || *editor == '\0')
178: editor = EDIT_PGM;
179: }
1.7 millert 180: editproto = lgetenv("LESSEDIT");
1.1 etheisen 181: if (editproto == NULL || *editproto == '\0')
182: editproto = "%E ?lm+%lm. %f";
183:
184: /*
185: * Call get_ifile with all the command line filenames
186: * to "register" them with the ifile system.
187: */
188: ifile = NULL_IFILE;
1.11 shadchin 189: if (dohelp)
1.15 schwarze 190: ifile = get_ifile(helpfile(), ifile);
1.17 nicm 191: while (argc-- > 0) {
1.7 millert 192: char *filename;
193: filename = shell_quote(*argv);
194: if (filename == NULL)
195: filename = *argv;
196: argv++;
197: (void) get_ifile(filename, ifile);
198: ifile = prev_ifile(NULL_IFILE);
1.13 shadchin 199: free(filename);
1.1 etheisen 200: }
201: /*
202: * Set up terminal, etc.
203: */
1.17 nicm 204: if (!is_tty) {
1.1 etheisen 205: /*
206: * Output is not a tty.
207: * Just copy the input file(s) to output.
208: */
1.17 nicm 209: if (nifile() == 0) {
1.1 etheisen 210: if (edit_stdin() == 0)
211: cat_file();
1.17 nicm 212: } else if (edit_first() == 0) {
1.1 etheisen 213: do {
214: cat_file();
215: } while (edit_next(1) == 0);
216: }
217: quit(QUIT_OK);
218: }
219:
1.17 nicm 220: if (missing_cap && !know_dumb)
1.7 millert 221: error("WARNING: terminal is not fully functional", NULL_PARG);
1.1 etheisen 222: init_mark();
1.7 millert 223: open_getchr();
1.23 ! deraadt 224:
! 225: if (secure)
! 226: if (pledge("stdio rpath tty", NULL) == -1)
! 227: err(1, "pledge");
! 228:
1.1 etheisen 229: raw_mode(1);
230: init_signals(1);
231:
232: /*
233: * Select the first file to examine.
234: */
1.17 nicm 235: if (tagoption != NULL || strcmp(tags, "-") == 0) {
1.1 etheisen 236: /*
237: * A -t option was given.
238: * Verify that no filenames were also given.
239: * Edit the file selected by the "tags" search,
240: * and search for the proper line in the file.
241: */
1.17 nicm 242: if (nifile() > 0) {
1.1 etheisen 243: error("No filenames allowed with -t option", NULL_PARG);
244: quit(QUIT_ERROR);
245: }
246: findtag(tagoption);
1.7 millert 247: if (edit_tagfile()) /* Edit file which contains the tag */
1.1 etheisen 248: quit(QUIT_ERROR);
249: /*
250: * Search for the line which contains the tag.
251: * Set up initial_scrpos so we display that line.
252: */
253: initial_scrpos.pos = tagsearch();
1.17 nicm 254: if (initial_scrpos.pos == -1)
1.1 etheisen 255: quit(QUIT_ERROR);
256: initial_scrpos.ln = jump_sline;
1.17 nicm 257: } else if (nifile() == 0) {
1.1 etheisen 258: if (edit_stdin()) /* Edit standard input */
259: quit(QUIT_ERROR);
1.17 nicm 260: } else {
1.1 etheisen 261: if (edit_first()) /* Edit first valid file in cmd line */
262: quit(QUIT_ERROR);
263: }
264:
265: init();
266: commands();
267: quit(QUIT_OK);
268: /*NOTREACHED*/
1.7 millert 269: return (0);
1.1 etheisen 270: }
271:
272: /*
273: * Allocate memory.
274: * Like calloc(), but never returns an error (NULL).
275: */
1.17 nicm 276: void *
277: ecalloc(int count, unsigned int size)
1.1 etheisen 278: {
1.17 nicm 279: void *p;
1.1 etheisen 280:
1.17 nicm 281: p = calloc(count, size);
1.1 etheisen 282: if (p != NULL)
283: return (p);
284: error("Cannot allocate memory", NULL_PARG);
285: quit(QUIT_ERROR);
286: /*NOTREACHED*/
1.7 millert 287: return (NULL);
1.1 etheisen 288: }
289:
1.17 nicm 290: char *
291: easprintf(const char *fmt, ...)
292: {
293: char *p = NULL;
294: int rv;
295: va_list ap;
296:
297: va_start(ap, fmt);
298: rv = vasprintf(&p, fmt, ap);
299: va_end(ap);
300:
301: if (p == NULL || rv < 0) {
302: error("Cannot allocate memory", NULL_PARG);
303: quit(QUIT_ERROR);
304: /*NOTREACHED*/
305: }
306: return (p);
307: }
308:
309: char *
310: estrdup(const char *str)
311: {
1.20 tedu 312: char *n;
313:
314: n = strdup(str);
315: if (n == NULL) {
1.17 nicm 316: error("Cannot allocate memory", NULL_PARG);
1.20 tedu 317: quit(QUIT_ERROR);
1.17 nicm 318: }
319: return (n);
320: }
321:
1.1 etheisen 322: /*
323: * Skip leading spaces in a string.
324: */
1.17 nicm 325: char *
326: skipsp(char *s)
1.1 etheisen 327: {
1.17 nicm 328: while (*s == ' ' || *s == '\t')
1.1 etheisen 329: s++;
330: return (s);
331: }
332:
333: /*
1.7 millert 334: * See how many characters of two strings are identical.
335: * If uppercase is true, the first string must begin with an uppercase
336: * character; the remainder of the first string may be either case.
337: */
1.17 nicm 338: int
339: sprefix(char *ps, char *s, int uppercase)
1.7 millert 340: {
1.17 nicm 341: int c;
342: int sc;
343: int len = 0;
1.7 millert 344:
1.17 nicm 345: for (; *s != '\0'; s++, ps++) {
1.7 millert 346: c = *ps;
1.17 nicm 347: if (uppercase) {
348: if (len == 0 && isupper(c))
1.7 millert 349: return (-1);
1.17 nicm 350: if (isupper(c))
351: c = tolower(c);
1.7 millert 352: }
353: sc = *s;
1.17 nicm 354: if (len > 0 && isupper(sc))
355: sc = tolower(sc);
1.7 millert 356: if (c != sc)
357: break;
358: len++;
359: }
360: return (len);
361: }
362:
363: /*
1.1 etheisen 364: * Exit the program.
365: */
1.17 nicm 366: void
367: quit(int status)
1.1 etheisen 368: {
369: static int save_status;
370:
371: /*
372: * Put cursor at bottom left corner, clear the line,
373: * reset the terminal modes, and exit.
374: */
375: if (status < 0)
376: status = save_status;
377: else
378: save_status = status;
379: quitting = 1;
1.17 nicm 380: edit(NULL);
1.22 deraadt 381: if (!secure)
382: save_cmdhist();
1.7 millert 383: if (any_display && is_tty)
1.1 etheisen 384: clear_bot();
385: deinit();
386: flush();
387: raw_mode(0);
388: exit(status);
1.15 schwarze 389: }
390:
1.17 nicm 391: char *
1.15 schwarze 392: helpfile(void)
393: {
394: return (less_is_more ? HELPDIR "/more.help" : HELPDIR "/less.help");
1.1 etheisen 395: }