chiark / gitweb /
prefork-interp: protocol documentation
[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   Protocol, and functions of the script
249
250   1. Script interpreter will be spawned apparently as normal;
251      should run synchronously in the normal way until
252      "initialisation complete" point.  At initialisation complete:
253
254   2. Env var PREFORK_INTERP contains:
255
256          v1,SECS.NSECS[,...] LISTEN,CALL,WATCHE,WATCHI[,...][ ???]
257
258      To parse it: treat as bytes and split on ASCII space, taking
259      the first two words.  (There may or may not be
260      further "words"; and if there are they might be binary data.)
261      Then split each of the first two words (which will contain only
262      ASCII printing characters) on comma.  Take the first two items:
263
264         v1    Protocol version indicator - literal.  If something else,
265               fail (means installation is incompatible somehow).
266
267         SECS.NSECS
268               timestamp just before script started running, as a
269               decimal time_t.  NSECS is exactly 9 digits.
270               To be used for auto reloading (see below).
271
272      The 2nd word's items are file descriptors:
273
274         LISTEN   listening socket                 nonblocking
275         CALL     call socket for initial call     blocking
276         WATCHE   liveness watcher stderr          nonblocking
277         WATCHI   liveness sentinel                unspecified
278
279         (any further descriptors should be ignored, not closed)
280
281   3. Library should do the following:
282
283      1. Read and understand the PREFORK_INTERP env var.
284         If it is not set, initialisation complete should simply return.
285         (This allows simple synchronous operation.)
286
287      2. Open syslog
288      3. fork/exit (fork and have parent exit) (to make server)
289      4. setsid (to become session leader)
290      5. fork initial service (monitor) child, using CALL (see below)
291      6. Replace stdin/stdout/stderr with /dev/null,
292         and make a note to send all error messages to syslog
293      7. Enter select loop, looking for the following:
294
295         A. accept on LISTEN:
296             i. see if we need to reload: is any file forming part
297                of the program newer than the SECS.NSECS ?
298                If so, log at LOG_INFO, and exit immediately
299                (dropping CALL, LISTEN, WATCHI, etc.)
300             ii. see if we can reap any children, possibly waiting
301                for children if we are at our concurrency limit
302                (limit should be configured through library, default 4)
303                Report child exit status if not zero or SIGPIPE.
304             iii. fork service (monitor) child, using accepted fd
305
306         B. WATCHE is readable:
307             * EOF: log at LOG_INFO, and exit
308             * data to read: read what is available immediately;
309               it will be an error message: log it at LOG_ERR, and exit
310
311   4. service (monitor) child does the following:
312
313       1. close all of LISTEN, WATCHI, WATCHE
314       2. setpgrp
315       3. send a greeting (on CALL) "PFI\n\0\0\0\0" (8 bytes)
316       4. read a single byte, fail if it's not zero
317       5. three times, receive a single byte with a file descriptor
318          attached as ancillary data.  (These descriptors will be
319          service stdin, stdout, stderr.)
320       6. read a 4-byte big-endian length
321       7. read that many bytes, the initial service request message,
322          which contains the following nul-terminated strings:
323             * environment variable settings in the format NAME=value
324             * an empty string
325             * arguments NOT INCLUDING argv[0] or script filename
326          (not that this means the service request must end in a nul)
327       8. make a new pipe EXECTERM
328       9. fork for the service executor; in the child
329             i. redirect stdin/stdout/stderr to the recevied fds
330             ii. replace environment and arguments with those received,
331             iii. close descriptors: close the original received descriptors;
332                  close CALL; keep only the writing end of EXECTERM
333             iv. if the script programming language does things with SIGINT,
334                 set it set back to default handling (immediate termination).
335             v. return back to script, now in the grandchild
336
337       10. in the parent, close EXECTERM writing end, and
338       11. select, looking for one of the following:
339            * CALL is readable
340            * EXECTERM reading end is readable
341           No need to actually read, since these shouldn't produce
342           spurious wakeups (but do loop on EINTR).
343       12. set SIGINT to ignored
344       13. send SIGINT to the entire process group
345       14. wait, blocking, for the executor child
346       15. write the wait status, in 32-bit big-endian, to CAL
347       16. exit 0
348
349      Errors detected in the service monitor should be sent to
350      syslog, or stderr, depending on whether this is the initial
351      service monitor (from part 3 step 5) or an accepted socket
352      service monitor (from part 4 step 9); this can be achieved
353      easily by having a global flag (set at part 3 step 6),
354      or perhaps using logger(8) and redirecting stderr (but
355      then be careful to ensure everyone gets only the necessary fds).
356
357      EOF on CALL, or EPIPE/SIGPIPE writing to it, are not errors.
358      In this case, exit zero or die with SIGPIPE, so parent
359      won't report error either (part 3 step 7(A)(ii)).
360
361 ***************************************************************************
362 \f
363 */
364
365 #include <arpa/inet.h>
366
367 #include <uv.h>
368
369 #include "prefork.h"
370
371 const char our_name[] = "prefork-interp";
372
373 static struct sockaddr_un sockaddr_sun;
374 static FILE *call_sock;
375
376 #define ACK_BYTE '\n'
377
378 static const char *const *executor_argv;
379
380 static const char header_magic[4] = "PFI\n";
381
382 void fusagemessage(FILE *f) {
383   fprintf(f, "usage: #!/usr/bin/prefork-interp [<options>]\n");
384 }
385
386 #define MODE_NORMAL 0
387 #define MODE_KILL   'k'
388 #define MODE_FRESH  'f'
389
390 #define MEDIATION_UNSPECIFIED 0
391 #define MEDIATION_UNLAUNDERED 'U'
392
393 static int mediation = MEDIATION_UNSPECIFIED;
394 static int mode = MODE_NORMAL;
395 static int max_sockets = 100; // maximum entries in the run dir is 2x this
396
397 static struct stat initial_stab;
398
399 const struct cmdinfo cmdinfos[]= {
400   PREFORK_CMDINFOS
401   { 0,         'U',   0, .iassignto= &mediation, .arg= MEDIATION_UNLAUNDERED },
402   { "kill",     0,    0, .iassignto= &mode,      .arg= MODE_KILL   },
403   { 0,         'f',   0, .iassignto= &mode,      .arg= MODE_FRESH  },
404   { 0 }
405 };
406
407 void ident_addinit(void) {
408   char ident_magic[1] = { 0 };
409   sha256_update(&identsc, sizeof(ident_magic), ident_magic);
410 }
411
412 static void propagate_exit_status(int status, const char *what) {
413   int r;
414
415   if (WIFEXITED(status)) {
416     _exit(status);
417   }
418
419   if (WIFSIGNALED(status)) {
420     int sig = WTERMSIG(status);
421     const char *signame = strsignal(sig);
422     if (signame == 0) signame = "unknown signal";
423
424     if (! WCOREDUMP(status) &&
425         (sig == SIGINT ||
426          sig == SIGHUP ||
427          sig == SIGPIPE ||
428          sig == SIGKILL)) {
429       struct sigaction sa;
430       FILLZERO(sa);
431       sa.sa_handler = SIG_DFL;
432       r = sigaction(sig, &sa, 0);
433       if (r) diee("failed to reset signal handler while propagating %s",
434                   signame);
435
436       sigset_t sset;
437       sigemptyset(&sset);
438       sigaddset(&sset, sig);
439       r = sigprocmask(SIG_UNBLOCK, &sset, 0);
440       if (r) diee("failed to reset signal block while propagating %s",
441                   signame);
442
443       raise(sig);
444       die("unexpectedly kept running after raising (to propagate) %s",
445           signame);
446     }
447
448     die("%s failed due to signal %d %s%s", what, sig, signame,
449         WCOREDUMP(status) ? " (core dumped)" : "");
450   }
451
452   die("%s failed with weird wait status %d 0x%x", what, status, status);
453 }
454
455 typedef struct {
456   char *name_hash;
457   time_t atime;
458 } PrecleanEntry;
459
460 static int preclean_entry_compar_name(const void *av, const void *bv) {
461   const PrecleanEntry *a = av;
462   const PrecleanEntry *b = bv;
463   return strcmp(a->name_hash, b->name_hash);
464 }
465
466 static int preclean_entry_compar_atime(const void *av, const void *bv) {
467   const PrecleanEntry *ae = av;  time_t a = ae->atime;
468   const PrecleanEntry *be = bv;  time_t b = be->atime;
469   return (a > b ? +1 :
470           a < b ? -1 : 0);
471 }
472
473 static time_t preclean_stat_atime(const char *s_path) {
474   struct stat stab;
475   int r= lstat(s_path, &stab);
476   if (r) {
477     if (errno!=ENOENT) diee("pre-cleanup: stat socket (%s)", s_path);
478     return 0;
479   }
480   return stab.st_atime;
481 }
482
483 static void preclean(void) {
484   DIR *dir = opendir(run_base);
485   if (!dir) {
486     if (errno == ENOENT) return;
487     diee("pre-cleanup: open run dir (%s)", run_base);
488   }
489
490   PrecleanEntry *entries=0;
491   size_t avail_entries=0;
492   size_t used_entries=0;
493
494   struct dirent *de;
495   while ((errno = 0, de = readdir(dir))) {
496     char c0 = de->d_name[0];
497     if (!(c0 == 'l' || c0 == 's')) continue;
498     char *name_hash = m_asprintf("%s", de->d_name+1);
499     char *s_path = m_asprintf("%s/s%s", run_base, name_hash);
500     time_t atime = preclean_stat_atime(s_path);
501
502     if (avail_entries == used_entries) {
503       assert(avail_entries < INT_MAX / 4 / sizeof(PrecleanEntry));
504       avail_entries <<= 1;
505       avail_entries += 10;
506       entries = realloc(entries, avail_entries * sizeof(PrecleanEntry));
507     }
508     entries[used_entries].name_hash = name_hash;
509     entries[used_entries].atime = atime;
510     used_entries++;
511   }
512   if (errno) diee("pre-cleanup: read run dir (%s)", run_base);
513
514   // First we dedupe (after sorting by path)
515   qsort(entries, used_entries, sizeof(PrecleanEntry),
516         preclean_entry_compar_name);
517   PrecleanEntry *p, *q;
518   for (p=entries, q=entries; p < entries + used_entries; p++) {
519     if (q > entries && !strcmp(p->name_hash, (q-1)->name_hash))
520       continue;
521     *q++ = *p;
522   }
523   used_entries = q - entries;
524
525   // Now maybe delete some things
526   //
527   // Actually this has an off-by-one error since we are about
528   // to create a socket, so the actual number of sockets is one more.
529   // But, *actually*, since there might be multiple of us running at once,
530   // we might have even more than that.  This doesn't really matter.
531   if (used_entries > max_sockets) {
532     qsort(entries, used_entries, sizeof(PrecleanEntry),
533           preclean_entry_compar_atime);
534     for (p=entries; p < entries + max_sockets; p++) {
535       char *l_path = m_asprintf("%s/l%s", run_base, p->name_hash);
536       char *s_path = m_asprintf("%s/s%s", run_base, p->name_hash);
537       int lock_fd = flock_file(l_path);
538       // Recheck atime - we might have raced!
539       time_t atime = preclean_stat_atime(s_path);
540       if (atime != p->atime) {
541         // Raced.  This will leave use deleting too few things.  Whatever.
542       } else {
543         int r= unlink(s_path);
544         if (r && errno!=ENOENT) diee("preclean: delete stale (%s)", s_path);
545         r= unlink(l_path);
546         if (r) diee("preclean: delete stale lock (%s)", s_path);
547         // NB we don't hold the lock any more now.
548       }
549       close(lock_fd);
550       free(l_path);
551       free(s_path);
552     }
553   }
554
555   for (p=entries; p < entries + used_entries; p++)
556     free(p->name_hash);
557   free(entries);
558 }
559
560 static __attribute((noreturn)) void die_data_overflow(void) {
561   die("cannot handle data with length >2^32");
562 }
563
564 static void prepare_data(size_t *len, char **buf,
565                          const void *data, size_t dl) {
566   if (len) {
567     if (dl >= SIZE_MAX - *len)
568       die_data_overflow();
569     *len += dl;
570   }
571   if (buf) {
572     memcpy(*buf, data, dl);
573     *buf += dl;
574   }
575 }
576
577 static void prepare_length(size_t *len, char **buf, size_t dl_sz) {
578   if (dl_sz > UINT32_MAX) die_data_overflow();
579   uint32_t dl = htonl(dl_sz);
580   prepare_data(len, buf, &dl, sizeof(dl));
581 }
582
583 static void prepare_string(size_t *len, char **buf, const char *s) {
584   size_t sl = strlen(s);
585   prepare_data(len, buf, s, sl+1);
586 }
587
588 static void prepare_message(size_t *len, char **buf) {
589   const char *s;
590
591   const char *const *p = (void*)environ;
592   while ((s = *p++)) {
593     if (strchr(s, '='))
594       prepare_string(len, buf, s);
595   }
596
597   prepare_string(len, buf, "");
598
599   p = executor_argv;
600   while ((s = *p++))
601     prepare_string(len, buf, s);
602 }
603
604 static void send_fd(int payload_fd) {
605   int via_fd = fileno(call_sock);
606
607   union {
608     struct cmsghdr align;
609     char buf[CMSG_SPACE(sizeof(payload_fd))];
610   } cmsg_buf;
611
612   struct msghdr msg;
613   FILLZERO(msg);
614   FILLZERO(cmsg_buf);
615
616   char dummy_byte = 0;
617   struct iovec iov;
618   FILLZERO(iov);
619   iov.iov_base = &dummy_byte;
620   iov.iov_len = 1;
621
622   msg.msg_name = 0;
623   msg.msg_iov = &iov;
624   msg.msg_iovlen = 1;
625   msg.msg_control = cmsg_buf.buf;
626   msg.msg_controllen = sizeof(cmsg_buf.buf);
627
628   struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
629   cmsg->cmsg_level = SOL_SOCKET;
630   cmsg->cmsg_type = SCM_RIGHTS;
631   cmsg->cmsg_len = CMSG_LEN(sizeof(payload_fd));
632   *(int*)CMSG_DATA(cmsg) = payload_fd;
633
634   msg.msg_controllen = sizeof(cmsg_buf.buf);
635
636   for (;;) {
637     ssize_t r = sendmsg(via_fd, &msg, 0);
638     if (r == -1) {
639       if (errno == EINTR) continue;
640       diee("send fd");
641     }
642     assert(r == 1);
643     break;
644   }
645 }
646
647 static void send_request(void) {
648   char ibyte= 0;
649   ssize_t sr = fwrite(&ibyte, 1, 1, call_sock);
650   if (sr != 1) diee("write signalling byte");
651
652   // Sending these before the big message makes it easier for the script to
653   // use buffered IO for the message.
654   send_fd(0);
655   send_fd(1);
656   send_fd(2);
657
658   size_t len = 0;
659   prepare_message(&len, 0);
660
661   size_t tlen = len + 4;
662   char *m = xmalloc(tlen);
663   char *p = m;
664   prepare_length(0, &p, len);
665   prepare_message(0, &p);
666   assert(p == m + tlen);
667
668   sr = fwrite(m, tlen, 1, call_sock);
669   if (sr != 1) diee("write request (buffer)");
670
671   if (fflush(call_sock)) diee("write request");
672 }
673
674 static FILE *call_sock_from_fd(int fd) {
675   int r;
676
677   FILE *call_sock = fdopen(fd, "r+");
678   if (!call_sock) diee("fdopen socket");
679
680   r = setvbuf(call_sock, 0, _IONBF, 0);
681   if (r) die("setvbuf socket");
682
683   return call_sock;
684 }
685
686 static bool was_eof(FILE *call_sock) {
687   return feof(call_sock) || errno==ECONNRESET;
688 }
689
690 // Returns -1 on EOF
691 static int protocol_read_maybe(void *data, size_t sz) {
692   if (!sz) return 0;
693   size_t sr = fread(data, sz, 1, call_sock);
694   if (sr != 1) {
695     if (was_eof(call_sock)) return -1;
696     diee("read() on monitor call socket (%zd)", sz);
697   }
698   return 0;
699 }
700
701 static void protocol_read(void *data, size_t sz) {
702   if (protocol_read_maybe(data, sz) < 0)
703     die("monitor process quit unexpectedly");
704 }
705
706 // Returns 0 if OK, error msg if peer was garbage.
707 static const char *read_greeting(void) {
708   char got_magic[sizeof(header_magic)];
709
710   if (protocol_read_maybe(&got_magic, sizeof(got_magic)) < 0)
711     return "initial monitor process quit";
712
713   if (memcmp(got_magic, header_magic, sizeof(header_magic)))
714     die("got unexpected protocol magic 0x%02x%02x%02x%02x",
715         got_magic[0], got_magic[1], got_magic[2], got_magic[3]);
716
717   uint32_t xdata_len;
718   protocol_read(&xdata_len, sizeof(xdata_len));
719   void *xdata = xmalloc(xdata_len);
720   protocol_read(xdata, xdata_len);
721
722   return 0;
723 }
724
725 // Returns: call(client-end), or 0 to mean "is garbage"
726 // find_socket_path must have been called
727 static FILE *connect_existing(void) {
728   int r;
729   int fd = -1;
730
731   if (mode != MODE_NORMAL) return 0;
732
733   fd = socket(AF_UNIX, SOCK_STREAM, 0);
734   if (fd==-1) diee("socket() for client");
735
736   socklen_t salen = sizeof(sockaddr_sun);
737   r = connect(fd, (const struct sockaddr*)&sockaddr_sun, salen);
738   if (r==-1) {
739     if (errno==ECONNREFUSED || errno==ENOENT) goto x_garbage;
740     diee("connect() %s", socket_path);
741   }
742
743   call_sock = call_sock_from_fd(fd);
744   fd = -1;
745
746   if (read_greeting())
747     goto x_garbage;
748
749   return call_sock;
750
751  x_garbage:
752   if (call_sock) { fclose(call_sock); call_sock=0; }
753   if (fd >= 0) close(fd);
754   return 0;
755 }
756
757 static void watcher_cb_stdin(uv_poll_t *handle, int status, int events) {
758   char c;
759   int r;
760
761   if ((errno = -status)) diee("watcher: poll stdin");
762   for (;;) {
763     r= read(0, &c, 1);
764     if (r!=-1) _exit(0);
765     if (!(errno==EINTR || errno==EWOULDBLOCK || errno==EAGAIN))
766       diee("watcher: read sentinel stdin");
767   }
768 }
769
770 static void watcher_cb_sockpath(uv_fs_event_t *handle, const char *filename,
771                                 int events, int status) {
772   int r;
773   struct stat now_stab;
774
775   if ((errno = -status)) diee("watcher: poll stdin");
776   for (;;) {
777     r= stat(socket_path, &now_stab);
778     if (r==-1) {
779       if (errno==ENOENT) _exit(0);
780       if (errno==EINTR) continue;
781       diee("stat socket: %s", socket_path);
782     }
783     if (!stabs_same_inode(&now_stab, &initial_stab))
784       _exit(0);
785   }
786 }
787
788 // On entry, stderr is still inherited, but 0 and 1 are the pipes
789 static __attribute__((noreturn))
790 void become_watcher(void) {
791   uv_loop_t loop;
792   uv_poll_t uvhandle_stdin;
793   uv_fs_event_t uvhandle_sockpath;
794   int r;
795
796   nonblock(0);
797
798   errno= -uv_loop_init(&loop);
799   if (errno) diee("watcher: uv_loop_init");
800
801   errno= -uv_poll_init(&loop, &uvhandle_stdin, 0);
802   if (errno) diee("watcher: uv_poll_init");
803   errno= -uv_poll_start(&uvhandle_stdin,
804                         UV_READABLE | UV_WRITABLE | UV_DISCONNECT,
805                         watcher_cb_stdin);
806   if (errno) diee("watcher: uv_poll_start");
807
808   errno= -uv_fs_event_init(&loop, &uvhandle_sockpath);
809   if (errno) diee("watcher: uv_fs_event_init");
810
811   errno= -uv_fs_event_start(&uvhandle_sockpath, watcher_cb_sockpath,
812                             socket_path, 0);
813   if (errno) diee("watcher: uv_fs_event_start");
814
815   // OK everything is set up, let us daemonise
816   if (dup2(1,2) != 2) diee("watcher: set daemonised stderr");
817   r= setvbuf(stderr, 0, _IOLBF, BUFSIZ);
818   if (r) diee("watcher: setvbuf stderr");
819
820   pid_t child = fork();
821   if (child == (pid_t)-1) diee("watcher: fork");
822   if (child) _exit(0);
823
824   if (setsid() == (pid_t)-1) diee("watcher: setsid");
825
826   r= uv_run(&loop, UV_RUN_DEFAULT);
827   die("uv_run returned (%d)", r);
828 }
829
830 static __attribute__((noreturn))
831 void become_setup(int sfd, int lockfd, int fake_pair[2],
832                   int watcher_stdin, int watcher_stderr) {
833   close(lockfd);
834   close(fake_pair[0]);
835   int call_fd = fake_pair[1];
836
837   int null_0 = open("/dev/null", O_RDONLY);  if (null_0 < 0) diee("open null");
838   if (dup2(null_0, 0)) diee("dup2 /dev/null onto stdin");
839   close(null_0);
840   if (dup2(2, 1) != 1) die("dup2 stderr onto stdout");
841
842   nonblock(sfd);
843
844   // Extension could work like this:
845   //
846   // We could advertise a new protocol (perhaps one which is nearly entirely
847   // different after the connect) by putting a name for it comma-separated
848   // next to "v1".  Simple extension can be done by having the script
849   // side say something about it in the ack xdata, which we currently ignore.
850   // Or we could add other extra data after v1.
851   putenv(m_asprintf("PREFORK_INTERP=v1,%jd.%09ld %d,%d,%d,%d",
852                     (intmax_t)initial_stab.st_mtim.tv_sec,
853                     (long)initial_stab.st_mtim.tv_nsec,
854                     sfd, call_fd, watcher_stdin, watcher_stderr));
855
856   execvp(executor_argv[0], (char**)executor_argv);
857   diee("execute %s", executor_argv[0]);
858 }
859
860 static void connect_or_spawn(void) {
861   int r;
862
863   call_sock = connect_existing();
864   if (call_sock) return;
865
866   // We're going to make a new one, so clean out old ones
867   preclean();
868
869   int lockfd = acquire_lock();
870
871   if (mode == MODE_KILL) {
872     r= unlink(socket_path);
873     if (r && errno != ENOENT) diee("remove socket %s", socket_path);
874
875     r= unlink(lock_path);
876     if (r) diee("rmeove lock %s", lock_path);
877     _exit(0);
878   }
879
880   call_sock = connect_existing();
881   if (call_sock) { close(lockfd); return; }
882
883   // We must start a fresh one, and we hold the lock
884
885   r = unlink(socket_path);
886   if (r<0 && errno!=ENOENT)
887     diee("failed to remove stale socket %s", socket_path);
888
889   int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
890   if (sfd<0) diee("socket() for new listener");
891
892   socklen_t salen = sizeof(sockaddr_sun);
893   r= bind(sfd, (const struct sockaddr*)&sockaddr_sun, salen);
894   if (r<0) diee("bind() on new listener");
895
896   r= stat(socket_path, &initial_stab);
897   if (r<0) diee("stat() fresh socket");
898
899   // We never want callers to get ECONNREFUSED.  But:
900   // There is a race here: from my RTFM they may get ECONNREFUSED
901   // if they try between our bind() and listen().  But if they do, they'll
902   // acquire the lock (serialising with us) and retry, and then it will work.
903   r = listen(sfd, INT_MAX);
904   if (r<0) diee("listen() for new listener");
905
906   // Fork watcher
907
908   int watcher_stdin[2];
909   int watcher_stderr[2];
910   if (pipe(watcher_stdin) || pipe(watcher_stderr))
911     diee("pipe() for socket inode watcher");
912
913   pid_t watcher = fork();
914   if (watcher == (pid_t)-1) diee("fork for watcher");
915   if (!watcher) {
916     close(sfd);
917     close(lockfd);
918     close(watcher_stdin[1]);
919     close(watcher_stderr[0]);
920     if (dup2(watcher_stdin[0], 0) != 0 ||
921         dup2(watcher_stderr[1], 1) != 1)
922       diee("initial dup2() for watcher");
923     close(watcher_stdin[0]);
924     close(watcher_stderr[1]);
925     become_watcher();
926   }
927
928   close(watcher_stdin[0]);
929   close(watcher_stderr[1]);
930   nonblock(watcher_stderr[0]);
931
932   // Fork setup
933
934   int fake_pair[2];
935   r = socketpair(AF_UNIX, SOCK_STREAM, 0, fake_pair);
936   if (r<0) diee("socketpair() for fake initial connection");
937
938   pid_t setup_pid = fork();
939   if (setup_pid == (pid_t)-1) diee("fork for spawn setup");
940   if (!setup_pid) become_setup(sfd, lockfd, fake_pair,
941                                watcher_stdin[1], watcher_stderr[0]);
942   close(fake_pair[1]);
943   close(sfd);
944
945   call_sock = call_sock_from_fd(fake_pair[0]);
946
947   int status;
948   pid_t got = waitpid(setup_pid, &status, 0);
949   if (got == (pid_t)-1) diee("waitpid setup [%ld]", (long)setup_pid);
950   if (got != setup_pid) diee("waitpid setup [%ld] gave [%ld]!",
951                              (long)setup_pid, (long)got);
952   if (status != 0) propagate_exit_status(status, "setup");
953
954   const char *emsg = read_greeting();
955   if (emsg) die("setup failed: %s", emsg);
956
957   close(lockfd);
958   return;
959 }
960
961 static void make_executor_argv(const char *const *argv) {
962   switch (mediation) {
963   case MEDIATION_UNLAUNDERED: break;
964   default: die("need -U (specifying unlaundered argument handling)");
965   }
966
967   const char *arg;
968   #define EACH_NEW_ARG(EACH) {                  \
969     arg = interp; { EACH }                      \
970     if ((arg = script)) { EACH }                \
971     const char *const *walk = argv;             \
972     while ((arg = *walk++)) { EACH }            \
973   }
974
975   size_t count = 1;
976   EACH_NEW_ARG( (void)arg; count++; );
977
978   const char **out = calloc(count, sizeof(char*));
979   executor_argv = (const char* const*)out;
980   if (!executor_argv) diee("allocate for arguments");
981
982   EACH_NEW_ARG( *out++ = arg; );
983   *out++ = 0;
984 }
985
986 int main(int argc_unused, const char *const *argv) {
987   process_opts(&argv);
988
989   // Now we have
990   //  - possibly interp
991   //  - possibly script
992   //  - remaining args
993   // which ought to be passed on to the actual executor.
994   make_executor_argv(argv);
995
996   find_socket_path();
997   FILLZERO(sockaddr_sun);
998   sockaddr_sun.sun_family = AF_UNIX;
999   assert(strlen(socket_path) <= sizeof(sockaddr_sun.sun_path));
1000   strncpy(sockaddr_sun.sun_path, socket_path, sizeof(sockaddr_sun.sun_path));
1001
1002   connect_or_spawn();
1003
1004   // We're committed now, send the request (or bail out)
1005   send_request();
1006
1007   uint32_t status;
1008   protocol_read(&status, sizeof(status));
1009
1010   status = ntohl(status);
1011   if (status > INT_MAX) die("status 0x%lx does not fit in an int",
1012                             (unsigned long)status);
1013
1014   propagate_exit_status(status, "invocation");
1015 }