static char *load_input(int fd, const char *path);
static int set_sort_flags(int r);
static void statusbar(char *path);
-static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool page);
+static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool multi, bool page);
#ifndef NOFIFO
static void notify_fifo(bool force);
#endif
i = getorderstr(info);
- if (cfg.fileinfo && ndents && get_output("file", "-b", pdents[cur].name, -1, FALSE))
+ if (cfg.fileinfo && ndents && get_output("file", "-b", pdents[cur].name, -1, FALSE, FALSE))
mvaddstr(xlines - 2, 2, g_buf);
else {
snprintf(info + i, REGEX_MAX - i - 1, " %s [/], %4s [:]",
}
/*
- * This function does one of the following depending on the values of `fdout` and `page`:
- * 1) fdout == -1 && !page: Write up to CMD_LEN_MAX bytes of command output into g_buf
- * 2) fdout == -1 && page: Create a temp file, write full command output into it and show in pager.
- * 3) fdout != -1 && !page: Write full command output into the provided file.
- * 4) fdout != -1 && page: Don't use! Returns FASLE.
- *
- * g_buf is modified only in case 1.
- * g_tmpfpath is modified only in case 2.
+ * Gets only a single line (that's what we need for now) or shows full command output in pager.
+ * Uses g_buf internally.
*/
-static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool page)
+static bool get_output(char *file, char *arg1, char *arg2, int fdout, bool multi, bool page)
{
pid_t pid;
int pipefd[2];
int index = 0, flags;
bool ret = FALSE;
- bool have_file = fdout != -1;
- int prog_in_fd = -1;
- int prog_out_fd = -1;
+ bool tmpfile = ((fdout == -1) && page);
+ char *argv[EXEC_ARGS_MAX] = {0};
+ char *cmd = NULL;
+ int fd = -1;
ssize_t len;
- /*
- * In this case the logic of the function dictates that we should write the output of the command
- * to `fd` and show it in the pager. But since we didn't open the file descriptor we have no right
- * to close it, the caller must do it. We don't even know the path to pass to the pager and
- * it's a real hassle to get it. In general this just invites problems so we are blocking it.
- */
- if (have_file && page)
- return FALSE;
-
- /* Setup file descriptors for child command */
- if (!have_file && page) {
- // Case 2
+ if (tmpfile) {
fdout = create_tmp_file();
if (fdout == -1)
return FALSE;
+ }
- prog_in_fd = STDIN_FILENO;
- prog_out_fd = fdout;
- } else if (have_file) {
- // Case 3
- prog_in_fd = STDIN_FILENO;
- prog_out_fd = fdout;
- } else {
- // Case 1
- if (pipe(pipefd) == -1)
- errexit();
+ if (multi) {
+ cmd = parseargs(file, argv, &index);
+ if (!cmd)
+ return FALSE;
+ } else
+ argv[index++] = file;
- for (index = 0; index < 2; ++index) {
- /* Get previous flags */
- flags = fcntl(pipefd[index], F_GETFL, 0);
+ argv[index] = arg1;
+ argv[++index] = arg2;
+
+ if (pipe(pipefd) == -1) {
+ free(cmd);
+ errexit();
+ }
- /* Set bit for non-blocking flag */
- flags |= O_NONBLOCK;
+ for (index = 0; index < 2; ++index) {
+ /* Get previous flags */
+ flags = fcntl(pipefd[index], F_GETFL, 0);
- /* Change flags on fd */
- fcntl(pipefd[index], F_SETFL, flags);
- }
+ /* Set bit for non-blocking flag */
+ flags |= O_NONBLOCK;
- prog_in_fd = pipefd[0];
- prog_out_fd = pipefd[1];
+ /* Change flags on fd */
+ fcntl(pipefd[index], F_SETFL, flags);
}
pid = fork();
if (pid == 0) {
- close(prog_in_fd);
- dup2(prog_out_fd, STDOUT_FILENO);
- dup2(prog_out_fd, STDERR_FILENO);
- close(prog_out_fd);
-
- spawn(utils[UTIL_SH_EXEC], file, arg1, arg2, F_MULTI);
+ /* In child */
+ close(pipefd[0]);
+ dup2(pipefd[1], STDOUT_FILENO);
+ dup2(pipefd[1], STDERR_FILENO);
+ close(pipefd[1]);
+ execvp(*argv, argv);
_exit(EXIT_SUCCESS);
}
/* In parent */
waitpid(pid, NULL, 0);
+ close(pipefd[1]);
+ free(cmd);
+
+ while ((len = read(pipefd[0], g_buf, CMD_LEN_MAX - 1)) > 0) {
+ ret = TRUE;
+ if (fdout == -1) /* Read only the first line of output to buffer */
+ break;
+ if (write(fdout, g_buf, len) != len)
+ break;
+ }
- /* Do what each case should do */
- if (!have_file && page) {
- // Case 2
+ close(pipefd[0]);
+ if (!page)
+ return ret;
+
+ if (tmpfile) {
close(fdout);
+ close(fd);
+ }
- spawn(pager, g_tmpfpath, NULL, NULL, F_CLI | F_TTY);
+ spawn(pager, g_tmpfpath, NULL, NULL, F_CLI | F_TTY);
+ if (tmpfile)
unlink(g_tmpfpath);
- return TRUE;
- } else if (have_file)
- // Case 3
- return TRUE;
-
- // Case 1
- len = read(pipefd[0], g_buf, CMD_LEN_MAX - 1);
- if (len > 0)
- ret = TRUE;
- close(pipefd[0]);
- close(pipefd[1]);
- return ret;
+ return TRUE;
}
/*
return FALSE;
while (r)
- get_output(cmds[--r], fpath, NULL, fd, FALSE);
+ get_output(cmds[--r], fpath, NULL, fd, TRUE, FALSE);
close(fd);
if (op == 'x') /* extract */
spawn(util, arg, fpath, NULL, F_NORMAL | F_MULTI);
else /* list */
- get_output(util, arg, fpath, -1, TRUE);
+ get_output(util, arg, fpath, -1, TRUE, TRUE);
if (x_to) {
if (chdir(xdirname(fpath)) == -1) {
char *prog = xgetenv(env_cfg[NNN_HELP], NULL);
if (prog)
- get_output(prog, NULL, NULL, fd, FALSE);
+ get_output(prog, NULL, NULL, fd, TRUE, FALSE);
start = end = helpstr;
while (*end) {
runfile = NULL;
if (flags & F_PAGE)
- get_output(g_buf, runfile, NULL, -1, TRUE);
+ get_output(g_buf, runfile, NULL, -1, TRUE, TRUE);
else // F_NOTRACE
spawn(g_buf, runfile, NULL, NULL, flags);
} else
attron(COLOR_PAIR(cfg.curctx + 1));
- if (cfg.fileinfo && get_output("file", "-b", pdents[cur].name, -1, FALSE))
+ if (cfg.fileinfo && get_output("file", "-b", pdents[cur].name, -1, FALSE, FALSE))
mvaddstr(xlines - 2, 2, g_buf);
tolastln();
if (cfg.useeditor
#ifdef FILE_MIME_OPTS
- && get_output("file", FILE_MIME_OPTS, newpath, -1, FALSE)
+ && get_output("file", FILE_MIME_OPTS, newpath, -1, FALSE, FALSE)
&& is_prefix(g_buf, "text/", 5)
#else
/* no MIME option; guess from description instead */