main.c revision 1.2.2.2 1 /*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988, 1993
4 * Regents of the University of California. 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, 1993
39 Regents of the University of California. All rights reserved.\n";
40 #endif /* not lint */
41
42 #ifndef lint
43 static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/7/93";
44 #endif /* not lint */
45
46 /*
47 * Entry point, initialization, miscellaneous routines.
48 */
49
50 #include <sys/types.h>
51 #include <sys/file.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <less.h>
55
56 int ispipe;
57 int new_file;
58 int is_tty;
59 char *current_file, *previous_file, *current_name, *next_name;
60 off_t prev_pos;
61 int any_display;
62 int scroll;
63 int ac;
64 char **av;
65 int curr_ac;
66 int quitting;
67
68 extern int file;
69 extern int cbufs;
70 extern int errmsgs;
71
72 /*
73 * Edit a new file.
74 * Filename "-" means standard input.
75 * No filename means the "current" file, from the command line.
76 */
77 edit(filename)
78 register char *filename;
79 {
80 extern int errno;
81 register int f;
82 register char *m;
83 off_t initial_pos, position();
84 static int didpipe;
85 char message[100], *p;
86 char *rindex(), *strerror(), *save(), *bad_file();
87
88 initial_pos = NULL_POSITION;
89 if (filename == NULL || *filename == '\0') {
90 if (curr_ac >= ac) {
91 error("No current file");
92 return(0);
93 }
94 filename = save(av[curr_ac]);
95 }
96 else if (strcmp(filename, "#") == 0) {
97 if (*previous_file == '\0') {
98 error("no previous file");
99 return(0);
100 }
101 filename = save(previous_file);
102 initial_pos = prev_pos;
103 } else
104 filename = save(filename);
105
106 /* use standard input. */
107 if (!strcmp(filename, "-")) {
108 if (didpipe) {
109 error("Can view standard input only once");
110 return(0);
111 }
112 f = 0;
113 }
114 else if ((m = bad_file(filename, message, sizeof(message))) != NULL) {
115 error(m);
116 free(filename);
117 return(0);
118 }
119 else if ((f = open(filename, O_RDONLY, 0)) < 0) {
120 (void)sprintf(message, "%s: %s", filename, strerror(errno));
121 error(message);
122 free(filename);
123 return(0);
124 }
125
126 if (isatty(f)) {
127 /*
128 * Not really necessary to call this an error,
129 * but if the control terminal (for commands)
130 * and the input file (for data) are the same,
131 * we get weird results at best.
132 */
133 error("Can't take input from a terminal");
134 if (f > 0)
135 (void)close(f);
136 (void)free(filename);
137 return(0);
138 }
139
140 /*
141 * We are now committed to using the new file.
142 * Close the current input file and set up to use the new one.
143 */
144 if (file > 0)
145 (void)close(file);
146 new_file = 1;
147 if (previous_file != NULL)
148 free(previous_file);
149 previous_file = current_file;
150 current_file = filename;
151 pos_clear();
152 prev_pos = position(TOP);
153 ispipe = (f == 0);
154 if (ispipe) {
155 didpipe = 1;
156 current_name = "stdin";
157 } else
158 current_name = (p = rindex(filename, '/')) ? p + 1 : filename;
159 if (curr_ac >= ac)
160 next_name = NULL;
161 else
162 next_name = av[curr_ac + 1];
163 file = f;
164 ch_init(cbufs, 0);
165 init_mark();
166
167 if (is_tty) {
168 int no_display = !any_display;
169 any_display = 1;
170 if (no_display && errmsgs > 0) {
171 /*
172 * We displayed some messages on error output
173 * (file descriptor 2; see error() function).
174 * Before erasing the screen contents,
175 * display the file name and wait for a keystroke.
176 */
177 error(filename);
178 }
179 /*
180 * Indicate there is nothing displayed yet.
181 */
182 if (initial_pos != NULL_POSITION)
183 jump_loc(initial_pos);
184 clr_linenum();
185 }
186 return(1);
187 }
188
189 /*
190 * Edit the next file in the command line list.
191 */
192 next_file(n)
193 int n;
194 {
195 extern int quit_at_eof;
196 off_t position();
197
198 if (curr_ac + n >= ac) {
199 if (quit_at_eof || position(TOP) == NULL_POSITION)
200 quit();
201 error("No (N-th) next file");
202 }
203 else
204 (void)edit(av[curr_ac += n]);
205 }
206
207 /*
208 * Edit the previous file in the command line list.
209 */
210 prev_file(n)
211 int n;
212 {
213 if (curr_ac - n < 0)
214 error("No (N-th) previous file");
215 else
216 (void)edit(av[curr_ac -= n]);
217 }
218
219 /*
220 * copy a file directly to standard output; used if stdout is not a tty.
221 * the only processing is to squeeze multiple blank input lines.
222 */
223 static
224 cat_file()
225 {
226 extern int squeeze;
227 register int c, empty;
228
229 if (squeeze) {
230 empty = 0;
231 while ((c = ch_forw_get()) != EOI)
232 if (c != '\n') {
233 putchr(c);
234 empty = 0;
235 }
236 else if (empty < 2) {
237 putchr(c);
238 ++empty;
239 }
240 }
241 else while ((c = ch_forw_get()) != EOI)
242 putchr(c);
243 flush();
244 }
245
246 main(argc, argv)
247 int argc;
248 char **argv;
249 {
250 int envargc, argcnt;
251 char *envargv[2], *getenv();
252
253 /*
254 * Process command line arguments and MORE environment arguments.
255 * Command line arguments override environment arguments.
256 */
257 if (envargv[1] = getenv("MORE")) {
258 envargc = 2;
259 envargv[0] = "more";
260 envargv[2] = NULL;
261 (void)option(envargc, envargv);
262 }
263 argcnt = option(argc, argv);
264 argv += argcnt;
265 argc -= argcnt;
266
267 /*
268 * Set up list of files to be examined.
269 */
270 ac = argc;
271 av = argv;
272 curr_ac = 0;
273
274 /*
275 * Set up terminal, etc.
276 */
277 is_tty = isatty(1);
278 if (!is_tty) {
279 /*
280 * Output is not a tty.
281 * Just copy the input file(s) to output.
282 */
283 if (ac < 1) {
284 (void)edit("-");
285 cat_file();
286 } else {
287 do {
288 (void)edit((char *)NULL);
289 if (file >= 0)
290 cat_file();
291 } while (++curr_ac < ac);
292 }
293 exit(0);
294 }
295
296 raw_mode(1);
297 get_term();
298 open_getchr();
299 init();
300 init_signals(1);
301
302 /* select the first file to examine. */
303 if (ac < 1)
304 (void)edit("-"); /* Standard input */
305 else {
306 /*
307 * Try all the files named as command arguments.
308 * We are simply looking for one which can be
309 * opened without error.
310 */
311 do {
312 (void)edit((char *)NULL);
313 } while (file < 0 && ++curr_ac < ac);
314 }
315
316 if (file >= 0)
317 commands();
318 quit();
319 /*NOTREACHED*/
320 }
321
322 /*
323 * Copy a string to a "safe" place
324 * (that is, to a buffer allocated by malloc).
325 */
326 char *
327 save(s)
328 char *s;
329 {
330 char *p, *strcpy(), *malloc();
331
332 p = malloc((u_int)strlen(s)+1);
333 if (p == NULL)
334 {
335 error("cannot allocate memory");
336 quit();
337 }
338 return(strcpy(p, s));
339 }
340
341 /*
342 * Exit the program.
343 */
344 quit()
345 {
346 /*
347 * Put cursor at bottom left corner, clear the line,
348 * reset the terminal modes, and exit.
349 */
350 quitting = 1;
351 lower_left();
352 clear_eol();
353 deinit();
354 flush();
355 raw_mode(0);
356 exit(0);
357 }
358