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