mirror of
https://github.com/jarun/nnn.git
synced 2024-09-11 13:06:14 +03:00
parent
653cab9dff
commit
6b94911bc9
141
src/nnn.c
141
src/nnn.c
@ -837,7 +837,7 @@ static void move_cursor(int target, int ignore_scrolloff);
|
|||||||
static char *load_input(int fd, const char *path);
|
static char *load_input(int fd, const char *path);
|
||||||
static int set_sort_flags(int r);
|
static int set_sort_flags(int r);
|
||||||
static void statusbar(char *path);
|
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
|
#ifndef NOFIFO
|
||||||
static void notify_fifo(bool force);
|
static void notify_fifo(bool force);
|
||||||
#endif
|
#endif
|
||||||
@ -3188,7 +3188,7 @@ static void showfilterinfo(void)
|
|||||||
|
|
||||||
i = getorderstr(info);
|
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);
|
mvaddstr(xlines - 2, 2, g_buf);
|
||||||
else {
|
else {
|
||||||
snprintf(info + i, REGEX_MAX - i - 1, " %s [/], %4s [:]",
|
snprintf(info + i, REGEX_MAX - i - 1, " %s [/], %4s [:]",
|
||||||
@ -4425,103 +4425,92 @@ static void set_smart_ctx(int ctx, char *nextpath, char **path, char *file, char
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function does one of the following depending on the values of `fdout` and `page`:
|
* Gets only a single line (that's what we need for now) or shows full command output in pager.
|
||||||
* 1) fdout == -1 && !page: Write up to CMD_LEN_MAX bytes of command output into g_buf
|
* Uses g_buf internally.
|
||||||
* 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.
|
|
||||||
*/
|
*/
|
||||||
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;
|
pid_t pid;
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
int index = 0, flags;
|
int index = 0, flags;
|
||||||
bool ret = FALSE;
|
bool ret = FALSE;
|
||||||
bool have_file = fdout != -1;
|
bool tmpfile = ((fdout == -1) && page);
|
||||||
int prog_in_fd = -1;
|
char *argv[EXEC_ARGS_MAX] = {0};
|
||||||
int prog_out_fd = -1;
|
char *cmd = NULL;
|
||||||
|
int fd = -1;
|
||||||
ssize_t len;
|
ssize_t len;
|
||||||
|
|
||||||
/*
|
if (tmpfile) {
|
||||||
* 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
|
|
||||||
fdout = create_tmp_file();
|
fdout = create_tmp_file();
|
||||||
if (fdout == -1)
|
if (fdout == -1)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
prog_in_fd = STDIN_FILENO;
|
if (multi) {
|
||||||
prog_out_fd = fdout;
|
cmd = parseargs(file, argv, &index);
|
||||||
} else if (have_file) {
|
if (!cmd)
|
||||||
// Case 3
|
return FALSE;
|
||||||
prog_in_fd = STDIN_FILENO;
|
} else
|
||||||
prog_out_fd = fdout;
|
argv[index++] = file;
|
||||||
} else {
|
|
||||||
// Case 1
|
|
||||||
if (pipe(pipefd) == -1)
|
|
||||||
errexit();
|
|
||||||
|
|
||||||
for (index = 0; index < 2; ++index) {
|
argv[index] = arg1;
|
||||||
/* Get previous flags */
|
argv[++index] = arg2;
|
||||||
flags = fcntl(pipefd[index], F_GETFL, 0);
|
|
||||||
|
|
||||||
/* Set bit for non-blocking flag */
|
if (pipe(pipefd) == -1) {
|
||||||
flags |= O_NONBLOCK;
|
free(cmd);
|
||||||
|
errexit();
|
||||||
|
}
|
||||||
|
|
||||||
/* Change flags on fd */
|
for (index = 0; index < 2; ++index) {
|
||||||
fcntl(pipefd[index], F_SETFL, flags);
|
/* Get previous flags */
|
||||||
}
|
flags = fcntl(pipefd[index], F_GETFL, 0);
|
||||||
|
|
||||||
prog_in_fd = pipefd[0];
|
/* Set bit for non-blocking flag */
|
||||||
prog_out_fd = pipefd[1];
|
flags |= O_NONBLOCK;
|
||||||
|
|
||||||
|
/* Change flags on fd */
|
||||||
|
fcntl(pipefd[index], F_SETFL, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
pid = fork();
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
close(prog_in_fd);
|
/* In child */
|
||||||
dup2(prog_out_fd, STDOUT_FILENO);
|
close(pipefd[0]);
|
||||||
dup2(prog_out_fd, STDERR_FILENO);
|
dup2(pipefd[1], STDOUT_FILENO);
|
||||||
close(prog_out_fd);
|
dup2(pipefd[1], STDERR_FILENO);
|
||||||
|
close(pipefd[1]);
|
||||||
spawn(utils[UTIL_SH_EXEC], file, arg1, arg2, F_MULTI);
|
execvp(*argv, argv);
|
||||||
_exit(EXIT_SUCCESS);
|
_exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In parent */
|
/* In parent */
|
||||||
waitpid(pid, NULL, 0);
|
waitpid(pid, NULL, 0);
|
||||||
|
close(pipefd[1]);
|
||||||
|
free(cmd);
|
||||||
|
|
||||||
/* Do what each case should do */
|
while ((len = read(pipefd[0], g_buf, CMD_LEN_MAX - 1)) > 0) {
|
||||||
if (!have_file && page) {
|
|
||||||
// Case 2
|
|
||||||
close(fdout);
|
|
||||||
|
|
||||||
spawn(pager, g_tmpfpath, NULL, NULL, F_CLI | F_TTY);
|
|
||||||
|
|
||||||
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;
|
ret = TRUE;
|
||||||
|
if (fdout == -1) /* Read only the first line of output to buffer */
|
||||||
|
break;
|
||||||
|
if (write(fdout, g_buf, len) != len)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
close(pipefd[0]);
|
close(pipefd[0]);
|
||||||
close(pipefd[1]);
|
if (!page)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
if (tmpfile) {
|
||||||
|
close(fdout);
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
spawn(pager, g_tmpfpath, NULL, NULL, F_CLI | F_TTY);
|
||||||
|
|
||||||
|
if (tmpfile)
|
||||||
|
unlink(g_tmpfpath);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4547,7 +4536,7 @@ static bool show_stats(char *fpath)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
while (r)
|
while (r)
|
||||||
get_output(cmds[--r], fpath, NULL, fd, FALSE);
|
get_output(cmds[--r], fpath, NULL, fd, TRUE, FALSE);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -4694,7 +4683,7 @@ static bool handle_archive(char *fpath /* in-out param */, char op)
|
|||||||
if (op == 'x') /* extract */
|
if (op == 'x') /* extract */
|
||||||
spawn(util, arg, fpath, NULL, F_NORMAL | F_MULTI);
|
spawn(util, arg, fpath, NULL, F_NORMAL | F_MULTI);
|
||||||
else /* list */
|
else /* list */
|
||||||
get_output(util, arg, fpath, -1, TRUE);
|
get_output(util, arg, fpath, -1, TRUE, TRUE);
|
||||||
|
|
||||||
if (x_to) {
|
if (x_to) {
|
||||||
if (chdir(xdirname(fpath)) == -1) {
|
if (chdir(xdirname(fpath)) == -1) {
|
||||||
@ -5094,7 +5083,7 @@ static void show_help(const char *path)
|
|||||||
|
|
||||||
char *prog = xgetenv(env_cfg[NNN_HELP], NULL);
|
char *prog = xgetenv(env_cfg[NNN_HELP], NULL);
|
||||||
if (prog)
|
if (prog)
|
||||||
get_output(prog, NULL, NULL, fd, FALSE);
|
get_output(prog, NULL, NULL, fd, TRUE, FALSE);
|
||||||
|
|
||||||
start = end = helpstr;
|
start = end = helpstr;
|
||||||
while (*end) {
|
while (*end) {
|
||||||
@ -5190,7 +5179,7 @@ static void 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(g_buf, runfile, NULL, -1, TRUE);
|
get_output(g_buf, runfile, NULL, -1, TRUE, TRUE);
|
||||||
else // F_NOTRACE
|
else // F_NOTRACE
|
||||||
spawn(g_buf, runfile, NULL, NULL, flags);
|
spawn(g_buf, runfile, NULL, NULL, flags);
|
||||||
} else
|
} else
|
||||||
@ -6336,7 +6325,7 @@ static void statusbar(char *path)
|
|||||||
|
|
||||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
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);
|
mvaddstr(xlines - 2, 2, g_buf);
|
||||||
|
|
||||||
tolastln();
|
tolastln();
|
||||||
@ -7056,7 +7045,7 @@ nochange:
|
|||||||
|
|
||||||
if (cfg.useeditor
|
if (cfg.useeditor
|
||||||
#ifdef FILE_MIME_OPTS
|
#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)
|
&& is_prefix(g_buf, "text/", 5)
|
||||||
#else
|
#else
|
||||||
/* no MIME option; guess from description instead */
|
/* no MIME option; guess from description instead */
|
||||||
|
Loading…
Reference in New Issue
Block a user