use malloc, not calloc; lint cleanups;
[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
b64140ba 30static char sccsid[] = "@(#)main.c 5.5 (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
bfe13c81 60public char * editor;
bfe13c81 61
bfe13c81
KB
62extern char * tagfile;
63extern char * tagpattern;
64extern int tagoption;
bfe13c81 65
bfe13c81
KB
66/*
67 * Edit a new file.
68 * Filename "-" means standard input.
69 * No filename means the "current" file, from the command line.
70 */
71 public void
72edit(filename)
73 register char *filename;
74{
75 register int f;
76 register char *m;
77 POSITION initial_pos;
78 char message[100];
79 static int didpipe;
80
81 initial_pos = NULL_POSITION;
82 if (filename == NULL || *filename == '\0')
83 {
84 if (curr_ac >= ac)
85 {
86 error("No current file");
87 return;
88 }
89 filename = save(av[curr_ac]);
90 } else if (strcmp(filename, "#") == 0)
91 {
92 if (*previous_file == '\0')
93 {
94 error("no previous file");
95 return;
96 }
97 filename = save(previous_file);
98 initial_pos = prev_pos;
99 } else
100 filename = save(filename);
101
102 if (strcmp(filename, "-") == 0)
103 {
104 /*
105 * Use standard input.
106 */
107 if (didpipe)
108 {
109 error("Can view standard input only once");
110 return;
111 }
112 f = 0;
113 } else if ((m = bad_file(filename, message, sizeof(message))) != NULL)
114 {
115 error(m);
116 free(filename);
117 return;
118 } else if ((f = open(filename, 0)) < 0)
119 {
120 error(errno_message(filename, message, sizeof(message)));
121 free(filename);
122 return;
123 }
124
125 if (isatty(f))
126 {
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 close(f);
136 free(filename);
137 return;
138 }
139
bfe13c81
KB
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 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 prev_pos = position(TOP);
152 ispipe = (f == 0);
153 if (ispipe)
154 didpipe = 1;
155 file = f;
156 ch_init(cbufs, 0);
157 init_mark();
158
159 if (every_first_cmd != NULL)
160 first_cmd = every_first_cmd;
161
162 if (is_tty)
163 {
164 int no_display = !any_display;
165 any_display = 1;
166 if (no_display && errmsgs > 0)
167 {
168 /*
169 * We displayed some messages on error output
170 * (file descriptor 2; see error() function).
171 * Before erasing the screen contents,
172 * display the file name and wait for a keystroke.
173 */
174 error(filename);
175 }
176 /*
177 * Indicate there is nothing displayed yet.
178 */
179 pos_clear();
180 if (initial_pos != NULL_POSITION)
181 jump_loc(initial_pos);
182 clr_linenum();
183 }
184}
185
186/*
187 * Edit the next file in the command line list.
188 */
189 public void
190next_file(n)
191 int n;
192{
193 if (curr_ac + n >= ac)
194 {
195 if (quit_at_eof)
196 quit();
197 error("No (N-th) next file");
198 } else
199 edit(av[curr_ac += n]);
200}
201
202/*
203 * Edit the previous file in the command line list.
204 */
205 public void
206prev_file(n)
207 int n;
208{
209 if (curr_ac - n < 0)
210 error("No (N-th) previous file");
211 else
212 edit(av[curr_ac -= n]);
213}
214
215/*
216 * Copy a file directly to standard output.
217 * Used if standard output is not a tty.
218 */
219 static void
220cat_file()
221{
222 register int c;
223
224 while ((c = ch_forw_get()) != EOI)
225 putchr(c);
226 flush();
227}
228
bfe13c81
KB
229/*
230 * Entry point.
231 */
232main(argc, argv)
233 int argc;
234 char *argv[];
235{
236 char *getenv();
237
238
239 /*
240 * Process command line arguments and LESS environment arguments.
241 * Command line arguments override environment arguments.
242 */
243 init_prompt();
244 init_option();
245 scan_option(getenv("LESS"));
246 argv++;
247 while ( (--argc > 0) &&
248 (argv[0][0] == '-' || argv[0][0] == '+') &&
249 argv[0][1] != '\0')
250 scan_option(*argv++);
251
bfe13c81
KB
252 editor = getenv("EDITOR");
253 if (editor == NULL || *editor == '\0')
254 editor = EDIT_PGM;
bfe13c81
KB
255
256 /*
257 * Set up list of files to be examined.
258 */
259 ac = argc;
260 av = argv;
261 curr_ac = 0;
262
263 /*
264 * Set up terminal, etc.
265 */
266 is_tty = isatty(1);
267 if (!is_tty)
268 {
269 /*
270 * Output is not a tty.
271 * Just copy the input file(s) to output.
272 */
273 if (ac < 1)
274 {
275 edit("-");
276 cat_file();
277 } else
278 {
279 do
280 {
281 edit((char *)NULL);
282 if (file >= 0)
283 cat_file();
284 } while (++curr_ac < ac);
285 }
286 exit(0);
287 }
288
289 raw_mode(1);
290 get_term();
291 open_getchr();
292 init();
293 init_cmd();
294
295 init_signals(1);
296
297 /*
298 * Select the first file to examine.
299 */
bfe13c81
KB
300 if (tagoption)
301 {
302 /*
303 * A -t option was given.
304 * Verify that no filenames were also given.
305 * Edit the file selected by the "tags" search,
306 * and search for the proper line in the file.
307 */
308 if (ac > 0)
309 {
310 error("No filenames allowed with -t option");
311 quit();
312 }
313 if (tagfile == NULL)
314 quit();
315 edit(tagfile);
316 if (file < 0)
317 quit();
318 if (tagsearch())
319 quit();
320 } else
bfe13c81
KB
321 if (ac < 1)
322 edit("-"); /* Standard input */
323 else
324 {
325 /*
326 * Try all the files named as command arguments.
327 * We are simply looking for one which can be
328 * opened without error.
329 */
330 do
331 {
332 edit((char *)NULL);
333 } while (file < 0 && ++curr_ac < ac);
334 }
335
336 if (file >= 0)
337 commands();
338 quit();
339 /*NOTREACHED*/
340}
341
342/*
343 * Copy a string, truncating to the specified length if necessary.
344 * Unlike strncpy(), the resulting string is guaranteed to be null-terminated.
345 */
346 public void
347strtcpy(to, from, len)
348 char *to;
349 char *from;
350 unsigned int len;
351{
352 strncpy(to, from, len);
353 to[len-1] = '\0';
354}
355
356/*
357 * Copy a string to a "safe" place
358 * (that is, to a buffer allocated by calloc).
359 */
360 public char *
361save(s)
362 char *s;
363{
364 register char *p;
365
366 p = calloc(strlen(s)+1, sizeof(char));
367 if (p == NULL)
368 {
369 error("cannot allocate memory");
370 quit();
371 }
372 strcpy(p, s);
373 return (p);
374}
375
376/*
377 * Exit the program.
378 */
379 public void
380quit()
381{
382 /*
383 * Put cursor at bottom left corner, clear the line,
384 * reset the terminal modes, and exit.
385 */
386 quitting = 1;
bfe13c81
KB
387 lower_left();
388 clear_eol();
389 deinit();
390 flush();
391 raw_mode(0);
392 exit(0);
393}