home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 4 / FreshFish_May-June1994.bin / bsd / src / make / make-amiga / job.c < prev    next >
C/C++ Source or Header  |  1993-09-23  |  76KB  |  2,637 lines

  1. /*
  2.  * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
  3.  * Copyright (c) 1988, 1989 by Adam de Boor
  4.  * Copyright (c) 1989 by Berkeley Softworks
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Adam de Boor.
  9.  *
  10.  * Redistribution and use in source and binary forms, with or without
  11.  * modification, are permitted provided that the following conditions
  12.  * are met:
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer.
  15.  * 2. Redistributions in binary form must reproduce the above copyright
  16.  *    notice, this list of conditions and the following disclaimer in the
  17.  *    documentation and/or other materials provided with the distribution.
  18.  * 3. All advertising materials mentioning features or use of this software
  19.  *    must display the following acknowledgement:
  20.  *    This product includes software developed by the University of
  21.  *    California, Berkeley and its contributors.
  22.  * 4. Neither the name of the University nor the names of its contributors
  23.  *    may be used to endorse or promote products derived from this software
  24.  *    without specific prior written permission.
  25.  *
  26.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  27.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  30.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  31.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  32.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  33.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  34.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  35.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  36.  * SUCH DAMAGE.
  37.  */
  38.  
  39. #ifndef lint
  40. static char sccsid[] = "@(#)job.c    5.15 (Berkeley) 3/1/91";
  41. #endif /* not lint */
  42.  
  43. /*-
  44.  * job.c --
  45.  *    handle the creation etc. of our child processes.
  46.  *
  47.  * Interface:
  48.  *    Job_Make              Start the creation of the given target.
  49.  *
  50.  *    Job_CatchChildren       Check for and handle the termination of any
  51.  *                          children. This must be called reasonably
  52.  *                          frequently to keep the whole make going at
  53.  *                          a decent clip, since job table entries aren't
  54.  *                          removed until their process is caught this way.
  55.  *                          Its single argument is TRUE if the function
  56.  *                          should block waiting for a child to terminate.
  57.  *
  58.  *    Job_CatchOutput            Print any output our children have produced.
  59.  *                          Should also be called fairly frequently to
  60.  *                          keep the user informed of what's going on.
  61.  *                          If no output is waiting, it will block for
  62.  *                          a time given by the SEL_* constants, below,
  63.  *                          or until output is ready.
  64.  *
  65.  *    Job_Init              Called to intialize this module. in addition,
  66.  *                          any commands attached to the .BEGIN target
  67.  *                          are executed before this function returns.
  68.  *                          Hence, the makefile must have been parsed
  69.  *                          before this function is called.
  70.  *
  71.  *    Job_Full              Return TRUE if the job table is filled.
  72.  *
  73.  *    Job_Empty             Return TRUE if the job table is completely
  74.  *                          empty.
  75.  *
  76.  *    Job_ParseShell            Given the line following a .SHELL target, parse
  77.  *                          the line as a shell specification. Returns
  78.  *                          FAILURE if the spec was incorrect.
  79.  *
  80.  *    Job_End                  Perform any final processing which needs doing.
  81.  *                          This includes the execution of any commands
  82.  *                          which have been/were attached to the .END
  83.  *                          target. It should only be called when the
  84.  *                          job table is empty.
  85.  *
  86.  *    Job_AbortAll            Abort all currently running jobs. It doesn't
  87.  *                          handle output or do anything for the jobs,
  88.  *                          just kills them. It should only be called in
  89.  *                          an emergency, as it were.
  90.  *
  91.  *    Job_CheckCommands       Verify that the commands for a target are
  92.  *                          ok. Provide them if necessary and possible.
  93.  *
  94.  *    Job_Touch             Update a target without really updating it.
  95.  *
  96.  *    Job_Wait              Wait for all currently-running jobs to finish.
  97.  */
  98.  
  99. #include "make.h"
  100. #include <sys/signal.h>
  101. #include <sys/stat.h>
  102. #include <sys/file.h>
  103. #include <sys/time.h>
  104. #include <sys/wait.h>
  105. #include <fcntl.h>
  106. #include <errno.h>
  107. #include <stdio.h>
  108. #include <string.h>
  109. #include "job.h"
  110. #include "pathnames.h"
  111.  
  112. extern int  errno;
  113.  
  114. /*
  115.  * error handling variables 
  116.  */
  117. int             errors = 0;        /* number of errors reported */
  118. int              aborting = 0;        /* why is the make aborting? */
  119. #define ABORT_ERROR    1           /* Because of an error */
  120. #define ABORT_INTERRUPT    2           /* Because it was interrupted */
  121. #define ABORT_WAIT    3           /* Waiting for jobs to finish */
  122.  
  123.  
  124. /*
  125.  * post-make command processing. The node postCommands is really just the
  126.  * .END target but we keep it around to avoid having to search for it
  127.  * all the time.
  128.  */
  129. static GNode         *postCommands;    /* node containing commands to execute when
  130.                      * everything else is done */
  131. static int           numCommands;         /* The number of commands actually printed
  132.                      * for a target. Should this number be
  133.                      * 0, no shell will be executed. */
  134.  
  135.  
  136. /*
  137.  * Return values from JobStart.
  138.  */
  139. #define JOB_RUNNING    0       /* Job is running */
  140. #define JOB_ERROR     1       /* Error in starting the job */
  141. #define JOB_FINISHED    2       /* The job is already finished */
  142. #define JOB_STOPPED    3       /* The job is stopped */
  143.  
  144. /*
  145.  * tfile is the name of a file into which all shell commands are put. It is
  146.  * used over by removing it before the child shell is executed. The XXXXX in
  147.  * the string are replaced by the pid of the make process in a 5-character
  148.  * field with leading zeroes. 
  149.  */
  150. static char     tfile[] = TMPPAT;
  151.  
  152.  
  153. /*
  154.  * Descriptions for various shells.
  155.  */
  156. static Shell    shells[] = {
  157.     /*
  158.      * CSH description. The csh can do echo control by playing
  159.      * with the setting of the 'echo' shell variable. Sadly,
  160.      * however, it is unable to do error control nicely.
  161.      */
  162. {
  163.     "csh",
  164.     TRUE, "unset verbose", "set verbose", "unset verbose", 10,
  165.     FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"",
  166.     "v", "e",
  167. },
  168.     /*
  169.      * SH description. Echo control is also possible and, under
  170.      * sun UNIX anyway, one can even control error checking.
  171.      */
  172. {
  173.     "sh",
  174.     TRUE, "set -", "set -v", "set -", 5,
  175.     FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n",
  176.     "v", "e",
  177. },
  178.     /*
  179.      * UNKNOWN.
  180.      */
  181. {
  182.     (char *)0,
  183.     FALSE, (char *)0, (char *)0, (char *)0, 0,
  184.     FALSE, (char *)0, (char *)0,
  185.     (char *)0, (char *)0,
  186. }
  187. };
  188. Shell           *commandShell = &shells[DEFSHELL]; /* this is the shell to
  189.                            * which we pass all
  190.                            * commands in the Makefile.
  191.                            * It is set by the
  192.                            * Job_ParseShell function */
  193. char            *shellPath = (char *) NULL,      /* full pathname of
  194.                            * executable image */
  195.                    *shellName;                          /* last component of shell */
  196.  
  197.  
  198. static int      maxJobs;        /* The most children we can run at once */
  199. static int      maxLocal;        /* The most local ones we can have */
  200. int              nJobs;            /* The number of children currently running */
  201. int              nLocal;        /* The number of local children */
  202. Lst              jobs;        /* The structures that describe them */
  203. Boolean            jobFull;        /* Flag to tell when the job table is full. It
  204.                  * is set TRUE when (1) the total number of
  205.                  * running jobs equals the maximum allowed or
  206.                  * (2) a job can only be run locally, but
  207.                  * nLocal equals maxLocal */
  208. #ifndef RMT_WILL_WATCH
  209. static fd_set      outputs;        /* Set of descriptors of pipes connected to
  210.                  * the output channels of children */
  211. #endif
  212.  
  213. GNode             *lastNode;    /* The node for which output was most recently
  214.                  * produced. */
  215. char             *targFmt;       /* Format string to use to head output from a
  216.                  * job when it's not the most-recent job heard
  217.                  * from */
  218. #define TARG_FMT  "--- %s ---\n" /* Default format */
  219.  
  220. /*
  221.  * When JobStart attempts to run a job remotely but can't, and isn't allowed
  222.  * to run the job locally, or when Job_CatchChildren detects a job that has
  223.  * been migrated home, the job is placed on the stoppedJobs queue to be run
  224.  * when the next job finishes. 
  225.  */
  226. Lst          stoppedJobs;    /* Lst of Job structures describing
  227.                  * jobs that were stopped due to concurrency
  228.                  * limits or migration home */
  229.  
  230.  
  231. # if defined(USE_PGRP)
  232. #define KILL(pid,sig)    killpg((pid),(sig))
  233. # else
  234. #define KILL(pid,sig)    kill((pid),(sig))
  235. # endif
  236.  
  237. static void JobRestart();
  238. static int  JobStart();
  239. static void JobInterrupt();
  240.  
  241. /*-
  242.  *-----------------------------------------------------------------------
  243.  * JobCondPassSig --
  244.  *    Pass a signal to a job if the job is remote or if USE_PGRP
  245.  *    is defined.
  246.  *
  247.  * Results:
  248.  *    === 0
  249.  *
  250.  * Side Effects:
  251.  *    None, except the job may bite it.
  252.  *
  253.  *-----------------------------------------------------------------------
  254.  */
  255. static int
  256. JobCondPassSig(job, signo)
  257.     Job            *job;        /* Job to biff */
  258.     int            signo;        /* Signal to send it */
  259. {
  260. #ifdef RMT_WANTS_SIGNALS
  261.     if (job->flags & JOB_REMOTE) {
  262.     (void)Rmt_Signal(job, signo);
  263.     } else {
  264.     KILL(job->pid, signo);
  265.     }
  266. #else
  267.     /*
  268.      * Assume that sending the signal to job->pid will signal any remote
  269.      * job as well.
  270.      */
  271.     KILL(job->pid, signo);
  272. #endif
  273.     return(0);
  274. }
  275.  
  276. /*-
  277.  *-----------------------------------------------------------------------
  278.  * JobPassSig --
  279.  *    Pass a signal on to all remote jobs and to all local jobs if
  280.  *    USE_PGRP is defined, then die ourselves.
  281.  *
  282.  * Results:
  283.  *    None.
  284.  *
  285.  * Side Effects:
  286.  *    We die by the same signal.
  287.  *    
  288.  *-----------------------------------------------------------------------
  289.  */
  290. static void
  291. JobPassSig(signo)
  292.     int        signo;    /* The signal number we've received */
  293. {
  294.     int        mask;
  295.     
  296.     Lst_ForEach(jobs, JobCondPassSig, (ClientData)signo);
  297.  
  298.     /*
  299.      * Deal with proper cleanup based on the signal received. We only run
  300.      * the .INTERRUPT target if the signal was in fact an interrupt. The other
  301.      * three termination signals are more of a "get out *now*" command.
  302.      */
  303.     if (signo == SIGINT) {
  304.     JobInterrupt(TRUE);
  305.     } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) {
  306.     JobInterrupt(FALSE);
  307.     }
  308.     
  309.     /*
  310.      * Leave gracefully if SIGQUIT, rather than core dumping.
  311.      */
  312.     if (signo == SIGQUIT) {
  313.     Finish();
  314.     }
  315.     
  316.     /*
  317.      * Send ourselves the signal now we've given the message to everyone else.
  318.      * Note we block everything else possible while we're getting the signal.
  319.      * This ensures that all our jobs get continued when we wake up before
  320.      * we take any other signal.
  321.      */
  322.     mask = sigblock(0);
  323.     (void) sigsetmask(~0 & ~(1 << (signo-1)));
  324.     signal(signo, SIG_DFL);
  325.  
  326.     kill(getpid(), signo);
  327.  
  328.     Lst_ForEach(jobs, JobCondPassSig, (ClientData)SIGCONT);
  329.  
  330.     sigsetmask(mask);
  331.     signal(signo, JobPassSig);
  332.  
  333. }
  334.  
  335. /*-
  336.  *-----------------------------------------------------------------------
  337.  * JobCmpPid  --
  338.  *    Compare the pid of the job with the given pid and return 0 if they
  339.  *    are equal. This function is called from Job_CatchChildren via
  340.  *    Lst_Find to find the job descriptor of the finished job.
  341.  *
  342.  * Results:
  343.  *    0 if the pid's match
  344.  *
  345.  * Side Effects:
  346.  *    None
  347.  *-----------------------------------------------------------------------
  348.  */
  349. static int
  350. JobCmpPid (job, pid)
  351.     int             pid;    /* process id desired */
  352.     Job            *job;    /* job to examine */
  353. {
  354.     return (pid - job->pid);
  355. }
  356.  
  357. /*-
  358.  *-----------------------------------------------------------------------
  359.  * JobPrintCommand  --
  360.  *    Put out another command for the given job. If the command starts
  361.  *    with an @ or a - we process it specially. In the former case,
  362.  *    so long as the -s and -n flags weren't given to make, we stick
  363.  *    a shell-specific echoOff command in the script. In the latter,
  364.  *    we ignore errors for the entire job, unless the shell has error
  365.  *    control.
  366.  *    If the command is just "..." we take all future commands for this
  367.  *    job to be commands to be executed once the entire graph has been
  368.  *    made and return non-zero to signal that the end of the commands
  369.  *    was reached. These commands are later attached to the postCommands
  370.  *    node and executed by Job_End when all things are done.
  371.  *    This function is called from JobStart via Lst_ForEach.
  372.  *
  373.  * Results:
  374.  *    Always 0, unless the command was "..."
  375.  *
  376.  * Side Effects:
  377.  *    If the command begins with a '-' and the shell has no error control,
  378.  *    the JOB_IGNERR flag is set in the job descriptor.
  379.  *    If the command is "..." and we're not ignoring such things,
  380.  *    tailCmds is set to the successor node of the cmd.
  381.  *    numCommands is incremented if the command is actually printed.
  382.  *-----------------------------------------------------------------------
  383.  */
  384. static int
  385. JobPrintCommand (cmd, job)
  386.     char           *cmd;                /* command string to print */
  387.     Job           *job;                /* job for which to print it */
  388. {
  389.     Boolean      noSpecials;        /* true if we shouldn't worry about
  390.                      * inserting special commands into
  391.                      * the input stream. */
  392.     Boolean       shutUp = FALSE;   /* true if we put a no echo command
  393.                      * into the command file */
  394.     Boolean      errOff = FALSE;   /* true if we turned error checking
  395.                      * off before printing the command
  396.                      * and need to turn it back on */
  397.     char             *cmdTemplate;        /* Template to use when printing the
  398.                      * command */
  399.     char          *cmdStart;        /* Start of expanded command */
  400.     LstNode       cmdNode;          /* Node for replacing the command */
  401.  
  402.     noSpecials = (noExecute && ! (job->node->type & OP_MAKE));
  403.  
  404.     if (strcmp (cmd, "...") == 0) {
  405.     if ((job->flags & JOB_IGNDOTS) == 0) {
  406.         job->tailCmds = Lst_Succ (Lst_Member (job->node->commands,
  407.                           (ClientData)cmd));
  408.         return (1);
  409.     }
  410.     return (0);
  411.     }
  412.  
  413. #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) printf (fmt, arg); fprintf (job->cmdFILE, fmt, arg)
  414.  
  415.     numCommands += 1;
  416.  
  417.     /*
  418.      * For debugging, we replace each command with the result of expanding
  419.      * the variables in the command.
  420.      */
  421.     cmdNode = Lst_Member (job->node->commands, (ClientData)cmd);
  422.     cmdStart = cmd = Var_Subst (cmd, job->node, FALSE);
  423.     Lst_Replace (cmdNode, (ClientData)cmdStart);
  424.  
  425.     cmdTemplate = "%s\n";
  426.  
  427.     /*
  428.      * Check for leading @' and -'s to control echoing and error checking.
  429.      */
  430.     while (*cmd == '@' || *cmd == '-') {
  431.     if (*cmd == '@') {
  432.         shutUp = TRUE;
  433.     } else {
  434.         errOff = TRUE;
  435.     }
  436.     cmd++;
  437.     }
  438.  
  439.     if (shutUp) {
  440.     if (! (job->flags & JOB_SILENT) && !noSpecials &&
  441.         commandShell->hasEchoCtl) {
  442.         DBPRINTF ("%s\n", commandShell->echoOff);
  443.     } else {
  444.         shutUp = FALSE;
  445.     }
  446.     }
  447.  
  448.     if (errOff) {
  449.     if ( ! (job->flags & JOB_IGNERR) && !noSpecials) {
  450.         if (commandShell->hasErrCtl) {
  451.         /*
  452.          * we don't want the error-control commands showing
  453.          * up either, so we turn off echoing while executing
  454.          * them. We could put another field in the shell
  455.          * structure to tell JobDoOutput to look for this
  456.          * string too, but why make it any more complex than
  457.          * it already is?
  458.          */
  459.         if (! (job->flags & JOB_SILENT) && !shutUp &&
  460.             commandShell->hasEchoCtl) {
  461.             DBPRINTF ("%s\n", commandShell->echoOff);
  462.             DBPRINTF ("%s\n", commandShell->ignErr);
  463.             DBPRINTF ("%s\n", commandShell->echoOn);
  464.         } else {
  465.             DBPRINTF ("%s\n", commandShell->ignErr);
  466.         }
  467.         } else if (commandShell->ignErr &&
  468.                (*commandShell->ignErr != '\0'))
  469.         {
  470.         /*
  471.          * The shell has no error control, so we need to be
  472.          * weird to get it to ignore any errors from the command.
  473.          * If echoing is turned on, we turn it off and use the
  474.          * errCheck template to echo the command. Leave echoing
  475.          * off so the user doesn't see the weirdness we go through
  476.          * to ignore errors. Set cmdTemplate to use the weirdness
  477.          * instead of the simple "%s\n" template.
  478.          */
  479.         if (! (job->flags & JOB_SILENT) && !shutUp &&
  480.             commandShell->hasEchoCtl) {
  481.             DBPRINTF ("%s\n", commandShell->echoOff);
  482.             DBPRINTF (commandShell->errCheck, cmd);
  483.             shutUp = TRUE;
  484.         }
  485.         cmdTemplate = commandShell->ignErr;
  486.         /*
  487.          * The error ignoration (hee hee) is already taken care
  488.          * of by the ignErr template, so pretend error checking
  489.          * is still on.
  490.          */
  491.         errOff = FALSE;
  492.         } else {
  493.         errOff = FALSE;
  494.         }
  495.     } else {
  496.         errOff = FALSE;
  497.     }
  498.     }
  499.     
  500.     DBPRINTF (cmdTemplate, cmd);
  501.     
  502.     if (errOff) {
  503.     /*
  504.      * If echoing is already off, there's no point in issuing the
  505.      * echoOff command. Otherwise we issue it and pretend it was on
  506.      * for the whole command...
  507.      */
  508.     if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
  509.         DBPRINTF ("%s\n", commandShell->echoOff);
  510.         shutUp = TRUE;
  511.     }
  512.     DBPRINTF ("%s\n", commandShell->errCheck);
  513.     }
  514.     if (shutUp) {
  515.     DBPRINTF ("%s\n", commandShell->echoOn);
  516.     }
  517.     return (0);
  518. }
  519.  
  520. /*-
  521.  *-----------------------------------------------------------------------
  522.  * JobSaveCommand --
  523.  *    Save a command to be executed when everything else is done.
  524.  *    Callback function for JobFinish...
  525.  *
  526.  * Results:
  527.  *    Always returns 0
  528.  *
  529.  * Side Effects:
  530.  *    The command is tacked onto the end of postCommands's commands list.
  531.  *
  532.  *-----------------------------------------------------------------------
  533.  */
  534. static int
  535. JobSaveCommand (cmd, gn)
  536.     char    *cmd;
  537.     GNode   *gn;
  538. {
  539.     cmd = Var_Subst (cmd, gn, FALSE);
  540.     (void)Lst_AtEnd (postCommands->commands, (ClientData)cmd);
  541.     return (0);
  542. }
  543.  
  544. /*-
  545.  *-----------------------------------------------------------------------
  546.  * JobFinish  --
  547.  *    Do final processing for the given job including updating
  548.  *    parents and starting new jobs as available/necessary. Note
  549.  *    that we pay no attention to the JOB_IGNERR flag here.
  550.  *    This is because when we're called because of a noexecute flag
  551.  *    or something, jstat.w_status is 0 and when called from
  552.  *    Job_CatchChildren, the status is zeroed if it s/b ignored.
  553.  *
  554.  * Results:
  555.  *    None
  556.  *
  557.  * Side Effects:
  558.  *    Some nodes may be put on the toBeMade queue.
  559.  *    Final commands for the job are placed on postCommands.
  560.  *
  561.  *    If we got an error and are aborting (aborting == ABORT_ERROR) and
  562.  *    the job list is now empty, we are done for the day.
  563.  *    If we recognized an error (errors !=0), we set the aborting flag
  564.  *    to ABORT_ERROR so no more jobs will be started.
  565.  *-----------------------------------------------------------------------
  566.  */
  567. /*ARGSUSED*/
  568. void
  569. JobFinish (job, status)
  570.     Job           *job;                /* job to finish */
  571.     union wait      status;           /* sub-why job went away */
  572. {
  573.     Boolean       done;
  574.  
  575.     if ((WIFEXITED(status) &&
  576.       (((status.w_retcode != 0) && !(job->flags & JOB_IGNERR)))) ||
  577.     (WIFSIGNALED(status) && (status.w_termsig != SIGCONT)))
  578.     {
  579.     /*
  580.      * If it exited non-zero and either we're doing things our
  581.      * way or we're not ignoring errors, the job is finished.
  582.      * Similarly, if the shell died because of a signal
  583.      * the job is also finished. In these
  584.      * cases, finish out the job's output before printing the exit
  585.      * status...
  586.      */
  587.     if (usePipes) {
  588. #ifdef RMT_WILL_WATCH
  589.         Rmt_Ignore(job->inPipe);
  590. #else
  591.         FD_CLR(job->inPipe, &outputs);
  592. #endif /* RMT_WILL_WATCH */
  593.         if (job->outPipe != job->inPipe) {
  594.         (void)close (job->outPipe);
  595.         }
  596.         JobDoOutput (job, TRUE);
  597.         (void)close (job->inPipe);
  598.     } else {
  599.         (void)close (job->outFd);
  600.         JobDoOutput (job, TRUE);
  601.     }
  602.  
  603.     if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
  604.         fclose(job->cmdFILE);
  605.     }
  606.     done = TRUE;
  607.     } else if (WIFEXITED(status) && status.w_retcode != 0) {
  608.     /*
  609.      * Deal with ignored errors in -B mode. We need to print a message
  610.      * telling of the ignored error as well as setting status.w_status
  611.      * to 0 so the next command gets run. To do this, we set done to be
  612.      * TRUE if in -B mode and the job exited non-zero. Note we don't
  613.      * want to close down any of the streams until we know we're at the
  614.      * end.
  615.      */
  616.     done = TRUE;
  617.     } else {
  618.     /*
  619.      * No need to close things down or anything.
  620.      */
  621.     done = FALSE;
  622.     }
  623.     
  624.     if (done ||
  625.     WIFSTOPPED(status) ||
  626.     (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) ||
  627.     DEBUG(JOB))
  628.     {
  629.     FILE      *out;
  630.     
  631.     if (!usePipes && (job->flags & JOB_IGNERR)) {
  632.         /*
  633.          * If output is going to a file and this job is ignoring
  634.          * errors, arrange to have the exit status sent to the
  635.          * output file as well.
  636.          */
  637.         out = fdopen (job->outFd, "w");
  638.     } else {
  639.         out = stdout;
  640.     }
  641.  
  642.     if (WIFEXITED(status)) {
  643.         if (status.w_retcode != 0) {
  644.         if (usePipes && job->node != lastNode) {
  645.             fprintf (out, targFmt, job->node->name);
  646.             lastNode = job->node;
  647.         }
  648.         fprintf (out, "*** Error code %d%s\n", status.w_retcode,
  649.              (job->flags & JOB_IGNERR) ? " (ignored)" : "");
  650.  
  651.         if (job->flags & JOB_IGNERR) {
  652.             status.w_status = 0;
  653.         }
  654.         } else if (DEBUG(JOB)) {
  655.         if (usePipes && job->node != lastNode) {
  656.             fprintf (out, targFmt, job->node->name);
  657.             lastNode = job->node;
  658.         }
  659.         fprintf (out, "*** Completed successfully\n");
  660.         }
  661.     } else if (WIFSTOPPED(status)) {
  662.         if (usePipes && job->node != lastNode) {
  663.         fprintf (out, targFmt, job->node->name);
  664.         lastNode = job->node;
  665.         }
  666.         if (! (job->flags & JOB_REMIGRATE)) {
  667.         fprintf (out, "*** Stopped -- signal %d\n", status.w_stopsig);
  668.         }
  669.         job->flags |= JOB_RESUME;
  670.         (void)Lst_AtEnd(stoppedJobs, (ClientData)job);
  671.         fflush(out);
  672.         return;
  673.     } else if (status.w_termsig == SIGCONT) {
  674.         /*
  675.          * If the beastie has continued, shift the Job from the stopped
  676.          * list to the running one (or re-stop it if concurrency is
  677.          * exceeded) and go and get another child.
  678.          */
  679.         if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) {
  680.         if (usePipes && job->node != lastNode) {
  681.             fprintf (out, targFmt, job->node->name);
  682.             lastNode = job->node;
  683.         }
  684.         fprintf (out, "*** Continued\n");
  685.         }
  686.         if (! (job->flags & JOB_CONTINUING)) {
  687.         JobRestart(job);
  688.         } else {
  689.         Lst_AtEnd(jobs, (ClientData)job);
  690.         nJobs += 1;
  691.         if (! (job->flags & JOB_REMOTE)) {
  692.             nLocal += 1;
  693.         }
  694.         if (nJobs == maxJobs) {
  695.             jobFull = TRUE;
  696.             if (DEBUG(JOB)) {
  697.             printf("Job queue is full.\n");
  698.             }
  699.         }
  700.         }
  701.         fflush(out);
  702.         return;
  703.     } else {
  704.         if (usePipes && job->node != lastNode) {
  705.         fprintf (out, targFmt, job->node->name);
  706.         lastNode = job->node;
  707.         }
  708.         fprintf (out, "*** Signal %d\n", status.w_termsig);
  709.     }
  710.  
  711.     fflush (out);
  712.     }
  713.  
  714.     /*
  715.      * Now handle the -B-mode stuff. If the beast still isn't finished,
  716.      * try and restart the job on the next command. If JobStart says it's
  717.      * ok, it's ok. If there's an error, this puppy is done.
  718.      */
  719.     if ((status.w_status == 0) &&
  720.     !Lst_IsAtEnd (job->node->commands))
  721.     {
  722.     switch (JobStart (job->node,
  723.               job->flags & JOB_IGNDOTS,
  724.               job))
  725.     {
  726.         case JOB_RUNNING:
  727.         done = FALSE;
  728.         break;
  729.         case JOB_ERROR:
  730.         done = TRUE;
  731.         status.w_retcode = 1;
  732.         break;
  733.         case JOB_FINISHED:
  734.         /*
  735.          * If we got back a JOB_FINISHED code, JobStart has already
  736.          * called Make_Update and freed the job descriptor. We set
  737.          * done to false here to avoid fake cycles and double frees.
  738.          * JobStart needs to do the update so we can proceed up the
  739.          * graph when given the -n flag..
  740.          */
  741.         done = FALSE;
  742.         break;
  743.     }
  744.     } else {
  745.     done = TRUE;
  746.     }
  747.         
  748.  
  749.     if (done &&
  750.     (aborting != ABORT_ERROR) &&
  751.     (aborting != ABORT_INTERRUPT) &&
  752.     (status.w_status == 0))
  753.     {
  754.     /*
  755.      * As long as we aren't aborting and the job didn't return a non-zero
  756.      * status that we shouldn't ignore, we call Make_Update to update
  757.      * the parents. In addition, any saved commands for the node are placed
  758.      * on the .END target.
  759.      */
  760.     if (job->tailCmds != NILLNODE) {
  761.         Lst_ForEachFrom (job->node->commands, job->tailCmds,
  762.                  JobSaveCommand,
  763.                  (ClientData)job->node);
  764.     }
  765.     job->node->made = MADE;
  766.     Make_Update (job->node);
  767.     free((Address)job);
  768.     } else if (status.w_status) {
  769.     errors += 1;
  770.     free((Address)job);
  771.     }
  772.  
  773.     while (!errors && !jobFull && !Lst_IsEmpty(stoppedJobs)) {
  774.     JobRestart((Job *)Lst_DeQueue(stoppedJobs));
  775.     }
  776.  
  777.     /*
  778.      * Set aborting if any error.
  779.      */
  780.     if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) {
  781.     /*
  782.      * If we found any errors in this batch of children and the -k flag
  783.      * wasn't given, we set the aborting flag so no more jobs get
  784.      * started.
  785.      */
  786.     aborting = ABORT_ERROR;
  787.     }
  788.     
  789.     if ((aborting == ABORT_ERROR) && Job_Empty()) {
  790.     /*
  791.      * If we are aborting and the job table is now empty, we finish.
  792.      */
  793.     (void) unlink (tfile);
  794.     Finish (errors);
  795.     }
  796. }
  797.  
  798. /*-
  799.  *-----------------------------------------------------------------------
  800.  * Job_Touch --
  801.  *    Touch the given target. Called by JobStart when the -t flag was
  802.  *    given
  803.  *
  804.  * Results:
  805.  *    None
  806.  *
  807.  * Side Effects:
  808.  *    The data modification of the file is changed. In addition, if the
  809.  *    file did not exist, it is created.
  810.  *-----------------------------------------------------------------------
  811.  */
  812. void
  813. Job_Touch (gn, silent)
  814.     GNode         *gn;              /* the node of the file to touch */
  815.     Boolean       silent;       /* TRUE if should not print messages */
  816. {
  817.     int          streamID;       /* ID of stream opened to do the touch */
  818.     struct timeval times[2];    /* Times for utimes() call */
  819.     struct stat attr;        /* Attributes of the file */
  820.  
  821.     if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
  822.     /*
  823.      * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
  824.      * and, as such, shouldn't really be created.
  825.      */
  826.     return;
  827.     }
  828.     
  829.     if (!silent) {
  830.     printf ("touch %s\n", gn->name);
  831.     }
  832.  
  833.     if (noExecute) {
  834.     return;
  835.     }
  836.  
  837.     if (gn->type & OP_ARCHV) {
  838.     Arch_Touch (gn);
  839.     } else if (gn->type & OP_LIB) {
  840.     Arch_TouchLib (gn);
  841.     } else {
  842.     char    *file = gn->path ? gn->path : gn->name;
  843.  
  844.     times[0].tv_sec = times[1].tv_sec = now;
  845.     times[0].tv_usec = times[1].tv_usec = 0;
  846.     if (utimes(file, times) < 0){
  847.         streamID = open (file, O_RDWR | O_CREAT, 0666);
  848.  
  849.         if (streamID >= 0) {
  850.         char    c;
  851.  
  852.         /*
  853.          * Read and write a byte to the file to change the
  854.          * modification time, then close the file.
  855.          */
  856.         if (read(streamID, &c, 1) == 1) {
  857.             lseek(streamID, 0L, L_SET);
  858.             write(streamID, &c, 1);
  859.         }
  860.         
  861.         (void)close (streamID);
  862.         } else
  863.         printf("*** couldn't touch %s: %s", file, strerror(errno));
  864.     }
  865.     }
  866. }
  867.  
  868. /*-
  869.  *-----------------------------------------------------------------------
  870.  * Job_CheckCommands --
  871.  *    Make sure the given node has all the commands it needs. 
  872.  *
  873.  * Results:
  874.  *    TRUE if the commands list is/was ok.
  875.  *
  876.  * Side Effects:
  877.  *    The node will have commands from the .DEFAULT rule added to it
  878.  *    if it needs them.
  879.  *-----------------------------------------------------------------------
  880.  */
  881. Boolean
  882. Job_CheckCommands (gn, abortProc)
  883.     GNode          *gn;                /* The target whose commands need
  884.                      * verifying */
  885.     void          (*abortProc)();   /* Function to abort with message */
  886. {
  887.     if (OP_NOP(gn->type) && Lst_IsEmpty (gn->commands) &&
  888.     (gn->type & OP_LIB) == 0) {
  889.     /*
  890.      * No commands. Look for .DEFAULT rule from which we might infer
  891.      * commands 
  892.      */
  893.     if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) {
  894.         /*
  895.          * Make only looks for a .DEFAULT if the node was never the
  896.          * target of an operator, so that's what we do too. If
  897.          * a .DEFAULT was given, we substitute its commands for gn's
  898.          * commands and set the IMPSRC variable to be the target's name
  899.          * The DEFAULT node acts like a transformation rule, in that
  900.          * gn also inherits any attributes or sources attached to
  901.          * .DEFAULT itself.
  902.          */
  903.         Make_HandleUse(DEFAULT, gn);
  904.         Var_Set (IMPSRC, Var_Value (TARGET, gn), gn);
  905.     } else if (Dir_MTime (gn) == 0) {
  906.         /*
  907.          * The node wasn't the target of an operator we have no .DEFAULT
  908.          * rule to go on and the target doesn't already exist. There's
  909.          * nothing more we can do for this branch. If the -k flag wasn't
  910.          * given, we stop in our tracks, otherwise we just don't update
  911.          * this node's parents so they never get examined. 
  912.          */
  913.         if (gn->type & OP_OPTIONAL) {
  914.         printf ("make: don't know how to make %s (ignored)\n",
  915.             gn->name);
  916.         } else if (keepgoing) {
  917.         printf ("make: don't know how to make %s (continuing)\n",
  918.             gn->name);
  919.         return (FALSE);
  920.         } else {
  921.         (*abortProc) ("make: don't know how to make %s. Stop",
  922.                  gn->name);
  923.         return(FALSE);
  924.         }
  925.     }
  926.     }
  927.     return (TRUE);
  928. }
  929. #ifdef RMT_WILL_WATCH
  930. /*-
  931.  *-----------------------------------------------------------------------
  932.  * JobLocalInput --
  933.  *    Handle a pipe becoming readable. Callback function for Rmt_Watch
  934.  *
  935.  * Results:
  936.  *    None
  937.  *
  938.  * Side Effects:
  939.  *    JobDoOutput is called.
  940.  *    
  941.  *-----------------------------------------------------------------------
  942.  */
  943. /*ARGSUSED*/
  944. static void
  945. JobLocalInput(stream, job)
  946.     int        stream;     /* Stream that's ready (ignored) */
  947.     Job        *job;       /* Job to which the stream belongs */
  948. {
  949.     JobDoOutput(job, FALSE);
  950. }
  951. #endif /* RMT_WILL_WATCH */
  952.  
  953. /*-
  954.  *-----------------------------------------------------------------------
  955.  * JobExec --
  956.  *    Execute the shell for the given job. Called from JobStart and
  957.  *    JobRestart.
  958.  *
  959.  * Results:
  960.  *    None.
  961.  *
  962.  * Side Effects:
  963.  *    A shell is executed, outputs is altered and the Job structure added
  964.  *    to the job table.
  965.  *
  966.  *-----------------------------------------------------------------------
  967.  */
  968. static void
  969. JobExec(job, argv)
  970.     Job              *job;     /* Job to execute */
  971.     char          **argv;
  972. {
  973.     int              cpid;            /* ID of new child */
  974.     
  975.     if (DEBUG(JOB)) {
  976.     int       i;
  977.     
  978.     printf("Running %s %sly\n", job->node->name,
  979.            job->flags&JOB_REMOTE?"remote":"local");
  980.     printf("\tCommand: ");
  981.     for (i = 0; argv[i] != (char *)NULL; i++) {
  982.         printf("%s ", argv[i]);
  983.     }
  984.     printf("\n");
  985.     }
  986.     
  987.     /*
  988.      * Some jobs produce no output and it's disconcerting to have
  989.      * no feedback of their running (since they produce no output, the
  990.      * banner with their name in it never appears). This is an attempt to
  991.      * provide that feedback, even if nothing follows it.
  992.      */
  993.     if ((lastNode != job->node) && (job->flags & JOB_FIRST) &&
  994.     !(job->flags & JOB_SILENT))
  995.     {
  996.     printf(targFmt, job->node->name);
  997.     lastNode = job->node;
  998.     }
  999.     
  1000. #ifdef RMT_NO_EXEC
  1001.     if (job->flags & JOB_REMOTE) {
  1002.     goto jobExecFinish;
  1003.     }
  1004. #endif /* RMT_NO_EXEC */
  1005.  
  1006.     if ((cpid =  vfork()) == -1) {
  1007.     Punt ("Cannot fork");
  1008.     } else if (cpid == 0) {
  1009.  
  1010.     /*
  1011.      * Must duplicate the input stream down to the child's input and
  1012.      * reset it to the beginning (again). Since the stream was marked
  1013.      * close-on-exec, we must clear that bit in the new input.
  1014.      */
  1015.     (void) dup2(fileno(job->cmdFILE), 0);
  1016.     fcntl(0, F_SETFD, 0);
  1017.     lseek(0, 0, L_SET);
  1018.     
  1019.     if (usePipes) {
  1020.         /*
  1021.          * Set up the child's output to be routed through the pipe
  1022.          * we've created for it.
  1023.          */
  1024.         (void) dup2 (job->outPipe, 1);
  1025.     } else {
  1026.         /*
  1027.          * We're capturing output in a file, so we duplicate the
  1028.          * descriptor to the temporary file into the standard
  1029.          * output.
  1030.          */
  1031.         (void) dup2 (job->outFd, 1);
  1032.     }
  1033.     /*
  1034.      * The output channels are marked close on exec. This bit was
  1035.      * duplicated by the dup2 (on some systems), so we have to clear
  1036.      * it before routing the shell's error output to the same place as
  1037.      * its standard output.
  1038.      */
  1039.     fcntl(1, F_SETFD, 0);
  1040.     (void) dup2 (1, 2);
  1041.  
  1042. #ifdef USE_PGRP
  1043.     /*
  1044.      * We want to switch the child into a different process family so
  1045.      * we can kill it and all its descendants in one fell swoop,
  1046.      * by killing its process family, but not commit suicide.
  1047.      */
  1048.     
  1049.     (void) setpgrp(0, getpid());
  1050. #endif USE_PGRP
  1051.  
  1052.     (void) execv (shellPath, argv);
  1053.     (void) write (2, "Could not execute shell\n",
  1054.          sizeof ("Could not execute shell"));
  1055.     _exit (1);
  1056.     } else {
  1057.     job->pid = cpid;
  1058.  
  1059.     if (usePipes && (job->flags & JOB_FIRST) ) {
  1060.         /*
  1061.          * The first time a job is run for a node, we set the current
  1062.          * position in the buffer to the beginning and mark another
  1063.          * stream to watch in the outputs mask
  1064.          */
  1065.         job->curPos = 0;
  1066.         
  1067. #ifdef RMT_WILL_WATCH
  1068.         Rmt_Watch(job->inPipe, JobLocalInput, job);
  1069. #else
  1070.         FD_SET(job->inPipe, &outputs);
  1071. #endif /* RMT_WILL_WATCH */
  1072.     }
  1073.  
  1074.     if (job->flags & JOB_REMOTE) {
  1075.         job->rmtID = (char *)0;
  1076.     } else {
  1077.         nLocal += 1;
  1078.         /*
  1079.          * XXX: Used to not happen if CUSTOMS. Why?
  1080.          */
  1081.         if (job->cmdFILE != stdout) {
  1082.         fclose(job->cmdFILE);
  1083.         job->cmdFILE = NULL;
  1084.         }
  1085.     }
  1086.     }
  1087.  
  1088. jobExecFinish:    
  1089.     /*
  1090.      * Now the job is actually running, add it to the table.
  1091.      */
  1092.     nJobs += 1;
  1093.     (void)Lst_AtEnd (jobs, (ClientData)job);
  1094.     if (nJobs == maxJobs) {
  1095.     jobFull = TRUE;
  1096.     }
  1097. }
  1098.  
  1099. /*-
  1100.  *-----------------------------------------------------------------------
  1101.  * JobMakeArgv --
  1102.  *    Create the argv needed to execute the shell for a given job.
  1103.  *    
  1104.  *
  1105.  * Results:
  1106.  *
  1107.  * Side Effects:
  1108.  *
  1109.  *-----------------------------------------------------------------------
  1110.  */
  1111. static void
  1112. JobMakeArgv(job, argv)
  1113.     Job              *job;
  1114.     char      **argv;
  1115. {
  1116.     int              argc;
  1117.     static char      args[10];     /* For merged arguments */
  1118.     
  1119.     argv[0] = shellName;
  1120.     argc = 1;
  1121.  
  1122.     if ((commandShell->exit && (*commandShell->exit != '-')) ||
  1123.     (commandShell->echo && (*commandShell->echo != '-')))
  1124.     {
  1125.     /*
  1126.      * At least one of the flags doesn't have a minus before it, so
  1127.      * merge them together. Have to do this because the *(&(@*#*&#$#
  1128.      * Bourne shell thinks its second argument is a file to source.
  1129.      * Grrrr. Note the ten-character limitation on the combined arguments.
  1130.      */
  1131.     (void)sprintf(args, "-%s%s",
  1132.               ((job->flags & JOB_IGNERR) ? "" :
  1133.                (commandShell->exit ? commandShell->exit : "")),
  1134.               ((job->flags & JOB_SILENT) ? "" :
  1135.                (commandShell->echo ? commandShell->echo : "")));
  1136.  
  1137.     if (args[1]) {
  1138.         argv[argc] = args;
  1139.         argc++;
  1140.     }
  1141.     } else {
  1142.     if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
  1143.         argv[argc] = commandShell->exit;
  1144.         argc++;
  1145.     }
  1146.     if (!(job->flags & JOB_SILENT) && commandShell->echo) {
  1147.         argv[argc] = commandShell->echo;
  1148.         argc++;
  1149.     }
  1150.     }
  1151.     argv[argc] = (char *)NULL;
  1152. }
  1153.  
  1154. /*-
  1155.  *-----------------------------------------------------------------------
  1156.  * JobRestart --
  1157.  *    Restart a job that stopped for some reason. 
  1158.  *
  1159.  * Results:
  1160.  *    None.
  1161.  *
  1162.  * Side Effects:
  1163.  *    jobFull will be set if the job couldn't be run.
  1164.  *
  1165.  *-----------------------------------------------------------------------
  1166.  */
  1167. static void
  1168. JobRestart(job)
  1169.     Job       *job;        /* Job to restart */
  1170. {
  1171.     if (job->flags & JOB_REMIGRATE) {
  1172.     if (DEBUG(JOB)) {
  1173.         printf("Remigrating %x\n", job->pid);
  1174.     }
  1175.     if (nLocal != maxLocal) {
  1176.         /*
  1177.          * Job cannot be remigrated, but there's room on the local
  1178.          * machine, so resume the job and note that another
  1179.          * local job has started.
  1180.          */
  1181.         if (DEBUG(JOB)) {
  1182.             printf("resuming on local machine\n");
  1183.             }
  1184.         KILL(job->pid, SIGCONT);
  1185.         nLocal +=1;
  1186.         job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
  1187.     } else {
  1188.         /*
  1189.          * Job cannot be restarted. Mark the table as full and
  1190.          * place the job back on the list of stopped jobs.
  1191.          */
  1192.         if (DEBUG(JOB)) {
  1193.             printf("holding\n");
  1194.         }
  1195.         (void)Lst_AtFront(stoppedJobs, (ClientData)job);
  1196.         jobFull = TRUE;
  1197.         if (DEBUG(JOB)) {
  1198.             printf("Job queue is full.\n");
  1199.         }
  1200.         return;
  1201.     }
  1202.     
  1203.     (void)Lst_AtEnd(jobs, (ClientData)job);
  1204.     nJobs += 1;
  1205.     if (nJobs == maxJobs) {
  1206.         jobFull = TRUE;
  1207.         if (DEBUG(JOB)) {
  1208.         printf("Job queue is full.\n");
  1209.         }
  1210.     }
  1211.     } else if (job->flags & JOB_RESTART) {
  1212.     /*
  1213.      * Set up the control arguments to the shell. This is based on the
  1214.      * flags set earlier for this job. If the JOB_IGNERR flag is clear,
  1215.      * the 'exit' flag of the commandShell is used to cause it to exit
  1216.      * upon receiving an error. If the JOB_SILENT flag is clear, the
  1217.      * 'echo' flag of the commandShell is used to get it to start echoing
  1218.      * as soon as it starts processing commands. 
  1219.      */
  1220.     char      *argv[4];
  1221.     
  1222.     JobMakeArgv(job, argv);
  1223.     
  1224.     if (DEBUG(JOB)) {
  1225.         printf("Restarting %s...", job->node->name);
  1226.     }
  1227.     if (((nLocal >= maxLocal) && ! (job->flags & JOB_SPECIAL))) {
  1228.         /*
  1229.          * Can't be exported and not allowed to run locally -- put it
  1230.          * back on the hold queue and mark the table full
  1231.          */
  1232.         if (DEBUG(JOB)) {
  1233.             printf("holding\n");
  1234.         }
  1235.         (void)Lst_AtFront(stoppedJobs, (ClientData)job);
  1236.         jobFull = TRUE;
  1237.         if (DEBUG(JOB)) {
  1238.             printf("Job queue is full.\n");
  1239.         }
  1240.         return;
  1241.     } else {
  1242.         /*
  1243.          * Job may be run locally.
  1244.          */
  1245.         if (DEBUG(JOB)) {
  1246.             printf("running locally\n");
  1247.         }
  1248.         job->flags &= ~JOB_REMOTE;
  1249.     }
  1250.     JobExec(job, argv);
  1251.     } else {
  1252.     /*
  1253.      * The job has stopped and needs to be restarted. Why it stopped,
  1254.      * we don't know...
  1255.      */
  1256.     if (DEBUG(JOB)) {
  1257.         printf("Resuming %s...", job->node->name);
  1258.     }
  1259.     if (((job->flags & JOB_REMOTE) ||
  1260.          (nLocal < maxLocal) ||
  1261.          (((job->flags & JOB_SPECIAL)) &&
  1262.           (maxLocal == 0))) &&
  1263.         (nJobs != maxJobs))
  1264.     {
  1265.         /*
  1266.          * If the job is remote, it's ok to resume it as long as the
  1267.          * maximum concurrency won't be exceeded. If it's local and
  1268.          * we haven't reached the local concurrency limit already (or the
  1269.          * job must be run locally and maxLocal is 0), it's also ok to
  1270.          * resume it.
  1271.          */
  1272.         Boolean error;
  1273.         extern int errno;
  1274.         union wait status;
  1275.         
  1276. #ifdef RMT_WANTS_SIGNALS
  1277.         if (job->flags & JOB_REMOTE) {
  1278.         error = !Rmt_Signal(job, SIGCONT);
  1279.         } else
  1280. #endif    /* RMT_WANTS_SIGNALS */
  1281.         error = (KILL(job->pid, SIGCONT) != 0);
  1282.  
  1283.         if (!error) {
  1284.         /*
  1285.          * Make sure the user knows we've continued the beast and
  1286.          * actually put the thing in the job table.
  1287.          */
  1288.         job->flags |= JOB_CONTINUING;
  1289.         status.w_termsig = SIGCONT;
  1290.         JobFinish(job, status);
  1291.         
  1292.         job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
  1293.         if (DEBUG(JOB)) {
  1294.             printf("done\n");
  1295.         }
  1296.         } else {
  1297.         Error("couldn't resume %s: %s",
  1298.             job->node->name, strerror(errno));
  1299.         status.w_status = 0;
  1300.         status.w_retcode = 1;
  1301.         JobFinish(job, status);
  1302.         }
  1303.     } else {
  1304.         /*
  1305.          * Job cannot be restarted. Mark the table as full and
  1306.          * place the job back on the list of stopped jobs.
  1307.          */
  1308.         if (DEBUG(JOB)) {
  1309.         printf("table full\n");
  1310.         }
  1311.         (void)Lst_AtFront(stoppedJobs, (ClientData)job);
  1312.         jobFull = TRUE;
  1313.         if (DEBUG(JOB)) {
  1314.         printf("Job queue is full.\n");
  1315.         }
  1316.     }
  1317.     }
  1318. }
  1319.  
  1320. /*-
  1321.  *-----------------------------------------------------------------------
  1322.  * JobStart  --
  1323.  *    Start a target-creation process going for the target described
  1324.  *    by the graph node gn. 
  1325.  *
  1326.  * Results:
  1327.  *    JOB_ERROR if there was an error in the commands, JOB_FINISHED
  1328.  *    if there isn't actually anything left to do for the job and
  1329.  *    JOB_RUNNING if the job has been started.
  1330.  *
  1331.  * Side Effects:
  1332.  *    A new Job node is created and added to the list of running
  1333.  *    jobs. PMake is forked and a child shell created.
  1334.  *-----------------------------------------------------------------------
  1335.  */
  1336. static int
  1337. JobStart (gn, flags, previous)
  1338.     GNode         *gn;          /* target to create */
  1339.     short      flags;      /* flags for the job to override normal ones.
  1340.                    * e.g. JOB_SPECIAL or JOB_IGNDOTS */
  1341.     Job       *previous;  /* The previous Job structure for this node,
  1342.                    * if any. */
  1343. {
  1344.     register Job  *job;       /* new job descriptor */
  1345.     char      *argv[4];   /* Argument vector to shell */
  1346.     char          args[5];    /* arguments to shell */
  1347.     static int    jobno = 0;  /* job number of catching output in a file */
  1348.     Boolean      cmdsOK;     /* true if the nodes commands were all right */
  1349.     Boolean       local;      /* Set true if the job was run locally */
  1350.     Boolean       noExec;     /* Set true if we decide not to run the job */
  1351.  
  1352.     if (previous != (Job *)NULL) {
  1353.     previous->flags &= ~ (JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
  1354.     job = previous;
  1355.     } else {
  1356.     job = (Job *) emalloc (sizeof (Job));
  1357.     if (job == (Job *)NULL) {
  1358.         Punt("JobStart out of memory");
  1359.     }
  1360.     flags |= JOB_FIRST;
  1361.     }
  1362.  
  1363.     job->node = gn;
  1364.     job->tailCmds = NILLNODE;
  1365.  
  1366.     /*
  1367.      * Set the initial value of the flags for this job based on the global
  1368.      * ones and the node's attributes... Any flags supplied by the caller
  1369.      * are also added to the field.
  1370.      */
  1371.     job->flags = 0;
  1372.     if (Targ_Ignore (gn)) {
  1373.     job->flags |= JOB_IGNERR;
  1374.     }
  1375.     if (Targ_Silent (gn)) {
  1376.     job->flags |= JOB_SILENT;
  1377.     }
  1378.     job->flags |= flags;
  1379.  
  1380.     /*
  1381.      * Check the commands now so any attributes from .DEFAULT have a chance
  1382.      * to migrate to the node
  1383.      */
  1384.     if (job->flags & JOB_FIRST) {
  1385.     cmdsOK = Job_CheckCommands(gn, Error);
  1386.     } else {
  1387.     cmdsOK = TRUE;
  1388.     }
  1389.     
  1390.     /*
  1391.      * If the -n flag wasn't given, we open up OUR (not the child's)
  1392.      * temporary file to stuff commands in it. The thing is rd/wr so we don't
  1393.      * need to reopen it to feed it to the shell. If the -n flag *was* given,
  1394.      * we just set the file to be stdout. Cute, huh?
  1395.      */
  1396.     if ((gn->type & OP_MAKE) || (!noExecute && !touchFlag)) {
  1397.     /*
  1398.      * We're serious here, but if the commands were bogus, we're
  1399.      * also dead...
  1400.      */
  1401.     if (!cmdsOK) {
  1402.         DieHorribly();
  1403.     }
  1404.     
  1405.     job->cmdFILE = fopen (tfile, "w+");
  1406.     if (job->cmdFILE == (FILE *) NULL) {
  1407.         Punt ("Could not open %s", tfile);
  1408.     }
  1409.     fcntl(fileno(job->cmdFILE), F_SETFD, 1);
  1410.     /*
  1411.      * Send the commands to the command file, flush all its buffers then
  1412.      * rewind and remove the thing.
  1413.      */
  1414.     noExec = FALSE;
  1415.  
  1416.     /*
  1417.      * used to be backwards; replace when start doing multiple commands
  1418.      * per shell.
  1419.      */
  1420.     if (1) {
  1421.         /*
  1422.          * Be compatible: If this is the first time for this node,
  1423.          * verify its commands are ok and open the commands list for
  1424.          * sequential access by later invocations of JobStart.
  1425.          * Once that is done, we take the next command off the list
  1426.          * and print it to the command file. If the command was an
  1427.          * ellipsis, note that there's nothing more to execute.
  1428.          */
  1429.         if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){
  1430.         cmdsOK = FALSE;
  1431.         } else {
  1432.         LstNode    ln = Lst_Next (gn->commands);
  1433.             
  1434.         if ((ln == NILLNODE) ||
  1435.             JobPrintCommand ((char *)Lst_Datum (ln), job))
  1436.         {
  1437.             noExec = TRUE;
  1438.             Lst_Close (gn->commands);
  1439.         }
  1440.         if (noExec && !(job->flags & JOB_FIRST)) {
  1441.             /*
  1442.              * If we're not going to execute anything, the job
  1443.              * is done and we need to close down the various
  1444.              * file descriptors we've opened for output, then
  1445.              * call JobDoOutput to catch the final characters or
  1446.              * send the file to the screen... Note that the i/o streams
  1447.              * are only open if this isn't the first job.
  1448.              * Note also that this could not be done in
  1449.              * Job_CatchChildren b/c it wasn't clear if there were
  1450.              * more commands to execute or not...
  1451.              */
  1452.             if (usePipes) {
  1453. #ifdef RMT_WILL_WATCH
  1454.             Rmt_Ignore(job->inPipe);
  1455. #else
  1456.             FD_CLR(job->inPipe, &outputs);
  1457. #endif
  1458.             if (job->outPipe != job->inPipe) {
  1459.                 (void)close (job->outPipe);
  1460.             }
  1461.             JobDoOutput (job, TRUE);
  1462.             (void)close (job->inPipe);
  1463.             } else {
  1464.             (void)close (job->outFd);
  1465.             JobDoOutput (job, TRUE);
  1466.             }
  1467.         }
  1468.         }
  1469.     } else {
  1470.         /*
  1471.          * We can do all the commands at once. hooray for sanity
  1472.          */
  1473.         numCommands = 0;
  1474.         Lst_ForEach (gn->commands, JobPrintCommand, (ClientData)job);
  1475.         
  1476.         /*
  1477.          * If we didn't print out any commands to the shell script,
  1478.          * there's not much point in executing the shell, is there?
  1479.          */
  1480.         if (numCommands == 0) {
  1481.         noExec = TRUE;
  1482.         }
  1483.     }
  1484.     } else if (noExecute) {
  1485.     /*
  1486.      * Not executing anything -- just print all the commands to stdout
  1487.      * in one fell swoop. This will still set up job->tailCmds correctly.
  1488.      */
  1489.     if (lastNode != gn) {
  1490.         printf (targFmt, gn->name);
  1491.         lastNode = gn;
  1492.     }
  1493.     job->cmdFILE = stdout;
  1494.     /*
  1495.      * Only print the commands if they're ok, but don't die if they're
  1496.      * not -- just let the user know they're bad and keep going. It
  1497.      * doesn't do any harm in this case and may do some good.
  1498.      */
  1499.     if (cmdsOK) {
  1500.         Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
  1501.     }
  1502.     /*
  1503.      * Don't execute the shell, thank you.
  1504.      */
  1505.     noExec = TRUE;
  1506.     } else {
  1507.     /*
  1508.      * Just touch the target and note that no shell should be executed.
  1509.      * Set cmdFILE to stdout to make life easier. Check the commands, too,
  1510.      * but don't die if they're no good -- it does no harm to keep working
  1511.      * up the graph.
  1512.      */
  1513.     job->cmdFILE = stdout;
  1514.         Job_Touch (gn, job->flags&JOB_SILENT);
  1515.     noExec = TRUE;
  1516.     }
  1517.  
  1518.     /*
  1519.      * If we're not supposed to execute a shell, don't. 
  1520.      */
  1521.     if (noExec) {
  1522.     /*
  1523.      * Unlink and close the command file if we opened one
  1524.      */
  1525.     if (job->cmdFILE != stdout) {
  1526.         (void) unlink (tfile);
  1527.         fclose(job->cmdFILE);
  1528.     } else {
  1529.         fflush (stdout);
  1530.     }
  1531.  
  1532.     /*
  1533.      * We only want to work our way up the graph if we aren't here because
  1534.      * the commands for the job were no good.
  1535.      */
  1536.     if (cmdsOK) {
  1537.         if (aborting == 0) {
  1538.         if (job->tailCmds != NILLNODE) {
  1539.             Lst_ForEachFrom(job->node->commands, job->tailCmds,
  1540.                     JobSaveCommand,
  1541.                     (ClientData)job->node);
  1542.         }
  1543.         Make_Update(job->node);
  1544.         }
  1545.         free((Address)job);
  1546.         return(JOB_FINISHED);
  1547.     } else {
  1548.         free((Address)job);
  1549.         return(JOB_ERROR);
  1550.     }
  1551.     } else {
  1552.     fflush (job->cmdFILE);
  1553.     (void) unlink (tfile);
  1554.     }
  1555.  
  1556.     /*
  1557.      * Set up the control arguments to the shell. This is based on the flags
  1558.      * set earlier for this job.
  1559.      */
  1560.     JobMakeArgv(job, argv);
  1561.  
  1562.     /*
  1563.      * If we're using pipes to catch output, create the pipe by which we'll
  1564.      * get the shell's output. If we're using files, print out that we're
  1565.      * starting a job and then set up its temporary-file name. This is just
  1566.      * tfile with two extra digits tacked on -- jobno.
  1567.      */
  1568.     if (job->flags & JOB_FIRST) {
  1569.     if (usePipes) {
  1570.         int fd[2];
  1571.         (void) pipe(fd); 
  1572.         job->inPipe = fd[0];
  1573.         job->outPipe = fd[1];
  1574.         (void)fcntl (job->inPipe, F_SETFD, 1);
  1575.         (void)fcntl (job->outPipe, F_SETFD, 1);
  1576.     } else {
  1577.         printf ("Remaking `%s'\n", gn->name);
  1578.         fflush (stdout);
  1579.         sprintf (job->outFile, "%s%02d", tfile, jobno);
  1580.         jobno = (jobno + 1) % 100;
  1581.         job->outFd = open(job->outFile,O_WRONLY|O_CREAT|O_APPEND,0600);
  1582.         (void)fcntl (job->outFd, F_SETFD, 1);
  1583.     }
  1584.     }
  1585.  
  1586.     local = TRUE;
  1587.  
  1588.     if (local && (((nLocal >= maxLocal) &&
  1589.      !(job->flags & JOB_SPECIAL) &&
  1590.      (maxLocal != 0))))
  1591.     {
  1592.     /*
  1593.      * The job can only be run locally, but we've hit the limit of
  1594.      * local concurrency, so put the job on hold until some other job
  1595.      * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END)
  1596.      * may be run locally even when the local limit has been reached
  1597.      * (e.g. when maxLocal == 0), though they will be exported if at
  1598.      * all possible. 
  1599.      */
  1600.     jobFull = TRUE;
  1601.     
  1602.     if (DEBUG(JOB)) {
  1603.         printf("Can only run job locally.\n");
  1604.     }
  1605.     job->flags |= JOB_RESTART;
  1606.     (void)Lst_AtEnd(stoppedJobs, (ClientData)job);
  1607.     } else {
  1608.     if ((nLocal >= maxLocal) && local) {
  1609.         /*
  1610.          * If we're running this job locally as a special case (see above),
  1611.          * at least say the table is full.
  1612.          */
  1613.         jobFull = TRUE;
  1614.         if (DEBUG(JOB)) {
  1615.         printf("Local job queue is full.\n");
  1616.         }
  1617.     }
  1618.     JobExec(job, argv);
  1619.     }
  1620.     return(JOB_RUNNING);
  1621. }
  1622.  
  1623. /*-
  1624.  *-----------------------------------------------------------------------
  1625.  * JobDoOutput  --
  1626.  *    This function is called at different times depending on
  1627.  *    whether the user has specified that output is to be collected
  1628.  *    via pipes or temporary files. In the former case, we are called
  1629.  *    whenever there is something to read on the pipe. We collect more
  1630.  *    output from the given job and store it in the job's outBuf. If
  1631.  *    this makes up a line, we print it tagged by the job's identifier,
  1632.  *    as necessary.
  1633.  *    If output has been collected in a temporary file, we open the
  1634.  *    file and read it line by line, transfering it to our own
  1635.  *    output channel until the file is empty. At which point we
  1636.  *    remove the temporary file.
  1637.  *    In both cases, however, we keep our figurative eye out for the
  1638.  *    'noPrint' line for the shell from which the output came. If
  1639.  *    we recognize a line, we don't print it. If the command is not
  1640.  *    alone on the line (the character after it is not \0 or \n), we
  1641.  *    do print whatever follows it.
  1642.  *
  1643.  * Results:
  1644.  *    None
  1645.  *
  1646.  * Side Effects:
  1647.  *    curPos may be shifted as may the contents of outBuf.
  1648.  *-----------------------------------------------------------------------
  1649.  */
  1650. void
  1651. JobDoOutput (job, finish)
  1652.     register Job   *job;      /* the job whose output needs printing */
  1653.     Boolean       finish;      /* TRUE if this is the last time we'll be
  1654.                    * called for this job */
  1655. {
  1656.     Boolean       gotNL = FALSE;  /* true if got a newline */
  1657.     register int  nr;                /* number of bytes read */
  1658.     register int  i;                /* auxiliary index into outBuf */
  1659.     register int  max;                /* limit for i (end of current data) */
  1660.     int          nRead;            /* (Temporary) number of bytes read */
  1661.  
  1662.     char          c;          /* character after noPrint string */
  1663.     FILE            *oFILE;      /* Stream pointer to shell's output file */
  1664.     char          inLine[132];
  1665.  
  1666.     
  1667.     if (usePipes) {
  1668.     /*
  1669.      * Read as many bytes as will fit in the buffer.
  1670.      */
  1671. end_loop:
  1672.     
  1673.     nRead = read (job->inPipe, &job->outBuf[job->curPos],
  1674.              JOB_BUFSIZE - job->curPos);
  1675.     if (nRead < 0) {
  1676.         if (DEBUG(JOB)) {
  1677.         perror("JobDoOutput(piperead)");
  1678.         }
  1679.         nr = 0;
  1680.     } else {
  1681.         nr = nRead;
  1682.     }
  1683.  
  1684.     /*
  1685.      * If we hit the end-of-file (the job is dead), we must flush its
  1686.      * remaining output, so pretend we read a newline if there's any
  1687.      * output remaining in the buffer.
  1688.      * Also clear the 'finish' flag so we stop looping.
  1689.      */
  1690.     if ((nr == 0) && (job->curPos != 0)) {
  1691.         job->outBuf[job->curPos] = '\n';
  1692.         nr = 1;
  1693.         finish = FALSE;
  1694.     } else if (nr == 0) {
  1695.         finish = FALSE;
  1696.     }
  1697.     
  1698.     /*
  1699.      * Look for the last newline in the bytes we just got. If there is
  1700.      * one, break out of the loop with 'i' as its index and gotNL set
  1701.      * TRUE. 
  1702.      */
  1703.     max = job->curPos + nr;
  1704.     for (i = job->curPos + nr - 1; i >= job->curPos; i--) {
  1705.         if (job->outBuf[i] == '\n') {
  1706.         gotNL = TRUE;
  1707.         break;
  1708.         } else if (job->outBuf[i] == '\0') {
  1709.         /*
  1710.          * Why?
  1711.          */
  1712.         job->outBuf[i] = ' ';
  1713.         }
  1714.     }
  1715.     
  1716.     if (!gotNL) {
  1717.         job->curPos += nr;
  1718.         if (job->curPos == JOB_BUFSIZE) {
  1719.         /*
  1720.          * If we've run out of buffer space, we have no choice
  1721.          * but to print the stuff. sigh. 
  1722.          */
  1723.         gotNL = TRUE;
  1724.         i = job->curPos;
  1725.         }
  1726.     }
  1727.     if (gotNL) {
  1728.         /*
  1729.          * Need to send the output to the screen. Null terminate it
  1730.          * first, overwriting the newline character if there was one.
  1731.          * So long as the line isn't one we should filter (according
  1732.          * to the shell description), we print the line, preceeded
  1733.          * by a target banner if this target isn't the same as the
  1734.          * one for which we last printed something.
  1735.          * The rest of the data in the buffer are then shifted down
  1736.          * to the start of the buffer and curPos is set accordingly. 
  1737.          */
  1738.         job->outBuf[i] = '\0';
  1739.         if (i >= job->curPos) {
  1740.         register char    *cp, *ecp;
  1741.  
  1742.         cp = job->outBuf;
  1743.         if (commandShell->noPrint) {
  1744.             ecp = Str_FindSubstring(job->outBuf,
  1745.                         commandShell->noPrint);
  1746.             while (ecp != (char *)NULL) {
  1747.             if (cp != ecp) {
  1748.                 *ecp = '\0';
  1749.                 if (job->node != lastNode) {
  1750.                 printf (targFmt, job->node->name);
  1751.                 lastNode = job->node;
  1752.                 }
  1753.                 /*
  1754.                  * The only way there wouldn't be a newline after
  1755.                  * this line is if it were the last in the buffer.
  1756.                  * however, since the non-printable comes after it,
  1757.                  * there must be a newline, so we don't print one.
  1758.                  */
  1759.                 printf ("%s", cp);
  1760.             }
  1761.             cp = ecp + commandShell->noPLen;
  1762.             if (cp != &job->outBuf[i]) {
  1763.                 /*
  1764.                  * Still more to print, look again after skipping
  1765.                  * the whitespace following the non-printable
  1766.                  * command....
  1767.                  */
  1768.                 cp++;
  1769.                 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
  1770.                 cp++;
  1771.                 }
  1772.                 ecp = Str_FindSubstring (cp,
  1773.                              commandShell->noPrint);
  1774.             } else {
  1775.                 break;
  1776.             }
  1777.             }
  1778.         }
  1779.  
  1780.         /*
  1781.          * There's still more in that thar buffer. This time, though,
  1782.          * we know there's no newline at the end, so we add one of
  1783.          * our own free will.
  1784.          */
  1785.         if (*cp != '\0') {
  1786.             if (job->node != lastNode) {
  1787.             printf (targFmt, job->node->name);
  1788.             lastNode = job->node;
  1789.             }
  1790.             printf ("%s\n", cp);
  1791.         }
  1792.  
  1793.         fflush (stdout);
  1794.         }
  1795.         if (i < max - 1) {
  1796.         bcopy (&job->outBuf[i + 1], /* shift the remaining */
  1797.                job->outBuf,        /* characters down */
  1798.                max - (i + 1));
  1799.         job->curPos = max - (i + 1);
  1800.         
  1801.         } else {
  1802.         /*
  1803.          * We have written everything out, so we just start over
  1804.          * from the start of the buffer. No copying. No nothing.
  1805.          */
  1806.         job->curPos = 0;
  1807.         }
  1808.     }
  1809.     if (finish) {
  1810.         /*
  1811.          * If the finish flag is true, we must loop until we hit
  1812.          * end-of-file on the pipe. This is guaranteed to happen eventually
  1813.          * since the other end of the pipe is now closed (we closed it
  1814.          * explicitly and the child has exited). When we do get an EOF,
  1815.          * finish will be set FALSE and we'll fall through and out.
  1816.          */
  1817.         goto end_loop;
  1818.     }
  1819.     } else {
  1820.     /*
  1821.      * We've been called to retrieve the output of the job from the
  1822.      * temporary file where it's been squirreled away. This consists of
  1823.      * opening the file, reading the output line by line, being sure not
  1824.      * to print the noPrint line for the shell we used, then close and
  1825.      * remove the temporary file. Very simple.
  1826.      *
  1827.      * Change to read in blocks and do FindSubString type things as for
  1828.      * pipes? That would allow for "@echo -n..."
  1829.      */
  1830.     oFILE = fopen (job->outFile, "r");
  1831.     if (oFILE != (FILE *) NULL) {
  1832.         printf ("Results of making %s:\n", job->node->name);
  1833.         while (fgets (inLine, sizeof(inLine), oFILE) != NULL) {
  1834.         register char    *cp, *ecp, *endp;
  1835.  
  1836.         cp = inLine;
  1837.         endp = inLine + strlen(inLine);
  1838.         if (endp[-1] == '\n') {
  1839.             *--endp = '\0';
  1840.         }
  1841.         if (commandShell->noPrint) {
  1842.             ecp = Str_FindSubstring(cp, commandShell->noPrint);
  1843.             while (ecp != (char *)NULL) {
  1844.             if (cp != ecp) {
  1845.                 *ecp = '\0';
  1846.                 /*
  1847.                  * The only way there wouldn't be a newline after
  1848.                  * this line is if it were the last in the buffer.
  1849.                  * however, since the non-printable comes after it,
  1850.                  * there must be a newline, so we don't print one.
  1851.                  */
  1852.                 printf ("%s", cp);
  1853.             }
  1854.             cp = ecp + commandShell->noPLen;
  1855.             if (cp != endp) {
  1856.                 /*
  1857.                  * Still more to print, look again after skipping
  1858.                  * the whitespace following the non-printable
  1859.                  * command....
  1860.                  */
  1861.                 cp++;
  1862.                 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
  1863.                 cp++;
  1864.                 }
  1865.                 ecp = Str_FindSubstring(cp, commandShell->noPrint);
  1866.             } else {
  1867.                 break;
  1868.             }
  1869.             }
  1870.         }
  1871.  
  1872.         /*
  1873.          * There's still more in that thar buffer. This time, though,
  1874.          * we know there's no newline at the end, so we add one of
  1875.          * our own free will.
  1876.          */
  1877.         if (*cp != '\0') {
  1878.             printf ("%s\n", cp);
  1879.         }
  1880.         }
  1881.         fclose (oFILE);
  1882.         (void) unlink (job->outFile);
  1883.     }
  1884.     }
  1885.     fflush(stdout);
  1886. }
  1887.  
  1888. /*-
  1889.  *-----------------------------------------------------------------------
  1890.  * Job_CatchChildren --
  1891.  *    Handle the exit of a child. Called from Make_Make.
  1892.  *
  1893.  * Results:
  1894.  *    none.
  1895.  *
  1896.  * Side Effects:
  1897.  *    The job descriptor is removed from the list of children.
  1898.  *
  1899.  * Notes:
  1900.  *    We do waits, blocking or not, according to the wisdom of our
  1901.  *    caller, until there are no more children to report. For each
  1902.  *    job, call JobFinish to finish things off. This will take care of
  1903.  *    putting jobs on the stoppedJobs queue.
  1904.  *
  1905.  *-----------------------------------------------------------------------
  1906.  */
  1907. void
  1908. Job_CatchChildren (block)
  1909.     Boolean      block;        /* TRUE if should block on the wait. */
  1910. {
  1911.     int          pid;            /* pid of dead child */
  1912.     register Job  *job;            /* job descriptor for dead child */
  1913.     LstNode       jnode;        /* list element for finding job */
  1914.     union wait      status;       /* Exit/termination status */
  1915.  
  1916.     /*
  1917.      * Don't even bother if we know there's no one around.
  1918.      */
  1919.     if (nLocal == 0) {
  1920.     return;
  1921.     }
  1922.     
  1923.     while ((pid = wait3((int *)&status, (block?0:WNOHANG)|WUNTRACED,
  1924.             (struct rusage *)0)) > 0)
  1925.     {
  1926.     if (DEBUG(JOB))
  1927.         printf("Process %d exited or stopped.\n", pid);
  1928.         
  1929.  
  1930.     jnode = Lst_Find (jobs, (ClientData)pid, JobCmpPid);
  1931.  
  1932.     if (jnode == NILLNODE) {
  1933.         if (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) {
  1934.         jnode = Lst_Find(stoppedJobs, (ClientData)pid, JobCmpPid);
  1935.         if (jnode == NILLNODE) {
  1936.             Error("Resumed child (%d) not in table", pid);
  1937.             continue;
  1938.         }
  1939.         job = (Job *)Lst_Datum(jnode);
  1940.         (void)Lst_Remove(stoppedJobs, jnode);
  1941.         } else {
  1942.         Error ("Child (%d) not in table?", pid);
  1943.         continue;
  1944.         }
  1945.     } else {
  1946.         job = (Job *) Lst_Datum (jnode);
  1947.         (void)Lst_Remove (jobs, jnode);
  1948.         nJobs -= 1;
  1949.         if (jobFull && DEBUG(JOB)) {
  1950.         printf("Job queue is no longer full.\n");
  1951.         }
  1952.         jobFull = FALSE;
  1953.         nLocal -= 1;
  1954.     }
  1955.  
  1956.     JobFinish (job, status);
  1957.     }
  1958. }
  1959.  
  1960. /*-
  1961.  *-----------------------------------------------------------------------
  1962.  * Job_CatchOutput --
  1963.  *    Catch the output from our children, if we're using
  1964.  *    pipes do so. Otherwise just block time until we get a
  1965.  *    signal (most likely a SIGCHLD) since there's no point in
  1966.  *    just spinning when there's nothing to do and the reaping
  1967.  *    of a child can wait for a while. 
  1968.  *
  1969.  * Results:
  1970.  *    None 
  1971.  *
  1972.  * Side Effects:
  1973.  *    Output is read from pipes if we're piping.
  1974.  * -----------------------------------------------------------------------
  1975.  */
  1976. void
  1977. Job_CatchOutput ()
  1978. {
  1979.     int                 nfds;
  1980.     struct timeval      timeout;
  1981.     fd_set                 readfds;
  1982.     register LstNode      ln;
  1983.     register Job         *job;
  1984.     int                    pnJobs;       /* Previous nJobs */
  1985.  
  1986.     fflush(stdout);
  1987. #ifdef RMT_WILL_WATCH
  1988.     pnJobs = nJobs;
  1989.  
  1990.     /*
  1991.      * It is possible for us to be called with nJobs equal to 0. This happens
  1992.      * if all the jobs finish and a job that is stopped cannot be run
  1993.      * locally (eg if maxLocal is 0) and cannot be exported. The job will
  1994.      * be placed back on the stoppedJobs queue, Job_Empty() will return false,
  1995.      * Make_Run will call us again when there's nothing for which to wait.
  1996.      * nJobs never changes, so we loop forever. Hence the check. It could
  1997.      * be argued that we should sleep for a bit so as not to swamp the
  1998.      * exportation system with requests. Perhaps we should.
  1999.      *
  2000.      * NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren
  2001.      * IN A TIMELY FASHION TO CATCH ANY LOCALLY RUNNING JOBS THAT EXIT.
  2002.      * It may use the variable nLocal to determine if it needs to call
  2003.      * Job_CatchChildren (if nLocal is 0, there's nothing for which to
  2004.      * wait...)
  2005.      */
  2006.     while (nJobs != 0 && pnJobs == nJobs) {
  2007.     Rmt_Wait();
  2008.     }
  2009. #else
  2010.     if (usePipes) {
  2011.     readfds = outputs;
  2012.     timeout.tv_sec = SEL_SEC;
  2013.     timeout.tv_usec = SEL_USEC;
  2014.  
  2015.     if ((nfds = select (FD_SETSIZE, &readfds, (int *) 0, (int *) 0, &timeout)) < 0)
  2016.     {
  2017.         return;
  2018.     } else {
  2019.         if (Lst_Open (jobs) == FAILURE) {
  2020.         Punt ("Cannot open job table");
  2021.         }
  2022.         while (nfds && (ln = Lst_Next (jobs)) != NILLNODE) {
  2023.         job = (Job *) Lst_Datum (ln);
  2024.         if (FD_ISSET(job->inPipe, &readfds)) {
  2025.             JobDoOutput (job, FALSE);
  2026.             nfds -= 1;
  2027.         }
  2028.         }
  2029.         Lst_Close (jobs);
  2030.     }
  2031.     }
  2032. #endif /* RMT_WILL_WATCH */
  2033. }
  2034.  
  2035. /*-
  2036.  *-----------------------------------------------------------------------
  2037.  * Job_Make --
  2038.  *    Start the creation of a target. Basically a front-end for
  2039.  *    JobStart used by the Make module.
  2040.  *
  2041.  * Results:
  2042.  *    None.
  2043.  *
  2044.  * Side Effects:
  2045.  *    Another job is started.
  2046.  *
  2047.  *-----------------------------------------------------------------------
  2048.  */
  2049. void
  2050. Job_Make (gn)
  2051.     GNode   *gn;
  2052. {
  2053.     (void)JobStart (gn, 0, (Job *)NULL);
  2054. }
  2055.  
  2056. /*-
  2057.  *-----------------------------------------------------------------------
  2058.  * Job_Init --
  2059.  *    Initialize the process module
  2060.  *
  2061.  * Results:
  2062.  *    none
  2063.  *
  2064.  * Side Effects:
  2065.  *    lists and counters are initialized
  2066.  *-----------------------------------------------------------------------
  2067.  */
  2068. void
  2069. Job_Init (maxproc, maxlocal)
  2070.     int           maxproc;  /* the greatest number of jobs which may be
  2071.                  * running at one time */
  2072.     int              maxlocal; /* the greatest number of local jobs which may
  2073.                  * be running at once. */
  2074. {
  2075.     GNode         *begin;     /* node for commands to do at the very start */
  2076.  
  2077.     sprintf (tfile, "/tmp/make%05d", getpid());
  2078.  
  2079.     jobs =        Lst_Init (FALSE);
  2080.     stoppedJobs = Lst_Init(FALSE);
  2081.     maxJobs =       maxproc;
  2082.     maxLocal =       maxlocal;
  2083.     nJobs =       0;
  2084.     nLocal =       0;
  2085.     jobFull =       FALSE;
  2086.  
  2087.     aborting =       0;
  2088.     errors =       0;
  2089.  
  2090.     lastNode =      NILGNODE;
  2091.  
  2092.     if (maxJobs == 1) {
  2093.     /*
  2094.      * If only one job can run at a time, there's no need for a banner,
  2095.      * no is there?
  2096.      */
  2097.     targFmt = "";
  2098.     } else {
  2099.     targFmt = TARG_FMT;
  2100.     }
  2101.     
  2102.     if (shellPath == (char *) NULL) {
  2103.     /*
  2104.      * The user didn't specify a shell to use, so we are using the
  2105.      * default one... Both the absolute path and the last component
  2106.      * must be set. The last component is taken from the 'name' field
  2107.      * of the default shell description pointed-to by commandShell.
  2108.      * All default shells are located in _PATH_DEFSHELLDIR.
  2109.      */
  2110.     shellName = commandShell->name;
  2111.     shellPath = str_concat (_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
  2112.     }
  2113.  
  2114.     if (commandShell->exit == (char *)NULL) {
  2115.     commandShell->exit = "";
  2116.     }
  2117.     if (commandShell->echo == (char *)NULL) {
  2118.     commandShell->echo = "";
  2119.     }
  2120.  
  2121.     /*
  2122.      * Catch the four signals that POSIX specifies if they aren't ignored.
  2123.      * JobPassSig will take care of calling JobInterrupt if appropriate.
  2124.      */
  2125.     if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
  2126.     signal (SIGINT, JobPassSig);
  2127.     }
  2128.     if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
  2129.     signal (SIGHUP, JobPassSig);
  2130.     }
  2131.     if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) {
  2132.     signal (SIGQUIT, JobPassSig);
  2133.     }
  2134.     if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
  2135.     signal (SIGTERM, JobPassSig);
  2136.     }
  2137.     /*
  2138.      * There are additional signals that need to be caught and passed if
  2139.      * either the export system wants to be told directly of signals or if
  2140.      * we're giving each job its own process group (since then it won't get
  2141.      * signals from the terminal driver as we own the terminal)
  2142.      */
  2143. #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)
  2144.     if (signal (SIGTSTP, SIG_IGN) != SIG_IGN) {
  2145.     signal (SIGTSTP, JobPassSig);
  2146.     }
  2147.     if (signal (SIGTTOU, SIG_IGN) != SIG_IGN) {
  2148.     signal (SIGTTOU, JobPassSig);
  2149.     }
  2150.     if (signal (SIGTTIN, SIG_IGN) != SIG_IGN) {
  2151.     signal (SIGTTIN, JobPassSig);
  2152.     }
  2153.     if (signal (SIGWINCH, SIG_IGN) != SIG_IGN) {
  2154.     signal (SIGWINCH, JobPassSig);
  2155.     }
  2156. #endif
  2157.     
  2158.     begin = Targ_FindNode (".BEGIN", TARG_NOCREATE);
  2159.  
  2160.     if (begin != NILGNODE) {
  2161.     JobStart (begin, JOB_SPECIAL, (Job *)0);
  2162.     while (nJobs) {
  2163.         Job_CatchOutput();
  2164. #ifndef RMT_WILL_WATCH
  2165.         Job_CatchChildren (!usePipes);
  2166. #endif /* RMT_WILL_WATCH */
  2167.     }
  2168.     }
  2169.     postCommands = Targ_FindNode (".END", TARG_CREATE);
  2170. }
  2171.  
  2172. /*-
  2173.  *-----------------------------------------------------------------------
  2174.  * Job_Full --
  2175.  *    See if the job table is full. It is considered full if it is OR
  2176.  *    if we are in the process of aborting OR if we have
  2177.  *    reached/exceeded our local quota. This prevents any more jobs
  2178.  *    from starting up.
  2179.  *
  2180.  * Results:
  2181.  *    TRUE if the job table is full, FALSE otherwise
  2182.  * Side Effects:
  2183.  *    None.
  2184.  *-----------------------------------------------------------------------
  2185.  */
  2186. Boolean
  2187. Job_Full ()
  2188. {
  2189.     return (aborting || jobFull);
  2190. }
  2191.  
  2192. /*-
  2193.  *-----------------------------------------------------------------------
  2194.  * Job_Empty --
  2195.  *    See if the job table is empty.  Because the local concurrency may
  2196.  *    be set to 0, it is possible for the job table to become empty,
  2197.  *    while the list of stoppedJobs remains non-empty. In such a case,
  2198.  *    we want to restart as many jobs as we can.
  2199.  *
  2200.  * Results:
  2201.  *    TRUE if it is. FALSE if it ain't.
  2202.  *
  2203.  * Side Effects:
  2204.  *    None.
  2205.  *
  2206.  * -----------------------------------------------------------------------
  2207.  */
  2208. Boolean
  2209. Job_Empty ()
  2210. {
  2211.     if (nJobs == 0) {
  2212.     if (!Lst_IsEmpty(stoppedJobs) && !aborting) {
  2213.         /*
  2214.          * The job table is obviously not full if it has no jobs in
  2215.          * it...Try and restart the stopped jobs.
  2216.          */
  2217.         jobFull = FALSE;
  2218.         while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {
  2219.         JobRestart((Job *)Lst_DeQueue(stoppedJobs));
  2220.         }
  2221.         return(FALSE);
  2222.     } else {
  2223.         return(TRUE);
  2224.     }
  2225.     } else {
  2226.     return(FALSE);
  2227.     }
  2228. }
  2229.  
  2230. /*-
  2231.  *-----------------------------------------------------------------------
  2232.  * JobMatchShell --
  2233.  *    Find a matching shell in 'shells' given its final component.
  2234.  *
  2235.  * Results:
  2236.  *    A pointer to the Shell structure.
  2237.  *
  2238.  * Side Effects:
  2239.  *    None.
  2240.  *
  2241.  *-----------------------------------------------------------------------
  2242.  */
  2243. static Shell *
  2244. JobMatchShell (name)
  2245.     char      *name;      /* Final component of shell path */
  2246. {
  2247.     register Shell *sh;          /* Pointer into shells table */
  2248.     Shell       *match;    /* Longest-matching shell */
  2249.     register char *cp1,
  2250.           *cp2;
  2251.     char      *eoname;
  2252.  
  2253.     eoname = name + strlen (name);
  2254.  
  2255.     match = (Shell *) NULL;
  2256.  
  2257.     for (sh = shells; sh->name != NULL; sh++) {
  2258.     for (cp1 = eoname - strlen (sh->name), cp2 = sh->name;
  2259.          *cp1 != '\0' && *cp1 == *cp2;
  2260.          cp1++, cp2++) {
  2261.          continue;
  2262.     }
  2263.     if (*cp1 != *cp2) {
  2264.         continue;
  2265.     } else if (match == (Shell *) NULL ||
  2266.            strlen (match->name) < strlen (sh->name)) {
  2267.                match = sh;
  2268.     }
  2269.     }
  2270.     return (match == (Shell *) NULL ? sh : match);
  2271. }
  2272.  
  2273. /*-
  2274.  *-----------------------------------------------------------------------
  2275.  * Job_ParseShell --
  2276.  *    Parse a shell specification and set up commandShell, shellPath
  2277.  *    and shellName appropriately.
  2278.  *
  2279.  * Results:
  2280.  *    FAILURE if the specification was incorrect.
  2281.  *
  2282.  * Side Effects:
  2283.  *    commandShell points to a Shell structure (either predefined or
  2284.  *    created from the shell spec), shellPath is the full path of the
  2285.  *    shell described by commandShell, while shellName is just the
  2286.  *    final component of shellPath.
  2287.  *
  2288.  * Notes:
  2289.  *    A shell specification consists of a .SHELL target, with dependency
  2290.  *    operator, followed by a series of blank-separated words. Double
  2291.  *    quotes can be used to use blanks in words. A backslash escapes
  2292.  *    anything (most notably a double-quote and a space) and
  2293.  *    provides the functionality it does in C. Each word consists of
  2294.  *    keyword and value separated by an equal sign. There should be no
  2295.  *    unnecessary spaces in the word. The keywords are as follows:
  2296.  *        name          Name of shell.
  2297.  *        path          Location of shell. Overrides "name" if given
  2298.  *        quiet         Command to turn off echoing.
  2299.  *        echo          Command to turn echoing on
  2300.  *        filter        Result of turning off echoing that shouldn't be
  2301.  *                      printed.
  2302.  *        echoFlag        Flag to turn echoing on at the start
  2303.  *        errFlag        Flag to turn error checking on at the start
  2304.  *        hasErrCtl        True if shell has error checking control
  2305.  *        check         Command to turn on error checking if hasErrCtl
  2306.  *                      is TRUE or template of command to echo a command
  2307.  *                      for which error checking is off if hasErrCtl is
  2308.  *                      FALSE.
  2309.  *        ignore        Command to turn off error checking if hasErrCtl
  2310.  *                      is TRUE or template of command to execute a
  2311.  *                      command so as to ignore any errors it returns if
  2312.  *                      hasErrCtl is FALSE.
  2313.  *
  2314.  *-----------------------------------------------------------------------
  2315.  */
  2316. ReturnStatus
  2317. Job_ParseShell (line)
  2318.     char      *line;  /* The shell spec */
  2319. {
  2320.     char          **words;
  2321.     int              wordCount;
  2322.     register char **argv;
  2323.     register int  argc;
  2324.     char          *path;
  2325.     Shell         newShell;
  2326.     Boolean       fullSpec = FALSE;
  2327.  
  2328.     while (isspace (*line)) {
  2329.     line++;
  2330.     }
  2331.     words = brk_string (line, &wordCount);
  2332.  
  2333.     bzero ((Address)&newShell, sizeof(newShell));
  2334.     
  2335.     /*
  2336.      * Parse the specification by keyword
  2337.      */
  2338.     for (path = (char *)NULL, argc = wordCount - 1, argv = words + 1;
  2339.      argc != 0;
  2340.      argc--, argv++) {
  2341.          if (strncmp (*argv, "path=", 5) == 0) {
  2342.          path = &argv[0][5];
  2343.          } else if (strncmp (*argv, "name=", 5) == 0) {
  2344.          newShell.name = &argv[0][5];
  2345.          } else {
  2346.          if (strncmp (*argv, "quiet=", 6) == 0) {
  2347.              newShell.echoOff = &argv[0][6];
  2348.          } else if (strncmp (*argv, "echo=", 5) == 0) {
  2349.              newShell.echoOn = &argv[0][5];
  2350.          } else if (strncmp (*argv, "filter=", 7) == 0) {
  2351.              newShell.noPrint = &argv[0][7];
  2352.              newShell.noPLen = strlen(newShell.noPrint);
  2353.          } else if (strncmp (*argv, "echoFlag=", 9) == 0) {
  2354.              newShell.echo = &argv[0][9];
  2355.          } else if (strncmp (*argv, "errFlag=", 8) == 0) {
  2356.              newShell.exit = &argv[0][8];
  2357.          } else if (strncmp (*argv, "hasErrCtl=", 10) == 0) {
  2358.              char c = argv[0][10];
  2359.              newShell.hasErrCtl = !((c != 'Y') && (c != 'y') &&
  2360.                         (c != 'T') && (c != 't'));
  2361.          } else if (strncmp (*argv, "check=", 6) == 0) {
  2362.              newShell.errCheck = &argv[0][6];
  2363.          } else if (strncmp (*argv, "ignore=", 7) == 0) {
  2364.              newShell.ignErr = &argv[0][7];
  2365.          } else {
  2366.              Parse_Error (PARSE_FATAL, "Unknown keyword \"%s\"",
  2367.                   *argv);
  2368.              return (FAILURE);
  2369.          }
  2370.          fullSpec = TRUE;
  2371.          }
  2372.     }
  2373.  
  2374.     if (path == (char *)NULL) {
  2375.     /*
  2376.      * If no path was given, the user wants one of the pre-defined shells,
  2377.      * yes? So we find the one s/he wants with the help of JobMatchShell
  2378.      * and set things up the right way. shellPath will be set up by
  2379.      * Job_Init.
  2380.      */
  2381.     if (newShell.name == (char *)NULL) {
  2382.         Parse_Error (PARSE_FATAL, "Neither path nor name specified");
  2383.         return (FAILURE);
  2384.     } else {
  2385.         commandShell = JobMatchShell (newShell.name);
  2386.         shellName = newShell.name;
  2387.     }
  2388.     } else {
  2389.     /*
  2390.      * The user provided a path. If s/he gave nothing else (fullSpec is
  2391.      * FALSE), try and find a matching shell in the ones we know of.
  2392.      * Else we just take the specification at its word and copy it
  2393.      * to a new location. In either case, we need to record the
  2394.      * path the user gave for the shell.
  2395.      */
  2396.     shellPath = path;
  2397.     path = rindex (path, '/');
  2398.     if (path == (char *)NULL) {
  2399.         path = shellPath;
  2400.     } else {
  2401.         path += 1;
  2402.     }
  2403.     if (newShell.name != (char *)NULL) {
  2404.         shellName = newShell.name;
  2405.     } else {
  2406.         shellName = path;
  2407.     }
  2408.     if (!fullSpec) {
  2409.         commandShell = JobMatchShell (shellName);
  2410.     } else {
  2411.         commandShell = (Shell *) emalloc(sizeof(Shell));
  2412.         *commandShell = newShell;
  2413.     }
  2414.     }
  2415.  
  2416.     if (commandShell->echoOn && commandShell->echoOff) {
  2417.     commandShell->hasEchoCtl = TRUE;
  2418.     }
  2419.     
  2420.     if (!commandShell->hasErrCtl) {
  2421.     if (commandShell->errCheck == (char *)NULL) {
  2422.         commandShell->errCheck = "";
  2423.     }
  2424.     if (commandShell->ignErr == (char *)NULL) {
  2425.         commandShell->ignErr = "%s\n";
  2426.     }
  2427.     }
  2428.     
  2429.     /*
  2430.      * Do not free up the words themselves, since they might be in use by the
  2431.      * shell specification...
  2432.      */
  2433.     free (words);
  2434.     return SUCCESS;
  2435. }
  2436.  
  2437. /*-
  2438.  *-----------------------------------------------------------------------
  2439.  * JobInterrupt --
  2440.  *    Handle the receipt of an interrupt.
  2441.  *
  2442.  * Results:
  2443.  *    None
  2444.  *
  2445.  * Side Effects:
  2446.  *    All children are killed. Another job will be started if the
  2447.  *    .INTERRUPT target was given.
  2448.  *-----------------------------------------------------------------------
  2449.  */
  2450. static void
  2451. JobInterrupt (runINTERRUPT)
  2452.     int        runINTERRUPT;       /* Non-zero if commands for the .INTERRUPT
  2453.                  * target should be executed */
  2454. {
  2455.     LstNode       ln;        /* element in job table */
  2456.     Job           *job;            /* job descriptor in that element */
  2457.     GNode         *interrupt;    /* the node describing the .INTERRUPT target */
  2458.     
  2459.     aborting = ABORT_INTERRUPT;
  2460.  
  2461.     (void)Lst_Open (jobs);
  2462.     while ((ln = Lst_Next (jobs)) != NILLNODE) {
  2463.     job = (Job *) Lst_Datum (ln);
  2464.  
  2465.     if (!Targ_Precious (job->node)) {
  2466.         char      *file = (job->node->path == (char *)NULL ?
  2467.                  job->node->name :
  2468.                  job->node->path);
  2469.         if (unlink (file) == 0) {
  2470.         Error ("*** %s removed", file);
  2471.         }
  2472.     }
  2473. #ifdef RMT_WANTS_SIGNALS
  2474.     if (job->flags & JOB_REMOTE) {
  2475.         /*
  2476.          * If job is remote, let the Rmt module do the killing.
  2477.          */
  2478.         if (!Rmt_Signal(job, SIGINT)) {
  2479.         /*
  2480.          * If couldn't kill the thing, finish it out now with an
  2481.          * error code, since no exit report will come in likely.
  2482.          */
  2483.         union wait status;
  2484.  
  2485.         status.w_status = 0;
  2486.         status.w_retcode = 1;
  2487.         JobFinish(job, status);
  2488.         }
  2489.     } else if (job->pid) {
  2490.         KILL(job->pid, SIGINT);
  2491.     }
  2492. #else
  2493.     if (job->pid) {
  2494.         KILL(job->pid, SIGINT);
  2495.     }
  2496. #endif /* RMT_WANTS_SIGNALS */
  2497.     }
  2498.     Lst_Close (jobs);
  2499.  
  2500.     if (runINTERRUPT && !touchFlag) {
  2501.     interrupt = Targ_FindNode (".INTERRUPT", TARG_NOCREATE);
  2502.     if (interrupt != NILGNODE) {
  2503.         ignoreErrors = FALSE;
  2504.  
  2505.         JobStart (interrupt, JOB_IGNDOTS, (Job *)0);
  2506.         while (nJobs) {
  2507.         Job_CatchOutput();
  2508. #ifndef RMT_WILL_WATCH
  2509.         Job_CatchChildren (!usePipes);
  2510. #endif /* RMT_WILL_WATCH */
  2511.         }
  2512.     }
  2513.     }
  2514.     (void) unlink (tfile);
  2515.     exit (0);
  2516. }
  2517.  
  2518. /*
  2519.  *-----------------------------------------------------------------------
  2520.  * Job_End --
  2521.  *    Do final processing such as the running of the commands
  2522.  *    attached to the .END target. 
  2523.  *
  2524.  * Results:
  2525.  *    Number of errors reported.
  2526.  *
  2527.  * Side Effects:
  2528.  *    The process' temporary file (tfile) is removed if it still
  2529.  *    existed.
  2530.  *-----------------------------------------------------------------------
  2531.  */
  2532. int
  2533. Job_End ()
  2534. {
  2535.     if (postCommands != NILGNODE && !Lst_IsEmpty (postCommands->commands)) {
  2536.     if (errors) {
  2537.         Error ("Errors reported so .END ignored");
  2538.     } else {
  2539.         JobStart (postCommands, JOB_SPECIAL | JOB_IGNDOTS,
  2540.                (Job *)0);
  2541.  
  2542.         while (nJobs) {
  2543.         Job_CatchOutput();
  2544. #ifndef RMT_WILL_WATCH
  2545.         Job_CatchChildren (!usePipes);
  2546. #endif /* RMT_WILL_WATCH */
  2547.         }
  2548.     }
  2549.     }
  2550.     (void) unlink (tfile);
  2551.     return(errors);
  2552. }
  2553.  
  2554. /*-
  2555.  *-----------------------------------------------------------------------
  2556.  * Job_Wait --
  2557.  *    Waits for all running jobs to finish and returns. Sets 'aborting'
  2558.  *    to ABORT_WAIT to prevent other jobs from starting.
  2559.  *
  2560.  * Results:
  2561.  *    None.
  2562.  *
  2563.  * Side Effects:
  2564.  *    Currently running jobs finish.
  2565.  *
  2566.  *-----------------------------------------------------------------------
  2567.  */
  2568. void
  2569. Job_Wait()
  2570. {
  2571.     aborting = ABORT_WAIT;
  2572.     while (nJobs != 0) {
  2573.     Job_CatchOutput();
  2574. #ifndef RMT_WILL_WATCH
  2575.     Job_CatchChildren(!usePipes);
  2576. #endif /* RMT_WILL_WATCH */
  2577.     }
  2578.     aborting = 0;
  2579. }
  2580.  
  2581. /*-
  2582.  *-----------------------------------------------------------------------
  2583.  * Job_AbortAll --
  2584.  *    Abort all currently running jobs without handling output or anything.
  2585.  *    This function is to be called only in the event of a major
  2586.  *    error. Most definitely NOT to be called from JobInterrupt.
  2587.  *
  2588.  * Results:
  2589.  *    None
  2590.  *
  2591.  * Side Effects:
  2592.  *    All children are killed, not just the firstborn
  2593.  *-----------------------------------------------------------------------
  2594.  */
  2595. void
  2596. Job_AbortAll ()
  2597. {
  2598.     LstNode               ln;        /* element in job table */
  2599.     Job                *job;    /* the job descriptor in that element */
  2600.     int               foo;
  2601.     
  2602.     aborting = ABORT_ERROR;
  2603.     
  2604.     if (nJobs) {
  2605.  
  2606.     (void)Lst_Open (jobs);
  2607.     while ((ln = Lst_Next (jobs)) != NILLNODE) {
  2608.         job = (Job *) Lst_Datum (ln);
  2609.  
  2610.         /*
  2611.          * kill the child process with increasingly drastic signals to make
  2612.          * darn sure it's dead. 
  2613.          */
  2614. #ifdef RMT_WANTS_SIGNALS
  2615.         if (job->flags & JOB_REMOTE) {
  2616.         Rmt_Signal(job, SIGINT);
  2617.         Rmt_Signal(job, SIGKILL);
  2618.         } else {
  2619.         KILL(job->pid, SIGINT);
  2620.         KILL(job->pid, SIGKILL);
  2621.         }
  2622. #else
  2623.         KILL(job->pid, SIGINT);
  2624.         KILL(job->pid, SIGKILL);
  2625. #endif /* RMT_WANTS_SIGNALS */
  2626.     }
  2627.     }
  2628.     
  2629.     /*
  2630.      * Catch as many children as want to report in at first, then give up
  2631.      */
  2632.     while (wait3(&foo, WNOHANG, (struct rusage *)0) > 0) {
  2633.     ;
  2634.     }
  2635.     (void) unlink (tfile);
  2636. }
  2637.