main.c revision 1.1.1.1 1 1.1 tron /* $NetBSD */
2 1.1 tron
3 1.1 tron /*
4 1.1 tron * Copyright (C) 1984-2011 Mark Nudelman
5 1.1 tron *
6 1.1 tron * You may distribute under the terms of either the GNU General Public
7 1.1 tron * License or the Less License, as specified in the README file.
8 1.1 tron *
9 1.1 tron * For more information about less, or for information on how to
10 1.1 tron * contact the author, see the README file.
11 1.1 tron */
12 1.1 tron
13 1.1 tron
14 1.1 tron /*
15 1.1 tron * Entry point, initialization, miscellaneous routines.
16 1.1 tron */
17 1.1 tron
18 1.1 tron #include "less.h"
19 1.1 tron #if MSDOS_COMPILER==WIN32C
20 1.1 tron #include <windows.h>
21 1.1 tron #endif
22 1.1 tron
23 1.1 tron public char * every_first_cmd = NULL;
24 1.1 tron public int new_file;
25 1.1 tron public int is_tty;
26 1.1 tron public IFILE curr_ifile = NULL_IFILE;
27 1.1 tron public IFILE old_ifile = NULL_IFILE;
28 1.1 tron public struct scrpos initial_scrpos;
29 1.1 tron public int any_display = FALSE;
30 1.1 tron public POSITION start_attnpos = NULL_POSITION;
31 1.1 tron public POSITION end_attnpos = NULL_POSITION;
32 1.1 tron public int wscroll;
33 1.1 tron public char * progname;
34 1.1 tron public int quitting;
35 1.1 tron public int secure;
36 1.1 tron public int dohelp;
37 1.1 tron
38 1.1 tron #if LOGFILE
39 1.1 tron public int logfile = -1;
40 1.1 tron public int force_logfile = FALSE;
41 1.1 tron public char * namelogfile = NULL;
42 1.1 tron #endif
43 1.1 tron
44 1.1 tron #if EDITOR
45 1.1 tron public char * editor;
46 1.1 tron public char * editproto;
47 1.1 tron #endif
48 1.1 tron
49 1.1 tron #if TAGS
50 1.1 tron extern char * tags;
51 1.1 tron extern char * tagoption;
52 1.1 tron extern int jump_sline;
53 1.1 tron #endif
54 1.1 tron
55 1.1 tron #ifdef WIN32
56 1.1 tron static char consoleTitle[256];
57 1.1 tron #endif
58 1.1 tron
59 1.1 tron extern int less_is_more;
60 1.1 tron extern int missing_cap;
61 1.1 tron extern int know_dumb;
62 1.1 tron extern int quit_if_one_screen;
63 1.1 tron extern int pr_type;
64 1.1 tron
65 1.1 tron
66 1.1 tron /*
67 1.1 tron * Entry point.
68 1.1 tron */
69 1.1 tron int
70 1.1 tron main(argc, argv)
71 1.1 tron int argc;
72 1.1 tron char *argv[];
73 1.1 tron {
74 1.1 tron IFILE ifile;
75 1.1 tron char *s;
76 1.1 tron
77 1.1 tron #ifdef __EMX__
78 1.1 tron _response(&argc, &argv);
79 1.1 tron _wildcard(&argc, &argv);
80 1.1 tron #endif
81 1.1 tron
82 1.1 tron progname = *argv++;
83 1.1 tron argc--;
84 1.1 tron
85 1.1 tron secure = 0;
86 1.1 tron s = lgetenv("LESSSECURE");
87 1.1 tron if (s != NULL && *s != '\0')
88 1.1 tron secure = 1;
89 1.1 tron
90 1.1 tron #ifdef WIN32
91 1.1 tron if (getenv("HOME") == NULL)
92 1.1 tron {
93 1.1 tron /*
94 1.1 tron * If there is no HOME environment variable,
95 1.1 tron * try the concatenation of HOMEDRIVE + HOMEPATH.
96 1.1 tron */
97 1.1 tron char *drive = getenv("HOMEDRIVE");
98 1.1 tron char *path = getenv("HOMEPATH");
99 1.1 tron if (drive != NULL && path != NULL)
100 1.1 tron {
101 1.1 tron char *env = (char *) ecalloc(strlen(drive) +
102 1.1 tron strlen(path) + 6, sizeof(char));
103 1.1 tron strcpy(env, "HOME=");
104 1.1 tron strcat(env, drive);
105 1.1 tron strcat(env, path);
106 1.1 tron putenv(env);
107 1.1 tron }
108 1.1 tron }
109 1.1 tron GetConsoleTitle(consoleTitle, sizeof(consoleTitle)/sizeof(char));
110 1.1 tron #endif /* WIN32 */
111 1.1 tron
112 1.1 tron /*
113 1.1 tron * Process command line arguments and LESS environment arguments.
114 1.1 tron * Command line arguments override environment arguments.
115 1.1 tron */
116 1.1 tron is_tty = isatty(1);
117 1.1 tron get_term();
118 1.1 tron init_cmds();
119 1.1 tron init_charset();
120 1.1 tron init_line();
121 1.1 tron init_cmdhist();
122 1.1 tron init_option();
123 1.1 tron init_search();
124 1.1 tron
125 1.1 tron /*
126 1.1 tron * If the name of the executable program is "more",
127 1.1 tron * act like LESS_IS_MORE is set.
128 1.1 tron */
129 1.1 tron for (s = progname + strlen(progname); s > progname; s--)
130 1.1 tron {
131 1.1 tron if (s[-1] == PATHNAME_SEP[0])
132 1.1 tron break;
133 1.1 tron }
134 1.1 tron if (strcmp(s, "more") == 0)
135 1.1 tron less_is_more = 1;
136 1.1 tron
137 1.1 tron init_prompt();
138 1.1 tron
139 1.1 tron s = lgetenv(less_is_more ? "MORE" : "LESS");
140 1.1 tron if (s != NULL)
141 1.1 tron scan_option(save(s));
142 1.1 tron
143 1.1 tron #define isoptstring(s) (((s)[0] == '-' || (s)[0] == '+') && (s)[1] != '\0')
144 1.1 tron while (argc > 0 && (isoptstring(*argv) || isoptpending()))
145 1.1 tron {
146 1.1 tron s = *argv++;
147 1.1 tron argc--;
148 1.1 tron if (strcmp(s, "--") == 0)
149 1.1 tron break;
150 1.1 tron scan_option(s);
151 1.1 tron }
152 1.1 tron #undef isoptstring
153 1.1 tron
154 1.1 tron if (isoptpending())
155 1.1 tron {
156 1.1 tron /*
157 1.1 tron * Last command line option was a flag requiring a
158 1.1 tron * following string, but there was no following string.
159 1.1 tron */
160 1.1 tron nopendopt();
161 1.1 tron quit(QUIT_OK);
162 1.1 tron }
163 1.1 tron
164 1.1 tron if (less_is_more && get_quit_at_eof())
165 1.1 tron quit_if_one_screen = TRUE;
166 1.1 tron
167 1.1 tron #if EDITOR
168 1.1 tron editor = lgetenv("VISUAL");
169 1.1 tron if (editor == NULL || *editor == '\0')
170 1.1 tron {
171 1.1 tron editor = lgetenv("EDITOR");
172 1.1 tron if (editor == NULL || *editor == '\0')
173 1.1 tron editor = EDIT_PGM;
174 1.1 tron }
175 1.1 tron editproto = lgetenv("LESSEDIT");
176 1.1 tron if (editproto == NULL || *editproto == '\0')
177 1.1 tron editproto = "%E ?lm+%lm. %f";
178 1.1 tron #endif
179 1.1 tron
180 1.1 tron /*
181 1.1 tron * Call get_ifile with all the command line filenames
182 1.1 tron * to "register" them with the ifile system.
183 1.1 tron */
184 1.1 tron ifile = NULL_IFILE;
185 1.1 tron if (dohelp)
186 1.1 tron ifile = get_ifile(FAKE_HELPFILE, ifile);
187 1.1 tron while (argc-- > 0)
188 1.1 tron {
189 1.1 tron char *filename;
190 1.1 tron #if (MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC)
191 1.1 tron /*
192 1.1 tron * Because the "shell" doesn't expand filename patterns,
193 1.1 tron * treat each argument as a filename pattern rather than
194 1.1 tron * a single filename.
195 1.1 tron * Expand the pattern and iterate over the expanded list.
196 1.1 tron */
197 1.1 tron struct textlist tlist;
198 1.1 tron char *gfilename;
199 1.1 tron
200 1.1 tron gfilename = lglob(*argv++);
201 1.1 tron init_textlist(&tlist, gfilename);
202 1.1 tron filename = NULL;
203 1.1 tron while ((filename = forw_textlist(&tlist, filename)) != NULL)
204 1.1 tron {
205 1.1 tron (void) get_ifile(filename, ifile);
206 1.1 tron ifile = prev_ifile(NULL_IFILE);
207 1.1 tron }
208 1.1 tron free(gfilename);
209 1.1 tron #else
210 1.1 tron filename = shell_quote(*argv);
211 1.1 tron if (filename == NULL)
212 1.1 tron filename = *argv;
213 1.1 tron argv++;
214 1.1 tron (void) get_ifile(filename, ifile);
215 1.1 tron ifile = prev_ifile(NULL_IFILE);
216 1.1 tron #endif
217 1.1 tron }
218 1.1 tron /*
219 1.1 tron * Set up terminal, etc.
220 1.1 tron */
221 1.1 tron if (!is_tty)
222 1.1 tron {
223 1.1 tron /*
224 1.1 tron * Output is not a tty.
225 1.1 tron * Just copy the input file(s) to output.
226 1.1 tron */
227 1.1 tron SET_BINARY(1);
228 1.1 tron if (nifile() == 0)
229 1.1 tron {
230 1.1 tron if (edit_stdin() == 0)
231 1.1 tron cat_file();
232 1.1 tron } else if (edit_first() == 0)
233 1.1 tron {
234 1.1 tron do {
235 1.1 tron cat_file();
236 1.1 tron } while (edit_next(1) == 0);
237 1.1 tron }
238 1.1 tron quit(QUIT_OK);
239 1.1 tron }
240 1.1 tron
241 1.1 tron if (missing_cap && !know_dumb)
242 1.1 tron error("WARNING: terminal is not fully functional", NULL_PARG);
243 1.1 tron init_mark();
244 1.1 tron open_getchr();
245 1.1 tron raw_mode(1);
246 1.1 tron init_signals(1);
247 1.1 tron
248 1.1 tron /*
249 1.1 tron * Select the first file to examine.
250 1.1 tron */
251 1.1 tron #if TAGS
252 1.1 tron if (tagoption != NULL || strcmp(tags, "-") == 0)
253 1.1 tron {
254 1.1 tron /*
255 1.1 tron * A -t option was given.
256 1.1 tron * Verify that no filenames were also given.
257 1.1 tron * Edit the file selected by the "tags" search,
258 1.1 tron * and search for the proper line in the file.
259 1.1 tron */
260 1.1 tron if (nifile() > 0)
261 1.1 tron {
262 1.1 tron error("No filenames allowed with -t option", NULL_PARG);
263 1.1 tron quit(QUIT_ERROR);
264 1.1 tron }
265 1.1 tron findtag(tagoption);
266 1.1 tron if (edit_tagfile()) /* Edit file which contains the tag */
267 1.1 tron quit(QUIT_ERROR);
268 1.1 tron /*
269 1.1 tron * Search for the line which contains the tag.
270 1.1 tron * Set up initial_scrpos so we display that line.
271 1.1 tron */
272 1.1 tron initial_scrpos.pos = tagsearch();
273 1.1 tron if (initial_scrpos.pos == NULL_POSITION)
274 1.1 tron quit(QUIT_ERROR);
275 1.1 tron initial_scrpos.ln = jump_sline;
276 1.1 tron } else
277 1.1 tron #endif
278 1.1 tron if (nifile() == 0)
279 1.1 tron {
280 1.1 tron if (edit_stdin()) /* Edit standard input */
281 1.1 tron quit(QUIT_ERROR);
282 1.1 tron } else
283 1.1 tron {
284 1.1 tron if (edit_first()) /* Edit first valid file in cmd line */
285 1.1 tron quit(QUIT_ERROR);
286 1.1 tron }
287 1.1 tron
288 1.1 tron init();
289 1.1 tron commands();
290 1.1 tron quit(QUIT_OK);
291 1.1 tron /*NOTREACHED*/
292 1.1 tron return (0);
293 1.1 tron }
294 1.1 tron
295 1.1 tron /*
296 1.1 tron * Copy a string to a "safe" place
297 1.1 tron * (that is, to a buffer allocated by calloc).
298 1.1 tron */
299 1.1 tron public char *
300 1.1 tron save(s)
301 1.1 tron char *s;
302 1.1 tron {
303 1.1 tron register char *p;
304 1.1 tron
305 1.1 tron p = (char *) ecalloc(strlen(s)+1, sizeof(char));
306 1.1 tron strcpy(p, s);
307 1.1 tron return (p);
308 1.1 tron }
309 1.1 tron
310 1.1 tron /*
311 1.1 tron * Allocate memory.
312 1.1 tron * Like calloc(), but never returns an error (NULL).
313 1.1 tron */
314 1.1 tron public VOID_POINTER
315 1.1 tron ecalloc(count, size)
316 1.1 tron int count;
317 1.1 tron unsigned int size;
318 1.1 tron {
319 1.1 tron register VOID_POINTER p;
320 1.1 tron
321 1.1 tron p = (VOID_POINTER) calloc(count, size);
322 1.1 tron if (p != NULL)
323 1.1 tron return (p);
324 1.1 tron error("Cannot allocate memory", NULL_PARG);
325 1.1 tron quit(QUIT_ERROR);
326 1.1 tron /*NOTREACHED*/
327 1.1 tron return (NULL);
328 1.1 tron }
329 1.1 tron
330 1.1 tron /*
331 1.1 tron * Skip leading spaces in a string.
332 1.1 tron */
333 1.1 tron public char *
334 1.1 tron skipsp(s)
335 1.1 tron register char *s;
336 1.1 tron {
337 1.1 tron while (*s == ' ' || *s == '\t')
338 1.1 tron s++;
339 1.1 tron return (s);
340 1.1 tron }
341 1.1 tron
342 1.1 tron /*
343 1.1 tron * See how many characters of two strings are identical.
344 1.1 tron * If uppercase is true, the first string must begin with an uppercase
345 1.1 tron * character; the remainder of the first string may be either case.
346 1.1 tron */
347 1.1 tron public int
348 1.1 tron sprefix(ps, s, uppercase)
349 1.1 tron char *ps;
350 1.1 tron char *s;
351 1.1 tron int uppercase;
352 1.1 tron {
353 1.1 tron register int c;
354 1.1 tron register int sc;
355 1.1 tron register int len = 0;
356 1.1 tron
357 1.1 tron for ( ; *s != '\0'; s++, ps++)
358 1.1 tron {
359 1.1 tron c = *ps;
360 1.1 tron if (uppercase)
361 1.1 tron {
362 1.1 tron if (len == 0 && ASCII_IS_LOWER(c))
363 1.1 tron return (-1);
364 1.1 tron if (ASCII_IS_UPPER(c))
365 1.1 tron c = ASCII_TO_LOWER(c);
366 1.1 tron }
367 1.1 tron sc = *s;
368 1.1 tron if (len > 0 && ASCII_IS_UPPER(sc))
369 1.1 tron sc = ASCII_TO_LOWER(sc);
370 1.1 tron if (c != sc)
371 1.1 tron break;
372 1.1 tron len++;
373 1.1 tron }
374 1.1 tron return (len);
375 1.1 tron }
376 1.1 tron
377 1.1 tron /*
378 1.1 tron * Exit the program.
379 1.1 tron */
380 1.1 tron public void
381 1.1 tron quit(status)
382 1.1 tron int status;
383 1.1 tron {
384 1.1 tron static int save_status;
385 1.1 tron
386 1.1 tron /*
387 1.1 tron * Put cursor at bottom left corner, clear the line,
388 1.1 tron * reset the terminal modes, and exit.
389 1.1 tron */
390 1.1 tron if (status < 0)
391 1.1 tron status = save_status;
392 1.1 tron else
393 1.1 tron save_status = status;
394 1.1 tron quitting = 1;
395 1.1 tron edit((char*)NULL);
396 1.1 tron save_cmdhist();
397 1.1 tron if (any_display && is_tty)
398 1.1 tron clear_bot();
399 1.1 tron deinit();
400 1.1 tron flush();
401 1.1 tron raw_mode(0);
402 1.1 tron #if MSDOS_COMPILER && MSDOS_COMPILER != DJGPPC
403 1.1 tron /*
404 1.1 tron * If we don't close 2, we get some garbage from
405 1.1 tron * 2's buffer when it flushes automatically.
406 1.1 tron * I cannot track this one down RB
407 1.1 tron * The same bug shows up if we use ^C^C to abort.
408 1.1 tron */
409 1.1 tron close(2);
410 1.1 tron #endif
411 1.1 tron #ifdef WIN32
412 1.1 tron SetConsoleTitle(consoleTitle);
413 1.1 tron #endif
414 1.1 tron close_getchr();
415 1.1 tron exit(status);
416 1.1 tron }
417