Drop unreliable popen() call [e.g. fails if filename has "]

This commit is contained in:
Arun Prakash Jana 2021-06-12 22:31:27 +05:30
parent 69926a8eff
commit 0dd76e7aec
No known key found for this signature in database
GPG Key ID: A75979F35C080412
1 changed files with 33 additions and 52 deletions

View File

@ -4027,25 +4027,24 @@ static uchar_t get_free_ctx(void)
} }
/* /*
* Gets only a single line (that's what we need * Gets only a single line (that's what we need for now) or shows full command output in pager.
* for now) or shows full command output in pager. * Uses g_buf internally.
* * If page is valid, parses argument 'file' as multi-arg, returns NULL.
* If page is valid, parses argument 'file' as multi-arg, returns NULL
*/ */
static char *get_output(char *buf, const size_t bytes, char *file, char *arg1, char *arg2, bool page) static bool get_output(char *file, char *arg1, char *arg2, FILE *fout, bool multi, bool page)
{ {
pid_t pid; pid_t pid;
int pipefd[2]; int pipefd[2];
FILE *pf; FILE *fin;
int index = 0, flags; int index = 0, flags;
char *ret = NULL; bool ret = FALSE;
char *argv[EXEC_ARGS_MAX] = {0}; char *argv[EXEC_ARGS_MAX] = {0};
char *cmd = NULL; char *cmd = NULL;
if (page) { if (multi) {
cmd = parseargs(file, argv, &index); cmd = parseargs(file, argv, &index);
if (!cmd) if (!cmd)
return NULL; return FALSE;
} else } else
argv[index++] = file; argv[index++] = file;
@ -4085,12 +4084,18 @@ static char *get_output(char *buf, const size_t bytes, char *file, char *arg1, c
free(cmd); free(cmd);
if (!page) { if (!page) {
pf = fdopen(pipefd[0], "r"); fin = fdopen(pipefd[0], "r");
if (pf) { if (fin) {
ret = fgets(buf, bytes, pf); while (fgets(g_buf, CMD_LEN_MAX - 1, fin)) {
close(pipefd[0]); ret = TRUE;
if (!fout) /* Read only the first line of output to buffer */
break;
fprintf(fout, "%s", g_buf);
}
fclose(fin);
} }
close(pipefd[0]);
return ret; return ret;
} }
@ -4107,45 +4112,22 @@ static char *get_output(char *buf, const size_t bytes, char *file, char *arg1, c
waitpid(pid, NULL, 0); waitpid(pid, NULL, 0);
close(pipefd[0]); close(pipefd[0]);
return NULL; return FALSE;
}
static void pipetof(char *cmd, FILE *fout, uint_t lines)
{
FILE *fin = popen(cmd, "r");
if (fin) {
while (lines && fgets(g_buf, CMD_LEN_MAX - 1, fin)) {
fprintf(fout, "%s", g_buf);
--lines;
}
pclose(fin);
}
}
static void wrap_cmd(char *buf, const char *cmd, char *fpath)
{
size_t r = xstrsncpy(buf, cmd, CMD_LEN_MAX);
r += xstrsncpy(buf + r - 1, fpath, PATH_MAX);
buf[r - 2] = '\"';
buf[r - 1] = '\0';
} }
/* /*
* Follows the stat(1) output closely * Follows the stat(1) output closely
*/ */
static bool show_stats(char *fpath, const struct stat *sb) static bool show_stats(char *fpath)
{ {
static const char * const cmds[] = { static char * const cmds[] = {
#ifdef FILE_MIME_OPTS #ifdef FILE_MIME_OPTS
"file " FILE_MIME_OPTS " \"", ("file " FILE_MIME_OPTS),
#endif #endif
"file -b \"", "file -b",
"stat \"", "stat",
}; };
char *p, *begin = g_buf;
size_t r = ELEMENTS(cmds); size_t r = ELEMENTS(cmds);
int fd = create_tmp_file(); int fd = create_tmp_file();
if (fd == -1) if (fd == -1)
@ -4158,8 +4140,7 @@ static bool show_stats(char *fpath, const struct stat *sb)
} }
while (r) { while (r) {
wrap_cmd(g_buf, cmds[--r], fpath); get_output(cmds[--r], fpath, NULL, fp, TRUE, FALSE);
pipetof(g_buf, fp, (uint_t)-1);
fprintf(fp, "\n"); fprintf(fp, "\n");
} }
fclose(fp); fclose(fp);
@ -4218,7 +4199,7 @@ static void handle_archive(char *fpath, char op)
if (op == 'x') /* extract */ if (op == 'x') /* extract */
spawn(util, arg, fpath, NULL, F_NORMAL); spawn(util, arg, fpath, NULL, F_NORMAL);
else /* list */ else /* list */
get_output(NULL, 0, util, arg, fpath, TRUE); get_output(util, arg, fpath, NULL, TRUE, TRUE);
} }
static char *visit_parent(char *path, char *newpath, int *presel) static char *visit_parent(char *path, char *newpath, int *presel)
@ -4643,9 +4624,9 @@ static void show_help(const char *path)
if (g_state.fortune && getutil("fortune")) if (g_state.fortune && getutil("fortune"))
#ifndef __HAIKU__ #ifndef __HAIKU__
pipetof("fortune -s", fp, (uint_t)-1); get_output("fortune", "-s", NULL, fp, FALSE, FALSE);
#else #else
pipetof("fortune", fp, (uint_t)-1); get_output("fortune", NULL, NULL, fp, FALSE, FALSE);
#endif #endif
start = end = helpstr; start = end = helpstr;
@ -4711,7 +4692,7 @@ static bool run_cmd_as_plugin(const char *file, char *runfile, uchar_t flags)
runfile = NULL; runfile = NULL;
if (flags & F_PAGE) if (flags & F_PAGE)
get_output(NULL, 0, g_buf, runfile, NULL, TRUE); get_output(g_buf, runfile, NULL, NULL, TRUE, TRUE);
else else
spawn(g_buf, runfile, NULL, NULL, flags); spawn(g_buf, runfile, NULL, NULL, flags);
@ -6470,11 +6451,11 @@ nochange:
if (cfg.useeditor if (cfg.useeditor
#ifdef FILE_MIME_OPTS #ifdef FILE_MIME_OPTS
&& get_output(g_buf, CMD_LEN_MAX, "file", FILE_MIME_OPTS, newpath, FALSE) && get_output("file", FILE_MIME_OPTS, newpath, NULL, FALSE, FALSE)
&& is_prefix(g_buf, "text/", 5) && is_prefix(g_buf, "text/", 5)
#else #else
/* no MIME option; guess from description instead */ /* no MIME option; guess from description instead */
&& get_output(g_buf, CMD_LEN_MAX, "file", "-bL", newpath, FALSE) && get_output("file", "-bL", newpath, NULL, FALSE, FALSE)
&& strstr(g_buf, "text") && strstr(g_buf, "text")
#endif #endif
) { ) {
@ -6725,8 +6706,8 @@ nochange:
tmp = (listpath && xstrcmp(path, listpath) == 0) ? listroot : path; tmp = (listpath && xstrcmp(path, listpath) == 0) ? listroot : path;
mkpath(tmp, pdents[cur].name, newpath); mkpath(tmp, pdents[cur].name, newpath);
if (lstat(newpath, &sb) == -1 if ((sel == SEL_STATS && !show_stats(newpath))
|| (sel == SEL_STATS && !show_stats(newpath, &sb)) || (lstat(newpath, &sb) == -1)
|| (sel == SEL_CHMODX && !xchmod(newpath, sb.st_mode))) { || (sel == SEL_CHMODX && !xchmod(newpath, sb.st_mode))) {
printwarn(&presel); printwarn(&presel);
goto nochange; goto nochange;