rip out TAGS option, make default
[unix-history] / usr / src / usr.bin / more / main.c
CommitLineData
bfe13c81
KB
1/*
2 * Copyright (c) 1988 Mark Nudleman
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * Mark Nudleman.
8 *
9 * Redistribution and use in source and binary forms are permitted
10 * provided that the above copyright notice and this paragraph are
11 * duplicated in all such forms and that any documentation,
12 * advertising materials, and other materials related to such
13 * distribution and use acknowledge that the software was developed
14 * by the University of California, Berkeley. The name of the
15 * University may not be used to endorse or promote products derived
16 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
19 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22#ifndef lint
23char copyright[] =
24"@(#) Copyright (c) 1988 Mark Nudleman.\n\
25@(#) Copyright (c) 1988 Regents of the University of California.\n\
26 All rights reserved.\n";
27#endif /* not lint */
28
29#ifndef lint
e867893c 30static char sccsid[] = "@(#)main.c 5.4 (Berkeley) %G%";
bfe13c81
KB
31#endif /* not lint */
32
33/*
34 * Entry point, initialization, miscellaneous routines.
35 */
36
37#include "less.h"
38#include "position.h"
39
40public int ispipe;
41public char * first_cmd;
42public char * every_first_cmd;
43public int new_file;
44public int is_tty;
45public char *current_file;
46public char *previous_file;
47public POSITION prev_pos;
48public int any_display;
49public int scroll;
50public int ac;
51public char ** av;
52public int curr_ac;
53public int quitting;
54
55extern int file;
56extern int quit_at_eof;
57extern int cbufs;
58extern int errmsgs;
59
60#if LOGFILE
61public int logfile = -1;
62public int force_logfile = 0;
63public char * namelogfile = NULL;
64#endif
65
bfe13c81 66public char * editor;
bfe13c81 67
bfe13c81
KB
68extern char * tagfile;
69extern char * tagpattern;
70extern int tagoption;
bfe13c81 71
bfe13c81
KB
72/*
73 * Edit a new file.
74 * Filename "-" means standard input.
75 * No filename means the "current" file, from the command line.
76 */
77 public void
78edit(filename)
79 register char *filename;
80{
81 register int f;
82 register char *m;
83 POSITION initial_pos;
84 char message[100];
85 static int didpipe;
86
87 initial_pos = NULL_POSITION;
88 if (filename == NULL || *filename == '\0')
89 {
90 if (curr_ac >= ac)
91 {
92 error("No current file");
93 return;
94 }
95 filename = save(av[curr_ac]);
96 } else if (strcmp(filename, "#") == 0)
97 {
98 if (*previous_file == '\0')
99 {
100 error("no previous file");
101 return;
102 }
103 filename = save(previous_file);
104 initial_pos = prev_pos;
105 } else
106 filename = save(filename);
107
108 if (strcmp(filename, "-") == 0)
109 {
110 /*
111 * Use standard input.
112 */
113 if (didpipe)
114 {
115 error("Can view standard input only once");
116 return;
117 }
118 f = 0;
119 } else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
120 {
121 error(m);
122 free(filename);
123 return;
124 } else if ((f = open(filename, 0)) < 0)
125 {
126 error(errno_message(filename, message, sizeof(message)));
127 free(filename);
128 return;
129 }
130
131 if (isatty(f))
132 {
133 /*
134 * Not really necessary to call this an error,
135 * but if the control terminal (for commands)
136 * and the input file (for data) are the same,
137 * we get weird results at best.
138 */
139 error("Can't take input from a terminal");
140 if (f > 0)
141 close(f);
142 free(filename);
143 return;
144 }
145
146#if LOGFILE
147 if (f == 0 && namelogfile != NULL && is_tty)
148 use_logfile();
149#endif
150
151 /*
152 * We are now committed to using the new file.
153 * Close the current input file and set up to use the new one.
154 */
155 if (file > 0)
156 close(file);
157 new_file = 1;
158 if (previous_file != NULL)
159 free(previous_file);
160 previous_file = current_file;
161 current_file = filename;
162 prev_pos = position(TOP);
163 ispipe = (f == 0);
164 if (ispipe)
165 didpipe = 1;
166 file = f;
167 ch_init(cbufs, 0);
168 init_mark();
169
170 if (every_first_cmd != NULL)
171 first_cmd = every_first_cmd;
172
173 if (is_tty)
174 {
175 int no_display = !any_display;
176 any_display = 1;
177 if (no_display && errmsgs > 0)
178 {
179 /*
180 * We displayed some messages on error output
181 * (file descriptor 2; see error() function).
182 * Before erasing the screen contents,
183 * display the file name and wait for a keystroke.
184 */
185 error(filename);
186 }
187 /*
188 * Indicate there is nothing displayed yet.
189 */
190 pos_clear();
191 if (initial_pos != NULL_POSITION)
192 jump_loc(initial_pos);
193 clr_linenum();
194 }
195}
196
197/*
198 * Edit the next file in the command line list.
199 */
200 public void
201next_file(n)
202 int n;
203{
204 if (curr_ac + n >= ac)
205 {
206 if (quit_at_eof)
207 quit();
208 error("No (N-th) next file");
209 } else
210 edit(av[curr_ac += n]);
211}
212
213/*
214 * Edit the previous file in the command line list.
215 */
216 public void
217prev_file(n)
218 int n;
219{
220 if (curr_ac - n < 0)
221 error("No (N-th) previous file");
222 else
223 edit(av[curr_ac -= n]);
224}
225
226/*
227 * Copy a file directly to standard output.
228 * Used if standard output is not a tty.
229 */
230 static void
231cat_file()
232{
233 register int c;
234
235 while ((c = ch_forw_get()) != EOI)
236 putchr(c);
237 flush();
238}
239
240#if LOGFILE
241
242use_logfile()
243{
244 int exists;
245 int answer;
246 char message[100];
247
248 /*
249 * If he asked for a log file and we have opened standard input,
250 * create the log file.
251 * We take care not to blindly overwrite an existing file.
252 */
253 end_logfile();
254
255 /*
256 * {{ We could use access() here. }}
257 */
258 exists = open(namelogfile, 0);
259 close(exists);
260 exists = (exists >= 0);
261
262 if (exists && !force_logfile)
263 {
264 static char w[] = "WARNING: log file exists: ";
265 strcpy(message, w);
266 strtcpy(message+sizeof(w)-1, namelogfile,
267 sizeof(message)-sizeof(w));
268 error(message);
269 answer = 'X'; /* Ask the user what to do */
270 } else
271 answer = 'O'; /* Create the log file */
272
273loop:
274 switch (answer)
275 {
276 case 'O': case 'o':
277 logfile = creat(namelogfile, 0644);
278 break;
279 case 'A': case 'a':
280 logfile = open(namelogfile, 1);
51eb338d 281 if (lseek(logfile, (off_t)0, L_XTND) < 0)
bfe13c81
KB
282 {
283 close(logfile);
284 logfile = -1;
285 }
286 break;
287 case 'D': case 'd':
288 answer = 0; /* Don't print an error message */
289 break;
290 case 'q':
291 quit();
292 default:
293 putstr("\n Overwrite, Append, or Don't log? ");
294 answer = getchr();
295 putstr("\n");
296 flush();
297 goto loop;
298 }
299
300 if (logfile < 0 && answer != 0)
301 {
302 sprintf(message, "Cannot write to \"%s\"",
303 namelogfile);
304 error(message);
305 }
306}
307
308/*
309 * Entry point.
310 */
311main(argc, argv)
312 int argc;
313 char *argv[];
314{
315 char *getenv();
316
317
318 /*
319 * Process command line arguments and LESS environment arguments.
320 * Command line arguments override environment arguments.
321 */
322 init_prompt();
323 init_option();
324 scan_option(getenv("LESS"));
325 argv++;
326 while ( (--argc > 0) &&
327 (argv[0][0] == '-' || argv[0][0] == '+') &&
328 argv[0][1] != '\0')
329 scan_option(*argv++);
330
bfe13c81
KB
331 editor = getenv("EDITOR");
332 if (editor == NULL || *editor == '\0')
333 editor = EDIT_PGM;
bfe13c81
KB
334
335 /*
336 * Set up list of files to be examined.
337 */
338 ac = argc;
339 av = argv;
340 curr_ac = 0;
341
342 /*
343 * Set up terminal, etc.
344 */
345 is_tty = isatty(1);
346 if (!is_tty)
347 {
348 /*
349 * Output is not a tty.
350 * Just copy the input file(s) to output.
351 */
352 if (ac < 1)
353 {
354 edit("-");
355 cat_file();
356 } else
357 {
358 do
359 {
360 edit((char *)NULL);
361 if (file >= 0)
362 cat_file();
363 } while (++curr_ac < ac);
364 }
365 exit(0);
366 }
367
368 raw_mode(1);
369 get_term();
370 open_getchr();
371 init();
372 init_cmd();
373
374 init_signals(1);
375
376 /*
377 * Select the first file to examine.
378 */
bfe13c81
KB
379 if (tagoption)
380 {
381 /*
382 * A -t option was given.
383 * Verify that no filenames were also given.
384 * Edit the file selected by the "tags" search,
385 * and search for the proper line in the file.
386 */
387 if (ac > 0)
388 {
389 error("No filenames allowed with -t option");
390 quit();
391 }
392 if (tagfile == NULL)
393 quit();
394 edit(tagfile);
395 if (file < 0)
396 quit();
397 if (tagsearch())
398 quit();
399 } else
bfe13c81
KB
400 if (ac < 1)
401 edit("-"); /* Standard input */
402 else
403 {
404 /*
405 * Try all the files named as command arguments.
406 * We are simply looking for one which can be
407 * opened without error.
408 */
409 do
410 {
411 edit((char *)NULL);
412 } while (file < 0 && ++curr_ac < ac);
413 }
414
415 if (file >= 0)
416 commands();
417 quit();
418 /*NOTREACHED*/
419}
420
421/*
422 * Copy a string, truncating to the specified length if necessary.
423 * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
424 */
425 public void
426strtcpy(to, from, len)
427 char *to;
428 char *from;
429 unsigned int len;
430{
431 strncpy(to, from, len);
432 to[len-1] = '\0';
433}
434
435/*
436 * Copy a string to a "safe" place
437 * (that is, to a buffer allocated by calloc).
438 */
439 public char *
440save(s)
441 char *s;
442{
443 register char *p;
444
445 p = calloc(strlen(s)+1, sizeof(char));
446 if (p == NULL)
447 {
448 error("cannot allocate memory");
449 quit();
450 }
451 strcpy(p, s);
452 return (p);
453}
454
455/*
456 * Exit the program.
457 */
458 public void
459quit()
460{
461 /*
462 * Put cursor at bottom left corner, clear the line,
463 * reset the terminal modes, and exit.
464 */
465 quitting = 1;
466#if LOGFILE
467 end_logfile();
468#endif
469 lower_left();
470 clear_eol();
471 deinit();
472 flush();
473 raw_mode(0);
474 exit(0);
475}