chiark / gitweb /
62e5ff05b72b2e5f78c91f98a8137e797c12ce75
[chiark-utils.git] / cprogs / prefork-interp.c
1 /*
2  * "Interpreter" that you can put in #! like this
3  *   #!/usr/bin/prefork-interp [<options>] <interpreter>
4  *
5  * Usages:
6  *   prefork-interp  [<option> ..] <interpreter>  [<script> [<args> ...]]
7  *   prefork-interp  [<option>,..],<interpreter>   <script> [<args> ...]
8  *   prefork-interp '[<option> ..] <interpreter>'  <script> [<args> ...]
9  *
10  * Options must specify argument laundering mode.
11  * Currently the only mode supported is:
12  *   -U    unlaundered: setup and executor both get all arguments and env vars
13  *         ident covers only env vars specified  with -E
14  *         ident covers only arguments interpreter and (if present) script
15  */
16
17 /*
18 ***************************************************************************
19 \f
20   State during service execution, process parentage and key fds
21
22       CALLER
23         ||
24         ||
25         ||                               listen     watch-err/in
26         ||       call                 (accept) \     ,------2
27         || ,-----------------------------.     SERVER -----0 WATCHER(C)
28       CLIENT 2--=fdpassed>=---------.     \      || &&          |      &&
29        (C)  1--=fdpassed>=---------. \     \     ||           inotify
30            0--=fdpassed>=---------. \ \     \    ||           sockpath
31                                    \ \ \     \   ||
32                                    | | |\     |  ||
33                                    | | | \    |  ||
34                                    | \ |  \   \  ||
35                                     \ \ \  \   MONITOR &
36                                      \ \ \  `12  ||  |
37                                       \ \ \      ||  |
38                                        \ \ \     ||  |execterm
39                                         \ \ \    ||  |
40                                          \ \ \   ||  |
41                                           \ \ 2  ||  |
42                                            \ 1 EXECUTOR
43                                             0
44     ----      pipes, sockets
45     012       descriptors
46     -==-      fds shared
47     ||        process parentage
48     &&        session leader (daemon)
49     &         process group leader
50
51 ***************************************************************************
52 \f
53  Control flow and causality
54
55       CALLER
56          |
57          |fork/exec
58          |
59       CLIENT
60          |
61       attempt to connect, and read greeting
62          |failure?                \success?
63          |                         \
64       tidy up stale /run entries    *1 (continue from send_fds, below)
65       acquire lock
66          |
67       retry attempt to connect, and read greeting
68          |failure?                \success?
69          |                         \
70       create listening socket     release lock
71          |                           \
72       fork/daemonise                  *1
73          |    `------------------.
74          |                      WATCHER(C) &&
75          |
76        make "fake" initial call socketpair                               (C)
77          |                                                    prefork-interp
78        fork/exec   #########################################################
79          |      `-------------.                                  application
80          |         #        SCRIPT (setup)
81          |         #          |
82          |         #       script initialisation
83          |         #          |                                  application
84          |         #  ########|#############################################
85          |         #          |                               prefork-interp
86          |         #       identify fds from envirnment               (Perl)
87          |         #       open syslog
88          |         #          |
89          |         #       dzemonize
90          |   ,.....<....../   |
91       waitpid      #        fork for initial service
92          |         #          |child?       |parent?
93          |         #          |             |
94          |         #          |         SCRIPT [server] &&
95          |         #          |             |
96          |         #          |         ** accept / event loop **
97          |         #          |        accepted?    \      \ \
98          |         #          |            /         \ watch\ \idle
99          |         #          |        fork child     \stderr\ \timeout?
100          |         #          | _________/            |       | |
101          |         #          |/                      |read?  | |
102          |         #     SCRIPT [monitor]             |   eof?| |
103          |         #       setpgrpt &                 |       | |
104          |         #          |                     log msg   | |
105        read   ,....<.....send greeting                |       | |
106       greeting     #          |                    ___________________
107          |         #          |
108       release      #          |
109       lock    *1   #          |
110          |   /     #          |
111       send fds.....>....      |
112          |         #    \receive fds
113          |         #             |
114          |         #         fork for executor                        (Perl)
115          |         #          |parent?        \child?         prefork-interp
116          |         #          |          ######\############################
117          |         #          |          #  SCRIPT (executor)    application
118          |         #          |          #  execute service
119          |         #    wait for read    #       |
120          |         #      (select)       #   terminates
121          |         #        |   |        #       |
122          |         #            |        #    kernel closes execterm
123          |         #            | ,......<....../|
124          |         #      execterm?      #       |
125          |         #            |        #     zombie
126          |         #        |   | ,......<...../
127          |         #       waitpid       #  _______________
128          |         #          |          #
129          |    ,....<....,..send status   #
130     read status    #  ________________   #
131    _____________   #
132
133
134   ********** Or, if client is killed **********
135
136          |         #          |          #  execute service
137      terminates    #    wait for read    #       |
138          |         #      (select)       #       |
139       kernel       #        |   |        #       |
140      closes call   #        |            #       |
141                 \..>......_ |            #       |
142    _____________   #       \|call?       #       |
143                    #        |            #       |
144                    #  kill whole pgrp... #    killled
145                    #        |            #     zombie
146                    #        |   | ,......<....../
147                    #       waitpid       #  _______________
148                    #          |          #
149                    #   send exit status  #
150                    #  _____SIGPIPE______ #
151
152     | - \ /    process control flow
153     ... < >    causes mediated by fds or other IPC etc.
154     &&         session leader (daemon)
155     &          process group leader
156     #          language/implementation boundary
157     *1         line continued elsewhere
158     event?     condition
159     ______     process termination (after reaping, if shown)
160
161 ***************************************************************************
162 \f
163   Sequence of events and fd pluming.
164   NB INCOMPLETE - does not cover execterm, cleanup
165  
166    client (C wrapper)        connects to server
167                                (including reading ack byte)
168                              if fails or garbage
169                              === acquires lock ===
170                              makes new listening socket
171                              makes watcher pipes
172                              forks watcher and awaits
173                              makes first-instance socketpair
174                              forks setup (script, sock fds indicated in env)
175                              fd0, fd1, fd2: from-outer
176                              other fd: call(client-end)(fake)
177                              reaps setup (and reports error)
178                              (implicitly releases lock)
179  
180       watcher                fd[012]: watcher pipes
181                              starts watch on socket path
182                              sets stderr to line buffered
183                              sets stdin to nonblocking
184                              daemonises (one fork, becomes session leader)
185                              when socket stat changes, quit
186  
187       setup (pre-exec)       fd0: null,
188                              fd[12]: fd2-from-outer
189                              env fds: listener, call(server-end)(fake),
190                                        watcher read, watcher write
191                              close fd: lockfile
192                              possibly clean env, argv
193  
194       setup (script)         runs initialisation parts of the script
195                              at prefork establishment point:
196       setup (pm) [1]         opens syslog
197                              forks for server
198                  [2]         exits
199  
200          server (pm) [1]     [fd0: null],
201                              [fd[12]: fd2-from-outer]
202                              setsid
203                              right away, forks init monitor
204                      [2]     closes outer caller fds and call(fake)
205          [server (pm)]       fd[012]: null
206                              other fds: listener, syslog
207                              runs in loop accepting and forking,
208                              reaping and limiting children (incl init monitor)
209                              reports failures of monitors to syslog
210  
211    [client (C wrapper)]      if client connect succeeds:
212                              now fd: call(client-end)
213                                 sends message with: cmdline, env
214                                 sends fds
215  
216          [server (script)]   accepts, forks subseq monitor
217  
218            monitor [1]       [fd0: null]
219             (init            [fd[12]: init: fd2-from-outer; subseq: null]
220               or             errors: init: fd2; subseq: syslog
221              subseq)         other fds: syslog, call(server-end)
222                              sends ack byte
223                              receives args, env, fds
224                              forks executor
225  
226              executor        sorts out fds:
227                              fd0, fd1, fd2: from-outer
228                              close fds: call(server-end)
229                              retained fds: syslog
230  
231                              sets cmdline, env
232                              runs main part of script
233                              exits normally
234  
235            [monitor]         [fd[012]: null]
236                              [fd[12]: init: fd2-from-outer; subseq: null]
237                              [errors: init: fd2; subseq: syslog]
238                              reaps executor
239                              reports status via socket
240  
241      [client (C wrapper)]    [fd0, fd1, fd2: from-outer]
242                              [other fd: call(client-end)]
243                              receives status, exits appropriately
244                              (if was bad signal, reports to stderr, exits 127)
245
246 ***************************************************************************
247 \f
248 */
249
250 #include <arpa/inet.h>
251
252 #include <uv.h>
253
254 #include "prefork.h"
255
256 const char our_name[] = "prefork-interp";
257
258 static struct sockaddr_un sockaddr_sun;
259 static FILE *call_sock;
260
261 #define ACK_BYTE '\n'
262
263 static const char *const *executor_argv;
264
265 static const char header_magic[4] = "PFI\n";
266
267 void fusagemessage(FILE *f) {
268   fprintf(f, "usage: #!/usr/bin/prefork-interp [<options>]\n");
269 }
270
271 #define MODE_NORMAL 0
272 #define MODE_KILL   'k'
273 #define MODE_FRESH  'f'
274
275 #define MEDIATION_UNSPECIFIED 0
276 #define MEDIATION_UNLAUNDERED 'U'
277
278 static int mediation = MEDIATION_UNSPECIFIED;
279 static int mode = MODE_NORMAL;
280 static int max_sockets = 100; // maximum entries in the run dir is 2x this
281
282 static struct stat initial_stab;
283
284 const struct cmdinfo cmdinfos[]= {
285   PREFORK_CMDINFOS
286   { 0,         'U',   0, .iassignto= &mediation, .arg= MEDIATION_UNLAUNDERED },
287   { "kill",     0,    0, .iassignto= &mode,      .arg= MODE_KILL   },
288   { 0,         'f',   0, .iassignto= &mode,      .arg= MODE_FRESH  },
289   { 0 }
290 };
291
292 void ident_addinit(void) {
293   char ident_magic[1] = { 0 };
294   sha256_update(&identsc, sizeof(ident_magic), ident_magic);
295 }
296
297 static void propagate_exit_status(int status, const char *what) {
298   int r;
299
300   if (WIFEXITED(status)) {
301     _exit(status);
302   }
303
304   if (WIFSIGNALED(status)) {
305     int sig = WTERMSIG(status);
306     const char *signame = strsignal(sig);
307     if (signame == 0) signame = "unknown signal";
308
309     if (! WCOREDUMP(status) &&
310         (sig == SIGINT ||
311          sig == SIGHUP ||
312          sig == SIGPIPE ||
313          sig == SIGKILL)) {
314       struct sigaction sa;
315       FILLZERO(sa);
316       sa.sa_handler = SIG_DFL;
317       r = sigaction(sig, &sa, 0);
318       if (r) diee("failed to reset signal handler while propagating %s",
319                   signame);
320
321       sigset_t sset;
322       sigemptyset(&sset);
323       sigaddset(&sset, sig);
324       r = sigprocmask(SIG_UNBLOCK, &sset, 0);
325       if (r) diee("failed to reset signal block while propagating %s",
326                   signame);
327
328       raise(sig);
329       die("unexpectedly kept running after raising (to propagate) %s",
330           signame);
331     }
332
333     die("%s failed due to signal %d %s%s", what, sig, signame,
334         WCOREDUMP(status) ? " (core dumped)" : "");
335   }
336
337   die("%s failed with weird wait status %d 0x%x", what, status, status);
338 }
339
340 typedef struct {
341   char *name_hash;
342   time_t atime;
343 } PrecleanEntry;
344
345 static int preclean_entry_compar_name(const void *av, const void *bv) {
346   const PrecleanEntry *a = av;
347   const PrecleanEntry *b = bv;
348   return strcmp(a->name_hash, b->name_hash);
349 }
350
351 static int preclean_entry_compar_atime(const void *av, const void *bv) {
352   const PrecleanEntry *ae = av;  time_t a = ae->atime;
353   const PrecleanEntry *be = bv;  time_t b = be->atime;
354   return (a > b ? +1 :
355           a < b ? -1 : 0);
356 }
357
358 static time_t preclean_stat_atime(const char *s_path) {
359   struct stat stab;
360   int r= lstat(s_path, &stab);
361   if (r) {
362     if (errno!=ENOENT) diee("pre-cleanup: stat socket (%s)", s_path);
363     return 0;
364   }
365   return stab.st_atime;
366 }
367
368 static void preclean(void) {
369   DIR *dir = opendir(run_base);
370   if (!dir) {
371     if (errno == ENOENT) return;
372     diee("pre-cleanup: open run dir (%s)", run_base);
373   }
374
375   PrecleanEntry *entries=0;
376   size_t avail_entries=0;
377   size_t used_entries=0;
378
379   struct dirent *de;
380   while ((errno = 0, de = readdir(dir))) {
381     char c0 = de->d_name[0];
382     if (!(c0 == 'l' || c0 == 's')) continue;
383     char *name_hash = m_asprintf("%s", de->d_name+1);
384     char *s_path = m_asprintf("%s/s%s", run_base, name_hash);
385     time_t atime = preclean_stat_atime(s_path);
386
387     if (avail_entries == used_entries) {
388       assert(avail_entries < INT_MAX / 4 / sizeof(PrecleanEntry));
389       avail_entries <<= 1;
390       avail_entries += 10;
391       entries = realloc(entries, avail_entries * sizeof(PrecleanEntry));
392     }
393     entries[used_entries].name_hash = name_hash;
394     entries[used_entries].atime = atime;
395     used_entries++;
396   }
397   if (errno) diee("pre-cleanup: read run dir (%s)", run_base);
398
399   // First we dedupe (after sorting by path)
400   qsort(entries, used_entries, sizeof(PrecleanEntry),
401         preclean_entry_compar_name);
402   PrecleanEntry *p, *q;
403   for (p=entries, q=entries; p < entries + used_entries; p++) {
404     if (q > entries && !strcmp(p->name_hash, (q-1)->name_hash))
405       continue;
406     *q++ = *p;
407   }
408   used_entries = q - entries;
409
410   // Now maybe delete some things
411   //
412   // Actually this has an off-by-one error since we are about
413   // to create a socket, so the actual number of sockets is one more.
414   // But, *actually*, since there might be multiple of us running at once,
415   // we might have even more than that.  This doesn't really matter.
416   if (used_entries > max_sockets) {
417     qsort(entries, used_entries, sizeof(PrecleanEntry),
418           preclean_entry_compar_atime);
419     for (p=entries; p < entries + max_sockets; p++) {
420       char *l_path = m_asprintf("%s/l%s", run_base, p->name_hash);
421       char *s_path = m_asprintf("%s/s%s", run_base, p->name_hash);
422       int lock_fd = flock_file(l_path);
423       // Recheck atime - we might have raced!
424       time_t atime = preclean_stat_atime(s_path);
425       if (atime != p->atime) {
426         // Raced.  This will leave use deleting too few things.  Whatever.
427       } else {
428         int r= unlink(s_path);
429         if (r && errno!=ENOENT) diee("preclean: delete stale (%s)", s_path);
430         r= unlink(l_path);
431         if (r) diee("preclean: delete stale lock (%s)", s_path);
432         // NB we don't hold the lock any more now.
433       }
434       close(lock_fd);
435       free(l_path);
436       free(s_path);
437     }
438   }
439
440   for (p=entries; p < entries + used_entries; p++)
441     free(p->name_hash);
442   free(entries);
443 }
444
445 static __attribute((noreturn)) void die_data_overflow(void) {
446   die("cannot handle data with length >2^32");
447 }
448
449 static void prepare_data(size_t *len, char **buf,
450                          const void *data, size_t dl) {
451   if (len) {
452     if (dl >= SIZE_MAX - *len)
453       die_data_overflow();
454     *len += dl;
455   }
456   if (buf) {
457     memcpy(*buf, data, dl);
458     *buf += dl;
459   }
460 }
461
462 static void prepare_length(size_t *len, char **buf, size_t dl_sz) {
463   if (dl_sz > UINT32_MAX) die_data_overflow();
464   uint32_t dl = htonl(dl_sz);
465   prepare_data(len, buf, &dl, sizeof(dl));
466 }
467
468 static void prepare_string(size_t *len, char **buf, const char *s) {
469   size_t sl = strlen(s);
470   prepare_data(len, buf, s, sl+1);
471 }
472
473 static void prepare_message(size_t *len, char **buf) {
474   const char *s;
475
476   const char *const *p = (void*)environ;
477   while ((s = *p++)) {
478     if (strchr(s, '='))
479       prepare_string(len, buf, s);
480   }
481
482   prepare_string(len, buf, "");
483
484   p = executor_argv;
485   while ((s = *p++))
486     prepare_string(len, buf, s);
487 }
488
489 static void send_fd(int payload_fd) {
490   int via_fd = fileno(call_sock);
491
492   union {
493     struct cmsghdr align;
494     char buf[CMSG_SPACE(sizeof(payload_fd))];
495   } cmsg_buf;
496
497   struct msghdr msg;
498   FILLZERO(msg);
499   FILLZERO(cmsg_buf);
500
501   char dummy_byte = 0;
502   struct iovec iov;
503   FILLZERO(iov);
504   iov.iov_base = &dummy_byte;
505   iov.iov_len = 1;
506
507   msg.msg_name = 0;
508   msg.msg_iov = &iov;
509   msg.msg_iovlen = 1;
510   msg.msg_control = cmsg_buf.buf;
511   msg.msg_controllen = sizeof(cmsg_buf.buf);
512
513   struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
514   cmsg->cmsg_level = SOL_SOCKET;
515   cmsg->cmsg_type = SCM_RIGHTS;
516   cmsg->cmsg_len = CMSG_LEN(sizeof(payload_fd));
517   *(int*)CMSG_DATA(cmsg) = payload_fd;
518
519   msg.msg_controllen = sizeof(cmsg_buf.buf);
520
521   for (;;) {
522     ssize_t r = sendmsg(via_fd, &msg, 0);
523     if (r == -1) {
524       if (errno == EINTR) continue;
525       diee("send fd");
526     }
527     assert(r == 1);
528     break;
529   }
530 }
531
532 static void send_request(void) {
533   char ibyte= 0;
534   ssize_t sr = fwrite(&ibyte, 1, 1, call_sock);
535   if (sr != 1) diee("write signalling byte");
536
537   // Sending these before the big message makes it easier for the script to
538   // use buffered IO for the message.
539   send_fd(0);
540   send_fd(1);
541   send_fd(2);
542
543   size_t len = 0;
544   prepare_message(&len, 0);
545
546   size_t tlen = len + 4;
547   char *m = xmalloc(tlen);
548   char *p = m;
549   prepare_length(0, &p, len);
550   prepare_message(0, &p);
551   assert(p == m + tlen);
552
553   sr = fwrite(m, tlen, 1, call_sock);
554   if (sr != 1) diee("write request (buffer)");
555
556   if (fflush(call_sock)) diee("write request");
557 }
558
559 static FILE *call_sock_from_fd(int fd) {
560   int r;
561
562   FILE *call_sock = fdopen(fd, "r+");
563   if (!call_sock) diee("fdopen socket");
564
565   r = setvbuf(call_sock, 0, _IONBF, 0);
566   if (r) die("setvbuf socket");
567
568   return call_sock;
569 }
570
571 static bool was_eof(FILE *call_sock) {
572   return feof(call_sock) || errno==ECONNRESET;
573 }
574
575 // Returns -1 on EOF
576 static int protocol_read_maybe(void *data, size_t sz) {
577   if (!sz) return 0;
578   size_t sr = fread(data, sz, 1, call_sock);
579   if (sr != 1) {
580     if (was_eof(call_sock)) return -1;
581     diee("read() on monitor call socket (%zd)", sz);
582   }
583   return 0;
584 }
585
586 static void protocol_read(void *data, size_t sz) {
587   if (protocol_read_maybe(data, sz) < 0)
588     die("monitor process quit unexpectedly");
589 }
590
591 // Returns 0 if OK, error msg if peer was garbage.
592 static const char *read_greeting(void) {
593   char got_magic[sizeof(header_magic)];
594
595   if (protocol_read_maybe(&got_magic, sizeof(got_magic)) < 0)
596     return "initial monitor process quit";
597
598   if (memcmp(got_magic, header_magic, sizeof(header_magic)))
599     die("got unexpected protocol magic 0x%02x%02x%02x%02x",
600         got_magic[0], got_magic[1], got_magic[2], got_magic[3]);
601
602   uint32_t xdata_len;
603   protocol_read(&xdata_len, sizeof(xdata_len));
604   void *xdata = xmalloc(xdata_len);
605   protocol_read(xdata, xdata_len);
606
607   return 0;
608 }
609
610 // Returns: call(client-end), or 0 to mean "is garbage"
611 // find_socket_path must have been called
612 static FILE *connect_existing(void) {
613   int r;
614   int fd = -1;
615
616   if (mode != MODE_NORMAL) return 0;
617
618   fd = socket(AF_UNIX, SOCK_STREAM, 0);
619   if (fd==-1) diee("socket() for client");
620
621   socklen_t salen = sizeof(sockaddr_sun);
622   r = connect(fd, (const struct sockaddr*)&sockaddr_sun, salen);
623   if (r==-1) {
624     if (errno==ECONNREFUSED || errno==ENOENT) goto x_garbage;
625     diee("connect() %s", socket_path);
626   }
627
628   call_sock = call_sock_from_fd(fd);
629   fd = -1;
630
631   if (read_greeting())
632     goto x_garbage;
633
634   return call_sock;
635
636  x_garbage:
637   if (call_sock) { fclose(call_sock); call_sock=0; }
638   if (fd >= 0) close(fd);
639   return 0;
640 }
641
642 static void watcher_cb_stdin(uv_poll_t *handle, int status, int events) {
643   char c;
644   int r;
645
646   if ((errno = -status)) diee("watcher: poll stdin");
647   for (;;) {
648     r= read(0, &c, 1);
649     if (r!=-1) _exit(0);
650     if (!(errno==EINTR || errno==EWOULDBLOCK || errno==EAGAIN))
651       diee("watcher: read sentinel stdin");
652   }
653 }
654
655 static void watcher_cb_sockpath(uv_fs_event_t *handle, const char *filename,
656                                 int events, int status) {
657   int r;
658   struct stat now_stab;
659
660   if ((errno = -status)) diee("watcher: poll stdin");
661   for (;;) {
662     r= stat(socket_path, &now_stab);
663     if (r==-1) {
664       if (errno==ENOENT) _exit(0);
665       if (errno==EINTR) continue;
666       diee("stat socket: %s", socket_path);
667     }
668     if (!stabs_same_inode(&now_stab, &initial_stab))
669       _exit(0);
670   }
671 }
672
673 // On entry, stderr is still inherited, but 0 and 1 are the pipes
674 static __attribute__((noreturn))
675 void become_watcher(void) {
676   uv_loop_t loop;
677   uv_poll_t uvhandle_stdin;
678   uv_fs_event_t uvhandle_sockpath;
679   int r;
680
681   nonblock(0);
682
683   errno= -uv_loop_init(&loop);
684   if (errno) diee("watcher: uv_loop_init");
685
686   errno= -uv_poll_init(&loop, &uvhandle_stdin, 0);
687   if (errno) diee("watcher: uv_poll_init");
688   errno= -uv_poll_start(&uvhandle_stdin,
689                         UV_READABLE | UV_WRITABLE | UV_DISCONNECT,
690                         watcher_cb_stdin);
691   if (errno) diee("watcher: uv_poll_start");
692
693   errno= -uv_fs_event_init(&loop, &uvhandle_sockpath);
694   if (errno) diee("watcher: uv_fs_event_init");
695
696   errno= -uv_fs_event_start(&uvhandle_sockpath, watcher_cb_sockpath,
697                             socket_path, 0);
698   if (errno) diee("watcher: uv_fs_event_start");
699
700   // OK everything is set up, let us daemonise
701   if (dup2(1,2) != 2) diee("watcher: set daemonised stderr");
702   r= setvbuf(stderr, 0, _IOLBF, BUFSIZ);
703   if (r) diee("watcher: setvbuf stderr");
704
705   pid_t child = fork();
706   if (child == (pid_t)-1) diee("watcher: fork");
707   if (child) _exit(0);
708
709   if (setsid() == (pid_t)-1) diee("watcher: setsid");
710
711   r= uv_run(&loop, UV_RUN_DEFAULT);
712   die("uv_run returned (%d)", r);
713 }
714
715 static __attribute__((noreturn))
716 void become_setup(int sfd, int lockfd, int fake_pair[2],
717                   int watcher_stdin, int watcher_stderr) {
718   close(lockfd);
719   close(fake_pair[0]);
720   int call_fd = fake_pair[1];
721
722   int null_0 = open("/dev/null", O_RDONLY);  if (null_0 < 0) diee("open null");
723   if (dup2(null_0, 0)) diee("dup2 /dev/null onto stdin");
724   close(null_0);
725   if (dup2(2, 1) != 1) die("dup2 stderr onto stdout");
726
727   nonblock(sfd);
728
729   // Extension could work like this:
730   //
731   // We could advertise a new protocol (perhaps one which is nearly entirely
732   // different after the connect) by putting a name for it comma-separated
733   // next to "v1".  Simple extension can be done by having the script
734   // side say something about it in the ack xdata, which we currently ignore.
735   // Or we could add other extra data after v1.
736   putenv(m_asprintf("PREFORK_INTERP=v1,%jd.%09ld %d,%d,%d,%d",
737                     (intmax_t)initial_stab.st_mtim.tv_sec,
738                     (long)initial_stab.st_mtim.tv_nsec,
739                     sfd, call_fd, watcher_stdin, watcher_stderr));
740
741   execvp(executor_argv[0], (char**)executor_argv);
742   diee("execute %s", executor_argv[0]);
743 }
744
745 static void connect_or_spawn(void) {
746   int r;
747
748   call_sock = connect_existing();
749   if (call_sock) return;
750
751   // We're going to make a new one, so clean out old ones
752   preclean();
753
754   int lockfd = acquire_lock();
755
756   if (mode == MODE_KILL) {
757     r= unlink(socket_path);
758     if (r && errno != ENOENT) diee("remove socket %s", socket_path);
759
760     r= unlink(lock_path);
761     if (r) diee("rmeove lock %s", lock_path);
762     _exit(0);
763   }
764
765   call_sock = connect_existing();
766   if (call_sock) { close(lockfd); return; }
767
768   // We must start a fresh one, and we hold the lock
769
770   r = unlink(socket_path);
771   if (r<0 && errno!=ENOENT)
772     diee("failed to remove stale socket %s", socket_path);
773
774   int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
775   if (sfd<0) diee("socket() for new listener");
776
777   socklen_t salen = sizeof(sockaddr_sun);
778   r= bind(sfd, (const struct sockaddr*)&sockaddr_sun, salen);
779   if (r<0) diee("bind() on new listener");
780
781   r= stat(socket_path, &initial_stab);
782   if (r<0) diee("stat() fresh socket");
783
784   // We never want callers to get ECONNREFUSED.  But:
785   // There is a race here: from my RTFM they may get ECONNREFUSED
786   // if they try between our bind() and listen().  But if they do, they'll
787   // acquire the lock (serialising with us) and retry, and then it will work.
788   r = listen(sfd, INT_MAX);
789   if (r<0) diee("listen() for new listener");
790
791   // Fork watcher
792
793   int watcher_stdin[2];
794   int watcher_stderr[2];
795   if (pipe(watcher_stdin) || pipe(watcher_stderr))
796     diee("pipe() for socket inode watcher");
797
798   pid_t watcher = fork();
799   if (watcher == (pid_t)-1) diee("fork for watcher");
800   if (!watcher) {
801     close(sfd);
802     close(lockfd);
803     close(watcher_stdin[1]);
804     close(watcher_stderr[0]);
805     if (dup2(watcher_stdin[0], 0) != 0 ||
806         dup2(watcher_stderr[1], 1) != 1)
807       diee("initial dup2() for watcher");
808     close(watcher_stdin[0]);
809     close(watcher_stderr[1]);
810     become_watcher();
811   }
812
813   close(watcher_stdin[0]);
814   close(watcher_stderr[1]);
815   nonblock(watcher_stderr[0]);
816
817   // Fork setup
818
819   int fake_pair[2];
820   r = socketpair(AF_UNIX, SOCK_STREAM, 0, fake_pair);
821   if (r<0) diee("socketpair() for fake initial connection");
822
823   pid_t setup_pid = fork();
824   if (setup_pid == (pid_t)-1) diee("fork for spawn setup");
825   if (!setup_pid) become_setup(sfd, lockfd, fake_pair,
826                                watcher_stdin[1], watcher_stderr[0]);
827   close(fake_pair[1]);
828   close(sfd);
829
830   call_sock = call_sock_from_fd(fake_pair[0]);
831
832   int status;
833   pid_t got = waitpid(setup_pid, &status, 0);
834   if (got == (pid_t)-1) diee("waitpid setup [%ld]", (long)setup_pid);
835   if (got != setup_pid) diee("waitpid setup [%ld] gave [%ld]!",
836                              (long)setup_pid, (long)got);
837   if (status != 0) propagate_exit_status(status, "setup");
838
839   const char *emsg = read_greeting();
840   if (emsg) die("setup failed: %s", emsg);
841
842   close(lockfd);
843   return;
844 }
845
846 static void make_executor_argv(const char *const *argv) {
847   switch (mediation) {
848   case MEDIATION_UNLAUNDERED: break;
849   default: die("need -U (specifying unlaundered argument handling)");
850   }
851
852   const char *arg;
853   #define EACH_NEW_ARG(EACH) {                  \
854     arg = interp; { EACH }                      \
855     if ((arg = script)) { EACH }                \
856     const char *const *walk = argv;             \
857     while ((arg = *walk++)) { EACH }            \
858   }
859
860   size_t count = 1;
861   EACH_NEW_ARG( (void)arg; count++; );
862
863   const char **out = calloc(count, sizeof(char*));
864   executor_argv = (const char* const*)out;
865   if (!executor_argv) diee("allocate for arguments");
866
867   EACH_NEW_ARG( *out++ = arg; );
868   *out++ = 0;
869 }
870
871 int main(int argc_unused, const char *const *argv) {
872   process_opts(&argv);
873
874   // Now we have
875   //  - possibly interp
876   //  - possibly script
877   //  - remaining args
878   // which ought to be passed on to the actual executor.
879   make_executor_argv(argv);
880
881   find_socket_path();
882   FILLZERO(sockaddr_sun);
883   sockaddr_sun.sun_family = AF_UNIX;
884   assert(strlen(socket_path) <= sizeof(sockaddr_sun.sun_path));
885   strncpy(sockaddr_sun.sun_path, socket_path, sizeof(sockaddr_sun.sun_path));
886
887   connect_or_spawn();
888
889   // We're committed now, send the request (or bail out)
890   send_request();
891
892   uint32_t status;
893   protocol_read(&status, sizeof(status));
894
895   status = ntohl(status);
896   if (status > INT_MAX) die("status 0x%lx does not fit in an int",
897                             (unsigned long)status);
898
899   propagate_exit_status(status, "invocation");
900 }