Annotation of src/usr.bin/less/main.c, Revision 1.3
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;
1.2 etheisen 45: public int more_mode = 0;
1.1 etheisen 46:
47: extern int quit_at_eof;
48: extern int cbufs;
49: extern int errmsgs;
50: extern int screen_trashed;
51: extern int force_open;
52:
53: #if LOGFILE
54: public int logfile = -1;
55: public int force_logfile = FALSE;
56: public char * namelogfile = NULL;
57: #endif
58:
59: #if EDITOR
60: public char * editor;
61: public char * editproto;
62: #endif
63:
64: #if TAGS
65: extern char * tagfile;
66: extern char * tagoption;
67: extern int jump_sline;
68: #endif
69:
70:
71:
72: /*
73: * Entry point.
74: */
75: int
76: main(argc, argv)
77: int argc;
78: char *argv[];
79: {
80: IFILE ifile;
1.2 etheisen 81: extern char *__progname;
1.1 etheisen 82:
83: #ifdef __EMX__
84: _response(&argc, &argv);
85: _wildcard(&argc, &argv);
86: #endif
87:
88: progname = *argv++;
89:
90: /*
91: * Process command line arguments and LESS environment arguments.
92: * Command line arguments override environment arguments.
93: */
1.2 etheisen 94: if (strcmp(__progname, "more") == 0)
95: more_mode = 1;
96:
1.1 etheisen 97: get_term();
98: init_cmds();
99: init_prompt();
100: init_charset();
101: init_option();
1.2 etheisen 102:
103: if (more_mode) {
104: scan_option("-E");
105: scan_option("-m");
106: scan_option("-G");
107: scan_option(getenv("MORE"));
108: } else
109: scan_option(getenv("LESS"));
1.1 etheisen 110:
111: #if GNU_OPTIONS
112: /*
113: * Special case for "less --help" and "less --version".
114: */
115: if (argc == 2)
116: {
117: if (strcmp(argv[0], "--help") == 0)
118: scan_option("-?");
119: if (strcmp(argv[0], "--version") == 0)
120: scan_option("-V");
121: }
122: #endif
123: #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
1.3 ! deraadt 124: while (--argc > 0 && (isoptstring(argv[0]) || isoptpending())) {
! 125: if (strcmp(argv[0], "--") == 0) {
! 126: argv++;
! 127: argc--;
! 128: break;
! 129: }
1.1 etheisen 130: scan_option(*argv++);
1.3 ! deraadt 131: }
1.1 etheisen 132: #undef isoptstring
133:
134: if (isoptpending())
135: {
136: /*
137: * Last command line option was a flag requiring a
138: * following string, but there was no following string.
139: */
140: nopendopt();
141: quit(QUIT_OK);
142: }
143:
144: #if EDITOR
145: editor = getenv("VISUAL");
146: if (editor == NULL || *editor == '\0')
147: {
148: editor = getenv("EDITOR");
149: if (editor == NULL || *editor == '\0')
150: editor = EDIT_PGM;
151: }
152: editproto = getenv("LESSEDIT");
153: if (editproto == NULL || *editproto == '\0')
154: editproto = "%E ?lm+%lm. %f";
155: #endif
156:
157: /*
158: * Call get_ifile with all the command line filenames
159: * to "register" them with the ifile system.
160: */
161: ifile = NULL_IFILE;
162: while (--argc >= 0)
163: {
164: #if MSOFTC || OS2
165: /*
166: * Because the "shell" doesn't expand filename patterns,
167: * treat each argument as a filename pattern rather than
168: * a single filename.
169: * Expand the pattern and iterate over the expanded list.
170: */
171: struct textlist tlist;
172: char *gfilename;
173: char *filename;
174:
175: gfilename = glob(*argv++);
176: init_textlist(&tlist, gfilename);
177: filename = NULL;
178: while ((filename = forw_textlist(&tlist, filename)) != NULL)
179: ifile = get_ifile(filename, ifile);
180: free(gfilename);
181: #else
182: ifile = get_ifile(*argv++, ifile);
183: #endif
184: }
185: /*
186: * Set up terminal, etc.
187: */
188: is_tty = isatty(1);
189: if (!is_tty)
190: {
191: /*
192: * Output is not a tty.
193: * Just copy the input file(s) to output.
194: */
195: if (nifile() == 0)
196: {
197: if (edit_stdin() == 0)
198: cat_file();
199: } else if (edit_first() == 0)
200: {
201: do {
202: cat_file();
203: } while (edit_next(1) == 0);
204: }
205: quit(QUIT_OK);
206: }
207:
208: init_mark();
209: raw_mode(1);
210: open_getchr();
211: init_signals(1);
212:
213: /*
214: * Select the first file to examine.
215: */
216: #if TAGS
217: if (tagoption != NULL)
218: {
219: /*
220: * A -t option was given.
221: * Verify that no filenames were also given.
222: * Edit the file selected by the "tags" search,
223: * and search for the proper line in the file.
224: */
225: if (nifile() > 0)
226: {
227: error("No filenames allowed with -t option", NULL_PARG);
228: quit(QUIT_ERROR);
229: }
230: findtag(tagoption);
231: if (tagfile == NULL)
232: quit(QUIT_ERROR);
233: if (edit(tagfile)) /* Edit file which contains the tag */
234: quit(QUIT_ERROR);
235: /*
236: * Search for the line which contains the tag.
237: * Set up initial_scrpos so we display that line.
238: */
239: initial_scrpos.pos = tagsearch();
240: if (initial_scrpos.pos == NULL_POSITION)
241: quit(QUIT_ERROR);
242: initial_scrpos.ln = jump_sline;
243: } else
244: #endif
245: if (nifile() == 0)
246: {
247: if (edit_stdin()) /* Edit standard input */
248: quit(QUIT_ERROR);
249: } else
250: {
251: if (edit_first()) /* Edit first valid file in cmd line */
252: quit(QUIT_ERROR);
253: }
254:
255: init();
256: commands();
257: quit(QUIT_OK);
258: /*NOTREACHED*/
259: }
260:
261: /*
262: * Copy a string, truncating to the specified length if necessary.
263: * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
264: */
265: public void
266: strtcpy(to, from, len)
267: char *to;
268: char *from;
269: unsigned int len;
270: {
271: strncpy(to, from, len);
272: to[len-1] = '\0';
273: }
274:
275: /*
276: * Copy a string to a "safe" place
277: * (that is, to a buffer allocated by calloc).
278: */
279: public char *
280: save(s)
281: char *s;
282: {
283: register char *p;
284:
285: p = (char *) ecalloc(strlen(s)+1, sizeof(char));
286: strcpy(p, s);
287: return (p);
288: }
289:
290: /*
291: * Allocate memory.
292: * Like calloc(), but never returns an error (NULL).
293: */
294: public VOID_POINTER
295: ecalloc(count, size)
296: int count;
297: unsigned int size;
298: {
299: register VOID_POINTER p;
300:
301: p = (VOID_POINTER) calloc(count, size);
302: if (p != NULL)
303: return (p);
304: error("Cannot allocate memory", NULL_PARG);
305: quit(QUIT_ERROR);
306: /*NOTREACHED*/
307: }
308:
309: /*
310: * Skip leading spaces in a string.
311: */
312: public char *
313: skipsp(s)
314: register char *s;
315: {
316: while (*s == ' ' || *s == '\t')
317: s++;
318: return (s);
319: }
320:
321: /*
322: * Exit the program.
323: */
324: public void
325: quit(status)
326: int status;
327: {
328: static int save_status;
329:
330: /*
331: * Put cursor at bottom left corner, clear the line,
332: * reset the terminal modes, and exit.
333: */
334: if (status < 0)
335: status = save_status;
336: else
337: save_status = status;
338: quitting = 1;
339: edit((char*)NULL);
1.2 etheisen 340: if (is_tty && any_display)
1.1 etheisen 341: clear_bot();
342: deinit();
343: flush();
344: raw_mode(0);
345: #if MSOFTC
346: /*
347: * If we don't close 2, we get some garbage from
348: * 2's buffer when it flushes automatically.
349: * I cannot track this one down RB
350: * The same bug shows up if we use ^C^C to abort.
351: */
352: close(2);
353: #endif
354: exit(status);
355: }