chiark / gitweb /
prefork-interp: wip
[chiark-utils.git] / cprogs / prefork-interp.c
index 29d39fe5e2ef8e7676713a04c7ae7c459821b621..e1a703c05a4da07d5f5e006b4db123bfa522aea8 100644 (file)
@@ -88,6 +88,7 @@ struct sockaddr_un sun;
 #define ACK_BYTE '\n'
 
 static struct sockaddr_unix socket_sun;
+static const char *const *executor_argv;
 
 static void propagate_exit_status(int status, const char *what) {
   int r;
@@ -160,8 +161,7 @@ static void prepare_string(size_t *len, char **buf, const char *string) {
   prepare_data(len, buf, s, sl+1);
 }
 
-static void prepare_message(size_t *len, char **buf,
-                           const char *const *argv) {
+static void prepare_message(size_t *len, char **buf) {
   const char *s;
 
   const char *const *p = environ;
@@ -172,7 +172,7 @@ static void prepare_message(size_t *len, char **buf,
 
   prepare_string(len, buf, "");
 
-  p = argv;
+  p = executor_argv;
   while ((s = *p++))
     prepare_string(len, buf, s);
 }
@@ -302,7 +302,9 @@ static void become_setup(int sfd, int fake_pair[2])
 
   putenv(asprintf("PREFORK_INTERP=%d,%d,%d,%d,%s",
                  sfd, call_fd, fd0_save, fd1_save, socket_path));
-  execv(
+
+  execvp(executor_argv[0], executor_argv);
+  diee("execute %s", executor_argv[0]);
 }
 
 static int connect_or_spawn(void) {
@@ -353,8 +355,34 @@ static int connect_or_spawn(void) {
   return fake_pair[0];
 }
 
-int main(int argc, const char *const *argv) {
-  script = process_opts(argc, argv);
+static void make_executor_argv(const char *const *argv) {
+  #define EACH_NEW_ARGV(EACH) {                        \
+    arg = interp; { EACH }                     \
+    if ((arg = script)) { EACH }               \
+    const char *const *walk = argv;            \
+    while ((arg = *walk++)) { EACH }           \
+  }
+
+  size_t count = 1;
+  MAKE_NEW_ARGV( (void)arg; count++; );
+
+  executor_argv = calloc(count, sizeof(char*));
+  if (!executor_argv) diee("allocate for arguments");
+
+  char **out = executor_argv;
+  MAKE_NEW_ARGV( *out++ = arg; );
+  *out++ = 0;
+}  
+
+int main(int argc_unused, const char *const *argv) {
+  process_opts(&argv);
+
+  // Now we have
+  //  - possibly interp
+  //  - possibly script
+  //  - remaining args
+  // which ought to be passed on to the actual executor.
+  make_executor_argv(argv);
 
   find_socket_path();
   FILLZERO(sun);