Annotation of src/usr.bin/more/main.c, Revision 1.1.1.1
1.1 deraadt 1: /*
2: * Copyright (c) 1988 Mark Nudleman
3: * Copyright (c) 1988 Regents of the University of California.
4: * All rights reserved.
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: * 3. All advertising materials mentioning features or use of this software
15: * must display the following acknowledgement:
16: * This product includes software developed by the University of
17: * California, Berkeley and its contributors.
18: * 4. Neither the name of the University nor the names of its contributors
19: * may be used to endorse or promote products derived from this software
20: * without specific prior written permission.
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32: * SUCH DAMAGE.
33: */
34:
35: #ifndef lint
36: char copyright[] =
37: "@(#) Copyright (c) 1988 Mark Nudleman.\n\
38: @(#) Copyright (c) 1988 Regents of the University of California.\n\
39: All rights reserved.\n";
40: #endif /* not lint */
41:
42: #ifndef lint
43: /* from: static char sccsid[] = "@(#)main.c 5.13 (Berkeley) 6/1/90"; */
44: static char *rcsid = "$Id: main.c,v 1.3 1994/12/24 17:17:09 cgd Exp $";
45: #endif /* not lint */
46:
47: /*
48: * Entry point, initialization, miscellaneous routines.
49: */
50:
51: #include <sys/types.h>
52: #include <sys/file.h>
53: #include <stdio.h>
54: #include <string.h>
55: #include <less.h>
56:
57: int ispipe;
58: int new_file;
59: int is_tty;
60: char *current_file, *previous_file, *current_name, *next_name;
61: off_t prev_pos;
62: int any_display;
63: int scroll;
64: int ac;
65: char **av;
66: int curr_ac;
67: int quitting;
68:
69: extern int file;
70: extern int cbufs;
71: extern int errmsgs;
72:
73: extern char *tagfile;
74: extern int tagoption;
75:
76: /*
77: * Edit a new file.
78: * Filename "-" means standard input.
79: * No filename means the "current" file, from the command line.
80: */
81: edit(filename)
82: register char *filename;
83: {
84: extern int errno;
85: register int f;
86: register char *m;
87: off_t initial_pos, position();
88: static int didpipe;
89: char message[100], *p;
90: char *rindex(), *strerror(), *save(), *bad_file();
91:
92: initial_pos = NULL_POSITION;
93: if (filename == NULL || *filename == '\0') {
94: if (curr_ac >= ac) {
95: error("No current file");
96: return(0);
97: }
98: filename = save(av[curr_ac]);
99: }
100: else if (strcmp(filename, "#") == 0) {
101: if (*previous_file == '\0') {
102: error("no previous file");
103: return(0);
104: }
105: filename = save(previous_file);
106: initial_pos = prev_pos;
107: } else
108: filename = save(filename);
109:
110: /* use standard input. */
111: if (!strcmp(filename, "-")) {
112: if (didpipe) {
113: error("Can view standard input only once");
114: return(0);
115: }
116: f = 0;
117: }
118: else if ((m = bad_file(filename, message, sizeof(message))) != NULL) {
119: error(m);
120: free(filename);
121: return(0);
122: }
123: else if ((f = open(filename, O_RDONLY, 0)) < 0) {
124: (void)sprintf(message, "%s: %s", filename, strerror(errno));
125: error(message);
126: free(filename);
127: return(0);
128: }
129:
130: if (isatty(f)) {
131: /*
132: * Not really necessary to call this an error,
133: * but if the control terminal (for commands)
134: * and the input file (for data) are the same,
135: * we get weird results at best.
136: */
137: error("Can't take input from a terminal");
138: if (f > 0)
139: (void)close(f);
140: (void)free(filename);
141: return(0);
142: }
143:
144: /*
145: * We are now committed to using the new file.
146: * Close the current input file and set up to use the new one.
147: */
148: if (file > 0)
149: (void)close(file);
150: new_file = 1;
151: if (previous_file != NULL)
152: free(previous_file);
153: previous_file = current_file;
154: current_file = filename;
155: pos_clear();
156: prev_pos = position(TOP);
157: ispipe = (f == 0);
158: if (ispipe) {
159: didpipe = 1;
160: current_name = "stdin";
161: } else
162: current_name = (p = rindex(filename, '/')) ? p + 1 : filename;
163: if (curr_ac >= ac)
164: next_name = NULL;
165: else
166: next_name = av[curr_ac + 1];
167: file = f;
168: ch_init(cbufs, 0);
169: init_mark();
170:
171: if (is_tty) {
172: int no_display = !any_display;
173: any_display = 1;
174: if (no_display && errmsgs > 0) {
175: /*
176: * We displayed some messages on error output
177: * (file descriptor 2; see error() function).
178: * Before erasing the screen contents,
179: * display the file name and wait for a keystroke.
180: */
181: error(filename);
182: }
183: /*
184: * Indicate there is nothing displayed yet.
185: */
186: if (initial_pos != NULL_POSITION)
187: jump_loc(initial_pos);
188: clr_linenum();
189: }
190: return(1);
191: }
192:
193: /*
194: * Edit the next file in the command line list.
195: */
196: next_file(n)
197: int n;
198: {
199: extern int quit_at_eof;
200: off_t position();
201:
202: if (curr_ac + n >= ac) {
203: if (quit_at_eof || position(TOP) == NULL_POSITION)
204: quit();
205: error("No (N-th) next file");
206: }
207: else
208: (void)edit(av[curr_ac += n]);
209: }
210:
211: /*
212: * Edit the previous file in the command line list.
213: */
214: prev_file(n)
215: int n;
216: {
217: if (curr_ac - n < 0)
218: error("No (N-th) previous file");
219: else
220: (void)edit(av[curr_ac -= n]);
221: }
222:
223: /*
224: * copy a file directly to standard output; used if stdout is not a tty.
225: * the only processing is to squeeze multiple blank input lines.
226: */
227: static
228: cat_file()
229: {
230: extern int squeeze;
231: register int c, empty;
232:
233: if (squeeze) {
234: empty = 0;
235: while ((c = ch_forw_get()) != EOI)
236: if (c != '\n') {
237: putchr(c);
238: empty = 0;
239: }
240: else if (empty < 2) {
241: putchr(c);
242: ++empty;
243: }
244: }
245: else while ((c = ch_forw_get()) != EOI)
246: putchr(c);
247: flush();
248: }
249:
250: main(argc, argv)
251: int argc;
252: char **argv;
253: {
254: int envargc, argcnt;
255: char *envargv[2], *getenv();
256:
257: /*
258: * Process command line arguments and MORE environment arguments.
259: * Command line arguments override environment arguments.
260: */
261: if (envargv[1] = getenv("MORE")) {
262: envargc = 2;
263: envargv[0] = "more";
264: envargv[2] = NULL;
265: (void)option(envargc, envargv);
266: }
267: argcnt = option(argc, argv);
268: argv += argcnt;
269: argc -= argcnt;
270:
271: /*
272: * Set up list of files to be examined.
273: */
274: ac = argc;
275: av = argv;
276: curr_ac = 0;
277:
278: /*
279: * Set up terminal, etc.
280: */
281: is_tty = isatty(1);
282: if (!is_tty) {
283: /*
284: * Output is not a tty.
285: * Just copy the input file(s) to output.
286: */
287: if (ac < 1) {
288: (void)edit("-");
289: cat_file();
290: } else {
291: do {
292: (void)edit((char *)NULL);
293: if (file >= 0)
294: cat_file();
295: } while (++curr_ac < ac);
296: }
297: exit(0);
298: }
299:
300: raw_mode(1);
301: get_term();
302: open_getchr();
303: init();
304: init_signals(1);
305:
306: /* select the first file to examine. */
307: if (tagoption) {
308: /*
309: * A -t option was given; edit the file selected by the
310: * "tags" search, and search for the proper line in the file.
311: */
312: if (!tagfile || !edit(tagfile) || tagsearch())
313: quit();
314: }
315: else if (ac < 1)
316: (void)edit("-"); /* Standard input */
317: else {
318: /*
319: * Try all the files named as command arguments.
320: * We are simply looking for one which can be
321: * opened without error.
322: */
323: do {
324: (void)edit((char *)NULL);
325: } while (file < 0 && ++curr_ac < ac);
326: }
327:
328: if (file >= 0)
329: commands();
330: quit();
331: /*NOTREACHED*/
332: }
333:
334: /*
335: * Copy a string to a "safe" place
336: * (that is, to a buffer allocated by malloc).
337: */
338: char *
339: save(s)
340: char *s;
341: {
342: char *p, *strcpy(), *malloc();
343:
344: p = malloc((u_int)strlen(s)+1);
345: if (p == NULL)
346: {
347: error("cannot allocate memory");
348: quit();
349: }
350: return(strcpy(p, s));
351: }
352:
353: /*
354: * Exit the program.
355: */
356: quit()
357: {
358: /*
359: * Put cursor at bottom left corner, clear the line,
360: * reset the terminal modes, and exit.
361: */
362: quitting = 1;
363: lower_left();
364: clear_eol();
365: deinit();
366: flush();
367: raw_mode(0);
368: exit(0);
369: }