fe
terminal file explorer and picker
git clone https://9o.is/git/fe.git
commit 8dd5db74d17d9a44c73aa38608ac157ae638cce6 parent f2c2e9f0d792fcefd31b2abcbe6441f945e36780 Author: Jul <jul@9o.is> Date: Sun, 18 Jan 2026 04:04:09 -0500 use x_spawn function Diffstat:
| M | spawn.c | | | 93 | +++++++++++++++++++++---------------------------------------------------------- |
| M | spawn.h | | | 8 | +++++--- |
| M | tty_interface.c | | | 7 | ++++--- |
3 files changed, 34 insertions(+), 74 deletions(-)
diff --git a/spawn.c b/spawn.c @@ -7,87 +7,44 @@ #include <unistd.h> #include <stdio.h> #include <string.h> +#include "spawn.h" -void execute_program(const char *program, char *path) { - char *prog = strdup(program); - char *const argv[] = {prog, path, NULL}; +int x_spawn(const char *cmd, char *const argv[], int flags, char *out_buf, size_t out_sz) { + int pipefd[2]; - if (execvp(prog, argv) == -1) { - perror("execvp failed"); + if (flags & EXEC_CAPTURE) { + if (pipe(pipefd) == -1) return -1; } - free(prog); -} - -int execute_command(const char *command) { - pid_t pid; + pid_t pid = (flags & EXEC_REPLACE) ? 0 : fork(); - pid = fork(); - if (pid == -1) { - perror("fork"); - return -1; - } + if (pid == -1) return -1; if (pid == 0) { - char *command_copy = strdup(command); - char *const argv[] = {"sh", "-c", command_copy, NULL}; - - execvp(argv[0], argv); - - perror("execvp"); - free(command_copy); - exit(EXIT_FAILURE); - } else { - wait(NULL); - } - - return 0; -} - -int execute_command_output(const char *command, char *output_buffer, size_t buffer_size) { - int pipefd[2]; - pid_t pid; + if (flags & EXEC_CAPTURE) { + dup2(pipefd[1], STDOUT_FILENO); + close(pipefd[0]); + close(pipefd[1]); + } - if (pipe(pipefd) == -1) { - perror("pipe"); - return -1; - } + if (flags & EXEC_SHELL) { + execlp("sh", "sh", "-c", cmd, (char *)NULL); + } else { + execvp(cmd, argv); + } - pid = fork(); - if (pid == -1) { - perror("fork"); - return -1; + perror("exec failed"); + if (flags & EXEC_REPLACE) return -1; + _exit(EXIT_FAILURE); } - if (pid == 0) { - close(pipefd[0]); - - dup2(pipefd[1], STDOUT_FILENO); - close(pipefd[1]); - - char *command_copy = strdup(command); - char *const argv[] = {"sh", "-c", command_copy, NULL}; - - execvp(argv[0], argv); - - free(command_copy); - perror("execvp"); - exit(EXIT_FAILURE); - } else { + if (flags & EXEC_CAPTURE) { close(pipefd[1]); - - ssize_t bytes_read = read(pipefd[0], output_buffer, buffer_size - 1); - if (bytes_read >= 0) { - output_buffer[bytes_read] = '\0'; - } else { - perror("read"); - close(pipefd[0]); - return -1; - } - - wait(NULL); + read(pipefd[0], out_buf, out_sz - 1); close(pipefd[0]); } - return 0; + int status; + waitpid(pid, &status, 0); + return WEXITSTATUS(status); } diff --git a/spawn.h b/spawn.h @@ -1,3 +1,5 @@ -void execute_program(const char *program, char *path); -int execute_command_output(const char *command, char *output_buffer, size_t buffer_size); -int execute_command(const char *command); +#define EXEC_REPLACE 1 +#define EXEC_SHELL 2 +#define EXEC_CAPTURE 4 + +int x_spawn(const char *cmd, char *const argv[], int flags, char *out_buf, size_t out_sz); diff --git a/tty_interface.c b/tty_interface.c @@ -100,7 +100,8 @@ static void action_select(tty_interface_t *state, char *argv) { char fullpath[2*PATH_MAX]; snprintf(fullpath, sizeof(fullpath), "%s/%s", state->entries->path, selection->name); - execute_program(state->options->run, fullpath); + char *const argv[] = {(char *)state->options->run, fullpath, NULL}; + x_spawn(state->options->run, argv, EXEC_REPLACE, NULL, 0); state->exit = EXIT_FAILURE; } } @@ -197,7 +198,7 @@ static void action_run(tty_interface_t *state, char *argv) { snprintf(input, input_len, argv, state->entries->path, entry->name); clear(state); - execute_command(input); + x_spawn(input, NULL, EXEC_SHELL, NULL, 0); free(input); tty_hide_cursor(state->tty); @@ -218,7 +219,7 @@ static void action_setpath(tty_interface_t *state, char *argv) { char output[PATH_MAX]; clear(state); - if (0 == execute_command_output(input, output, sizeof(output))) + if (0 == x_spawn(input, NULL, EXEC_SHELL | EXEC_CAPTURE, output, sizeof(output))) entries_setpath(state->entries, output); free(input);