2 * Copyright (C) 1984-2014 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(tlist, str)
59 struct textlist *tlist;
63 #if SPACES_IN_FILENAMES
66 char *esc = get_meta_escape();
67 int esclen = (int) strlen(esc);
70 tlist->string = skipsp(str);
71 tlist->endstring = tlist->string + strlen(tlist->string);
72 for (s = str; s < tlist->endstring; s++)
74 #if SPACES_IN_FILENAMES
78 } else if (esclen > 0 && s + esclen < tlist->endstring &&
79 strncmp(s, esc, esclen) == 0)
83 } else if (delim_quoted)
87 } else /* (!delim_quoted) */
102 forw_textlist(tlist, prev)
103 struct textlist *tlist;
109 * prev == NULL means return the first word in the list.
110 * Otherwise, return the word after "prev".
115 s = prev + strlen(prev);
116 if (s >= tlist->endstring)
120 if (s >= tlist->endstring)
126 back_textlist(tlist, prev)
127 struct textlist *tlist;
133 * prev == NULL means return the last word in the list.
134 * Otherwise, return the word before "prev".
137 s = tlist->endstring;
138 else if (prev <= tlist->string)
144 if (s <= tlist->string)
146 while (s[-1] != '\0' && s > tlist->string)
152 * Close the current input file.
157 struct scrpos scrpos;
159 if (curr_ifile == NULL_IFILE)
163 * Save the current position so that we can return to
164 * the same position if we edit this file again.
167 if (scrpos.pos != NULL_POSITION)
169 store_pos(curr_ifile, &scrpos);
173 * Close the file descriptor, unless it is a pipe.
177 * If we opened a file using an alternate name,
178 * do special stuff to close it.
180 if (curr_altfilename != NULL)
182 close_altfile(curr_altfilename, get_filename(curr_ifile),
184 free(curr_altfilename);
185 curr_altfilename = NULL;
187 curr_ifile = NULL_IFILE;
189 curr_ino = curr_dev = 0;
194 * Edit a new file (given its name).
195 * Filename == "-" means standard input.
196 * Filename == NULL means just close the current file.
202 if (filename == NULL)
203 return (edit_ifile(NULL_IFILE));
204 return (edit_ifile(get_ifile(filename, curr_ifile)));
208 * Edit a new file (given its IFILE).
209 * ifile == NULL means just close the current file.
221 char *qopen_filename;
224 IFILE was_curr_ifile;
227 if (ifile == curr_ifile)
230 * Already have the correct file open.
236 * We must close the currently open file now.
237 * This is necessary to make the open_altfile/close_altfile pairs
238 * nest properly (or rather to avoid nesting at all).
239 * {{ Some stupid implementations of popen() mess up if you do:
240 * fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
245 was_curr_ifile = save_curr_ifile();
246 if (curr_ifile != NULL_IFILE)
248 chflags = ch_getflags();
250 if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
253 * Don't keep the help file in the ifile list.
255 del_ifile(was_curr_ifile);
256 was_curr_ifile = old_ifile;
260 if (ifile == NULL_IFILE)
263 * No new file to open.
264 * (Don't set old_ifile, because if you call edit_ifile(NULL),
265 * you're supposed to have saved curr_ifile yourself,
266 * and you'll restore it if necessary.)
268 unsave_ifile(was_curr_ifile);
272 filename = save(get_filename(ifile));
274 * See if LESSOPEN specifies an "alternate" file to open.
277 alt_filename = open_altfile(filename, &f, &alt_pipe);
278 open_filename = (alt_filename != NULL) ? alt_filename : filename;
279 qopen_filename = shell_unquote(open_filename);
282 if (alt_pipe != NULL)
285 * The alternate "file" is actually a pipe.
286 * f has already been set to the file descriptor of the pipe
287 * in the call to open_altfile above.
288 * Keep the file descriptor open because it was opened
289 * via popen(), and pclose() wants to close it.
291 chflags |= CH_POPENED;
292 } else if (strcmp(open_filename, "-") == 0)
295 * Use standard input.
296 * Keep the file descriptor open because we can't reopen it.
299 chflags |= CH_KEEPOPEN;
301 * Must switch stdin to BINARY mode.
304 #if MSDOS_COMPILER==DJGPPC
306 * Setting stdin to binary by default causes
307 * Ctrl-C to not raise SIGINT. We must undo
310 __djgpp_set_ctrl_c(1);
312 } else if (strcmp(open_filename, FAKE_EMPTYFILE) == 0)
315 chflags |= CH_NODATA;
316 } else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
319 chflags |= CH_HELPFILE;
320 } else if ((parg.p_string = bad_file(open_filename)) != NULL)
323 * It looks like a bad file. Don't try to open it.
328 if (alt_filename != NULL)
330 close_altfile(alt_filename, filename, alt_pipe);
334 free(qopen_filename);
337 * Re-open the current file.
339 if (was_curr_ifile == ifile)
342 * Whoops. The "current" ifile is the one we just deleted.
347 reedit_ifile(was_curr_ifile);
349 } else if ((f = open(qopen_filename, OPEN_READ)) < 0)
352 * Got an error trying to open it.
354 parg.p_string = errno_message(filename);
360 chflags |= CH_CANSEEK;
361 if (!force_open && !opened(ifile) && bin_file(f))
364 * Looks like a binary file.
365 * Ask user if we should proceed.
367 parg.p_string = filename;
368 answer = query("\"%s\" may be a binary file. See it anyway? ",
370 if (answer != 'y' && answer != 'Y')
380 * Get the saved position for the file.
382 if (was_curr_ifile != NULL_IFILE)
384 old_ifile = was_curr_ifile;
385 unsave_ifile(was_curr_ifile);
388 curr_altfilename = alt_filename;
389 curr_altpipe = alt_pipe;
390 set_open(curr_ifile); /* File has been opened */
391 get_pos(curr_ifile, &initial_scrpos);
395 if (!(chflags & CH_HELPFILE))
398 if (namelogfile != NULL && is_tty)
399 use_logfile(namelogfile);
402 /* Remember the i-number and device of the opened file. */
405 int r = stat(qopen_filename, &statbuf);
408 curr_ino = statbuf.st_ino;
409 curr_dev = statbuf.st_dev;
413 if (every_first_cmd != NULL)
415 ungetcc(CHAR_END_COMMAND);
416 ungetsc(every_first_cmd);
420 free(qopen_filename);
421 no_display = !any_display;
428 * Output is to a real tty.
432 * Indicate there is nothing displayed yet.
439 cmd_addhist(ml_examine, filename, 1);
440 if (no_display && errmsgs > 0)
443 * We displayed some messages on error output
444 * (file descriptor 2; see error() function).
445 * Before erasing the screen contents,
446 * display the file name and wait for a keystroke.
448 parg.p_string = filename;
457 * Edit a space-separated list of files.
458 * For each filename in the list, enter it into the ifile list.
459 * Then edit the first one.
470 struct textlist tl_files;
471 struct textlist tl_gfiles;
473 save_ifile = save_curr_ifile();
474 good_filename = NULL;
477 * Run thru each filename in the list.
478 * Try to glob the filename.
479 * If it doesn't expand, just try to open the filename.
480 * If it does expand, try to open each name in that list.
482 init_textlist(&tl_files, filelist);
484 while ((filename = forw_textlist(&tl_files, filename)) != NULL)
486 gfilelist = lglob(filename);
487 init_textlist(&tl_gfiles, gfilelist);
489 while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
491 if (edit(gfilename) == 0 && good_filename == NULL)
492 good_filename = get_filename(curr_ifile);
497 * Edit the first valid filename in the list.
499 if (good_filename == NULL)
501 unsave_ifile(save_ifile);
504 if (get_ifile(good_filename, curr_ifile) == curr_ifile)
507 * Trying to edit the current file; don't reopen it.
509 unsave_ifile(save_ifile);
512 reedit_ifile(save_ifile);
513 return (edit(good_filename));
517 * Edit the first file in the command line (ifile) list.
522 curr_ifile = NULL_IFILE;
523 return (edit_next(1));
527 * Edit the last file in the command line (ifile) list.
532 curr_ifile = NULL_IFILE;
533 return (edit_prev(1));
538 * Edit the n-th next or previous file in the command line (ifile) list.
541 edit_istep(h, n, dir)
549 * Skip n filenames, then try to edit each filename.
553 next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
556 if (edit_ifile(h) == 0)
559 if (next == NULL_IFILE)
562 * Reached end of the ifile list.
569 * Interrupt breaks out, if we're in a long
570 * list of files that can't be opened.
577 * Found a file that we can edit.
587 return (edit_istep(h, n, +1));
594 return edit_istep(curr_ifile, n, +1);
602 return (edit_istep(h, n, -1));
609 return edit_istep(curr_ifile, n, -1);
613 * Edit a specific file in the command line (ifile) list.
624 if ((h = next_ifile(h)) == NULL_IFILE)
627 * Reached end of the list without finding it.
631 } while (get_index(h) != n);
633 return (edit_ifile(h));
639 if (curr_ifile != NULL_IFILE)
640 hold_ifile(curr_ifile, 1);
645 unsave_ifile(save_ifile)
648 if (save_ifile != NULL_IFILE)
649 hold_ifile(save_ifile, -1);
653 * Reedit the ifile which was previously open.
656 reedit_ifile(save_ifile)
663 * Try to reopen the ifile.
664 * Note that opening it may fail (maybe the file was removed),
665 * in which case the ifile will be deleted from the list.
666 * So save the next and prev ifiles first.
668 unsave_ifile(save_ifile);
669 next = next_ifile(save_ifile);
670 prev = prev_ifile(save_ifile);
671 if (edit_ifile(save_ifile) == 0)
674 * If can't reopen it, open the next input file in the list.
676 if (next != NULL_IFILE && edit_inext(next, 0) == 0)
679 * If can't open THAT one, open the previous input file in the list.
681 if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
684 * If can't even open that, we're stuck. Just quit.
692 IFILE save_ifile = save_curr_ifile();
694 reedit_ifile(save_ifile);
698 * Edit standard input.
705 error("Missing filename (\"less --help\" for help)", NULL_PARG);
712 * Copy a file directly to standard output.
713 * Used if standard output is not a tty.
720 while ((c = ch_forw_get()) != EOI)
728 * If the user asked for a log file and our input file
729 * is standard input, create the log file.
730 * We take care not to blindly overwrite an existing file.
733 use_logfile(filename)
740 if (ch_getflags() & CH_CANSEEK)
742 * Can't currently use a log file on a file that can seek.
747 * {{ We could use access() here. }}
749 filename = shell_unquote(filename);
750 exists = open(filename, OPEN_READ);
753 exists = (exists >= 0);
756 * Decide whether to overwrite the log file or append to it.
757 * If it doesn't exist we "overwrite" it.
759 if (!exists || force_logfile)
762 * Overwrite (or create) the log file.
768 * Ask user what to do.
770 parg.p_string = filename;
771 answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
779 * Overwrite: create the file.
781 logfile = creat(filename, 0644);
785 * Append: open the file and seek to the end.
787 logfile = open(filename, OPEN_APPEND);
788 if (lseek(logfile, (off_t)0, SEEK_END) == BAD_LSEEK)
807 answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
814 * Error in opening logfile.
816 parg.p_string = filename;
817 error("Cannot write to \"%s\"", &parg);