version 1.30, 2024/04/14 08:34:00 |
version 1.31, 2024/04/14 18:11:54 |
|
|
|
|
extern int force_open; |
extern int force_open; |
extern int secure; |
extern int secure; |
extern int use_lessopen; |
|
extern int ctldisp; |
extern int ctldisp; |
extern int utf_mode; |
extern int utf_mode; |
extern IFILE curr_ifile; |
extern IFILE curr_ifile; |
|
|
free(filename); |
free(filename); |
free(ofilename); |
free(ofilename); |
return (gfilename); |
return (gfilename); |
} |
|
|
|
/* |
|
* Expand LESSOPEN or LESSCLOSE. Returns a newly allocated string |
|
* on success, NULL otherwise. |
|
*/ |
|
static char * |
|
expand_pct_s(const char *fmt, ...) |
|
{ |
|
int n; |
|
int len; |
|
char *r, *d; |
|
const char *f[3]; /* max expansions + 1 for NULL */ |
|
va_list ap; |
|
|
|
va_start(ap, fmt); |
|
for (n = 0; n < ((sizeof (f)/sizeof (f[0])) - 1); n++) { |
|
f[n] = (const char *)va_arg(ap, const char *); |
|
if (f[n] == NULL) { |
|
break; |
|
} |
|
} |
|
va_end(ap); |
|
f[n] = NULL; /* terminate list */ |
|
|
|
len = strlen(fmt) + 1; |
|
for (n = 0; f[n] != NULL; n++) { |
|
len += strlen(f[n]); /* technically could -2 for "%s" */ |
|
} |
|
r = ecalloc(len, sizeof (char)); |
|
|
|
for (n = 0, d = r; *fmt != 0; ) { |
|
if (*fmt != '%') { |
|
*d++ = *fmt++; |
|
continue; |
|
} |
|
fmt++; |
|
/* Permit embedded "%%" */ |
|
switch (*fmt) { |
|
case '%': |
|
*d++ = '%'; |
|
fmt++; |
|
break; |
|
case 's': |
|
if (f[n] == NULL) { |
|
va_end(ap); |
|
free(r); |
|
return (NULL); |
|
} |
|
(void) strlcpy(d, f[n++], r + len - d); |
|
fmt++; |
|
d += strlen(d); |
|
break; |
|
default: |
|
va_end(ap); |
|
free(r); |
|
return (NULL); |
|
} |
|
} |
|
*d = '\0'; |
|
return (r); |
|
} |
|
|
|
/* |
|
* See if we should open a "replacement file" |
|
* instead of the file we're about to open. |
|
*/ |
|
char * |
|
open_altfile(char *filename, int *pf, void **pfd) |
|
{ |
|
char *lessopen; |
|
char *cmd; |
|
FILE *fd; |
|
int returnfd = 0; |
|
|
|
if (!use_lessopen || secure) |
|
return (NULL); |
|
ch_ungetchar(-1); |
|
if ((lessopen = lgetenv("LESSOPEN")) == NULL) |
|
return (NULL); |
|
while (*lessopen == '|') { |
|
/* |
|
* If LESSOPEN starts with a |, it indicates |
|
* a "pipe preprocessor". |
|
*/ |
|
lessopen++; |
|
returnfd++; |
|
} |
|
if (*lessopen == '-') { |
|
/* |
|
* Lessopen preprocessor will accept "-" as a filename. |
|
*/ |
|
lessopen++; |
|
} else { |
|
if (strcmp(filename, "-") == 0) |
|
return (NULL); |
|
} |
|
|
|
if ((cmd = expand_pct_s(lessopen, filename, NULL)) == NULL) { |
|
error("Invalid LESSOPEN variable", NULL); |
|
return (NULL); |
|
} |
|
fd = shellcmd(cmd); |
|
free(cmd); |
|
if (fd == NULL) { |
|
/* |
|
* Cannot create the pipe. |
|
*/ |
|
return (NULL); |
|
} |
|
if (returnfd) { |
|
int f; |
|
char c; |
|
|
|
/* |
|
* Read one char to see if the pipe will produce any data. |
|
* If it does, push the char back on the pipe. |
|
*/ |
|
f = fileno(fd); |
|
if (read(f, &c, 1) != 1) { |
|
/* |
|
* Pipe is empty. |
|
* If more than 1 pipe char was specified, |
|
* the exit status tells whether the file itself |
|
* is empty, or if there is no alt file. |
|
* If only one pipe char, just assume no alt file. |
|
*/ |
|
int status = pclose(fd); |
|
if (returnfd > 1 && status == 0) { |
|
*pfd = NULL; |
|
*pf = -1; |
|
return (estrdup(FAKE_EMPTYFILE)); |
|
} |
|
return (NULL); |
|
} |
|
ch_ungetchar(c); |
|
*pfd = (void *) fd; |
|
*pf = f; |
|
return (estrdup("-")); |
|
} |
|
cmd = readfd(fd); |
|
pclose(fd); |
|
if (*cmd == '\0') |
|
/* |
|
* Pipe is empty. This means there is no alt file. |
|
*/ |
|
return (NULL); |
|
return (cmd); |
|
} |
|
|
|
/* |
|
* Close a replacement file. |
|
*/ |
|
void |
|
close_altfile(char *altfilename, char *filename, void *pipefd) |
|
{ |
|
char *lessclose; |
|
FILE *fd; |
|
char *cmd; |
|
|
|
if (secure) |
|
return; |
|
if (pipefd != NULL) { |
|
pclose((FILE *)pipefd); |
|
} |
|
if ((lessclose = lgetenv("LESSCLOSE")) == NULL) |
|
return; |
|
cmd = expand_pct_s(lessclose, filename, altfilename, NULL); |
|
if (cmd == NULL) { |
|
error("Invalid LESSCLOSE variable", NULL); |
|
return; |
|
} |
|
fd = shellcmd(cmd); |
|
free(cmd); |
|
if (fd != NULL) |
|
(void) pclose(fd); |
|
} |
} |
|
|
/* |
/* |