From: Ian Jackson Date: Sun, 17 Jul 2022 18:34:22 +0000 (+0100) Subject: prefork-interp: wip use stdio X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=3c04116f7323ef5ac4ee7103c9132482b54b82f0;p=chiark-utils.git prefork-interp: wip use stdio Signed-off-by: Ian Jackson --- diff --git a/cprogs/prefork-interp.c b/cprogs/prefork-interp.c index de63b42..fdc5da9 100644 --- a/cprogs/prefork-interp.c +++ b/cprogs/prefork-interp.c @@ -181,7 +181,9 @@ static void prepare_message(size_t *len, char **buf) { prepare_string(len, buf, s); } -static void send_fd(int via_fd, int payload_fd) { +static void send_fd(FILE *call_sock, int payload_fd) { + int via_fd = fileno(call_sock); + union { struct cmsghdr align; char buf[CMSG_SPACE(sizeof(payload_fd))]; @@ -222,12 +224,12 @@ static void send_fd(int via_fd, int payload_fd) { } } -static void send_request(int call_fd) { +static void send_request(FILE *call_sock) { // Sending these first makes it easier for the script to // use buffered IO for the message. - send_fd(call_fd, 0); - send_fd(call_fd, 1); - send_fd(call_fd, 2); + send_fd(call_sock, 0); + send_fd(call_sock, 1); + send_fd(call_sock, 2); size_t len = 4; prepare_message(&len, 0); @@ -238,25 +240,28 @@ static void send_request(int call_fd) { prepare_message(0, &p); assert(p == m + len); - p = m; - while (len) { - ssize_t r = write(call_fd, p, len); - if (r==-1) { - if (errno == EINTR) continue; - diee("write request"); - } - assert(r <= len); - assert(r > 0); - len -= r; - p += r; - } + ssize_t sr = fwrite(p, len, 1, call_sock); + if (sr != 1) diee("write request"); +} + +static FILE *call_sock_from_fd(int fd) { + int r; + + FILE *call_sock = fdopen(fd, "r+"); + if (!call_sock) diee("fdopen socket"); + + r = setvbuf(call_sock, 0, _IONBF, 0); + if (r) die("setvbuf socket"); + + return call_sock; } -// Returns: call(client-end) fd, or -1 to mean "is garbage" +// Returns: call(client-end), or 0 to mean "is garbage" // find_socket_path must have been called -static int connect_existing(void) { +static FILE *connect_existing(void) { int r; int fd = -1; + FILE *call_sock; fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd==-1) diee("socket() for client"); @@ -268,27 +273,26 @@ static int connect_existing(void) { diee("connect() %s", socket_path); } - for (;;) { - char ack; - size_t sr = read(fd, &ack, 1); - if (sr == -1) { - if (errno==ECONNRESET) goto x_garbage; - if (errno==EINTR) continue; - diee("read() ack byte"); - } - if (sr == 0) { goto x_garbage; } - if (ack != '\n') die("got ack byte 0x%02x, not '\n'", ack); - break; + call_sock = call_sock_from_fd(fd); + fd = -1; + + char ack; + size_t sr = fread(&ack, sizeof(ack), 1, call_sock); + if (sr != 1) { + if (feof(call_sock) || errno==ECONNRESET) goto x_garbage; + diee("read() ack byte"); } + if (ack != '\n') die("got ack byte 0x%02x, not '\n'", ack); // We're committed now, send the request (or bail out) - send_request(fd); + send_request(call_sock); - return fd; + return call_sock; x_garbage: + fclose(call_sock); if (fd >= 0) close(fd); - return -1; + return 0; } static __attribute__((noreturn)) @@ -310,15 +314,15 @@ void become_setup(int sfd, int fake_pair[2]) { diee("execute %s", executor_argv[0]); } -static int connect_or_spawn(void) { +static FILE *connect_or_spawn(void) { int r; - int fd = connect_existing(); - if (fd >= 0) return fd; + FILE *call_sock = connect_existing(); + if (call_sock) return call_sock; int lockfd = acquire_lock(); - fd = connect_existing(); - if (fd >= 0) { close(lockfd); return fd; } + call_sock = connect_existing(); + if (call_sock) { close(lockfd); return call_sock; } // We must start a fresh one, and we hold the lock @@ -357,7 +361,7 @@ static int connect_or_spawn(void) { if (status != 0) propagate_exit_status(status, "invocation"); close(lockfd); - return fake_pair[0]; + return call_sock_from_fd(fake_pair[0]); } static void make_executor_argv(const char *const *argv) { @@ -396,5 +400,5 @@ int main(int argc_unused, const char *const *argv) { assert(strlen(socket_path) <= sizeof(sun.sun_path)); strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path)); - int call_fd = connect_or_spawn(); + FILE *call_sock = connect_or_spawn(); }