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