Changeset View
Changeset View
Standalone View
Standalone View
contrib/less/filename.c
Show First 20 Lines • Show All 57 Lines • ▼ Show 20 Lines | |||||
extern char openquote; | extern char openquote; | ||||
extern char closequote; | extern char closequote; | ||||
#endif | #endif | ||||
/* | /* | ||||
* Remove quotes around a filename. | * Remove quotes around a filename. | ||||
*/ | */ | ||||
public char * | public char * | ||||
shell_unquote(str) | shell_unquote(char *str) | ||||
char *str; | |||||
{ | { | ||||
char *name; | char *name; | ||||
char *p; | char *p; | ||||
name = p = (char *) ecalloc(strlen(str)+1, sizeof(char)); | name = p = (char *) ecalloc(strlen(str)+1, sizeof(char)); | ||||
if (*str == openquote) | if (*str == openquote) | ||||
{ | { | ||||
str++; | str++; | ||||
Show All 21 Lines | shell_unquote(char *str) | ||||
*p = '\0'; | *p = '\0'; | ||||
return (name); | return (name); | ||||
} | } | ||||
/* | /* | ||||
* Get the shell's escape character. | * Get the shell's escape character. | ||||
*/ | */ | ||||
public char * | public char * | ||||
get_meta_escape() | get_meta_escape(void) | ||||
{ | { | ||||
char *s; | char *s; | ||||
s = lgetenv("LESSMETAESCAPE"); | s = lgetenv("LESSMETAESCAPE"); | ||||
if (s == NULL) | if (s == NULL) | ||||
s = DEF_METAESCAPE; | s = DEF_METAESCAPE; | ||||
return (s); | return (s); | ||||
} | } | ||||
/* | /* | ||||
* Get the characters which the shell considers to be "metacharacters". | * Get the characters which the shell considers to be "metacharacters". | ||||
*/ | */ | ||||
static char * | static char * | ||||
metachars() | metachars(void) | ||||
{ | { | ||||
static char *mchars = NULL; | static char *mchars = NULL; | ||||
if (mchars == NULL) | if (mchars == NULL) | ||||
{ | { | ||||
mchars = lgetenv("LESSMETACHARS"); | mchars = lgetenv("LESSMETACHARS"); | ||||
if (mchars == NULL) | if (mchars == NULL) | ||||
mchars = DEF_METACHARS; | mchars = DEF_METACHARS; | ||||
} | } | ||||
return (mchars); | return (mchars); | ||||
} | } | ||||
/* | /* | ||||
* Is this a shell metacharacter? | * Is this a shell metacharacter? | ||||
*/ | */ | ||||
static int | static int | ||||
metachar(c) | metachar(char c) | ||||
char c; | |||||
{ | { | ||||
return (strchr(metachars(), c) != NULL); | return (strchr(metachars(), c) != NULL); | ||||
} | } | ||||
/* | /* | ||||
* Insert a backslash before each metacharacter in a string. | * Insert a backslash before each metacharacter in a string. | ||||
*/ | */ | ||||
public char * | public char * | ||||
shell_quote(s) | shell_quote(char *s) | ||||
char *s; | |||||
{ | { | ||||
char *p; | char *p; | ||||
char *newstr; | char *newstr; | ||||
int len; | int len; | ||||
char *esc = get_meta_escape(); | char *esc = get_meta_escape(); | ||||
int esclen = (int) strlen(esc); | int esclen = (int) strlen(esc); | ||||
int use_quotes = 0; | int use_quotes = 0; | ||||
int have_quotes = 0; | int have_quotes = 0; | ||||
▲ Show 20 Lines • Show All 60 Lines • ▼ Show 20 Lines | shell_quote(char *s) | ||||
return (newstr); | return (newstr); | ||||
} | } | ||||
/* | /* | ||||
* Return a pathname that points to a specified file in a specified directory. | * Return a pathname that points to a specified file in a specified directory. | ||||
* Return NULL if the file does not exist in the directory. | * Return NULL if the file does not exist in the directory. | ||||
*/ | */ | ||||
static char * | static char * | ||||
dirfile(dirname, filename) | dirfile(char *dirname, char *filename) | ||||
char *dirname; | |||||
char *filename; | |||||
{ | { | ||||
char *pathname; | char *pathname; | ||||
char *qpathname; | char *qpathname; | ||||
int len; | int len; | ||||
int f; | int f; | ||||
if (dirname == NULL || *dirname == '\0') | if (dirname == NULL || *dirname == '\0') | ||||
return (NULL); | return (NULL); | ||||
Show All 21 Lines | dirfile(char *dirname, char *filename) | ||||
free(qpathname); | free(qpathname); | ||||
return (pathname); | return (pathname); | ||||
} | } | ||||
/* | /* | ||||
* Return the full pathname of the given file in the "home directory". | * Return the full pathname of the given file in the "home directory". | ||||
*/ | */ | ||||
public char * | public char * | ||||
homefile(filename) | homefile(char *filename) | ||||
char *filename; | |||||
{ | { | ||||
register char *pathname; | char *pathname; | ||||
/* | /* | ||||
* Try $HOME/filename. | * Try $HOME/filename. | ||||
*/ | */ | ||||
pathname = dirfile(lgetenv("HOME"), filename); | pathname = dirfile(lgetenv("HOME"), filename); | ||||
if (pathname != NULL) | if (pathname != NULL) | ||||
return (pathname); | return (pathname); | ||||
#if OS2 | #if OS2 | ||||
Show All 30 Lines | |||||
/* | /* | ||||
* Expand a string, substituting any "%" with the current filename, | * Expand a string, substituting any "%" with the current filename, | ||||
* and any "#" with the previous filename. | * and any "#" with the previous filename. | ||||
* But a string of N "%"s is just replaced with N-1 "%"s. | * But a string of N "%"s is just replaced with N-1 "%"s. | ||||
* Likewise for a string of N "#"s. | * Likewise for a string of N "#"s. | ||||
* {{ This is a lot of work just to support % and #. }} | * {{ This is a lot of work just to support % and #. }} | ||||
*/ | */ | ||||
public char * | public char * | ||||
fexpand(s) | fexpand(char *s) | ||||
char *s; | |||||
{ | { | ||||
register char *fr, *to; | char *fr, *to; | ||||
register int n; | int n; | ||||
register char *e; | char *e; | ||||
IFILE ifile; | IFILE ifile; | ||||
#define fchar_ifile(c) \ | #define fchar_ifile(c) \ | ||||
((c) == '%' ? curr_ifile : \ | ((c) == '%' ? curr_ifile : \ | ||||
(c) == '#' ? old_ifile : NULL_IFILE) | (c) == '#' ? old_ifile : NULL_IFILE) | ||||
/* | /* | ||||
* Make one pass to see how big a buffer we | * Make one pass to see how big a buffer we | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
#if TAB_COMPLETE_FILENAME | #if TAB_COMPLETE_FILENAME | ||||
/* | /* | ||||
* Return a blank-separated list of filenames which "complete" | * Return a blank-separated list of filenames which "complete" | ||||
* the given string. | * the given string. | ||||
*/ | */ | ||||
public char * | public char * | ||||
fcomplete(s) | fcomplete(char *s) | ||||
char *s; | |||||
{ | { | ||||
char *fpat; | char *fpat; | ||||
char *qs; | char *qs; | ||||
if (secure) | if (secure) | ||||
return (NULL); | return (NULL); | ||||
/* | /* | ||||
* Complete the filename "s" by globbing "s*". | * Complete the filename "s" by globbing "s*". | ||||
▲ Show 20 Lines • Show All 42 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#endif | #endif | ||||
/* | /* | ||||
* Try to determine if a file is "binary". | * Try to determine if a file is "binary". | ||||
* This is just a guess, and we need not try too hard to make it accurate. | * This is just a guess, and we need not try too hard to make it accurate. | ||||
*/ | */ | ||||
public int | public int | ||||
bin_file(f) | bin_file(int f) | ||||
int f; | |||||
{ | { | ||||
int n; | int n; | ||||
int bin_count = 0; | int bin_count = 0; | ||||
char data[256]; | char data[256]; | ||||
char* p; | constant char* p; | ||||
char* pend; | char* pend; | ||||
if (!seekable(f)) | if (!seekable(f)) | ||||
return (0); | return (0); | ||||
if (lseek(f, (off_t)0, SEEK_SET) == BAD_LSEEK) | if (lseek(f, (off_t)0, SEEK_SET) == BAD_LSEEK) | ||||
return (0); | return (0); | ||||
n = read(f, data, sizeof(data)); | n = read(f, data, sizeof(data)); | ||||
if (n <= 0) | if (n <= 0) | ||||
Show All 22 Lines | bin_file(int f) | ||||
*/ | */ | ||||
return (bin_count > 5); | return (bin_count > 5); | ||||
} | } | ||||
/* | /* | ||||
* Try to determine the size of a file by seeking to the end. | * Try to determine the size of a file by seeking to the end. | ||||
*/ | */ | ||||
static POSITION | static POSITION | ||||
seek_filesize(f) | seek_filesize(int f) | ||||
int f; | |||||
{ | { | ||||
off_t spos; | off_t spos; | ||||
spos = lseek(f, (off_t)0, SEEK_END); | spos = lseek(f, (off_t)0, SEEK_END); | ||||
if (spos == BAD_LSEEK) | if (spos == BAD_LSEEK) | ||||
return (NULL_POSITION); | return (NULL_POSITION); | ||||
return ((POSITION) spos); | return ((POSITION) spos); | ||||
} | } | ||||
/* | /* | ||||
* Read a string from a file. | * Read a string from a file. | ||||
* Return a pointer to the string in memory. | * Return a pointer to the string in memory. | ||||
*/ | */ | ||||
static char * | static char * | ||||
readfd(fd) | readfd(FILE *fd) | ||||
FILE *fd; | |||||
{ | { | ||||
int len; | int len; | ||||
int ch; | int ch; | ||||
char *buf; | char *buf; | ||||
char *p; | char *p; | ||||
/* | /* | ||||
* Make a guess about how many chars in the string | * Make a guess about how many chars in the string | ||||
Show All 31 Lines | |||||
FILE *popen(); | FILE *popen(); | ||||
/* | /* | ||||
* Execute a shell command. | * Execute a shell command. | ||||
* Return a pointer to a pipe connected to the shell command's standard output. | * Return a pointer to a pipe connected to the shell command's standard output. | ||||
*/ | */ | ||||
static FILE * | static FILE * | ||||
shellcmd(cmd) | shellcmd(char *cmd) | ||||
char *cmd; | |||||
{ | { | ||||
FILE *fd; | FILE *fd; | ||||
#if HAVE_SHELL | #if HAVE_SHELL | ||||
char *shell; | char *shell; | ||||
shell = lgetenv("SHELL"); | shell = lgetenv("SHELL"); | ||||
if (shell != NULL && *shell != '\0') | if (shell != NULL && *shell != '\0') | ||||
Show All 33 Lines | |||||
#endif /* HAVE_POPEN */ | #endif /* HAVE_POPEN */ | ||||
/* | /* | ||||
* Expand a filename, doing any system-specific metacharacter substitutions. | * Expand a filename, doing any system-specific metacharacter substitutions. | ||||
*/ | */ | ||||
public char * | public char * | ||||
lglob(filename) | lglob(char *filename) | ||||
char *filename; | |||||
{ | { | ||||
char *gfilename; | char *gfilename; | ||||
char *ofilename; | char *ofilename; | ||||
ofilename = fexpand(filename); | ofilename = fexpand(filename); | ||||
if (secure) | if (secure) | ||||
return (ofilename); | return (ofilename); | ||||
filename = shell_unquote(ofilename); | filename = shell_unquote(ofilename); | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
#else | #else | ||||
#ifdef DECL_GLOB_NAME | #ifdef DECL_GLOB_NAME | ||||
{ | { | ||||
/* | /* | ||||
* The globbing function returns a single name, and | * The globbing function returns a single name, and | ||||
* is called multiple times to walk thru all names. | * is called multiple times to walk thru all names. | ||||
*/ | */ | ||||
register char *p; | char *p; | ||||
register int len; | int len; | ||||
register int n; | int n; | ||||
char *pathname; | char *pathname; | ||||
char *qpathname; | char *qpathname; | ||||
DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) | DECL_GLOB_NAME(fnd,drive,dir,fname,ext,handle) | ||||
GLOB_FIRST_NAME(filename, &fnd, handle); | GLOB_FIRST_NAME(filename, &fnd, handle); | ||||
if (GLOB_FIRST_FAILED(handle)) | if (GLOB_FIRST_FAILED(handle)) | ||||
{ | { | ||||
free(filename); | free(filename); | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | #endif | ||||
return (gfilename); | return (gfilename); | ||||
} | } | ||||
/* | /* | ||||
* Return number of %s escapes in a string. | * Return number of %s escapes in a string. | ||||
* Return a large number if there are any other % escapes besides %s. | * Return a large number if there are any other % escapes besides %s. | ||||
*/ | */ | ||||
static int | static int | ||||
num_pct_s(lessopen) | num_pct_s(char *lessopen) | ||||
char *lessopen; | |||||
{ | { | ||||
int num = 0; | int num = 0; | ||||
while (*lessopen != '\0') | while (*lessopen != '\0') | ||||
{ | { | ||||
if (*lessopen == '%') | if (*lessopen == '%') | ||||
{ | { | ||||
if (lessopen[1] == '%') | if (lessopen[1] == '%') | ||||
++lessopen; | ++lessopen; | ||||
else if (lessopen[1] == 's') | else if (lessopen[1] == 's') | ||||
++num; | ++num; | ||||
else | else | ||||
return (999); | return (999); | ||||
} | } | ||||
++lessopen; | ++lessopen; | ||||
} | } | ||||
return (num); | return (num); | ||||
} | } | ||||
/* | /* | ||||
* See if we should open a "replacement file" | * See if we should open a "replacement file" | ||||
* instead of the file we're about to open. | * instead of the file we're about to open. | ||||
*/ | */ | ||||
public char * | public char * | ||||
open_altfile(filename, pf, pfd) | open_altfile(char *filename, int *pf, void **pfd) | ||||
char *filename; | |||||
int *pf; | |||||
void **pfd; | |||||
{ | { | ||||
#if !HAVE_POPEN | #if !HAVE_POPEN | ||||
return (NULL); | return (NULL); | ||||
#else | #else | ||||
char *lessopen; | char *lessopen; | ||||
char *cmd; | char *cmd; | ||||
int len; | int len; | ||||
FILE *fd; | FILE *fd; | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | #endif | ||||
return (cmd); | return (cmd); | ||||
#endif /* HAVE_POPEN */ | #endif /* HAVE_POPEN */ | ||||
} | } | ||||
/* | /* | ||||
* Close a replacement file. | * Close a replacement file. | ||||
*/ | */ | ||||
public void | public void | ||||
close_altfile(altfilename, filename, pipefd) | close_altfile(char *altfilename, char *filename, void *pipefd) | ||||
char *altfilename; | |||||
char *filename; | |||||
void *pipefd; | |||||
{ | { | ||||
#if HAVE_POPEN | #if HAVE_POPEN | ||||
char *lessclose; | char *lessclose; | ||||
FILE *fd; | FILE *fd; | ||||
char *cmd; | char *cmd; | ||||
int len; | int len; | ||||
if (secure) | if (secure) | ||||
Show All 25 Lines | if (fd != NULL) | ||||
pclose(fd); | pclose(fd); | ||||
#endif | #endif | ||||
} | } | ||||
/* | /* | ||||
* Is the specified file a directory? | * Is the specified file a directory? | ||||
*/ | */ | ||||
public int | public int | ||||
is_dir(filename) | is_dir(char *filename) | ||||
char *filename; | |||||
{ | { | ||||
int isdir = 0; | int isdir = 0; | ||||
filename = shell_unquote(filename); | filename = shell_unquote(filename); | ||||
#if HAVE_STAT | #if HAVE_STAT | ||||
{ | { | ||||
int r; | int r; | ||||
struct stat statbuf; | struct stat statbuf; | ||||
r = stat(filename, &statbuf); | r = stat(filename, &statbuf); | ||||
isdir = (r >= 0 && S_ISDIR(statbuf.st_mode)); | isdir = (r >= 0 && S_ISDIR(statbuf.st_mode)); | ||||
} | } | ||||
#else | #else | ||||
#ifdef _OSK | #ifdef _OSK | ||||
{ | { | ||||
register int f; | int f; | ||||
f = open(filename, S_IREAD | S_IFDIR); | f = open(filename, S_IREAD | S_IFDIR); | ||||
if (f >= 0) | if (f >= 0) | ||||
close(f); | close(f); | ||||
isdir = (f >= 0); | isdir = (f >= 0); | ||||
} | } | ||||
#endif | #endif | ||||
#endif | #endif | ||||
free(filename); | free(filename); | ||||
return (isdir); | return (isdir); | ||||
} | } | ||||
/* | /* | ||||
* Returns NULL if the file can be opened and | * Returns NULL if the file can be opened and | ||||
* is an ordinary file, otherwise an error message | * is an ordinary file, otherwise an error message | ||||
* (if it cannot be opened or is a directory, etc.) | * (if it cannot be opened or is a directory, etc.) | ||||
*/ | */ | ||||
public char * | public char * | ||||
bad_file(filename) | bad_file(char *filename) | ||||
char *filename; | |||||
{ | { | ||||
register char *m = NULL; | char *m = NULL; | ||||
filename = shell_unquote(filename); | filename = shell_unquote(filename); | ||||
if (!force_open && is_dir(filename)) | if (!force_open && is_dir(filename)) | ||||
{ | { | ||||
static char is_a_dir[] = " is a directory"; | static char is_a_dir[] = " is a directory"; | ||||
m = (char *) ecalloc(strlen(filename) + sizeof(is_a_dir), | m = (char *) ecalloc(strlen(filename) + sizeof(is_a_dir), | ||||
sizeof(char)); | sizeof(char)); | ||||
Show All 26 Lines | #endif | ||||
return (m); | return (m); | ||||
} | } | ||||
/* | /* | ||||
* Return the size of a file, as cheaply as possible. | * Return the size of a file, as cheaply as possible. | ||||
* In Unix, we can stat the file. | * In Unix, we can stat the file. | ||||
*/ | */ | ||||
public POSITION | public POSITION | ||||
filesize(f) | filesize(int f) | ||||
int f; | |||||
{ | { | ||||
#if HAVE_STAT | #if HAVE_STAT | ||||
struct stat statbuf; | struct stat statbuf; | ||||
if (fstat(f, &statbuf) >= 0) | if (fstat(f, &statbuf) >= 0) | ||||
return ((POSITION) statbuf.st_size); | return ((POSITION) statbuf.st_size); | ||||
#else | #else | ||||
#ifdef _OSK | #ifdef _OSK | ||||
long size; | long size; | ||||
if ((size = (long) _gs_size(f)) >= 0) | if ((size = (long) _gs_size(f)) >= 0) | ||||
return ((POSITION) size); | return ((POSITION) size); | ||||
#endif | #endif | ||||
#endif | #endif | ||||
return (seek_filesize(f)); | return (seek_filesize(f)); | ||||
} | } | ||||
/* | /* | ||||
* | * | ||||
*/ | */ | ||||
public char * | public char * | ||||
shell_coption() | shell_coption(void) | ||||
{ | { | ||||
return ("-c"); | return ("-c"); | ||||
} | } | ||||
/* | /* | ||||
* Return last component of a pathname. | * Return last component of a pathname. | ||||
*/ | */ | ||||
public char * | public char * | ||||
last_component(name) | last_component(char *name) | ||||
char *name; | |||||
{ | { | ||||
char *slash; | char *slash; | ||||
for (slash = name + strlen(name); slash > name; ) | for (slash = name + strlen(name); slash > name; ) | ||||
{ | { | ||||
--slash; | --slash; | ||||
if (*slash == *PATHNAME_SEP || *slash == '/') | if (*slash == *PATHNAME_SEP || *slash == '/') | ||||
return (slash + 1); | return (slash + 1); | ||||
} | } | ||||
return (name); | return (name); | ||||
} | } | ||||