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
59
char *esc = get_meta_escape();
60
int esclen = strlen(esc);
63
tlist->string = skipsp(str);
64
tlist->endstring = tlist->string + strlen(tlist->string);
65
for (s = str; s < tlist->endstring; s++)
67
#if SPACES_IN_FILENAMES
71
} else if (esclen > 0 && s + esclen < tlist->endstring &&
72
strncmp(s, esc, esclen) == 0)
76
} else if (delim_quoted)
80
} else /* (!delim_quoted) */
95
forw_textlist(tlist, prev)
96
struct textlist *tlist;
102
* prev == NULL means return the first word in the list.
103
* Otherwise, return the word after "prev".
108
s = prev + strlen(prev);
109
if (s >= tlist->endstring)
113
if (s >= tlist->endstring)
119
back_textlist(tlist, prev)
120
struct textlist *tlist;
126
* prev == NULL means return the last word in the list.
127
* Otherwise, return the word before "prev".
130
s = tlist->endstring;
131
else if (prev <= tlist->string)
137
if (s <= tlist->string)
139
while (s[-1] != '\0' && s > tlist->string)
145
* Close the current input file.
150
struct scrpos scrpos;
152
if (curr_ifile == NULL_IFILE)
156
* Save the current position so that we can return to
157
* the same position if we edit this file again.
160
if (scrpos.pos != NULL_POSITION)
162
store_pos(curr_ifile, &scrpos);
166
* Close the file descriptor, unless it is a pipe.
170
* If we opened a file using an alternate name,
171
* do special stuff to close it.
173
if (curr_altfilename != NULL)
175
close_altfile(curr_altfilename, get_filename(curr_ifile),
177
free(curr_altfilename);
178
curr_altfilename = NULL;
180
curr_ifile = NULL_IFILE;
184
* Edit a new file (given its name).
185
* Filename == "-" means standard input.
186
* Filename == NULL means just close the current file.
192
if (filename == NULL)
193
return (edit_ifile(NULL_IFILE));
194
return (edit_ifile(get_ifile(filename, curr_ifile)));
198
* Edit a new file (given its IFILE).
199
* ifile == NULL means just close the current file.
211
char *qopen_filename;
214
IFILE was_curr_ifile;
217
if (ifile == curr_ifile)
220
* Already have the correct file open.
226
* We must close the currently open file now.
227
* This is necessary to make the open_altfile/close_altfile pairs
228
* nest properly (or rather to avoid nesting at all).
229
* {{ Some stupid implementations of popen() mess up if you do:
230
* fA = popen("A"); fB = popen("B"); pclose(fA); pclose(fB); }}
235
was_curr_ifile = save_curr_ifile();
236
if (curr_ifile != NULL_IFILE)
238
chflags = ch_getflags();
240
if ((chflags & CH_HELPFILE) && held_ifile(was_curr_ifile) <= 1)
243
* Don't keep the help file in the ifile list.
245
del_ifile(was_curr_ifile);
246
was_curr_ifile = old_ifile;
250
if (ifile == NULL_IFILE)
253
* No new file to open.
254
* (Don't set old_ifile, because if you call edit_ifile(NULL),
255
* you're supposed to have saved curr_ifile yourself,
256
* and you'll restore it if necessary.)
258
unsave_ifile(was_curr_ifile);
262
filename = save(get_filename(ifile));
264
* See if LESSOPEN specifies an "alternate" file to open.
267
alt_filename = open_altfile(filename, &f, &alt_pipe);
268
open_filename = (alt_filename != NULL) ? alt_filename : filename;
269
qopen_filename = shell_unquote(open_filename);
272
if (alt_pipe != NULL)
275
* The alternate "file" is actually a pipe.
276
* f has already been set to the file descriptor of the pipe
277
* in the call to open_altfile above.
278
* Keep the file descriptor open because it was opened
279
* via popen(), and pclose() wants to close it.
281
chflags |= CH_POPENED;
282
} else if (strcmp(open_filename, "-") == 0)
285
* Use standard input.
286
* Keep the file descriptor open because we can't reopen it.
289
chflags |= CH_KEEPOPEN;
291
* Must switch stdin to BINARY mode.
294
#if MSDOS_COMPILER==DJGPPC
296
* Setting stdin to binary by default causes
297
* Ctrl-C to not raise SIGINT. We must undo
300
__djgpp_set_ctrl_c(1);
302
} else if (strcmp(open_filename, FAKE_HELPFILE) == 0)
305
chflags |= CH_HELPFILE;
306
} else if ((parg.p_string = bad_file(open_filename)) != NULL)
309
* It looks like a bad file. Don't try to open it.
314
if (alt_filename != NULL)
316
close_altfile(alt_filename, filename, alt_pipe);
320
free(qopen_filename);
323
* Re-open the current file.
325
reedit_ifile(was_curr_ifile);
327
} else if ((f = open(qopen_filename, OPEN_READ)) < 0)
330
* Got an error trying to open it.
332
parg.p_string = errno_message(filename);
338
chflags |= CH_CANSEEK;
339
if (!force_open && !opened(ifile) && bin_file(f))
342
* Looks like a binary file.
343
* Ask user if we should proceed.
345
parg.p_string = filename;
346
answer = query("\"%s\" may be a binary file. See it anyway? ",
348
if (answer != 'y' && answer != 'Y')
355
free(qopen_filename);
359
* Get the saved position for the file.
361
if (was_curr_ifile != NULL_IFILE)
363
old_ifile = was_curr_ifile;
364
unsave_ifile(was_curr_ifile);
367
curr_altfilename = alt_filename;
368
curr_altpipe = alt_pipe;
369
set_open(curr_ifile); /* File has been opened */
370
get_pos(curr_ifile, &initial_scrpos);
374
if (!(chflags & CH_HELPFILE))
377
if (namelogfile != NULL && is_tty)
378
use_logfile(namelogfile);
380
if (every_first_cmd != NULL)
381
ungetsc(every_first_cmd);
384
no_display = !any_display;
391
* Output is to a real tty.
395
* Indicate there is nothing displayed yet.
402
cmd_addhist(ml_examine, filename);
403
if (no_display && errmsgs > 0)
406
* We displayed some messages on error output
407
* (file descriptor 2; see error() function).
408
* Before erasing the screen contents,
409
* display the file name and wait for a keystroke.
411
parg.p_string = filename;
420
* Edit a space-separated list of files.
421
* For each filename in the list, enter it into the ifile list.
422
* Then edit the first one.
433
struct textlist tl_files;
434
struct textlist tl_gfiles;
436
save_ifile = save_curr_ifile();
437
good_filename = NULL;
440
* Run thru each filename in the list.
441
* Try to glob the filename.
442
* If it doesn't expand, just try to open the filename.
443
* If it does expand, try to open each name in that list.
445
init_textlist(&tl_files, filelist);
447
while ((filename = forw_textlist(&tl_files, filename)) != NULL)
449
gfilelist = lglob(filename);
450
init_textlist(&tl_gfiles, gfilelist);
452
while ((gfilename = forw_textlist(&tl_gfiles, gfilename)) != NULL)
454
if (edit(gfilename) == 0 && good_filename == NULL)
455
good_filename = get_filename(curr_ifile);
460
* Edit the first valid filename in the list.
462
if (good_filename == NULL)
464
unsave_ifile(save_ifile);
467
if (get_ifile(good_filename, curr_ifile) == curr_ifile)
470
* Trying to edit the current file; don't reopen it.
472
unsave_ifile(save_ifile);
475
reedit_ifile(save_ifile);
476
return (edit(good_filename));
480
* Edit the first file in the command line (ifile) list.
485
curr_ifile = NULL_IFILE;
486
return (edit_next(1));
490
* Edit the last file in the command line (ifile) list.
495
curr_ifile = NULL_IFILE;
496
return (edit_prev(1));
501
* Edit the next or previous file in the command line (ifile) list.
504
edit_istep(h, n, dir)
512
* Skip n filenames, then try to edit each filename.
516
next = (dir > 0) ? next_ifile(h) : prev_ifile(h);
519
if (edit_ifile(h) == 0)
522
if (next == NULL_IFILE)
525
* Reached end of the ifile list.
532
* Interrupt breaks out, if we're in a long
533
* list of files that can't be opened.
540
* Found a file that we can edit.
550
return (edit_istep(h, n, 1));
557
return edit_istep(curr_ifile, n, 1);
565
return (edit_istep(h, n, -1));
572
return edit_istep(curr_ifile, n, -1);
576
* Edit a specific file in the command line (ifile) list.
587
if ((h = next_ifile(h)) == NULL_IFILE)
590
* Reached end of the list without finding it.
594
} while (get_index(h) != n);
596
return (edit_ifile(h));
602
if (curr_ifile != NULL_IFILE)
603
hold_ifile(curr_ifile, 1);
608
unsave_ifile(save_ifile)
611
if (save_ifile != NULL_IFILE)
612
hold_ifile(save_ifile, -1);
616
* Reedit the ifile which was previously open.
619
reedit_ifile(save_ifile)
626
* Try to reopen the ifile.
627
* Note that opening it may fail (maybe the file was removed),
628
* in which case the ifile will be deleted from the list.
629
* So save the next and prev ifiles first.
631
unsave_ifile(save_ifile);
632
next = next_ifile(save_ifile);
633
prev = prev_ifile(save_ifile);
634
if (edit_ifile(save_ifile) == 0)
637
* If can't reopen it, open the next input file in the list.
639
if (next != NULL_IFILE && edit_inext(next, 0) == 0)
642
* If can't open THAT one, open the previous input file in the list.
644
if (prev != NULL_IFILE && edit_iprev(prev, 0) == 0)
647
* If can't even open that, we're stuck. Just quit.
653
* Edit standard input.
660
error("Missing filename (\"less --help\" for help)", NULL_PARG);
667
* Copy a file directly to standard output.
668
* Used if standard output is not a tty.
675
while ((c = ch_forw_get()) != EOI)
683
* If the user asked for a log file and our input file
684
* is standard input, create the log file.
685
* We take care not to blindly overwrite an existing file.
688
use_logfile(filename)
695
if (ch_getflags() & CH_CANSEEK)
697
* Can't currently use a log file on a file that can seek.
702
* {{ We could use access() here. }}
704
filename = shell_unquote(filename);
705
exists = open(filename, OPEN_READ);
707
exists = (exists >= 0);
710
* Decide whether to overwrite the log file or append to it.
711
* If it doesn't exist we "overwrite" it.
713
if (!exists || force_logfile)
716
* Overwrite (or create) the log file.
722
* Ask user what to do.
724
parg.p_string = filename;
725
answer = query("Warning: \"%s\" exists; Overwrite, Append or Don't log? ", &parg);
733
* Overwrite: create the file.
735
logfile = creat(filename, 0644);
739
* Append: open the file and seek to the end.
741
logfile = open(filename, OPEN_APPEND);
742
if (lseek(logfile, (off_t)0, 2) == BAD_LSEEK)
761
answer = query("Overwrite, Append, or Don't log? (Type \"O\", \"A\", \"D\" or \"q\") ", NULL_PARG);
768
* Error in opening logfile.
770
parg.p_string = filename;
771
error("Cannot write to \"%s\"", &parg);