2 * Copyright (C) 1984-2019 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.
25 extern char *every_first_cmd
;
26 extern int any_display
;
27 extern int force_open
;
30 extern IFILE curr_ifile
;
31 extern IFILE old_ifile
;
32 extern struct scrpos initial_scrpos
;
33 extern void *ml_examine
;
34 #if SPACES_IN_FILENAMES
35 extern char openquote
;
36 extern char closequote
;
41 extern int force_logfile
;
42 extern char *namelogfile
;
46 public dev_t curr_dev
;
47 public ino_t curr_ino
;
52 * Textlist functions deal with a list of words separated by spaces.
53 * init_textlist sets up a textlist structure.
54 * forw_textlist uses that structure to iterate thru the list of
55 * words, returning each one as a standard null-terminated string.
56 * back_textlist does the same, but runs thru the list backwards.
59 init_textlist(tlist
, str
)
60 struct textlist
*tlist
;
64 #if SPACES_IN_FILENAMES
67 char *esc
= get_meta_escape();
68 int esclen
= (int) strlen(esc
);
71 tlist
->string
= skipsp(str
);
72 tlist
->endstring
= tlist
->string
+ strlen(tlist
->string
);
73 for (s
= str
; s
< tlist
->endstring
; s
++)
75 #if SPACES_IN_FILENAMES
79 } else if (esclen
> 0 && s
+ esclen
< tlist
->endstring
&&
80 strncmp(s
, esc
, esclen
) == 0)
84 } else if (delim_quoted
)
88 } else /* (!delim_quoted) */
103 forw_textlist(tlist
, prev
)
104 struct textlist
*tlist
;
110 * prev == NULL means return the first word in the list.
111 * Otherwise, return the word after "prev".
116 s
= prev
+ strlen(prev
);
117 if (s
>= tlist
->endstring
)
121 if (s
>= tlist
->endstring
)
127 back_textlist(tlist
, prev
)
128 struct textlist
*tlist
;
134 * prev == NULL means return the last word in the list.
135 * Otherwise, return the word before "prev".
138 s
= tlist
->endstring
;
139 else if (prev
<= tlist
->string
)
145 if (s
<= tlist
->string
)
147 while (s
[-1] != '\0' && s
> tlist
->string
)
153 * Close a pipe opened via popen.
156 close_pipe(FILE *pipefd
)
162 * The pclose function of OS/2 emx sometimes fails.
163 * Send SIGINT to the piped process before closing it.
165 kill(pipefd
->_pid
, SIGINT
);
171 * Close the current input file.
174 close_file(VOID_PARAM
)
176 struct scrpos scrpos
;
181 if (curr_ifile
== NULL_IFILE
)
185 * Save the current position so that we can return to
186 * the same position if we edit this file again.
188 get_scrpos(&scrpos
, TOP
);
189 if (scrpos
.pos
!= NULL_POSITION
)
191 store_pos(curr_ifile
, &scrpos
);
195 * Close the file descriptor, unless it is a pipe.
197 chflags
= ch_getflags();
200 * If we opened a file using an alternate name,
201 * do special stuff to close it.
203 altfilename
= get_altfilename(curr_ifile
);
204 if (altfilename
!= NULL
)
206 altpipe
= get_altpipe(curr_ifile
);
207 if (altpipe
!= NULL
&& !(chflags
& CH_KEEPOPEN
))
210 set_altpipe(curr_ifile
, NULL
);
212 close_altfile(altfilename
, get_filename(curr_ifile
));
213 set_altfilename(curr_ifile
, NULL
);
215 curr_ifile
= NULL_IFILE
;
217 curr_ino
= curr_dev
= 0;
222 * Edit a new file (given its name).
223 * Filename == "-" means standard input.
224 * Filename == NULL means just close the current file.
230 if (filename
== NULL
)
231 return (edit_ifile(NULL_IFILE
));
232 return (edit_ifile(get_ifile(filename
, curr_ifile
)));
236 * Edit a new file (given its IFILE).
237 * ifile == NULL means just close the current file.
251 IFILE was_curr_ifile
;
254 if (ifile
== curr_ifile
)
257 * Already have the correct file open.
263 * We must close the currently open file now.
264 * This is necessary to make the open_altfile/close_altfile pairs
265 * nest properly (or rather to avoid nesting at all).
266 * {{ Some stupid implementations of popen() mess up if you do:
267 * fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
272 was_curr_ifile
= save_curr_ifile();
273 if (curr_ifile
!= NULL_IFILE
)
275 chflags
= ch_getflags();
277 if ((chflags
& CH_HELPFILE
) && held_ifile(was_curr_ifile
) <= 1)
280 * Don't keep the help file in the ifile list.
282 del_ifile(was_curr_ifile
);
283 was_curr_ifile
= old_ifile
;
287 if (ifile
== NULL_IFILE
)
290 * No new file to open.
291 * (Don't set old_ifile, because if you call edit_ifile(NULL),
292 * you're supposed to have saved curr_ifile yourself,
293 * and you'll restore it if necessary.)
295 unsave_ifile(was_curr_ifile
);
299 filename
= save(get_filename(ifile
));
302 * See if LESSOPEN specifies an "alternate" file to open.
304 altpipe
= get_altpipe(ifile
);
308 * File is already open.
309 * chflags and f are not used by ch_init if ifile has
310 * filestate which should be the case if we're here.
311 * Set them here to avoid uninitialized variable warnings.
315 alt_filename
= get_altfilename(ifile
);
316 open_filename
= (alt_filename
!= NULL
) ? alt_filename
: filename
;
319 if (strcmp(filename
, FAKE_HELPFILE
) == 0 ||
320 strcmp(filename
, FAKE_EMPTYFILE
) == 0)
323 alt_filename
= open_altfile(filename
, &f
, &altpipe
);
325 open_filename
= (alt_filename
!= NULL
) ? alt_filename
: filename
;
331 * The alternate "file" is actually a pipe.
332 * f has already been set to the file descriptor of the pipe
333 * in the call to open_altfile above.
334 * Keep the file descriptor open because it was opened
335 * via popen(), and pclose() wants to close it.
337 chflags
|= CH_POPENED
;
338 if (strcmp(filename
, "-") == 0)
339 chflags
|= CH_KEEPOPEN
;
340 } else if (strcmp(filename
, "-") == 0)
343 * Use standard input.
344 * Keep the file descriptor open because we can't reopen it.
347 chflags
|= CH_KEEPOPEN
;
349 * Must switch stdin to BINARY mode.
352 #if MSDOS_COMPILER==DJGPPC
354 * Setting stdin to binary by default causes
355 * Ctrl-C to not raise SIGINT. We must undo
358 __djgpp_set_ctrl_c(1);
360 } else if (strcmp(open_filename
, FAKE_EMPTYFILE
) == 0)
363 chflags
|= CH_NODATA
;
364 } else if (strcmp(open_filename
, FAKE_HELPFILE
) == 0)
367 chflags
|= CH_HELPFILE
;
368 } else if ((parg
.p_string
= bad_file(open_filename
)) != NULL
)
371 * It looks like a bad file. Don't try to open it.
376 if (alt_filename
!= NULL
)
379 close_altfile(alt_filename
, filename
);
385 * Re-open the current file.
387 if (was_curr_ifile
== ifile
)
390 * Whoops. The "current" ifile is the one we just deleted.
395 reedit_ifile(was_curr_ifile
);
397 } else if ((f
= open(open_filename
, OPEN_READ
)) < 0)
400 * Got an error trying to open it.
402 parg
.p_string
= errno_message(filename
);
408 chflags
|= CH_CANSEEK
;
409 if (!force_open
&& !opened(ifile
) && bin_file(f
))
412 * Looks like a binary file.
413 * Ask user if we should proceed.
415 parg
.p_string
= filename
;
416 answer
= query("\"%s\" may be a binary file. See it anyway? ",
418 if (answer
!= 'y' && answer
!= 'Y')
429 * Get the saved position for the file.
431 if (was_curr_ifile
!= NULL_IFILE
)
433 old_ifile
= was_curr_ifile
;
434 unsave_ifile(was_curr_ifile
);
437 set_altfilename(curr_ifile
, alt_filename
);
438 set_altpipe(curr_ifile
, altpipe
);
439 set_open(curr_ifile
); /* File has been opened */
440 get_pos(curr_ifile
, &initial_scrpos
);
444 if (!(chflags
& CH_HELPFILE
))
447 if (namelogfile
!= NULL
&& is_tty
)
448 use_logfile(namelogfile
);
451 /* Remember the i-number and device of the opened file. */
452 if (strcmp(open_filename
, "-") != 0)
455 int r
= stat(open_filename
, &statbuf
);
458 curr_ino
= statbuf
.st_ino
;
459 curr_dev
= statbuf
.st_dev
;
463 if (every_first_cmd
!= NULL
)
465 ungetcc(CHAR_END_COMMAND
);
466 ungetsc(every_first_cmd
);
470 no_display
= !any_display
;
477 * Output is to a real tty.
481 * Indicate there is nothing displayed yet.
488 if (strcmp(filename
, FAKE_HELPFILE
) && strcmp(filename
, FAKE_EMPTYFILE
))
490 char *qfilename
= shell_quote(filename
);
491 cmd_addhist(ml_examine
, qfilename
, 1);
495 if (no_display
&& errmsgs
> 0)
498 * We displayed some messages on error output
499 * (file descriptor 2; see error() function).
500 * Before erasing the screen contents,
501 * display the file name and wait for a keystroke.
503 parg
.p_string
= filename
;
512 * Edit a space-separated list of files.
513 * For each filename in the list, enter it into the ifile list.
514 * Then edit the first one.
526 struct textlist tl_files
;
527 struct textlist tl_gfiles
;
529 save_ifile
= save_curr_ifile();
530 good_filename
= NULL
;
533 * Run thru each filename in the list.
534 * Try to glob the filename.
535 * If it doesn't expand, just try to open the filename.
536 * If it does expand, try to open each name in that list.
538 init_textlist(&tl_files
, filelist
);
540 while ((filename
= forw_textlist(&tl_files
, filename
)) != NULL
)
542 gfilelist
= lglob(filename
);
543 init_textlist(&tl_gfiles
, gfilelist
);
545 while ((gfilename
= forw_textlist(&tl_gfiles
, gfilename
)) != NULL
)
547 qfilename
= shell_unquote(gfilename
);
548 if (edit(qfilename
) == 0 && good_filename
== NULL
)
549 good_filename
= get_filename(curr_ifile
);
555 * Edit the first valid filename in the list.
557 if (good_filename
== NULL
)
559 unsave_ifile(save_ifile
);
562 if (get_ifile(good_filename
, curr_ifile
) == curr_ifile
)
565 * Trying to edit the current file; don't reopen it.
567 unsave_ifile(save_ifile
);
570 reedit_ifile(save_ifile
);
571 return (edit(good_filename
));
575 * Edit the first file in the command line (ifile) list.
578 edit_first(VOID_PARAM
)
581 return (edit_stdin());
582 curr_ifile
= NULL_IFILE
;
583 return (edit_next(1));
587 * Edit the last file in the command line (ifile) list.
590 edit_last(VOID_PARAM
)
592 curr_ifile
= NULL_IFILE
;
593 return (edit_prev(1));
598 * Edit the n-th next or previous file in the command line (ifile) list.
601 edit_istep(h
, n
, dir
)
609 * Skip n filenames, then try to edit each filename.
613 next
= (dir
> 0) ? next_ifile(h
) : prev_ifile(h
);
616 if (edit_ifile(h
) == 0)
619 if (next
== NULL_IFILE
)
622 * Reached end of the ifile list.
629 * Interrupt breaks out, if we're in a long
630 * list of files that can't be opened.
637 * Found a file that we can edit.
647 return (edit_istep(h
, n
, +1));
654 return edit_istep(curr_ifile
, n
, +1);
662 return (edit_istep(h
, n
, -1));
669 return edit_istep(curr_ifile
, n
, -1);
673 * Edit a specific file in the command line (ifile) list.
684 if ((h
= next_ifile(h
)) == NULL_IFILE
)
687 * Reached end of the list without finding it.
691 } while (get_index(h
) != n
);
693 return (edit_ifile(h
));
697 save_curr_ifile(VOID_PARAM
)
699 if (curr_ifile
!= NULL_IFILE
)
700 hold_ifile(curr_ifile
, 1);
705 unsave_ifile(save_ifile
)
708 if (save_ifile
!= NULL_IFILE
)
709 hold_ifile(save_ifile
, -1);
713 * Reedit the ifile which was previously open.
716 reedit_ifile(save_ifile
)
723 * Try to reopen the ifile.
724 * Note that opening it may fail (maybe the file was removed),
725 * in which case the ifile will be deleted from the list.
726 * So save the next and prev ifiles first.
728 unsave_ifile(save_ifile
);
729 next
= next_ifile(save_ifile
);
730 prev
= prev_ifile(save_ifile
);
731 if (edit_ifile(save_ifile
) == 0)
734 * If can't reopen it, open the next input file in the list.
736 if (next
!= NULL_IFILE
&& edit_inext(next
, 0) == 0)
739 * If can't open THAT one, open the previous input file in the list.
741 if (prev
!= NULL_IFILE
&& edit_iprev(prev
, 0) == 0)
744 * If can't even open that, we're stuck. Just quit.
750 reopen_curr_ifile(VOID_PARAM
)
752 IFILE save_ifile
= save_curr_ifile();
754 reedit_ifile(save_ifile
);
758 * Edit standard input.
761 edit_stdin(VOID_PARAM
)
765 error("Missing filename (\"less --help\" for help)", NULL_PARG
);
772 * Copy a file directly to standard output.
773 * Used if standard output is not a tty.
780 while ((c
= ch_forw_get()) != EOI
)
788 * If the user asked for a log file and our input file
789 * is standard input, create the log file.
790 * We take care not to blindly overwrite an existing file.
793 use_logfile(filename
)
800 if (ch_getflags() & CH_CANSEEK
)
802 * Can't currently use a log file on a file that can seek.
807 * {{ We could use access() here. }}
809 exists
= open(filename
, OPEN_READ
);
812 exists
= (exists
>= 0);
815 * Decide whether to overwrite the log file or append to it.
816 * If it doesn't exist we "overwrite" it.
818 if (!exists
|| force_logfile
)
821 * Overwrite (or create) the log file.
827 * Ask user what to do.
829 parg
.p_string
= filename
;
830 answer
= query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg
);
838 * Overwrite: create the file.
840 logfile
= creat(filename
, 0644);
844 * Append: open the file and seek to the end.
846 logfile
= open(filename
, OPEN_APPEND
);
847 if (lseek(logfile
, (off_t
)0, SEEK_END
) == BAD_LSEEK
)
866 answer
= query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG
);
873 * Error in opening logfile.
875 parg
.p_string
= filename
;
876 error("Cannot write to \"%s\"", &parg
);