Annotation of src/usr.bin/less/main.c, Revision 1.2
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')
124: while (--argc > 0 && (isoptstring(argv[0]) || isoptpending()))
125: scan_option(*argv++);
126: #undef isoptstring
127:
128: if (isoptpending())
129: {
130: /*
131: * Last command line option was a flag requiring a
132: * following string, but there was no following string.
133: */
134: nopendopt();
135: quit(QUIT_OK);
136: }
137:
138: #if EDITOR
139: editor = getenv("VISUAL");
140: if (editor == NULL || *editor == '\0')
141: {
142: editor = getenv("EDITOR");
143: if (editor == NULL || *editor == '\0')
144: editor = EDIT_PGM;
145: }
146: editproto = getenv("LESSEDIT");
147: if (editproto == NULL || *editproto == '\0')
148: editproto = "%E ?lm+%lm. %f";
149: #endif
150:
151: /*
152: * Call get_ifile with all the command line filenames
153: * to "register" them with the ifile system.
154: */
155: ifile = NULL_IFILE;
156: while (--argc >= 0)
157: {
158: #if MSOFTC || OS2
159: /*
160: * Because the "shell" doesn't expand filename patterns,
161: * treat each argument as a filename pattern rather than
162: * a single filename.
163: * Expand the pattern and iterate over the expanded list.
164: */
165: struct textlist tlist;
166: char *gfilename;
167: char *filename;
168:
169: gfilename = glob(*argv++);
170: init_textlist(&tlist, gfilename);
171: filename = NULL;
172: while ((filename = forw_textlist(&tlist, filename)) != NULL)
173: ifile = get_ifile(filename, ifile);
174: free(gfilename);
175: #else
176: ifile = get_ifile(*argv++, ifile);
177: #endif
178: }
179: /*
180: * Set up terminal, etc.
181: */
182: is_tty = isatty(1);
183: if (!is_tty)
184: {
185: /*
186: * Output is not a tty.
187: * Just copy the input file(s) to output.
188: */
189: if (nifile() == 0)
190: {
191: if (edit_stdin() == 0)
192: cat_file();
193: } else if (edit_first() == 0)
194: {
195: do {
196: cat_file();
197: } while (edit_next(1) == 0);
198: }
199: quit(QUIT_OK);
200: }
201:
202: init_mark();
203: raw_mode(1);
204: open_getchr();
205: init_signals(1);
206:
207: /*
208: * Select the first file to examine.
209: */
210: #if TAGS
211: if (tagoption != NULL)
212: {
213: /*
214: * A -t option was given.
215: * Verify that no filenames were also given.
216: * Edit the file selected by the "tags" search,
217: * and search for the proper line in the file.
218: */
219: if (nifile() > 0)
220: {
221: error("No filenames allowed with -t option", NULL_PARG);
222: quit(QUIT_ERROR);
223: }
224: findtag(tagoption);
225: if (tagfile == NULL)
226: quit(QUIT_ERROR);
227: if (edit(tagfile)) /* Edit file which contains the tag */
228: quit(QUIT_ERROR);
229: /*
230: * Search for the line which contains the tag.
231: * Set up initial_scrpos so we display that line.
232: */
233: initial_scrpos.pos = tagsearch();
234: if (initial_scrpos.pos == NULL_POSITION)
235: quit(QUIT_ERROR);
236: initial_scrpos.ln = jump_sline;
237: } else
238: #endif
239: if (nifile() == 0)
240: {
241: if (edit_stdin()) /* Edit standard input */
242: quit(QUIT_ERROR);
243: } else
244: {
245: if (edit_first()) /* Edit first valid file in cmd line */
246: quit(QUIT_ERROR);
247: }
248:
249: init();
250: commands();
251: quit(QUIT_OK);
252: /*NOTREACHED*/
253: }
254:
255: /*
256: * Copy a string, truncating to the specified length if necessary.
257: * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
258: */
259: public void
260: strtcpy(to, from, len)
261: char *to;
262: char *from;
263: unsigned int len;
264: {
265: strncpy(to, from, len);
266: to[len-1] = '\0';
267: }
268:
269: /*
270: * Copy a string to a "safe" place
271: * (that is, to a buffer allocated by calloc).
272: */
273: public char *
274: save(s)
275: char *s;
276: {
277: register char *p;
278:
279: p = (char *) ecalloc(strlen(s)+1, sizeof(char));
280: strcpy(p, s);
281: return (p);
282: }
283:
284: /*
285: * Allocate memory.
286: * Like calloc(), but never returns an error (NULL).
287: */
288: public VOID_POINTER
289: ecalloc(count, size)
290: int count;
291: unsigned int size;
292: {
293: register VOID_POINTER p;
294:
295: p = (VOID_POINTER) calloc(count, size);
296: if (p != NULL)
297: return (p);
298: error("Cannot allocate memory", NULL_PARG);
299: quit(QUIT_ERROR);
300: /*NOTREACHED*/
301: }
302:
303: /*
304: * Skip leading spaces in a string.
305: */
306: public char *
307: skipsp(s)
308: register char *s;
309: {
310: while (*s == ' ' || *s == '\t')
311: s++;
312: return (s);
313: }
314:
315: /*
316: * Exit the program.
317: */
318: public void
319: quit(status)
320: int status;
321: {
322: static int save_status;
323:
324: /*
325: * Put cursor at bottom left corner, clear the line,
326: * reset the terminal modes, and exit.
327: */
328: if (status < 0)
329: status = save_status;
330: else
331: save_status = status;
332: quitting = 1;
333: edit((char*)NULL);
1.2 ! etheisen 334: if (is_tty && any_display)
1.1 etheisen 335: clear_bot();
336: deinit();
337: flush();
338: raw_mode(0);
339: #if MSOFTC
340: /*
341: * If we don't close 2, we get some garbage from
342: * 2's buffer when it flushes automatically.
343: * I cannot track this one down RB
344: * The same bug shows up if we use ^C^C to abort.
345: */
346: close(2);
347: #endif
348: exit(status);
349: }