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