summaryrefslogtreecommitdiff
path: root/process-posix.c
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-12-07 20:22:42 -0500
committerpommicket <pommicket@gmail.com>2022-12-07 20:22:42 -0500
commit62aea26c345c74ddee40712eb72eb290a1bfd902 (patch)
treeb6451e917533c9fc75f58c053ec87418871ab048 /process-posix.c
parent65b72b38ec6c3a51b33e5d32313b51df993b32e4 (diff)
more lsp stuff
Diffstat (limited to 'process-posix.c')
-rw-r--r--process-posix.c62
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) {