diff options
Diffstat (limited to 'git_hooks_client')
-rw-r--r-- | git_hooks_client/git_hooks_client.c | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/git_hooks_client/git_hooks_client.c b/git_hooks_client/git_hooks_client.c index 98269ad..4d62c91 100644 --- a/git_hooks_client/git_hooks_client.c +++ b/git_hooks_client/git_hooks_client.c @@ -10,36 +10,54 @@ int main(void) { const char *socket_path = getenv("LINDENII_FORGE_HOOKS_SOCKET_PATH"); if (socket_path == NULL) { - dprintf(STDERR_FILENO, "environment variable LINDENII_FORGE_HOOKS_SOCKET_PATH undefined\n"); + dprintf(STDERR_FILENO, "environment variable LINDENII_FORGE_HOOKS_SOCKET_PATH undefined\n"); return EXIT_FAILURE; } - /* - * All hooks in git (see builtin/receive-pack.c) use a pipe by setting - * .in = -1 on the child_process struct, which enables us to use - * splice(2) to move the data to the UNIX domain socket. Just to be + /* + * All hooks in git (see builtin/receive-pack.c) use a pipe by setting + * .in = -1 on the child_process struct, which enables us to use + * splice(2) to move the data to the UNIX domain socket. Just to be * safe, we check that stdin is a pipe; and additionally we fetch the * buffer size of the pipe to use as the maximum size for the splice. * * We connect to the UNIX domain socket after ensuring that standard * input matches our expectations. - */ + */ - struct stat stdin_stat; + struct stat stdin_stat; if (fstat(STDIN_FILENO, &stdin_stat) == -1) { perror("fstat on stdin"); return EXIT_FAILURE; } if (!S_ISFIFO(stdin_stat.st_mode)) { - dprintf(STDERR_FILENO, "stdin must be a pipe\n"); - return EXIT_FAILURE; + dprintf(STDERR_FILENO, "stdin must be a pipe\n"); + return EXIT_FAILURE; } - int pipe_size = fcntl(STDIN_FILENO, F_GETPIPE_SZ); - if (pipe_size == -1) { + int stdin_pipe_size = fcntl(STDIN_FILENO, F_GETPIPE_SZ); + if (stdin_pipe_size == -1) { perror("fcntl on stdin"); return EXIT_FAILURE; } + /* ... And we do the same for stderr */ + + struct stat stderr_stat; + if (fstat(STDERR_FILENO, &stderr_stat) == -1) { + perror("fstat on stderr"); + return EXIT_FAILURE; + } + if (!S_ISFIFO(stderr_stat.st_mode)) { + dprintf(STDERR_FILENO, "stderr must be a pipe\n"); + return EXIT_FAILURE; + } + int stderr_pipe_size = fcntl(STDERR_FILENO, F_GETPIPE_SZ); + if (stderr_pipe_size == -1) { + perror("fcntl on stderr"); + return EXIT_FAILURE; + } + + int sock; struct sockaddr_un addr; sock = socket(AF_UNIX, SOCK_STREAM, 0); @@ -57,12 +75,11 @@ int main(void) { return EXIT_FAILURE; } - - ssize_t bytes_spliced; - while ((bytes_spliced = splice(STDIN_FILENO, NULL, sock, NULL, pipe_size, SPLICE_F_MORE)) > 0) { + ssize_t stdin_bytes_spliced; + while ((stdin_bytes_spliced = splice(STDIN_FILENO, NULL, sock, NULL, stdin_pipe_size, SPLICE_F_MORE)) > 0) { } - if (bytes_spliced == -1) { + if (stdin_bytes_spliced == -1) { perror("splice stdin to internal socket"); close(sock); return EXIT_FAILURE; @@ -87,6 +104,16 @@ int main(void) { return EXIT_FAILURE; } + ssize_t stderr_bytes_spliced; + while ((stderr_bytes_spliced = splice(sock, NULL, STDERR_FILENO, NULL, stderr_pipe_size, SPLICE_F_MORE)) > 0) { + } + + if (stdin_bytes_spliced == -1) { + perror("splice internal socket to stderr"); + close(sock); + return EXIT_FAILURE; + } + close(sock); return *status_buf; } |