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