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.
13
* Routines to mess around with filenames (and files).
14
* Much of this is very OS dependent.
21
#if MSDOS_COMPILER==WIN32C && !defined(_MSC_VER)
24
#if MSDOS_COMPILER==DJGPPC
27
#define _MAX_PATH PATH_MAX
43
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
46
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
51
extern int force_open;
53
extern IFILE curr_ifile;
54
extern IFILE old_ifile;
55
#if SPACES_IN_FILENAMES
56
extern char openquote;
57
extern char closequote;
61
* Remove quotes around a filename.
70
name = p = (char *) ecalloc(strlen(str)+1, sizeof(char));
71
if (*str == openquote)
76
if (*str == closequote)
78
if (str[1] != closequote)
86
char *esc = get_meta_escape();
87
int esclen = strlen(esc);
90
if (esclen > 0 && strncmp(str, esc, esclen) == 0)
100
* Get the shell's escape character.
107
s = lgetenv("LESSMETAESCAPE");
114
* Get the characters which the shell considers to be "metacharacters".
119
static char *mchars = NULL;
123
mchars = lgetenv("LESSMETACHARS");
125
mchars = DEF_METACHARS;
131
* Is this a shell metacharacter?
137
return (strchr(metachars(), c) != NULL);
141
* Insert a backslash before each metacharacter in a string.
150
char *esc = get_meta_escape();
151
int esclen = strlen(esc);
156
* Determine how big a string we need to allocate.
158
len = 1; /* Trailing null byte */
159
for (p = s; *p != '\0'; p++)
162
if (*p == openquote || *p == closequote)
169
* We've got a metachar, but this shell
170
* doesn't support escape chars. Use quotes.
176
* Allow space for the escape char.
186
* We can't quote a string that contains quotes.
192
* Allocate and construct the new string.
194
newstr = p = (char *) ecalloc(len, sizeof(char));
197
sprintf(newstr, "%c%s%c", openquote, s, closequote);
205
* Add the escape char.
218
* Return a pathname that points to a specified file in a specified directory.
219
* Return NULL if the file does not exist in the directory.
222
dirfile(dirname, filename)
230
if (dirname == NULL || *dirname == '\0')
233
* Construct the full pathname.
235
pathname = (char *) calloc(strlen(dirname) + strlen(filename) + 2,
237
if (pathname == NULL)
239
sprintf(pathname, "%s%s%s", dirname, PATHNAME_SEP, filename);
241
* Make sure the file exists.
243
qpathname = shell_unquote(pathname);
244
f = open(qpathname, OPEN_READ);
258
* Return the full pathname of the given file in the "home directory".
264
register char *pathname;
267
* Try $HOME/filename.
269
pathname = dirfile(lgetenv("HOME"), filename);
270
if (pathname != NULL)
274
* Try $INIT/filename.
276
pathname = dirfile(lgetenv("INIT"), filename);
277
if (pathname != NULL)
280
#if MSDOS_COMPILER || OS2
282
* Look for the file anywhere on search path.
284
pathname = (char *) calloc(_MAX_PATH, sizeof(char));
285
#if MSDOS_COMPILER==DJGPPC
287
char *res = searchpath(filename);
291
strcpy(pathname, res);
294
_searchenv(filename, "PATH", pathname);
296
if (*pathname != '\0')
304
* Expand a string, substituting any "%" with the current filename,
305
* and any "#" with the previous filename.
306
* But a string of N "%"s is just replaced with N-1 "%"s.
307
* Likewise for a string of N "#"s.
308
* {{ This is a lot of work just to support % and #. }}
314
register char *fr, *to;
319
#define fchar_ifile(c) \
320
((c) == '%' ? curr_ifile : \
321
(c) == '#' ? old_ifile : NULL_IFILE)
324
* Make one pass to see how big a buffer we
325
* need to allocate for the expanded string.
328
for (fr = s; *fr != '\0'; fr++)
334
if (fr > s && fr[-1] == *fr)
337
* Second (or later) char in a string
338
* of identical chars. Treat as normal.
341
} else if (fr[1] != *fr)
344
* Single char (not repeated). Treat specially.
346
ifile = fchar_ifile(*fr);
347
if (ifile == NULL_IFILE)
350
n += strlen(get_filename(ifile));
353
* Else it is the first char in a string of
354
* identical chars. Just discard it.
363
e = (char *) ecalloc(n+1, sizeof(char));
366
* Now copy the string, expanding any "%" or "#".
369
for (fr = s; *fr != '\0'; fr++)
375
if (fr > s && fr[-1] == *fr)
378
} else if (fr[1] != *fr)
380
ifile = fchar_ifile(*fr);
381
if (ifile == NULL_IFILE)
385
strcpy(to, get_filename(ifile));
399
#if TAB_COMPLETE_FILENAME
402
* Return a blank-separated list of filenames which "complete"
415
* Complete the filename "s" by globbing "s*".
417
#if MSDOS_COMPILER && (MSDOS_COMPILER == MSOFTC || MSDOS_COMPILER == BORLANDC)
419
* But in DOS, we have to glob "s*.*".
420
* But if the final component of the filename already has
421
* a dot in it, just do "s*".
422
* (Thus, "FILE" is globbed as "FILE*.*",
423
* but "FILE.A" is globbed as "FILE.A*").
427
for (slash = s+strlen(s)-1; slash > s; slash--)
428
if (*slash == *PATHNAME_SEP || *slash == '/')
430
fpat = (char *) ecalloc(strlen(s)+4, sizeof(char));
431
if (strchr(slash, '.') == NULL)
432
sprintf(fpat, "%s*.*", s);
434
sprintf(fpat, "%s*", s);
437
fpat = (char *) ecalloc(strlen(s)+2, sizeof(char));
438
sprintf(fpat, "%s*", s);
441
s = shell_unquote(qs);
442
if (strcmp(s,fpat) == 0)
445
* The filename didn't expand.
457
* Try to determine if a file is "binary".
458
* This is just a guess, and we need not try too hard to make it accurate.
466
unsigned char data[64];
470
if (lseek(f, (off_t)0, 0) == BAD_LSEEK)
472
n = read(f, data, sizeof(data));
473
for (i = 0; i < n; i++)
474
if (binary_char(data[i]))
480
* Try to determine the size of a file by seeking to the end.
488
spos = lseek(f, (off_t)0, 2);
489
if (spos == BAD_LSEEK)
490
return (NULL_POSITION);
491
return ((POSITION) spos);
495
* Read a string from a file.
496
* Return a pointer to the string in memory.
508
* Make a guess about how many chars in the string
509
* and allocate a buffer to hold it.
512
buf = (char *) ecalloc(len, sizeof(char));
515
if ((ch = getc(fd)) == '\n' || ch == EOF)
517
if (p - buf >= len-1)
520
* The string is too big to fit in the buffer we have.
521
* Allocate a new buffer, twice as big.
525
p = (char *) ecalloc(len, sizeof(char));
529
p = buf + strlen(buf);
544
* Execute a shell command.
545
* Return a pointer to a pipe connected to the shell command's standard output.
556
shell = lgetenv("SHELL");
557
if (shell != NULL && *shell != '\0')
563
* Read the output of <$SHELL -c cmd>.
564
* Escape any metacharacters in the command.
566
esccmd = shell_quote(cmd);
569
fd = popen(cmd, "r");
572
scmd = (char *) ecalloc(strlen(shell) + strlen(esccmd) + 5,
574
sprintf(scmd, "%s %s %s", shell, shell_coption(), esccmd);
576
fd = popen(scmd, "r");
582
fd = popen(cmd, "r");
585
* Redirection in `popen' might have messed with the
586
* standard devices. Restore binary input mode.
592
#endif /* HAVE_POPEN */
596
* Expand a filename, doing any system-specific metacharacter substitutions.
605
ofilename = fexpand(filename);
608
filename = shell_unquote(ofilename);
610
#ifdef DECL_GLOB_LIST
613
* The globbing function returns a list of names.
620
GLOB_LIST(filename, list);
621
if (GLOB_LIST_FAILED(list))
626
length = 1; /* Room for trailing null byte */
627
for (SCAN_GLOB_LIST(list, p))
629
INIT_GLOB_LIST(list, p);
630
qfilename = shell_quote(p);
631
if (qfilename != NULL)
633
length += strlen(qfilename) + 1;
637
gfilename = (char *) ecalloc(length, sizeof(char));
638
for (SCAN_GLOB_LIST(list, p))
640
INIT_GLOB_LIST(list, p);
641
qfilename = shell_quote(p);
642
if (qfilename != NULL)
644
sprintf(gfilename + strlen(gfilename), "%s ", qfilename);
649
* Overwrite the final trailing space with a null terminator.
652
GLOB_LIST_DONE(list);
655
#ifdef DECL_GLOB_NAME
658
* The globbing function returns a single name, and
659
* is called multiple times to walk thru all names.
666
DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle)
668
GLOB_FIRST_NAME(filename, &fnd, handle);
669
if (GLOB_FIRST_FAILED(handle))
675
_splitpath(filename, drive, dir, fname, ext);
677
gfilename = (char *) ecalloc(len, sizeof(char));
680
n = strlen(drive) + strlen(dir) + strlen(fnd.GLOB_NAME) + 1;
681
pathname = (char *) ecalloc(n, sizeof(char));
682
sprintf(pathname, "%s%s%s", drive, dir, fnd.GLOB_NAME);
683
qpathname = shell_quote(pathname);
685
if (qpathname != NULL)
687
n = strlen(qpathname);
688
while (p - gfilename + n + 2 >= len)
691
* No room in current buffer.
692
* Allocate a bigger one.
696
p = (char *) ecalloc(len, sizeof(char));
697
strcpy(p, gfilename);
700
p = gfilename + strlen(gfilename);
702
strcpy(p, qpathname);
707
} while (GLOB_NEXT_NAME(handle, &fnd) == 0);
710
* Overwrite the final trailing space with a null terminator.
713
GLOB_NAME_DONE(handle);
719
* We get the shell to glob the filename for us by passing
720
* an "echo" command to the shell and reading its output.
728
esc = get_meta_escape();
729
if (strlen(esc) == 0)
731
esc = shell_quote(esc);
737
lessecho = lgetenv("LESSECHO");
738
if (lessecho == NULL || *lessecho == '\0')
739
lessecho = "lessecho";
741
* Invoke lessecho, and read its output (a globbed list of filenames).
743
cmd = (char *) ecalloc(strlen(lessecho) + strlen(ofilename) + (7*strlen(metachars())) + 24, sizeof(char));
744
sprintf(cmd, "%s -p0x%x -d0x%x -e%s ", lessecho, openquote, closequote, esc);
746
for (s = metachars(); *s != '\0'; s++)
747
sprintf(cmd + strlen(cmd), "-n0x%x ", *s);
748
sprintf(cmd + strlen(cmd), "-- %s", ofilename);
754
* Cannot create the pipe.
755
* Just return the original (fexpanded) filename.
760
gfilename = readfd(fd);
762
if (*gfilename == '\0')
771
* No globbing functions at all. Just use the fexpanded filename.
773
gfilename = save(filename);
783
* See if we should open a "replacement file"
784
* instead of the file we're about to open.
787
open_altfile(filename, pf, pfd)
805
if ((lessopen = lgetenv("LESSOPEN")) == NULL)
807
if (strcmp(filename, "-") == 0)
809
if (*lessopen == '|')
812
* If LESSOPEN starts with a |, it indicates
813
* a "pipe preprocessor".
819
error("LESSOPEN pipe is not supported", NULL_PARG);
824
cmd = (char *) ecalloc(strlen(lessopen) + strlen(filename) + 2,
826
sprintf(cmd, lessopen, filename);
832
* Cannot create the pipe.
843
* Read one char to see if the pipe will produce any data.
844
* If it does, push the char back on the pipe.
848
if (read(f, &c, 1) != 1)
851
* Pipe is empty. This means there is no alt file.
866
* Pipe is empty. This means there is no alt file.
870
#endif /* HAVE_POPEN */
874
* Close a replacement file.
877
close_altfile(altfilename, filename, pipefd)
893
* The pclose function of OS/2 emx sometimes fails.
894
* Send SIGINT to the piped process before closing it.
896
kill(((FILE*)pipefd)->_pid, SIGINT);
898
pclose((FILE*) pipefd);
900
if ((lessclose = lgetenv("LESSCLOSE")) == NULL)
902
cmd = (char *) ecalloc(strlen(lessclose) + strlen(filename) +
903
strlen(altfilename) + 2, sizeof(char));
904
sprintf(cmd, lessclose, filename, altfilename);
913
* Is the specified file a directory?
921
filename = shell_unquote(filename);
927
r = stat(filename, &statbuf);
928
isdir = (r >= 0 && S_ISDIR(statbuf.st_mode));
935
f = open(filename, S_IREAD | S_IFDIR);
947
* Returns NULL if the file can be opened and
948
* is an ordinary file, otherwise an error message
949
* (if it cannot be opened or is a directory, etc.)
955
register char *m = NULL;
957
filename = shell_unquote(filename);
958
if (is_dir(filename))
960
static char is_dir[] = " is a directory";
962
m = (char *) ecalloc(strlen(filename) + sizeof(is_dir),
972
r = stat(filename, &statbuf);
975
m = errno_message(filename);
976
} else if (force_open)
979
} else if (!S_ISREG(statbuf.st_mode))
981
static char not_reg[] = " is not a regular file (use -f to see it)";
982
m = (char *) ecalloc(strlen(filename) + sizeof(not_reg),
994
* Return the size of a file, as cheaply as possible.
995
* In Unix, we can stat the file.
1002
struct stat statbuf;
1004
if (fstat(f, &statbuf) >= 0)
1005
return ((POSITION) statbuf.st_size);
1010
if ((size = (long) _gs_size(f)) >= 0)
1011
return ((POSITION) size);
1014
return (seek_filesize(f));