diff options
author | pommicket <pommicket@gmail.com> | 2022-12-07 20:22:42 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-12-07 20:22:42 -0500 |
commit | 62aea26c345c74ddee40712eb72eb290a1bfd902 (patch) | |
tree | b6451e917533c9fc75f58c053ec87418871ab048 /process-posix.c | |
parent | 65b72b38ec6c3a51b33e5d32313b51df993b32e4 (diff) |
more lsp stuff
Diffstat (limited to 'process-posix.c')
-rw-r--r-- | process-posix.c | 62 |
1 files changed, 50 insertions, 12 deletions
diff --git a/process-posix.c b/process-posix.c index 1463487..c8ea376 100644 --- a/process-posix.c +++ b/process-posix.c @@ -7,6 +7,8 @@ struct Process { pid_t pid; int stdout_pipe; + // only applicable if separate_stderr was specified. + int stderr_pipe; int stdin_pipe; char error[64]; }; @@ -15,10 +17,14 @@ int process_get_id(void) { return getpid(); } +static void set_nonblocking(int fd) { + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK); +} + bool process_run_ex(Process *proc, const char *command, const ProcessSettings *settings) { memset(proc, 0, sizeof *proc); - int stdin_pipe[2] = {0}, stdout_pipe[2] = {0}; + int stdin_pipe[2] = {0}, stdout_pipe[2] = {0}, stderr_pipe[2] = {0}; if (pipe(stdin_pipe) != 0) { strbuf_printf(proc->error, "%s", strerror(errno)); return false; @@ -29,6 +35,16 @@ bool process_run_ex(Process *proc, const char *command, const ProcessSettings *s close(stdin_pipe[1]); return false; } + if (settings->separate_stderr) { + if (pipe(stderr_pipe) != 0) { + strbuf_printf(proc->error, "%s", strerror(errno)); + close(stdin_pipe[0]); + close(stdin_pipe[1]); + close(stdout_pipe[0]); + close(stdout_pipe[1]); + return false; + } + } bool success = false; pid_t pid = fork(); @@ -40,13 +56,20 @@ bool process_run_ex(Process *proc, const char *command, const ProcessSettings *s setpgid(0, 0); // pipe stuff dup2(stdout_pipe[1], STDOUT_FILENO); - dup2(stdout_pipe[1], STDERR_FILENO); + if (stderr_pipe[1]) + dup2(stderr_pipe[1], STDERR_FILENO); + else + dup2(stdout_pipe[1], STDERR_FILENO); dup2(stdin_pipe[0], STDIN_FILENO); // don't need these file descriptors anymore - close(stdout_pipe[0]); - close(stdout_pipe[1]); close(stdin_pipe[0]); close(stdin_pipe[1]); + close(stdout_pipe[0]); + close(stdout_pipe[1]); + if (stderr_pipe[0]) { + close(stderr_pipe[0]); + close(stderr_pipe[1]); + } char *program = "/bin/sh"; char *argv[] = {program, "-c", (char *)command, NULL}; @@ -57,18 +80,24 @@ bool process_run_ex(Process *proc, const char *command, const ProcessSettings *s } else if (pid > 0) { // parent process - // we're reading from (the child's) stdout and writing to stdin, + // we're reading from (the child's) stdout/stderr and writing to stdin, // so we don't need the write end of the stdout pipe or the // read end of the stdin pipe. close(stdout_pipe[1]); + if (stderr_pipe[1]) + close(stderr_pipe[1]); close(stdin_pipe[0]); // set pipes to non-blocking if (!settings->stdout_blocking) - fcntl(stdout_pipe[0], F_SETFL, fcntl(stdout_pipe[0], F_GETFL) | O_NONBLOCK); + set_nonblocking(stdout_pipe[0]); + if (stderr_pipe[0] && !settings->stderr_blocking) + set_nonblocking(stderr_pipe[0]); if (!settings->stdin_blocking) - fcntl(stdin_pipe[1], F_SETFL, fcntl(stdin_pipe[1], F_GETFL) | O_NONBLOCK); + set_nonblocking(stdin_pipe[1]); proc->pid = pid; proc->stdout_pipe = stdout_pipe[0]; + if (stderr_pipe[0]) + proc->stderr_pipe = stderr_pipe[0]; proc->stdin_pipe = stdin_pipe[1]; success = true; } @@ -98,9 +127,9 @@ long long process_write(Process *proc, const char *data, size_t size) { } } -long long process_read(Process *proc, char *data, size_t size) { - assert(proc->stdout_pipe); - ssize_t bytes_read = read(proc->stdout_pipe, data, size); +static long long process_read_fd(Process *proc, int fd, char *data, size_t size) { + assert(fd); + ssize_t bytes_read = read(fd, data, size); if (bytes_read >= 0) { return (long long)bytes_read; } else if (errno == EAGAIN) { @@ -109,14 +138,23 @@ long long process_read(Process *proc, char *data, size_t size) { strbuf_printf(proc->error, "%s", strerror(errno)); return -2; } +} + +long long process_read(Process *proc, char *data, size_t size) { + return process_read_fd(proc, proc->stdout_pipe, data, size); +} +long long process_read_stderr(Process *proc, char *data, size_t size) { + return process_read_fd(proc, proc->stderr_pipe, data, size); } static void process_close_pipes(Process *proc) { - close(proc->stdout_pipe); close(proc->stdin_pipe); - proc->stdout_pipe = 0; + close(proc->stdout_pipe); + close(proc->stderr_pipe); proc->stdin_pipe = 0; + proc->stdout_pipe = 0; + proc->stderr_pipe = 0; } void process_kill(Process *proc) { |