chiark / gitweb /
prefork-interp: change API
[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 #include <sys/utsname.h>
367
368 #include <uv.h>
369
370 #include "prefork.h"
371
372 const char our_name[] = "prefork-interp";
373
374 static struct sockaddr_un sockaddr_sun;
375 static FILE *call_sock;
376
377 #define ACK_BYTE '\n'
378
379 static const char *const *executor_argv;
380
381 static const char header_magic[4] = "PFI\n";
382
383 void fusagemessage(FILE *f) {
384   fprintf(f, "usage: #!/usr/bin/prefork-interp [<options>]\n");
385 }
386
387 #define MODE_NORMAL 0
388 #define MODE_KILL   'k'
389 #define MODE_FRESH  'f'
390
391 #define MEDIATION_UNSPECIFIED 0
392 #define MEDIATION_UNLAUNDERED 'U'
393
394 static int mediation = MEDIATION_UNSPECIFIED;
395 static int mode = MODE_NORMAL;
396 static int max_sockets = 100; // maximum entries in the run dir is 2x this
397
398 static struct stat initial_stab;
399
400 const struct cmdinfo cmdinfos[]= {
401   PREFORK_CMDINFOS
402   { 0,         'U',   0, .iassignto= &mediation, .arg= MEDIATION_UNLAUNDERED },
403   { "kill",     0,    0, .iassignto= &mode,      .arg= MODE_KILL   },
404   { 0,         'f',   0, .iassignto= &mode,      .arg= MODE_FRESH  },
405   { 0 }
406 };
407
408 static void ident_add_stat(const char *path) {
409   struct stat stab;
410   int r = stat(path, &stab);
411   if (r) diee("failed to stat %s", path);
412
413   IDENT_ADD_OBJ(stab.st_dev);
414   IDENT_ADD_OBJ(stab.st_ino);
415 }
416
417 void ident_addinit(void) {
418   char magic = 1;
419
420   IDENT_ADD_OBJ(magic);
421
422   struct utsname uts = { };
423   size_t utslen = sizeof(uts);
424   int r = uname(&uts);
425   if (r) diee("uname failed!");
426   IDENT_ADD_OBJ(utslen);
427   IDENT_ADD_OBJ(uts);
428
429   ident_add_stat(".");
430   ident_add_stat("/");
431 }
432
433 static void propagate_exit_status(int status, const char *what) {
434   int r;
435
436   if (WIFEXITED(status)) {
437     _exit(status);
438   }
439
440   if (WIFSIGNALED(status)) {
441     int sig = WTERMSIG(status);
442     const char *signame = strsignal(sig);
443     if (signame == 0) signame = "unknown signal";
444
445     if (! WCOREDUMP(status) &&
446         (sig == SIGINT ||
447          sig == SIGHUP ||
448          sig == SIGPIPE ||
449          sig == SIGKILL)) {
450       struct sigaction sa;
451       FILLZERO(sa);
452       sa.sa_handler = SIG_DFL;
453       r = sigaction(sig, &sa, 0);
454       if (r) diee("failed to reset signal handler while propagating %s",
455                   signame);
456
457       sigset_t sset;
458       sigemptyset(&sset);
459       sigaddset(&sset, sig);
460       r = sigprocmask(SIG_UNBLOCK, &sset, 0);
461       if (r) diee("failed to reset signal block while propagating %s",
462                   signame);
463
464       raise(sig);
465       die("unexpectedly kept running after raising (to propagate) %s",
466           signame);
467     }
468
469     die("%s failed due to signal %d %s%s", what, sig, signame,
470         WCOREDUMP(status) ? " (core dumped)" : "");
471   }
472
473   die("%s failed with weird wait status %d 0x%x", what, status, status);
474 }
475
476 typedef struct {
477   char *name_hash;
478   time_t atime;
479 } PrecleanEntry;
480
481 static int preclean_entry_compar_name(const void *av, const void *bv) {
482   const PrecleanEntry *a = av;
483   const PrecleanEntry *b = bv;
484   return strcmp(a->name_hash, b->name_hash);
485 }
486
487 static int preclean_entry_compar_atime(const void *av, const void *bv) {
488   const PrecleanEntry *ae = av;  time_t a = ae->atime;
489   const PrecleanEntry *be = bv;  time_t b = be->atime;
490   return (a > b ? +1 :
491           a < b ? -1 : 0);
492 }
493
494 static time_t preclean_stat_atime(const char *s_path) {
495   struct stat stab;
496   int r= lstat(s_path, &stab);
497   if (r) {
498     if (errno!=ENOENT) diee("pre-cleanup: stat socket (%s)", s_path);
499     return 0;
500   }
501   return stab.st_atime;
502 }
503
504 static void preclean(void) {
505   DIR *dir = opendir(run_base);
506   if (!dir) {
507     if (errno == ENOENT) return;
508     diee("pre-cleanup: open run dir (%s)", run_base);
509   }
510
511   PrecleanEntry *entries=0;
512   size_t avail_entries=0;
513   size_t used_entries=0;
514
515   struct dirent *de;
516   while ((errno = 0, de = readdir(dir))) {
517     char c0 = de->d_name[0];
518     if (!(c0 == 'l' || c0 == 's')) continue;
519     char *name_hash = m_asprintf("%s", de->d_name+1);
520     char *s_path = m_asprintf("%s/s%s", run_base, name_hash);
521     time_t atime = preclean_stat_atime(s_path);
522
523     if (avail_entries == used_entries) {
524       assert(avail_entries < INT_MAX / 4 / sizeof(PrecleanEntry));
525       avail_entries <<= 1;
526       avail_entries += 10;
527       entries = realloc(entries, avail_entries * sizeof(PrecleanEntry));
528     }
529     entries[used_entries].name_hash = name_hash;
530     entries[used_entries].atime = atime;
531     used_entries++;
532   }
533   if (errno) diee("pre-cleanup: read run dir (%s)", run_base);
534
535   // First we dedupe (after sorting by path)
536   qsort(entries, used_entries, sizeof(PrecleanEntry),
537         preclean_entry_compar_name);
538   PrecleanEntry *p, *q;
539   for (p=entries, q=entries; p < entries + used_entries; p++) {
540     if (q > entries && !strcmp(p->name_hash, (q-1)->name_hash))
541       continue;
542     *q++ = *p;
543   }
544   used_entries = q - entries;
545
546   // Now maybe delete some things
547   //
548   // Actually this has an off-by-one error since we are about
549   // to create a socket, so the actual number of sockets is one more.
550   // But, *actually*, since there might be multiple of us running at once,
551   // we might have even more than that.  This doesn't really matter.
552   if (used_entries > max_sockets) {
553     qsort(entries, used_entries, sizeof(PrecleanEntry),
554           preclean_entry_compar_atime);
555     for (p=entries; p < entries + max_sockets; p++) {
556       char *l_path = m_asprintf("%s/l%s", run_base, p->name_hash);
557       char *s_path = m_asprintf("%s/s%s", run_base, p->name_hash);
558       int lock_fd = flock_file(l_path);
559       // Recheck atime - we might have raced!
560       time_t atime = preclean_stat_atime(s_path);
561       if (atime != p->atime) {
562         // Raced.  This will leave use deleting too few things.  Whatever.
563       } else {
564         int r= unlink(s_path);
565         if (r && errno!=ENOENT) diee("preclean: delete stale (%s)", s_path);
566         r= unlink(l_path);
567         if (r) diee("preclean: delete stale lock (%s)", s_path);
568         // NB we don't hold the lock any more now.
569       }
570       close(lock_fd);
571       free(l_path);
572       free(s_path);
573     }
574   }
575
576   for (p=entries; p < entries + used_entries; p++)
577     free(p->name_hash);
578   free(entries);
579 }
580
581 static __attribute((noreturn)) void die_data_overflow(void) {
582   die("cannot handle data with length >2^32");
583 }
584
585 static void prepare_data(size_t *len, char **buf,
586                          const void *data, size_t dl) {
587   if (len) {
588     if (dl >= SIZE_MAX - *len)
589       die_data_overflow();
590     *len += dl;
591   }
592   if (buf) {
593     memcpy(*buf, data, dl);
594     *buf += dl;
595   }
596 }
597
598 static void prepare_length(size_t *len, char **buf, size_t dl_sz) {
599   if (dl_sz > UINT32_MAX) die_data_overflow();
600   uint32_t dl = htonl(dl_sz);
601   prepare_data(len, buf, &dl, sizeof(dl));
602 }
603
604 static void prepare_string(size_t *len, char **buf, const char *s) {
605   size_t sl = strlen(s);
606   prepare_data(len, buf, s, sl+1);
607 }
608
609 static void prepare_message(size_t *len, char **buf) {
610   const char *s;
611
612   const char *const *p = (void*)environ;
613   while ((s = *p++)) {
614     if (strchr(s, '='))
615       prepare_string(len, buf, s);
616   }
617
618   prepare_string(len, buf, "");
619
620   p = executor_argv;
621   while ((s = *p++))
622     prepare_string(len, buf, s);
623 }
624
625 static void send_fd(int payload_fd) {
626   int via_fd = fileno(call_sock);
627
628   union {
629     struct cmsghdr align;
630     char buf[CMSG_SPACE(sizeof(payload_fd))];
631   } cmsg_buf;
632
633   struct msghdr msg;
634   FILLZERO(msg);
635   FILLZERO(cmsg_buf);
636
637   char dummy_byte = 0;
638   struct iovec iov;
639   FILLZERO(iov);
640   iov.iov_base = &dummy_byte;
641   iov.iov_len = 1;
642
643   msg.msg_name = 0;
644   msg.msg_iov = &iov;
645   msg.msg_iovlen = 1;
646   msg.msg_control = cmsg_buf.buf;
647   msg.msg_controllen = sizeof(cmsg_buf.buf);
648
649   struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
650   cmsg->cmsg_level = SOL_SOCKET;
651   cmsg->cmsg_type = SCM_RIGHTS;
652   cmsg->cmsg_len = CMSG_LEN(sizeof(payload_fd));
653   *(int*)CMSG_DATA(cmsg) = payload_fd;
654
655   msg.msg_controllen = sizeof(cmsg_buf.buf);
656
657   for (;;) {
658     ssize_t r = sendmsg(via_fd, &msg, 0);
659     if (r == -1) {
660       if (errno == EINTR) continue;
661       diee("send fd");
662     }
663     assert(r == 1);
664     break;
665   }
666 }
667
668 static void send_request(void) {
669   char ibyte= 0;
670   ssize_t sr = fwrite(&ibyte, 1, 1, call_sock);
671   if (sr != 1) diee("write signalling byte");
672
673   // Sending these before the big message makes it easier for the script to
674   // use buffered IO for the message.
675   send_fd(0);
676   send_fd(1);
677   send_fd(2);
678
679   size_t len = 0;
680   prepare_message(&len, 0);
681
682   size_t tlen = len + 4;
683   char *m = xmalloc(tlen);
684   char *p = m;
685   prepare_length(0, &p, len);
686   prepare_message(0, &p);
687   assert(p == m + tlen);
688
689   sr = fwrite(m, tlen, 1, call_sock);
690   if (sr != 1) diee("write request (buffer)");
691
692   if (fflush(call_sock)) diee("write request");
693 }
694
695 static FILE *call_sock_from_fd(int fd) {
696   int r;
697
698   FILE *call_sock = fdopen(fd, "r+");
699   if (!call_sock) diee("fdopen socket");
700
701   r = setvbuf(call_sock, 0, _IONBF, 0);
702   if (r) die("setvbuf socket");
703
704   return call_sock;
705 }
706
707 static bool was_eof(FILE *call_sock) {
708   return feof(call_sock) || errno==ECONNRESET;
709 }
710
711 // Returns -1 on EOF
712 static int protocol_read_maybe(void *data, size_t sz) {
713   if (!sz) return 0;
714   size_t sr = fread(data, sz, 1, call_sock);
715   if (sr != 1) {
716     if (was_eof(call_sock)) return -1;
717     diee("read() on monitor call socket (%zd)", sz);
718   }
719   return 0;
720 }
721
722 static void protocol_read(void *data, size_t sz) {
723   if (protocol_read_maybe(data, sz) < 0)
724     die("monitor process quit unexpectedly");
725 }
726
727 // Returns 0 if OK, error msg if peer was garbage.
728 static const char *read_greeting(void) {
729   char got_magic[sizeof(header_magic)];
730
731   if (protocol_read_maybe(&got_magic, sizeof(got_magic)) < 0)
732     return "initial monitor process quit";
733
734   if (memcmp(got_magic, header_magic, sizeof(header_magic)))
735     die("got unexpected protocol magic 0x%02x%02x%02x%02x",
736         got_magic[0], got_magic[1], got_magic[2], got_magic[3]);
737
738   uint32_t xdata_len;
739   protocol_read(&xdata_len, sizeof(xdata_len));
740   void *xdata = xmalloc(xdata_len);
741   protocol_read(xdata, xdata_len);
742
743   return 0;
744 }
745
746 // Returns: call(client-end), or 0 to mean "is garbage"
747 // find_socket_path must have been called
748 static FILE *connect_existing(void) {
749   int r;
750   int fd = -1;
751
752   if (mode != MODE_NORMAL) return 0;
753
754   fd = socket(AF_UNIX, SOCK_STREAM, 0);
755   if (fd==-1) diee("socket() for client");
756
757   socklen_t salen = sizeof(sockaddr_sun);
758   r = connect(fd, (const struct sockaddr*)&sockaddr_sun, salen);
759   if (r==-1) {
760     if (errno==ECONNREFUSED || errno==ENOENT) goto x_garbage;
761     diee("connect() %s", socket_path);
762   }
763
764   call_sock = call_sock_from_fd(fd);
765   fd = -1;
766
767   if (read_greeting())
768     goto x_garbage;
769
770   return call_sock;
771
772  x_garbage:
773   if (call_sock) { fclose(call_sock); call_sock=0; }
774   if (fd >= 0) close(fd);
775   return 0;
776 }
777
778 static void watcher_cb_stdin(uv_poll_t *handle, int status, int events) {
779   char c;
780   int r;
781
782   if ((errno = -status)) diee("watcher: poll stdin");
783   for (;;) {
784     r= read(0, &c, 1);
785     if (r!=-1) _exit(0);
786     if (!(errno==EINTR || errno==EWOULDBLOCK || errno==EAGAIN))
787       diee("watcher: read sentinel stdin");
788   }
789 }
790
791 static void watcher_cb_sockpath(uv_fs_event_t *handle, const char *filename,
792                                 int events, int status) {
793   int r;
794   struct stat now_stab;
795
796   if ((errno = -status)) diee("watcher: poll stdin");
797   for (;;) {
798     r= stat(socket_path, &now_stab);
799     if (r==-1) {
800       if (errno==ENOENT) _exit(0);
801       if (errno==EINTR) continue;
802       diee("stat socket: %s", socket_path);
803     }
804     if (!stabs_same_inode(&now_stab, &initial_stab))
805       _exit(0);
806   }
807 }
808
809 // On entry, stderr is still inherited, but 0 and 1 are the pipes
810 static __attribute__((noreturn))
811 void become_watcher(void) {
812   uv_loop_t loop;
813   uv_poll_t uvhandle_stdin;
814   uv_fs_event_t uvhandle_sockpath;
815   int r;
816
817   nonblock(0);
818
819   errno= -uv_loop_init(&loop);
820   if (errno) diee("watcher: uv_loop_init");
821
822   errno= -uv_poll_init(&loop, &uvhandle_stdin, 0);
823   if (errno) diee("watcher: uv_poll_init");
824   errno= -uv_poll_start(&uvhandle_stdin,
825                         UV_READABLE | UV_WRITABLE | UV_DISCONNECT,
826                         watcher_cb_stdin);
827   if (errno) diee("watcher: uv_poll_start");
828
829   errno= -uv_fs_event_init(&loop, &uvhandle_sockpath);
830   if (errno) diee("watcher: uv_fs_event_init");
831
832   errno= -uv_fs_event_start(&uvhandle_sockpath, watcher_cb_sockpath,
833                             socket_path, 0);
834   if (errno) diee("watcher: uv_fs_event_start");
835
836   // OK everything is set up, let us daemonise
837   if (dup2(1,2) != 2) diee("watcher: set daemonised stderr");
838   r= setvbuf(stderr, 0, _IOLBF, BUFSIZ);
839   if (r) diee("watcher: setvbuf stderr");
840
841   pid_t child = fork();
842   if (child == (pid_t)-1) diee("watcher: fork");
843   if (child) _exit(0);
844
845   if (setsid() == (pid_t)-1) diee("watcher: setsid");
846
847   r= uv_run(&loop, UV_RUN_DEFAULT);
848   die("uv_run returned (%d)", r);
849 }
850
851 static __attribute__((noreturn))
852 void become_setup(int sfd, int lockfd, int fake_pair[2],
853                   int watcher_stdin, int watcher_stderr) {
854   close(lockfd);
855   close(fake_pair[0]);
856   int call_fd = fake_pair[1];
857
858   int null_0 = open("/dev/null", O_RDONLY);  if (null_0 < 0) diee("open null");
859   if (dup2(null_0, 0)) diee("dup2 /dev/null onto stdin");
860   close(null_0);
861   if (dup2(2, 1) != 1) die("dup2 stderr onto stdout");
862
863   nonblock(sfd);
864
865   // Extension could work like this:
866   //
867   // We could advertise a new protocol (perhaps one which is nearly entirely
868   // different after the connect) by putting a name for it comma-separated
869   // next to "v1".  Simple extension can be done by having the script
870   // side say something about it in the ack xdata, which we currently ignore.
871   // Or we could add other extra data after v1.
872   putenv(m_asprintf("PREFORK_INTERP=v1,%jd.%09ld %d,%d,%d,%d",
873                     (intmax_t)initial_stab.st_mtim.tv_sec,
874                     (long)initial_stab.st_mtim.tv_nsec,
875                     sfd, call_fd, watcher_stdin, watcher_stderr));
876
877   execvp(executor_argv[0], (char**)executor_argv);
878   diee("execute %s", executor_argv[0]);
879 }
880
881 static void connect_or_spawn(void) {
882   int r;
883
884   call_sock = connect_existing();
885   if (call_sock) return;
886
887   // We're going to make a new one, so clean out old ones
888   preclean();
889
890   int lockfd = acquire_lock();
891
892   if (mode == MODE_KILL) {
893     r= unlink(socket_path);
894     if (r && errno != ENOENT) diee("remove socket %s", socket_path);
895
896     r= unlink(lock_path);
897     if (r) diee("rmeove lock %s", lock_path);
898     _exit(0);
899   }
900
901   call_sock = connect_existing();
902   if (call_sock) { close(lockfd); return; }
903
904   // We must start a fresh one, and we hold the lock
905
906   r = unlink(socket_path);
907   if (r<0 && errno!=ENOENT)
908     diee("failed to remove stale socket %s", socket_path);
909
910   int sfd = socket(AF_UNIX, SOCK_STREAM, 0);
911   if (sfd<0) diee("socket() for new listener");
912
913   socklen_t salen = sizeof(sockaddr_sun);
914   r= bind(sfd, (const struct sockaddr*)&sockaddr_sun, salen);
915   if (r<0) diee("bind() on new listener");
916
917   r= stat(socket_path, &initial_stab);
918   if (r<0) diee("stat() fresh socket");
919
920   // We never want callers to get ECONNREFUSED.  But:
921   // There is a race here: from my RTFM they may get ECONNREFUSED
922   // if they try between our bind() and listen().  But if they do, they'll
923   // acquire the lock (serialising with us) and retry, and then it will work.
924   r = listen(sfd, INT_MAX);
925   if (r<0) diee("listen() for new listener");
926
927   // Fork watcher
928
929   int watcher_stdin[2];
930   int watcher_stderr[2];
931   if (pipe(watcher_stdin) || pipe(watcher_stderr))
932     diee("pipe() for socket inode watcher");
933
934   pid_t watcher = fork();
935   if (watcher == (pid_t)-1) diee("fork for watcher");
936   if (!watcher) {
937     close(sfd);
938     close(lockfd);
939     close(watcher_stdin[1]);
940     close(watcher_stderr[0]);
941     if (dup2(watcher_stdin[0], 0) != 0 ||
942         dup2(watcher_stderr[1], 1) != 1)
943       diee("initial dup2() for watcher");
944     close(watcher_stdin[0]);
945     close(watcher_stderr[1]);
946     become_watcher();
947   }
948
949   close(watcher_stdin[0]);
950   close(watcher_stderr[1]);
951   nonblock(watcher_stderr[0]);
952
953   // Fork setup
954
955   int fake_pair[2];
956   r = socketpair(AF_UNIX, SOCK_STREAM, 0, fake_pair);
957   if (r<0) diee("socketpair() for fake initial connection");
958
959   pid_t setup_pid = fork();
960   if (setup_pid == (pid_t)-1) diee("fork for spawn setup");
961   if (!setup_pid) become_setup(sfd, lockfd, fake_pair,
962                                watcher_stdin[1], watcher_stderr[0]);
963   close(fake_pair[1]);
964   close(sfd);
965
966   call_sock = call_sock_from_fd(fake_pair[0]);
967
968   int status;
969   pid_t got = waitpid(setup_pid, &status, 0);
970   if (got == (pid_t)-1) diee("waitpid setup [%ld]", (long)setup_pid);
971   if (got != setup_pid) diee("waitpid setup [%ld] gave [%ld]!",
972                              (long)setup_pid, (long)got);
973   if (status != 0) propagate_exit_status(status, "setup");
974
975   const char *emsg = read_greeting();
976   if (emsg) die("setup failed: %s", emsg);
977
978   close(lockfd);
979   return;
980 }
981
982 static void make_executor_argv(const char *const *argv) {
983   switch (mediation) {
984   case MEDIATION_UNLAUNDERED: break;
985   default: die("need -U (specifying unlaundered argument handling)");
986   }
987
988   const char *arg;
989   #define EACH_NEW_ARG(EACH) {                  \
990     arg = interp; { EACH }                      \
991     if ((arg = script)) { EACH }                \
992     const char *const *walk = argv;             \
993     while ((arg = *walk++)) { EACH }            \
994   }
995
996   size_t count = 1;
997   EACH_NEW_ARG( (void)arg; count++; );
998
999   const char **out = calloc(count, sizeof(char*));
1000   executor_argv = (const char* const*)out;
1001   if (!executor_argv) diee("allocate for arguments");
1002
1003   EACH_NEW_ARG( *out++ = arg; );
1004   *out++ = 0;
1005 }
1006
1007 int main(int argc_unused, const char *const *argv) {
1008   process_opts(&argv);
1009
1010   // Now we have
1011   //  - possibly interp
1012   //  - possibly script
1013   //  - remaining args
1014   // which ought to be passed on to the actual executor.
1015   make_executor_argv(argv);
1016
1017   find_socket_path();
1018   FILLZERO(sockaddr_sun);
1019   sockaddr_sun.sun_family = AF_UNIX;
1020   assert(strlen(socket_path) <= sizeof(sockaddr_sun.sun_path));
1021   strncpy(sockaddr_sun.sun_path, socket_path, sizeof(sockaddr_sun.sun_path));
1022
1023   connect_or_spawn();
1024
1025   // We're committed now, send the request (or bail out)
1026   send_request();
1027
1028   uint32_t status;
1029   protocol_read(&status, sizeof(status));
1030
1031   status = ntohl(status);
1032   if (status > INT_MAX) die("status 0x%lx does not fit in an int",
1033                             (unsigned long)status);
1034
1035   propagate_exit_status(status, "invocation");
1036 }