chiark / gitweb /
prefork-interp: wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sat, 9 Jul 2022 11:38:25 +0000 (12:38 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 21 Aug 2022 20:21:10 +0000 (21:21 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
prefork-interp.c [new file with mode: 0644]

diff --git a/prefork-interp.c b/prefork-interp.c
new file mode 100644 (file)
index 0000000..0921835
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * "Interpreter" that you can put in #! like this
+ *   #!/usr/bin/prefork-interp [<options>] <interpreter>
+ */
+
+/*
+ * 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) {
+      
+}