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