aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-02-17 15:10:16 +0800
committerRunxi Yu <me@runxiyu.org>2025-02-17 15:10:16 +0800
commitac1ca4327a2847d3dae8d6a248271b6c3bf30d03 (patch)
tree7fd404536c36d915cc29e52b179e5d86760e0d5c
parentmain.go: Restructure for uniformity (diff)
downloadforge-ac1ca4327a2847d3dae8d6a248271b6c3bf30d03.tar.gz
forge-ac1ca4327a2847d3dae8d6a248271b6c3bf30d03.tar.zst
forge-ac1ca4327a2847d3dae8d6a248271b6c3bf30d03.zip
git_hooks_client.c: Explain the code in more detail
-rw-r--r--git_hooks_client/git_hooks_client.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/git_hooks_client/git_hooks_client.c b/git_hooks_client/git_hooks_client.c
index 4d62c91..b1121a5 100644
--- a/git_hooks_client/git_hooks_client.c
+++ b/git_hooks_client/git_hooks_client.c
@@ -24,7 +24,6 @@ int main(void) {
* We connect to the UNIX domain socket after ensuring that standard
* input matches our expectations.
*/
-
struct stat stdin_stat;
if (fstat(STDIN_FILENO, &stdin_stat) == -1) {
perror("fstat on stdin");
@@ -40,8 +39,10 @@ int main(void) {
return EXIT_FAILURE;
}
- /* ... And we do the same for stderr */
-
+ /*
+ * ... And we do the same for stderr. Later we will splice from the
+ * socket to stderr, to let the daemon report back to the user.
+ */
struct stat stderr_stat;
if (fstat(STDERR_FILENO, &stderr_stat) == -1) {
perror("fstat on stderr");
@@ -57,7 +58,13 @@ int main(void) {
return EXIT_FAILURE;
}
-
+ /*
+ * Now that we know that stdin and stderr are pipes, we can connect to
+ * the UNIX domain socket. We don't do this earlier because we don't
+ * want to create unnecessary connections if the hook was called
+ * inappropriately (such as by a user with shell access in their
+ * terminal).
+ */
int sock;
struct sockaddr_un addr;
sock = socket(AF_UNIX, SOCK_STREAM, 0);
@@ -68,23 +75,34 @@ int main(void) {
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path) - 1);
-
if (connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr_un)) == -1) {
perror("internal socket connect");
close(sock);
return EXIT_FAILURE;
}
+ /*
+ * Now we can start splicing data from stdin to the UNIX domain socket.
+ * The format is irrelevant and depends on the hook being called. All we
+ * do is pass it to the socket for it to handle.
+ *
+ * TODO: The argument vector may need to be passed too. We may consider
+ * using an ancillary message.
+ */
ssize_t stdin_bytes_spliced;
while ((stdin_bytes_spliced = splice(STDIN_FILENO, NULL, sock, NULL, stdin_pipe_size, SPLICE_F_MORE)) > 0) {
}
-
if (stdin_bytes_spliced == -1) {
perror("splice stdin to internal socket");
close(sock);
return EXIT_FAILURE;
}
+ /*
+ * The first byte of the response from the UNIX domain socket is the
+ * status code. We read it and record it as our return value.
+ * (Realistically we just need a boolean to indicate success or failure.)
+ */
char status_buf[1];
ssize_t bytes_read = read(sock, status_buf, 1);
switch (bytes_read) {
@@ -104,10 +122,13 @@ int main(void) {
return EXIT_FAILURE;
}
+ /*
+ * Now we can splice data from the UNIX domain socket to stderr.
+ * This data is directly passed to the user (with "remote: " prepended).
+ */
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);