2 * Copyright (C) 1984-2015 Mark Nudelman
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
7 * For more information, see the README file.
21 extern char *every_first_cmd;
22 extern int any_display;
23 extern int force_open;
26 extern IFILE curr_ifile;
27 extern IFILE old_ifile;
28 extern struct scrpos initial_scrpos;
29 extern void * constant ml_examine;
30 #if SPACES_IN_FILENAMES
31 extern char openquote;
32 extern char closequote;
37 extern int force_logfile;
38 extern char *namelogfile;
42 public dev_t curr_dev;
43 public ino_t curr_ino;
46 char *curr_altfilename = NULL;
47 static void *curr_altpipe;
51 * Textlist functions deal with a list of words separated by spaces.
52 * init_textlist sets up a textlist structure.
53 * forw_textlist uses that structure to iterate thru the list of
54 * words, returning each one as a standard null-terminated string.
55 * back_textlist does the same, but runs thru the list backwards.
58 init_textlist(struct textlist *tlist, char *str)
61 #if SPACES_IN_FILENAMES
64 char *esc = get_meta_escape();
65 int esclen = (int) strlen(esc);
68 tlist->string = skipsp(str);
69 tlist->endstring = tlist->string + strlen(tlist->string);
70 for (s = str; s < tlist->endstring; s++)
72 #if SPACES_IN_FILENAMES
76 } else if (esclen > 0 && s + esclen < tlist->endstring &&
77 strncmp(s, esc, esclen) == 0)
81 } else if (delim_quoted)
85 } else /* (!delim_quoted) */
100 forw_textlist(struct textlist *tlist, char *prev)
105 * prev == NULL means return the first word in the list.
106 * Otherwise, return the word after "prev".
111 s = prev + strlen(prev);
112 if (s >= tlist->endstring)
116 if (s >= tlist->endstring)
122 back_textlist(struct textlist *tlist, char *prev)
127 * prev == NULL means return the last word in the list.
128 * Otherwise, return the word before "prev".
131 s = tlist->endstring;
132 else if (prev <= tlist->string)
138 if (s <= tlist->string)
140 while (s[-1] != '\0' && s > tlist->string)
146 * Close the current input file.
151 struct scrpos scrpos;
153 if (curr_ifile == NULL_IFILE)
157 * Save the current position so that we can return to
158 * the same position if we edit this file again.
161 if (scrpos.pos != NULL_POSITION)
163 store_pos(curr_ifile, &scrpos);
167 * Close the file descriptor, unless it is a pipe.
171 * If we opened a file using an alternate name,
172 * do special stuff to close it.
174 if (curr_altfilename != NULL)
176 close_altfile(curr_altfilename, get_filename(curr_ifile),
178 free(curr_altfilename);
179 curr_altfilename = NULL;
181 curr_ifile = NULL_IFILE;
183 curr_ino = curr_dev = 0;
188 * Edit a new file (given its name).
189 * Filename == "-" means standard input.
190 * Filename == NULL means just close the current file.
195 if (filename == NULL)
196 return (edit_ifile(NULL_IFILE));
197 return (edit_ifile(get_ifile(filename, curr_ifile)));
201 * Edit a new file (given its IFILE).
202 * ifile == NULL means just close the current file.
205 edit_ifile(IFILE ifile)
213 char *qopen_filename;
216 IFILE was_curr_ifile;
219 if (ifile == curr_ifile)
222 * Already have the correct file open.
228 * We must close the currently open file now.
229 * This is necessary to make the open_altfile/close_altfile pairs
230 * nest properly (or rather to avoid nesting at all).
231 * {{ Some stupid implementations of popen() mess up if you do:
232 * fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
237 was_curr_ifile = save_curr_ifile();
238 if (curr_ifile != NULL_IFILE)
240 chflags = ch_getflags();
242 if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
245 * Don't keep the help file in the ifile list.
247 del_ifile(was_curr_ifile);
248 was_curr_ifile = old_ifile;
252 if (ifile == NULL_IFILE)
255 * No new file to open.
256 * (Don't set old_ifile, because if you call edit_ifile(NULL),
257 * you're supposed to have saved curr_ifile yourself,
258 * and you'll restore it if necessary.)
260 unsave_ifile(was_curr_ifile);
264 filename = save(get_filename(ifile));
266 * See if LESSOPEN specifies an "alternate" file to open.
269 alt_filename = open_altfile(filename, &f, &alt_pipe);
270 open_filename = (alt_filename != NULL) ? alt_filename : filename;
271 qopen_filename = shell_unquote(open_filename);
274 if (alt_pipe != NULL)
277 * The alternate "file" is actually a pipe.
278 * f has already been set to the file descriptor of the pipe
279 * in the call to open_altfile above.
280 * Keep the file descriptor open because it was opened
281 * via popen(), and pclose() wants to close it.
283 chflags |= CH_POPENED;
284 } else if (strcmp(open_filename, "-") == 0)
287 * Use standard input.
288 * Keep the file descriptor open because we can't reopen it.
291 chflags |= CH_KEEPOPEN;
293 * Must switch stdin to BINARY mode.
296 #if MSDOS_COMPILER==DJGPPC
298 * Setting stdin to binary by default causes
299 * Ctrl-C to not raise SIGINT. We must undo
302 __djgpp_set_ctrl_c(1);
304 } else if (strcmp(open_filename, FAKE_EMPTYFILE) == 0)
307 chflags |= CH_NODATA;
308 } else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
311 chflags |= CH_HELPFILE;
312 } else if ((parg.p_string = bad_file(open_filename)) != NULL)
315 * It looks like a bad file. Don't try to open it.
320 if (alt_filename != NULL)
322 close_altfile(alt_filename, filename, alt_pipe);
326 free(qopen_filename);
329 * Re-open the current file.
331 if (was_curr_ifile == ifile)
334 * Whoops. The "current" ifile is the one we just deleted.
339 reedit_ifile(was_curr_ifile);
341 } else if ((f = open(qopen_filename, OPEN_READ)) < 0)
344 * Got an error trying to open it.
346 parg.p_string = errno_message(filename);
352 chflags |= CH_CANSEEK;
353 if (!force_open && !opened(ifile) && bin_file(f))
356 * Looks like a binary file.
357 * Ask user if we should proceed.
359 parg.p_string = filename;
360 answer = query("\"%s\" may be a binary file. See it anyway? ",
362 if (answer != 'y' && answer != 'Y')
372 * Get the saved position for the file.
374 if (was_curr_ifile != NULL_IFILE)
376 old_ifile = was_curr_ifile;
377 unsave_ifile(was_curr_ifile);
380 curr_altfilename = alt_filename;
381 curr_altpipe = alt_pipe;
382 set_open(curr_ifile); /* File has been opened */
383 get_pos(curr_ifile, &initial_scrpos);
387 if (!(chflags & CH_HELPFILE))
390 if (namelogfile != NULL && is_tty)
391 use_logfile(namelogfile);
394 /* Remember the i-number and device of the opened file. */
397 int r = stat(qopen_filename, &statbuf);
400 curr_ino = statbuf.st_ino;
401 curr_dev = statbuf.st_dev;
405 if (every_first_cmd != NULL)
407 ungetcc(CHAR_END_COMMAND);
408 ungetsc(every_first_cmd);
412 free(qopen_filename);
413 no_display = !any_display;
420 * Output is to a real tty.
424 * Indicate there is nothing displayed yet.
431 if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE))
432 cmd_addhist(ml_examine, filename, 1);
433 if (no_display && errmsgs > 0)
436 * We displayed some messages on error output
437 * (file descriptor 2; see error() function).
438 * Before erasing the screen contents,
439 * display the file name and wait for a keystroke.
441 parg.p_string = filename;
450 * Edit a space-separated list of files.
451 * For each filename in the list, enter it into the ifile list.
452 * Then edit the first one.
455 edit_list(char *filelist)
462 struct textlist tl_files;
463 struct textlist tl_gfiles;
465 save_ifile = save_curr_ifile();
466 good_filename = NULL;
469 * Run thru each filename in the list.
470 * Try to glob the filename.
471 * If it doesn't expand, just try to open the filename.
472 * If it does expand, try to open each name in that list.
474 init_textlist(&tl_files, filelist);
476 while ((filename = forw_textlist(&tl_files, filename)) != NULL)
478 gfilelist = lglob(filename);
479 init_textlist(&tl_gfiles, gfilelist);
481 while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
483 if (edit(gfilename) == 0 && good_filename == NULL)
484 good_filename = get_filename(curr_ifile);
489 * Edit the first valid filename in the list.
491 if (good_filename == NULL)
493 unsave_ifile(save_ifile);
496 if (get_ifile(good_filename, curr_ifile) == curr_ifile)
499 * Trying to edit the current file; don't reopen it.
501 unsave_ifile(save_ifile);
504 reedit_ifile(save_ifile);
505 return (edit(good_filename));
509 * Edit the first file in the command line (ifile) list.
514 curr_ifile = NULL_IFILE;
515 return (edit_next(1));
519 * Edit the last file in the command line (ifile) list.
524 curr_ifile = NULL_IFILE;
525 return (edit_prev(1));
530 * Edit the n-th next or previous file in the command line (ifile) list.
533 edit_istep(IFILE h, int n, int dir)
538 * Skip n filenames, then try to edit each filename.
542 next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
545 if (edit_ifile(h) == 0)
548 if (next == NULL_IFILE)
551 * Reached end of the ifile list.
558 * Interrupt breaks out, if we're in a long
559 * list of files that can't be opened.
566 * Found a file that we can edit.
572 edit_inext(IFILE h, int n)
574 return (edit_istep(h, n, +1));
580 return edit_istep(curr_ifile, n, +1);
584 edit_iprev(IFILE h, int n)
586 return (edit_istep(h, n, -1));
592 return edit_istep(curr_ifile, n, -1);
596 * Edit a specific file in the command line (ifile) list.
606 if ((h = next_ifile(h)) == NULL_IFILE)
609 * Reached end of the list without finding it.
613 } while (get_index(h) != n);
615 return (edit_ifile(h));
619 save_curr_ifile(void)
621 if (curr_ifile != NULL_IFILE)
622 hold_ifile(curr_ifile, 1);
627 unsave_ifile(IFILE save_ifile)
629 if (save_ifile != NULL_IFILE)
630 hold_ifile(save_ifile, -1);
634 * Reedit the ifile which was previously open.
637 reedit_ifile(IFILE save_ifile)
643 * Try to reopen the ifile.
644 * Note that opening it may fail (maybe the file was removed),
645 * in which case the ifile will be deleted from the list.
646 * So save the next and prev ifiles first.
648 unsave_ifile(save_ifile);
649 next = next_ifile(save_ifile);
650 prev = prev_ifile(save_ifile);
651 if (edit_ifile(save_ifile) == 0)
654 * If can't reopen it, open the next input file in the list.
656 if (next != NULL_IFILE && edit_inext(next, 0) == 0)
659 * If can't open THAT one, open the previous input file in the list.
661 if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
664 * If can't even open that, we're stuck. Just quit.
670 reopen_curr_ifile(void)
672 IFILE save_ifile = save_curr_ifile();
674 reedit_ifile(save_ifile);
678 * Edit standard input.
685 error("Missing filename (\"less --help\" for help)", NULL_PARG);
692 * Copy a file directly to standard output.
693 * Used if standard output is not a tty.
700 while ((c = ch_forw_get()) != EOI)
708 * If the user asked for a log file and our input file
709 * is standard input, create the log file.
710 * We take care not to blindly overwrite an existing file.
713 use_logfile(char *filename)
719 if (ch_getflags() & CH_CANSEEK)
721 * Can't currently use a log file on a file that can seek.
726 * {{ We could use access() here. }}
728 filename = shell_unquote(filename);
729 exists = open(filename, OPEN_READ);
732 exists = (exists >= 0);
735 * Decide whether to overwrite the log file or append to it.
736 * If it doesn't exist we "overwrite" it.
738 if (!exists || force_logfile)
741 * Overwrite (or create) the log file.
747 * Ask user what to do.
749 parg.p_string = filename;
750 answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
758 * Overwrite: create the file.
760 logfile = creat(filename, 0644);
764 * Append: open the file and seek to the end.
766 logfile = open(filename, OPEN_APPEND);
767 if (lseek(logfile, (off_t)0, SEEK_END) == BAD_LSEEK)
786 answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
793 * Error in opening logfile.
795 parg.p_string = filename;
796 error("Cannot write to \"%s\"", &parg);