From: Ian Jackson Date: Sat, 9 Jul 2022 11:38:25 +0000 (+0100) Subject: prefork-interp: wip X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=110c4de2e71ea472b3f06e690845220585b7a28e;p=chiark-utils.git prefork-interp: wip Signed-off-by: Ian Jackson --- diff --git a/prefork-interp.c b/prefork-interp.c new file mode 100644 index 0000000..0921835 --- /dev/null +++ b/prefork-interp.c @@ -0,0 +1,100 @@ +/* + * "Interpreter" that you can put in #! like this + * #!/usr/bin/prefork-interp [] + */ + +/* + * Process structure: + * client (C wrapper) connects to server + * if fails or garbage + * === acquire lock === + * makes new listening socket + * makes first-instance socketpair + * forks setup (script, sock fds indicated in env) + * fd0, fd1, fd2: from-outer-caller + * other fd: call(client-end)(fake) + * reaps setup (and reports error) + * (implicitly releases lock) + * + * setup (pre-exec) fd0: null, + * fd[12: fd2-from-outer-caller + * env fds: orig-fd[01], listener, + * env fds: call(server-end)(fake) + * close fd: lockfile + * + * setup (script) runs initialisation parts of the script + * at prefork establishment point: + * forks to logger(1) + * forks for server, now becomes like monitor below + * exits + * + * server (script) fd0: null, fd[12]: syslog + * other fds: orig-fd[01], listener, + * other fds: call(server-end)(fake) + * + * right away, forks one fake-accepted monitor: + * f-a monitor [fd0: null, fd[12]: syslgo] + * other fds: call(server-end)(fake) + * runs as monitor, below + * + * [server (script)] fd0: null, fd[12]: syslog + * other fds: listener + * closes fds: orig-fd[01], call(server-end)fake) + * runs in loop accepting and forking, + * reaping and limiting children + * reports failures of monitors to syslog + * + * [client (C wrapper)] if client connect succeeds: + * now fd: call(client-end) + * sends message with: cmdline, env + * sends fds + * + * [server (script)] accepts, forks monitor + * + * monitor [fd0: null, fd[12]: syslgo] + * other fds: call(server-end) + * receives args, env, fds + * forks executor + * + * executor sorts out fds: + * fd0, fd1, fd2: from-outer-caller + * close fds: call(server-end) + * implicitly closed fds: syslog + * + * sets cmdline, env + * runs main part of script + * exits normally + * + * [monitor] [fd0: null, fd[12]: syslgo] + * [other fds: call(server-end)] + * reaps executor + * reports status via socket + * + * [client (C wrapper)] [fd0, fd1, fd2: from-outer-caller] + * [other fd: call(client-end)] + * receives status, exits appropriately + * (if was bad signal, reports to stderr, exits 127) + */ + +struct sockaddr_un sun; + +int main(int argc, const char *const *argv) { + script = process_opts(argc, argv); + + find_socket_path(); + FILLZERO(sun); + sun.sun_family = AF_UNIX; + assert(strlen(socket_path) <= sizeof(sun.sun_path)); + strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path)); + + bool isgarbage = check_garbage(); + + int client_fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (client_fd==-1) diee("socket() for client"); + + salen_t salen = sizeof(sun); + r = connect(client, (const struct sockaddr*)sun, salen); + if (r==-1) { + if (errno==ECONNREFUSED || errno==ENOENT) { + +}