2 * Copyright (C) 1984-2000 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 about less, or for information on how to
8 * contact the author, see the README file.
19 extern char *every_first_cmd;
20 extern int any_display;
21 extern int force_open;
24 extern IFILE curr_ifile;
25 extern IFILE old_ifile;
26 extern struct scrpos initial_scrpos;
27 extern void constant *ml_examine;
28 #if SPACES_IN_FILENAMES
29 extern char openquote;
30 extern char closequote;
35 extern int force_logfile;
36 extern char *namelogfile;
39 char *curr_altfilename = NULL;
40 static void *curr_altpipe;
44 * Textlist functions deal with a list of words separated by spaces.
45 * init_textlist sets up a textlist structure.
46 * forw_textlist uses that structure to iterate thru the list of
47 * words, returning each one as a standard null-terminated string.
48 * back_textlist does the same, but runs thru the list backwards.
51 init_textlist(tlist, str)
52 struct textlist *tlist;
56 #if SPACES_IN_FILENAMES
60 tlist->string = skipsp(str);
61 tlist->endstring = tlist->string + strlen(tlist->string);
62 for (s = str; s < tlist->endstring; s++)
64 #if SPACES_IN_FILENAMES
65 if (*s == ' ' && !quoted)
67 if (!quoted && *s == openquote)
69 else if (quoted && *s == closequote)
79 forw_textlist(tlist, prev)
80 struct textlist *tlist;
86 * prev == NULL means return the first word in the list.
87 * Otherwise, return the word after "prev".
92 s = prev + strlen(prev);
93 if (s >= tlist->endstring)
97 if (s >= tlist->endstring)
103 back_textlist(tlist, prev)
104 struct textlist *tlist;
110 * prev == NULL means return the last word in the list.
111 * Otherwise, return the word before "prev".
114 s = tlist->endstring;
115 else if (prev <= tlist->string)
121 if (s <= tlist->string)
123 while (s[-1] != '\0' && s > tlist->string)
129 * Close the current input file.
134 struct scrpos scrpos;
137 if (curr_ifile == NULL_IFILE)
141 * Save the current position so that we can return to
142 * the same position if we edit this file again.
145 if (scrpos.pos != NULL_POSITION)
147 store_pos(curr_ifile, &scrpos);
151 * Close the file descriptor, unless it is a pipe.
155 * If we opened a file using an alternate name,
156 * do special stuff to close it.
158 if (curr_altfilename != NULL)
160 filename = unquote_file(get_filename(curr_ifile));
161 close_altfile(curr_altfilename, filename, curr_altpipe);
163 free(curr_altfilename);
164 curr_altfilename = NULL;
166 curr_ifile = NULL_IFILE;
170 * Edit a new file (given its name).
171 * Filename == "-" means standard input.
172 * Filename == NULL means just close the current file.
178 if (filename == NULL)
179 return (edit_ifile(NULL_IFILE));
180 return (edit_ifile(get_ifile(filename, curr_ifile)));
184 * Edit a new file (given its IFILE).
185 * ifile == NULL means just close the current file.
199 IFILE was_curr_ifile;
202 if (ifile == curr_ifile)
205 * Already have the correct file open.
211 * We must close the currently open file now.
212 * This is necessary to make the open_altfile/close_altfile pairs
213 * nest properly (or rather to avoid nesting at all).
214 * {{ Some stupid implementations of popen() mess up if you do:
215 * fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
220 was_curr_ifile = save_curr_ifile();
221 if (curr_ifile != NULL_IFILE)
223 chflags = ch_getflags();
225 if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
228 * Don't keep the help file in the ifile list.
230 del_ifile(was_curr_ifile);
231 was_curr_ifile = old_ifile;
235 if (ifile == NULL_IFILE)
238 * No new file to open.
239 * (Don't set old_ifile, because if you call edit_ifile(NULL),
240 * you're supposed to have saved curr_ifile yourself,
241 * and you'll restore it if necessary.)
243 unsave_ifile(was_curr_ifile);
247 filename = unquote_file(get_filename(ifile));
249 * See if LESSOPEN specifies an "alternate" file to open.
252 alt_filename = open_altfile(filename, &f, &alt_pipe);
253 open_filename = (alt_filename != NULL) ? alt_filename : filename;
256 if (alt_pipe != NULL)
259 * The alternate "file" is actually a pipe.
260 * f has already been set to the file descriptor of the pipe
261 * in the call to open_altfile above.
262 * Keep the file descriptor open because it was opened
263 * via popen(), and pclose() wants to close it.
265 chflags |= CH_POPENED;
266 } else if (strcmp(open_filename, "-") == 0)
269 * Use standard input.
270 * Keep the file descriptor open because we can't reopen it.
273 chflags |= CH_KEEPOPEN;
275 * Must switch stdin to BINARY mode.
278 #if MSDOS_COMPILER==DJGPPC
280 * Setting stdin to binary by default causes
281 * Ctrl-C to not raise SIGINT. We must undo
284 __djgpp_set_ctrl_c(1);
286 } else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
289 chflags |= CH_HELPFILE;
290 } else if ((parg.p_string = bad_file(open_filename)) != NULL)
293 * It looks like a bad file. Don't try to open it.
298 if (alt_filename != NULL)
300 close_altfile(alt_filename, filename, alt_pipe);
306 * Re-open the current file.
308 reedit_ifile(was_curr_ifile);
310 } else if ((f = open(open_filename, OPEN_READ)) < 0)
313 * Got an error trying to open it.
315 parg.p_string = errno_message(filename);
321 chflags |= CH_CANSEEK;
322 if (!force_open && !opened(ifile) && bin_file(f))
325 * Looks like a binary file.
326 * Ask user if we should proceed.
328 parg.p_string = filename;
329 answer = query("\"%s\" may be a binary file. See it anyway? ",
331 if (answer != 'y' && answer != 'Y')
341 * Get the saved position for the file.
343 if (was_curr_ifile != NULL_IFILE)
345 old_ifile = was_curr_ifile;
346 unsave_ifile(was_curr_ifile);
349 curr_altfilename = alt_filename;
350 curr_altpipe = alt_pipe;
351 set_open(curr_ifile); /* File has been opened */
352 get_pos(curr_ifile, &initial_scrpos);
356 if (!(chflags & CH_HELPFILE))
359 if (namelogfile != NULL && is_tty)
360 use_logfile(namelogfile);
362 if (every_first_cmd != NULL)
363 ungetsc(every_first_cmd);
366 no_display = !any_display;
373 * Output is to a real tty.
377 * Indicate there is nothing displayed yet.
384 cmd_addhist(ml_examine, filename);
385 if (no_display && errmsgs > 0)
388 * We displayed some messages on error output
389 * (file descriptor 2; see error() function).
390 * Before erasing the screen contents,
391 * display the file name and wait for a keystroke.
393 parg.p_string = filename;
402 * Edit a space-separated list of files.
403 * For each filename in the list, enter it into the ifile list.
404 * Then edit the first one.
415 struct textlist tl_files;
416 struct textlist tl_gfiles;
418 save_ifile = save_curr_ifile();
419 good_filename = NULL;
422 * Run thru each filename in the list.
423 * Try to glob the filename.
424 * If it doesn't expand, just try to open the filename.
425 * If it does expand, try to open each name in that list.
427 init_textlist(&tl_files, filelist);
429 while ((filename = forw_textlist(&tl_files, filename)) != NULL)
431 gfilelist = lglob(filename);
432 init_textlist(&tl_gfiles, gfilelist);
434 while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
436 if (edit(gfilename) == 0 && good_filename == NULL)
437 good_filename = get_filename(curr_ifile);
442 * Edit the first valid filename in the list.
444 if (good_filename == NULL)
446 unsave_ifile(save_ifile);
449 if (get_ifile(good_filename, curr_ifile) == curr_ifile)
452 * Trying to edit the current file; don't reopen it.
454 unsave_ifile(save_ifile);
457 reedit_ifile(save_ifile);
458 return (edit(good_filename));
462 * Edit the first file in the command line (ifile) list.
467 curr_ifile = NULL_IFILE;
468 return (edit_next(1));
472 * Edit the last file in the command line (ifile) list.
477 curr_ifile = NULL_IFILE;
478 return (edit_prev(1));
483 * Edit the next or previous file in the command line (ifile) list.
486 edit_istep(h, n, dir)
494 * Skip n filenames, then try to edit each filename.
498 next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
501 if (edit_ifile(h) == 0)
504 if (next == NULL_IFILE)
507 * Reached end of the ifile list.
514 * Interrupt breaks out, if we're in a long
515 * list of files that can't be opened.
522 * Found a file that we can edit.
532 return (edit_istep(h, n, 1));
539 return edit_istep(curr_ifile, n, 1);
547 return (edit_istep(h, n, -1));
554 return edit_istep(curr_ifile, n, -1);
558 * Edit a specific file in the command line (ifile) list.
569 if ((h = next_ifile(h)) == NULL_IFILE)
572 * Reached end of the list without finding it.
576 } while (get_index(h) != n);
578 return (edit_ifile(h));
584 if (curr_ifile != NULL_IFILE)
585 hold_ifile(curr_ifile, 1);
590 unsave_ifile(save_ifile)
593 if (save_ifile != NULL_IFILE)
594 hold_ifile(save_ifile, -1);
598 * Reedit the ifile which was previously open.
601 reedit_ifile(save_ifile)
608 * Try to reopen the ifile.
609 * Note that opening it may fail (maybe the file was removed),
610 * in which case the ifile will be deleted from the list.
611 * So save the next and prev ifiles first.
613 unsave_ifile(save_ifile);
614 next = next_ifile(save_ifile);
615 prev = prev_ifile(save_ifile);
616 if (edit_ifile(save_ifile) == 0)
619 * If can't reopen it, open the next input file in the list.
621 if (next != NULL_IFILE && edit_inext(next, 0) == 0)
624 * If can't open THAT one, open the previous input file in the list.
626 if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
629 * If can't even open that, we're stuck. Just quit.
635 * Edit standard input.
642 error("Missing filename (\"less --help\" for help)", NULL_PARG);
649 * Copy a file directly to standard output.
650 * Used if standard output is not a tty.
657 while ((c = ch_forw_get()) != EOI)
665 * If the user asked for a log file and our input file
666 * is standard input, create the log file.
667 * We take care not to blindly overwrite an existing file.
670 use_logfile(filename)
677 if (ch_getflags() & CH_CANSEEK)
679 * Can't currently use a log file on a file that can seek.
684 * {{ We could use access() here. }}
686 filename = unquote_file(filename);
687 exists = open(filename, OPEN_READ);
689 exists = (exists >= 0);
692 * Decide whether to overwrite the log file or append to it.
693 * If it doesn't exist we "overwrite" it.
695 if (!exists || force_logfile)
698 * Overwrite (or create) the log file.
704 * Ask user what to do.
706 parg.p_string = filename;
707 answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
715 * Overwrite: create the file.
717 logfile = creat(filename, 0644);
721 * Append: open the file and seek to the end.
723 logfile = open(filename, OPEN_APPEND);
724 if (lseek(logfile, (off_t)0, 2) == BAD_LSEEK)
743 answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
750 * Error in opening logfile.
752 parg.p_string = filename;
753 error("Cannot write to \"%s\"", &parg);