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