/*
 * "Interpreter" that you can put in #! like this
 *   #!/usr/bin/cgi-fcgi-interp [<options>] <interpreter>
 *
 * Usages:
 *   cgi-fcgi-interp  [<option> ..] <interpreter>  <script> [<ignored> ...]
 *   cgi-fcgi-interp  [<option>,..],<interpreter>  <script> [<ignored> ...]
 *   cgi-fcgi-interp '[<option> ..] <interpreter>' <script> [<ignored> ...]
 */
/*
 * cgi-fcgi-interp.[ch] - Convenience wrapper for cgi-fcgi
 *
 * Copyright 2016 Ian Jackson
 * Copyright 1982,1986,1993 The Regents of the University of California
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this file; if not, consult the Free Software
 * Foundation's website at www.fsf.org, or the GNU Project website at
 * www.gnu.org.
 *
 * See below for a BSD 3-clause notice regarding timespeccmp.
 */
/*
 * The result is a program which looks, when executed via the #!
 * line, like a CGI program.  But the script inside will be executed
 * via <interpreter> in an fcgi context.
 *
 * Options:
 *
 *  <interpreter>
 *          The real interpreter to use.  Eg "perl".  Need not
 *          be an absolute path; will be fed to execvp.
 *
 *  -G<ident-info>
 *          Add <ident-info> to the unique identifying information for
 *          this fcgi program.  May be repeated; order is significant.
 *
 *  -E<ident-info-env-var>
 *          Look <ident-info-env-var> up in the environment and add
 *          <ident-info-env-var>=<value> as if specified with -G.  If
 *          the variable is unset in the environment, it is as if
 *          -G<ident-info-env-var> was specified.
 *
 *  -g<ident>
 *          Use <ident> rather than hex(sha256(<interp>\0<script>\0))
 *          as the basename of the leafname of the fcgi rendezvous
 *          socket.  If <ident> contains only hex digit characters it
 *          ought to be no more than 32 characters.  <ident> should
 *          not contain spaces or commas (see below).
 *
 *  -M<numservers>
 *         Start <numservers> instances of the program.  This
 *         determines the maximum concurrency.  (Note that unlike
 *         speedy, the specified number of servers is started
 *         right away.)  The default is 4.
 *
 *  -c<interval>
 *         Stale server check interval, in seconds.  The worker
 *         process group will get a SIGTERM when it is no longer
 *         needed to process new requests.  Ideally it would continue
 *         to serve any existing requests.  The SIGTERM will arrive no
 *         earlier than <interval> after the last request arrived at
 *         the containing webserver.  Default is 300.
 *
 *  -D
 *         Debug mode.  Do not actually run program.  Instead, print
 *         out what we would do.
 *
 * <options> and <interpreter> can be put into a single argument
 * to cgi-fcgi-interp, separated by spaces or commas.  <interpreter>
 * must come last.
 *
 * cgi-fcgi-interp automatically expires old sockets, including
 * ones where the named script is out of date.
 */
/*
 * Uses one of two directories
 *   /var/run/user/<UID>/cgi-fcgi-interp/
 *   ~/.cgi-fcgi-interp/<node>/
 * and inside there uses these paths
 *   s<ident>
 *   l<ident>    used to lock around garbage collection
 *
 * If -M<ident> is not specified then an initial substring of the
 * lowercase hex of the sha256 of <interp>\0<script>\0 is
 * used.  The substring is chosen so that the whole path is 10 bytes
 * shorter than sizeof(sun_path).  But always at least 33 characters.
 *
 * <node> is truncated at the first `.' and after the first 32
 * characters.
 *
 * Algorithm:
 *  - see if /var/run/user exists
 *       if so, lstat /var/run/user/<UID> and check that
 *         we own it and it's X700; if not, fail
 *         if it's ok then <base> is /var/run/user/<UID>
 *       otherwise, look for and maybe create ~/.cgi-fcgi-interp
 *         (where ~ is HOME or from getpwuid)
 *         and then <base> is ~/.cgi-fcgi-interp/<node>
 *  - calculate pathname (checking <ident> length is OK)
 *  - check for and maybe create <base>
 *  - stat and lstat the <script>
 *  - stat the socket and check its timestamp
 *       if it is too old, unlink it
 *  - dup stderr, mark no cloexec
 *  - set CHIARKUTILS_CGIFCGIINTERP_STAGE2=<stderr-copy-fd>
 *  - run     cgi-fcgi -connect SOCKET <script>
 *
 * When CHIARKUTILS_CGIFCGIINTERP_STAGE2 is set, --stage2 does this:
 *  - dup2 <was-stderr> to fd 2
 *  - open /dev/null and expect fd 1 (and if not, close it)
 *  - become a new process group
 *  - lstat <socket> to find its inum, mtime
 *  - fork/exec <interp> <script>
 *  - periodically lstat <interp> and <script> and
 *      if mtime is newer than our start time
 *      kill process group (at second iteration)
 */
