[BACK]Return to job.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / make

Diff for /src/usr.bin/make/job.c between version 1.39 and 1.40

version 1.39, 2000/12/27 19:07:58 version 1.40, 2001/05/03 13:41:06
Line 1 
Line 1 
   /*      $OpenPackages$ */
 /*      $OpenBSD$       */  /*      $OpenBSD$       */
 /*      $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $        */  /*      $NetBSD: job.c,v 1.16 1996/11/06 17:59:08 christos Exp $        */
   
Line 44 
Line 45 
  *      handle the creation etc. of our child processes.   *      handle the creation etc. of our child processes.
  *   *
  * Interface:   * Interface:
  *      Job_Make                Start the creation of the given target.   *      Job_Make                Start the creation of the given target.
  *   *
  *      Job_CatchChildren       Check for and handle the termination of any   *      Job_CatchChildren       Check for and handle the termination of any
  *                              children. This must be called reasonably   *                              children. This must be called reasonably
  *                              frequently to keep the whole make going at   *                              frequently to keep the whole make going at
  *                              a decent clip, since job table entries aren't   *                              a decent clip, since job table entries aren't
  *                              removed until their process is caught this way.   *                              removed until their process is caught this way.
  *                              Its single argument is TRUE if the function   *                              Its single argument is TRUE if the function
  *                              should block waiting for a child to terminate.   *                              should block waiting for a child to terminate.
  *   *
  *      Job_CatchOutput         Print any output our children have produced.   *      Job_CatchOutput         Print any output our children have produced.
  *                              Should also be called fairly frequently to   *                              Should also be called fairly frequently to
  *                              keep the user informed of what's going on.   *                              keep the user informed of what's going on.
  *                              If no output is waiting, it will block for   *                              If no output is waiting, it will block for
  *                              a time given by the SEL_* constants, below,   *                              a time given by the SEL_* constants, below,
  *                              or until output is ready.   *                              or until output is ready.
  *   *
  *      Job_Init                Called to intialize this module. in addition,   *      Job_Init                Called to intialize this module. in addition,
  *                              any commands attached to the .BEGIN target   *                              any commands attached to the .BEGIN target
  *                              are executed before this function returns.   *                              are executed before this function returns.
  *                              Hence, the makefile must have been parsed   *                              Hence, the makefile must have been parsed
  *                              before this function is called.   *                              before this function is called.
  *   *
  *      Job_End                 Cleanup any memory used.   *      Job_End                 Cleanup any memory used.
  *   *
  *      Job_Full                Return TRUE if the job table is filled.   *      Job_Full                Return TRUE if the job table is filled.
  *   *
  *      Job_Empty               Return TRUE if the job table is completely   *      Job_Empty               Return TRUE if the job table is completely
  *                              empty.   *                              empty.
  *   *
  *      Job_ParseShell          Given the line following a .SHELL target, parse   *      Job_ParseShell          Given the line following a .SHELL target, parse
  *                              the line as a shell specification. Returns   *                              the line as a shell specification. Returns
  *                              FAILURE if the spec was incorrect.   *                              FAILURE if the spec was incorrect.
  *   *
  *      Job_Finish              Perform any final processing which needs doing.   *      Job_Finish              Perform any final processing which needs doing.
  *                              This includes the execution of any commands   *                              This includes the execution of any commands
  *                              which have been/were attached to the .END   *                              which have been/were attached to the .END
  *                              target. It should only be called when the   *                              target. It should only be called when the
  *                              job table is empty.   *                              job table is empty.
  *   *
  *      Job_AbortAll            Abort all currently running jobs. It doesn't   *      Job_AbortAll            Abort all currently running jobs. It doesn't
  *                              handle output or do anything for the jobs,   *                              handle output or do anything for the jobs,
  *                              just kills them. It should only be called in   *                              just kills them. It should only be called in
  *                              an emergency, as it were.   *                              an emergency, as it were.
  *   *
  *      Job_CheckCommands       Verify that the commands for a target are   *      Job_CheckCommands       Verify that the commands for a target are
  *                              ok. Provide them if necessary and possible.   *                              ok. Provide them if necessary and possible.
  *   *
  *      Job_Touch               Update a target without really updating it.   *      Job_Touch               Update a target without really updating it.
  *   *
  *      Job_Wait                Wait for all currently-running jobs to finish.   *      Job_Wait                Wait for all currently-running jobs to finish.
  */   */
   
 #include <sys/types.h>  #include <sys/types.h>
Line 130 
Line 131 
 #endif  #endif
 #endif /* not lint */  #endif /* not lint */
   
   
 /*  /*
  * error handling variables   * error handling variables
  */   */
 static int      errors = 0;         /* number of errors reported */  static int      errors = 0;         /* number of errors reported */
 static int      aborting = 0;       /* why is the make aborting? */  static int      aborting = 0;       /* why is the make aborting? */
 #define ABORT_ERROR     1           /* Because of an error */  #define ABORT_ERROR     1           /* Because of an error */
 #define ABORT_INTERRUPT 2           /* Because it was interrupted */  #define ABORT_INTERRUPT 2           /* Because it was interrupted */
 #define ABORT_WAIT      3           /* Waiting for jobs to finish */  #define ABORT_WAIT      3           /* Waiting for jobs to finish */
   
 /*  /*
  * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file   * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file
Line 150 
Line 152 
  * .END target but we keep it around to avoid having to search for it   * .END target but we keep it around to avoid having to search for it
  * all the time.   * all the time.
  */   */
 static GNode      *postCommands;    /* node containing commands to execute when  static GNode      *postCommands;    /* node containing commands to execute when
                                      * everything else is done */                                       * everything else is done */
 static int        numCommands;      /* The number of commands actually printed  static int        numCommands;      /* The number of commands actually printed
                                      * for a target. Should this number be                                       * for a target. Should this number be
                                      * 0, no shell will be executed. */                                       * 0, no shell will be executed. */
   
 /*  /*
  * Return values from JobStart.   * Return values from JobStart.
  */   */
 #define JOB_RUNNING     0       /* Job is running */  #define JOB_RUNNING     0       /* Job is running */
 #define JOB_ERROR       1       /* Error in starting the job */  #define JOB_ERROR       1       /* Error in starting the job */
 #define JOB_FINISHED    2       /* The job is already finished */  #define JOB_FINISHED    2       /* The job is already finished */
 #define JOB_STOPPED     3       /* The job is stopped */  #define JOB_STOPPED     3       /* The job is stopped */
   
 /*  /*
  * tfile is used to build temp file names to store shell commands to   * tfile is the name of a file into which all shell commands are put. It is
  * execute.   * used over by removing it before the child shell is executed. The XXXXXXXXXX
    * in the string are replaced by mkstemp(3).
  */   */
 static char     tfile[sizeof(TMPPAT)];  static char     tfile[sizeof(TMPPAT)];
   
   
 /*  /*
  * Descriptions for various shells.   * Descriptions for various shells.
  */   */
 static Shell    shells[] = {  static Shell    shells[] = {
     /*      /*
      * CSH description. The csh can do echo control by playing       * CSH description. The csh can do echo control by playing
      * with the setting of the 'echo' shell variable. Sadly,       * with the setting of the 'echo' shell variable. Sadly,
Line 203 
Line 206 
      * UNKNOWN.       * UNKNOWN.
      */       */
 {  {
     (char *) 0,      (char *)0,
     FALSE, (char *) 0, (char *) 0, (char *) 0, 0,      FALSE, (char *)0, (char *)0, (char *)0, 0,
     FALSE, (char *) 0, (char *) 0,      FALSE, (char *)0, (char *)0,
     (char *) 0, (char *) 0,      (char *)0, (char *)0,
 }  }
 };  };
 static Shell    *commandShell = &shells[DEFSHELL];/* this is the shell to  static Shell    *commandShell = &shells[DEFSHELL];/* this is the shell to
                                                    * which we pass all                                                     * which we pass all
                                                    * commands in the Makefile.                                                     * commands in the Makefile.
                                                    * It is set by the                                                     * It is set by the
                                                    * Job_ParseShell function */                                                     * Job_ParseShell function */
 static char     *shellPath = NULL,                /* full pathname of  static char     *shellPath = NULL,                /* full pathname of
                                                    * executable image */                                                     * executable image */
                 *shellName = NULL,                /* last component of shell */                  *shellName = NULL,                /* last component of shell */
                 *shellArgv = NULL;                /* Custom shell args */                  *shellArgv = NULL;                /* Custom shell args */
   
   
 static int      maxJobs;        /* The most children we can run at once */  static int      maxJobs;        /* The most children we can run at once */
 static int      maxLocal;       /* The most local ones we can have */  static int      maxLocal;       /* The most local ones we can have */
 STATIC int      nJobs;          /* The number of children currently running */  STATIC int      nJobs;          /* The number of children currently running */
 STATIC int      nLocal;         /* The number of local children */  STATIC int      nLocal;         /* The number of local children */
 STATIC LIST     jobs;           /* The structures that describe them */  STATIC LIST     jobs;           /* The structures that describe them */
 STATIC Boolean  jobFull;        /* Flag to tell when the job table is full. It  STATIC Boolean  jobFull;        /* Flag to tell when the job table is full. It
                                  * is set TRUE when (1) the total number of                                   * is set TRUE when (1) the total number of
                                  * running jobs equals the maximum allowed or                                   * running jobs equals the maximum allowed or
                                  * (2) a job can only be run locally, but                                   * (2) a job can only be run locally, but
                                  * nLocal equals maxLocal */                                   * nLocal equals maxLocal */
 #ifndef RMT_WILL_WATCH  #ifndef RMT_WILL_WATCH
 static fd_set   *outputsp;      /* Set of descriptors of pipes connected to  static fd_set   *outputsp;      /* Set of descriptors of pipes connected to
                                  * the output channels of children */                                   * the output channels of children */
 static int      outputsn;  static int      outputsn;
 #endif  #endif
   
 STATIC GNode    *lastNode;      /* The node for which output was most recently  STATIC GNode    *lastNode;      /* The node for which output was most recently
                                  * produced. */                                   * produced. */
 STATIC char     *targFmt;       /* Format string to use to head output from a  STATIC char     *targFmt;       /* Format string to use to head output from a
                                  * job when it's not the most-recent job heard                                   * job when it's not the most-recent job heard
                                  * from */                                   * from */
   
 #ifdef REMOTE  #ifdef REMOTE
 # define TARG_FMT  "--- %s at %s ---\n" /* Default format */  # define TARG_FMT  "--- %s at %s ---\n" /* Default format */
 # define MESSAGE(fp, gn) \  # define MESSAGE(fp, gn) \
         (void) fprintf(fp, targFmt, gn->name, gn->rem.hname);          (void)fprintf(fp, targFmt, gn->name, gn->rem.hname);
 #else  #else
 # define TARG_FMT  "--- %s ---\n" /* Default format */  # define TARG_FMT  "--- %s ---\n" /* Default format */
 # define MESSAGE(fp, gn) \  # define MESSAGE(fp, gn) \
         (void) fprintf(fp, targFmt, gn->name);          (void)fprintf(fp, targFmt, gn->name);
 #endif  #endif
   
 /*  /*
Line 264 
Line 267 
   
   
 #if defined(USE_PGRP) && defined(SYSV)  #if defined(USE_PGRP) && defined(SYSV)
 # define KILL(pid, sig)         killpg(-(pid), (sig))  # define KILL(pid, sig)         killpg(-(pid), (sig))
 #else  #else
 # if defined(USE_PGRP)  # if defined(USE_PGRP)
 #  define KILL(pid, sig)        killpg((pid), (sig))  #  define KILL(pid, sig)        killpg((pid), (sig))
Line 293 
Line 296 
 #define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS)  #define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS)
   
   
 static void JobCondPassSig __P((void *, void *));  static void JobCondPassSig(void *, void *);
 static void JobPassSig __P((int));  static void JobPassSig(int);
 static int JobCmpPid __P((void *, void *));  static int JobCmpPid(void *, void *);
 static int JobPrintCommand __P((void *, void *));  static int JobPrintCommand(void *, void *);
 static void JobSaveCommand __P((void *, void *));  static void JobSaveCommand(void *, void *);
 static void JobClose __P((Job *));  static void JobClose(Job *);
 #ifdef REMOTE  #ifdef REMOTE
 static int JobCmpRmtID __P((Job *, void *));  static int JobCmpRmtID(Job *, int);
 # ifdef RMT_WILL_WATCH  # ifdef RMT_WILL_WATCH
 static void JobLocalInput __P((int, Job *));  static void JobLocalInput(int, Job *);
 # endif  # endif
 #else  #else
 static void JobFinish __P((Job *, int *));  static void JobFinish(Job *, int *);
 static void JobExec __P((Job *, char **));  static void JobExec(Job *, char **);
 #endif  #endif
 static void JobMakeArgv __P((Job *, char **));  static void JobMakeArgv(Job *, char **);
 static void JobRestart __P((Job *));  static void JobRestart(Job *);
 static int JobStart __P((GNode *, int, Job *));  static int JobStart(GNode *, int, Job *);
 static char *JobOutput __P((Job *, char *, char *, int));  static char *JobOutput(Job *, char *, char *, int);
 static void JobDoOutput __P((Job *, Boolean));  static void JobDoOutput(Job *, Boolean);
 static Shell *JobMatchShell __P((char *));  static Shell *JobMatchShell(char *);
 static void JobInterrupt __P((int, int));  static void JobInterrupt(int, int);
 static void JobRestartJobs __P((void));  static void JobRestartJobs(void);
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
Line 325 
Line 328 
  *   *
  * Side Effects:   * Side Effects:
  *      None, except the job may bite it.   *      None, except the job may bite it.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobCondPassSig(jobp, signop)  JobCondPassSig(jobp, signop)
     void *jobp;         /* Job to biff */      void                *jobp;          /* Job to biff */
     void *signop;       /* Signal to send it */      void                *signop;        /* Signal to send it */
 {  {
     Job *job = (Job *) jobp;      Job *job = (Job *)jobp;
     int signo = *(int *) signop;      int signo = *(int *)signop;
 #ifdef RMT_WANTS_SIGNALS  #ifdef RMT_WANTS_SIGNALS
     if (job->flags & JOB_REMOTE) {      if (job->flags & JOB_REMOTE) {
         (void) Rmt_Signal(job, signo);          (void)Rmt_Signal(job, signo);
     } else {      } else {
         KILL(job->pid, signo);          KILL(job->pid, signo);
     }      }
Line 347 
Line 349 
      * job as well.       * job as well.
      */       */
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         (void) fprintf(stdout,          (void)fprintf(stdout,
                        "JobCondPassSig passing signal %d to child %d.\n",                         "JobCondPassSig passing signal %d to child %d.\n",
                        signo, job->pid);                         signo, job->pid);
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
     KILL(job->pid, signo);      KILL(job->pid, signo);
 #endif  #endif
Line 362 
Line 364 
  *      Pass a signal on to all remote jobs and to all local jobs if   *      Pass a signal on to all remote jobs and to all local jobs if
  *      USE_PGRP is defined, then die ourselves.   *      USE_PGRP is defined, then die ourselves.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      We die by the same signal.   *      We die by the same signal.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobPassSig(signo)  JobPassSig(signo)
     int     signo;      /* The signal number we've received */      int     signo;      /* The signal number we've received */
 {  {
     sigset_t nmask, omask;      sigset_t nmask, omask;
     struct sigaction act;      struct sigaction act;
   
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo);          (void)fprintf(stdout, "JobPassSig(%d) called.\n", signo);
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
     Lst_ForEach(&jobs, JobCondPassSig, &signo);      Lst_ForEach(&jobs, JobCondPassSig, &signo);
   
Line 390 
Line 388 
      */       */
     if (signo == SIGINT) {      if (signo == SIGINT) {
         JobInterrupt(TRUE, signo);          JobInterrupt(TRUE, signo);
     } else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) {      } else if (signo == SIGHUP || signo == SIGTERM || signo == SIGQUIT) {
         JobInterrupt(FALSE, signo);          JobInterrupt(FALSE, signo);
     }      }
   
Line 417 
Line 415 
     sigaction(signo, &act, NULL);      sigaction(signo, &act, NULL);
   
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         (void) fprintf(stdout,          (void)fprintf(stdout,
                        "JobPassSig passing signal to self, mask = %x.\n",                         "JobPassSig passing signal to self, mask = %x.\n",
                        ~0 & ~(1 << (signo-1)));                         ~0 & ~(1 << (signo-1)));
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
     (void) signal(signo, SIG_DFL);      (void)signal(signo, SIG_DFL);
   
     (void) KILL(getpid(), signo);      (void)KILL(getpid(), signo);
   
     signo = SIGCONT;      signo = SIGCONT;
     Lst_ForEach(&jobs, JobCondPassSig, &signo);      Lst_ForEach(&jobs, JobCondPassSig, &signo);
   
     (void) sigprocmask(SIG_SETMASK, &omask, NULL);      (void)sigprocmask(SIG_SETMASK, &omask, NULL);
     sigprocmask(SIG_SETMASK, &omask, NULL);      sigprocmask(SIG_SETMASK, &omask, NULL);
     act.sa_handler = JobPassSig;      act.sa_handler = JobPassSig;
     sigaction(signo, &act, NULL);      sigaction(signo, &act, NULL);
Line 444 
Line 442 
  *   *
  * Results:   * Results:
  *      0 if the pid's match   *      0 if the pid's match
  *  
  * Side Effects:  
  *      None  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
Line 460 
Line 455 
 #ifdef REMOTE  #ifdef REMOTE
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * JobCmpRmtID  --   * JobCmpRmtID  --
  *      Compare the rmtID of the job with the given rmtID and return 0 if they   *      Compare the rmtID of the job with the given rmtID and return 0 if they
  *      are equal.   *      are equal.
  *   *
  * Results:   * Results:
  *      0 if the rmtID's match   *      0 if the rmtID's match
  *  
  * Side Effects:  
  *      None.  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static int  static int
 JobCmpRmtID(job, rmtID)  JobCmpRmtID(job, rmtID)
     void *job;  /* job to examine */      void        *job;   /* job to examine */
     void *rmtID;        /* remote id desired */      void        *rmtID; /* remote id desired */
 {  {
     return *(int *) rmtID - *(int *) job->rmtID;      return *(int *)rmtID - *(int *)job->rmtID;
 }  }
 #endif  #endif
   
Line 494 
Line 486 
  *      made and return non-zero to signal that the end of the commands   *      made and return non-zero to signal that the end of the commands
  *      was reached. These commands are later attached to the postCommands   *      was reached. These commands are later attached to the postCommands
  *      node and executed by Job_End when all things are done.   *      node and executed by Job_End when all things are done.
  *      This function is called from JobStart via Lst_ForEach.   *      This function is called from JobStart via Lst_Find
  *   *
  * Results:   * Results:
  *      Always 1, unless the command was "..."   *      Always 1, unless the command was "..."
Line 509 
Line 501 
  */   */
 static int  static int
 JobPrintCommand(cmdp, jobp)  JobPrintCommand(cmdp, jobp)
     void *cmdp;             /* command string to print */      void        *cmdp;              /* command string to print */
     void *jobp;             /* job for which to print it */      void        *jobp;              /* job for which to print it */
 {  {
     Boolean       noSpecials;       /* true if we shouldn't worry about      Boolean       noSpecials;       /* true if we shouldn't worry about
                                      * inserting special commands into                                       * inserting special commands into
                                      * the input stream. */                                       * the input stream. */
     Boolean       shutUp = FALSE;   /* true if we put a no echo command      Boolean       shutUp = FALSE;   /* true if we put a no echo command
                                      * into the command file */                                       * into the command file */
     Boolean       errOff = FALSE;   /* true if we turned error checking      Boolean       errOff = FALSE;   /* true if we turned error checking
                                      * off before printing the command                                       * off before printing the command
                                      * and need to turn it back on */                                       * and need to turn it back on */
     char          *cmdTemplate;     /* Template to use when printing the      char          *cmdTemplate;     /* Template to use when printing the
                                      * command */                                       * command */
     char          *cmdStart;        /* Start of expanded command */      char          *cmdStart;        /* Start of expanded command */
     LstNode       cmdNode;          /* Node for replacing the command */      LstNode       cmdNode;          /* Node for replacing the command */
     char          *cmd = (char *) cmdp;      char          *cmd = (char *)cmdp;
     Job           *job = (Job *) jobp;      Job           *job = (Job *)jobp;
   
     noSpecials = (noExecute && !(job->node->type & OP_MAKE));      noSpecials = (noExecute && !(job->node->type & OP_MAKE));
   
Line 539 
Line 531 
     }      }
   
 #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) {    \  #define DBPRINTF(fmt, arg) if (DEBUG(JOB)) {    \
         (void) fprintf(stdout, fmt, arg);       \          (void)fprintf(stdout, fmt, arg);        \
         (void) fflush(stdout);                  \          (void)fflush(stdout);                   \
     }                                           \      }                                           \
    (void) fprintf(job->cmdFILE, fmt, arg);      \     (void)fprintf(job->cmdFILE, fmt, arg);       \
    (void) fflush(job->cmdFILE);     (void)fflush(job->cmdFILE);
   
     numCommands += 1;      numCommands += 1;
   
     /*      /* For debugging, we replace each command with the result of expanding
      * For debugging, we replace each command with the result of expanding       * the variables in the command.  */
      * the variables in the command.  
      */  
     cmdNode = Lst_Member(&job->node->commands, cmd);      cmdNode = Lst_Member(&job->node->commands, cmd);
     cmdStart = cmd = Var_Subst(cmd, &job->node->context, FALSE);      cmdStart = cmd = Var_Subst(cmd, &job->node->context, FALSE);
     Lst_Replace(cmdNode, cmdStart);      Lst_Replace(cmdNode, cmdStart);
Line 561 
Line 551 
      * Check for leading @' and -'s to control echoing and error checking.       * Check for leading @' and -'s to control echoing and error checking.
      */       */
     for (;; cmd++) {      for (;; cmd++) {
         if (*cmd == '@')          if (*cmd == '@')
             shutUp = TRUE;              shutUp = DEBUG(LOUD) ? FALSE : TRUE;
         else if (*cmd == '-')          else if (*cmd == '-')
             errOff = TRUE;              errOff = TRUE;
         else if (*cmd != '+')          else if (*cmd != '+')
             break;              break;
     }      }
   
     while (isspace((unsigned char) *cmd))      while (isspace(*cmd))
         cmd++;          cmd++;
   
     if (shutUp) {      if (shutUp) {
Line 661 
Line 651 
  *   *
  * Side Effects:   * Side Effects:
  *      The command is tacked onto the end of postCommands's commands list.   *      The command is tacked onto the end of postCommands's commands list.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobSaveCommand(cmd, gn)  JobSaveCommand(cmd, gn)
     void *cmd;      void        *cmd;
     void *gn;      void        *gn;
 {  {
     char *result;      GNode       *g = (GNode *)gn;
       char        *result;
   
     result = Var_Subst((char *)cmd, &((GNode *)gn)->context, FALSE);      result = Var_Subst((char *)cmd, &g->context, FALSE);
     Lst_AtEnd(&postCommands->commands, result);      Lst_AtEnd(&postCommands->commands, result);
 }  }
   
Line 681 
Line 671 
  * JobClose --   * JobClose --
  *      Called to close both input and output pipes when a job is finished.   *      Called to close both input and output pipes when a job is finished.
  *   *
  * Results:  
  *      Nada  
  *  
  * Side Effects:   * Side Effects:
  *      The file descriptors associated with the job are closed.   *      The file descriptors associated with the job are closed.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
Line 700 
Line 686 
         FD_CLR(job->inPipe, outputsp);          FD_CLR(job->inPipe, outputsp);
 #endif  #endif
         if (job->outPipe != job->inPipe) {          if (job->outPipe != job->inPipe) {
            (void) close(job->outPipe);             (void)close(job->outPipe);
         }          }
         JobDoOutput(job, TRUE);          JobDoOutput(job, TRUE);
         (void) close(job->inPipe);          (void)close(job->inPipe);
     } else {      } else {
         (void) close(job->outFd);          (void)close(job->outFd);
         JobDoOutput(job, TRUE);          JobDoOutput(job, TRUE);
     }      }
 }  }
Line 720 
Line 706 
  *      or something, jstat.w_status is 0 and when called from   *      or something, jstat.w_status is 0 and when called from
  *      Job_CatchChildren, the status is zeroed if it s/b ignored.   *      Job_CatchChildren, the status is zeroed if it s/b ignored.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      Some nodes may be put on the toBeMade queue.   *      Some nodes may be put on the toBeMade queue.
  *      Final commands for the job are placed on postCommands.   *      Final commands for the job are placed on postCommands.
Line 736 
Line 719 
 /*ARGSUSED*/  /*ARGSUSED*/
 static void  static void
 JobFinish(job, status)  JobFinish(job, status)
     Job         *job;             /* job to finish */      Job         *job;             /* job to finish */
     int         *status;          /* sub-why job went away */      int         *status;          /* sub-why job went away */
 {  {
     Boolean      done;      Boolean      done;
   
     if ((WIFEXITED(*status) &&      if ((WIFEXITED(*status) &&
          (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) ||           WEXITSTATUS(*status) != 0 && !(job->flags & JOB_IGNERR)) ||
         (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT)))          (WIFSIGNALED(*status) && WTERMSIG(*status) != SIGCONT))
     {      {
         /*          /*
          * If it exited non-zero and either we're doing things our           * If it exited non-zero and either we're doing things our
Line 758 
Line 741 
 #endif  #endif
         JobClose(job);          JobClose(job);
         if (job->cmdFILE != NULL && job->cmdFILE != stdout) {          if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
            (void) fclose(job->cmdFILE);             (void)fclose(job->cmdFILE);
         }          }
         done = TRUE;          done = TRUE;
 #ifdef REMOTE  #ifdef REMOTE
Line 794 
Line 777 
   
     if (done ||      if (done ||
         WIFSTOPPED(*status) ||          WIFSTOPPED(*status) ||
         (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) ||          (WIFSIGNALED(*status) && WTERMSIG(*status) == SIGCONT) ||
         DEBUG(JOB))          DEBUG(JOB))
     {      {
         FILE      *out;          FILE      *out;
Line 812 
Line 795 
   
         if (WIFEXITED(*status)) {          if (WIFEXITED(*status)) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "Process %d exited.\n", job->pid);                  (void)fprintf(stdout, "Process %d exited.\n", job->pid);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             if (WEXITSTATUS(*status) != 0) {              if (WEXITSTATUS(*status) != 0) {
                 if (usePipes && job->node != lastNode) {                  if (usePipes && job->node != lastNode) {
                     MESSAGE(out, job->node);                      MESSAGE(out, job->node);
                     lastNode = job->node;                      lastNode = job->node;
                 }                  }
                 (void) fprintf(out, "*** Error code %d%s\n",                  (void)fprintf(out, "*** Error code %d%s\n",
                                WEXITSTATUS(*status),                                 WEXITSTATUS(*status),
                                (job->flags & JOB_IGNERR) ? "(ignored)" : "");                                 (job->flags & JOB_IGNERR) ? "(ignored)" : "");
   
Line 832 
Line 815 
                     MESSAGE(out, job->node);                      MESSAGE(out, job->node);
                     lastNode = job->node;                      lastNode = job->node;
                 }                  }
                 (void) fprintf(out, "*** Completed successfully\n");                  (void)fprintf(out, "*** Completed successfully\n");
             }              }
         } else if (WIFSTOPPED(*status)) {          } else if (WIFSTOPPED(*status)) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "Process %d stopped.\n", job->pid);                  (void)fprintf(stdout, "Process %d stopped.\n", job->pid);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             if (usePipes && job->node != lastNode) {              if (usePipes && job->node != lastNode) {
                 MESSAGE(out, job->node);                  MESSAGE(out, job->node);
                 lastNode = job->node;                  lastNode = job->node;
             }              }
             if (!(job->flags & JOB_REMIGRATE)) {              if (!(job->flags & JOB_REMIGRATE)) {
                 (void) fprintf(out, "*** Stopped -- signal %d\n",                  (void)fprintf(out, "*** Stopped -- signal %d\n",
                     WSTOPSIG(*status));                      WSTOPSIG(*status));
             }              }
             job->flags |= JOB_RESUME;              job->flags |= JOB_RESUME;
Line 853 
Line 836 
             if (job->flags & JOB_REMIGRATE)              if (job->flags & JOB_REMIGRATE)
                 JobRestart(job);                  JobRestart(job);
 #endif  #endif
             (void) fflush(out);              (void)fflush(out);
             return;              return;
         } else if (WTERMSIG(*status) == SIGCONT) {          } else if (WTERMSIG(*status) == SIGCONT) {
             /*              /*
Line 866 
Line 849 
                     MESSAGE(out, job->node);                      MESSAGE(out, job->node);
                     lastNode = job->node;                      lastNode = job->node;
                 }                  }
                 (void) fprintf(out, "*** Continued\n");                  (void)fprintf(out, "*** Continued\n");
             }              }
             if (!(job->flags & JOB_CONTINUING)) {              if (!(job->flags & JOB_CONTINUING)) {
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout,                      (void)fprintf(stdout,
                                    "Warning: process %d was not continuing.\n",                                     "Warning: process %d was not continuing.\n",
                                    job->pid);                                     job->pid);
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
 #ifdef notdef  #ifdef notdef
                 /*                  /*
                  * We don't really want to restart a job from scratch just                   * We don't really want to restart a job from scratch just
                  * because it continued, especially not without killing the                   * because it continued, especially not without killing the
                  * continuing process!  That's why this is ifdef'ed out.                   * continuing process!  That's why this is ifdef'ed out.
                  * FD - 9/17/90                   * FD - 9/17/90
                  */                   */
                 JobRestart(job);                  JobRestart(job);
 #endif  #endif
             }              }
             job->flags &= ~JOB_CONTINUING;              job->flags &= ~JOB_CONTINUING;
             Lst_AtEnd(&jobs, job);              Lst_AtEnd(&jobs, job);
             nJobs += 1;              nJobs += 1;
             if (!(job->flags & JOB_REMOTE)) {              if (!(job->flags & JOB_REMOTE)) {
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout,                      (void)fprintf(stdout,
                                    "Process %d is continuing locally.\n",                                     "Process %d is continuing locally.\n",
                                    job->pid);                                     job->pid);
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 nLocal += 1;                  nLocal += 1;
             }              }
             if (nJobs == maxJobs) {              if (nJobs == maxJobs) {
                 jobFull = TRUE;                  jobFull = TRUE;
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout, "Job queue is full.\n");                      (void)fprintf(stdout, "Job queue is full.\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
             }              }
             (void) fflush(out);              (void)fflush(out);
             return;              return;
         } else {          } else {
             if (usePipes && job->node != lastNode) {              if (usePipes && job->node != lastNode) {
                 MESSAGE(out, job->node);                  MESSAGE(out, job->node);
                 lastNode = job->node;                  lastNode = job->node;
             }              }
             (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status));              (void)fprintf(out, "*** Signal %d\n", WTERMSIG(*status));
         }          }
   
         (void) fflush(out);          (void)fflush(out);
     }      }
   
     /*      /*
Line 922 
Line 905 
      * try and restart the job on the next command. If JobStart says it's       * try and restart the job on the next command. If JobStart says it's
      * ok, it's ok. If there's an error, this puppy is done.       * ok, it's ok. If there's an error, this puppy is done.
      */       */
     if (compatMake && (WIFEXITED(*status) &&      if (compatMake && WIFEXITED(*status) && job->node->current != NULL) {
         !Lst_IsAtEnd(&job->node->commands))) {  
         switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) {          switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) {
         case JOB_RUNNING:          case JOB_RUNNING:
             done = FALSE;              done = FALSE;
Line 943 
Line 925 
             done = FALSE;              done = FALSE;
             break;              break;
         }          }
     } else {      } else
         done = TRUE;          done = TRUE;
     }  
   
   
     if (done &&      if (done &&
         (aborting != ABORT_ERROR) &&          aborting != ABORT_ERROR &&
         (aborting != ABORT_INTERRUPT) &&          aborting != ABORT_INTERRUPT &&
         (*status == 0))          *status == 0) {
     {          /* As long as we aren't aborting and the job didn't return a non-zero
         /*  
          * As long as we aren't aborting and the job didn't return a non-zero  
          * status that we shouldn't ignore, we call Make_Update to update           * status that we shouldn't ignore, we call Make_Update to update
          * the parents. In addition, any saved commands for the node are placed           * the parents. In addition, any saved commands for the node are placed
          * on the .END target.           * on the .END target.  */
          */  
         Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node);          Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node);
         job->node->made = MADE;          job->node->made = MADE;
         Make_Update(job->node);          Make_Update(job->node);
Line 973 
Line 950 
     /*      /*
      * Set aborting if any error.       * Set aborting if any error.
      */       */
     if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) {      if (errors && !keepgoing && aborting != ABORT_INTERRUPT) {
         /*          /*
          * If we found any errors in this batch of children and the -k flag           * If we found any errors in this batch of children and the -k flag
          * wasn't given, we set the aborting flag so no more jobs get           * wasn't given, we set the aborting flag so no more jobs get
Line 982 
Line 959 
         aborting = ABORT_ERROR;          aborting = ABORT_ERROR;
     }      }
   
     if ((aborting == ABORT_ERROR) && Job_Empty())      if (aborting == ABORT_ERROR && Job_Empty()) {
         /*          /*
          * If we are aborting and the job table is now empty, we finish.           * If we are aborting and the job table is now empty, we finish.
          */           */
           (void)eunlink(tfile);
         Finish(errors);          Finish(errors);
       }
 }  }
   
 /*-  /*-
Line 995 
Line 974 
  *      Touch the given target. Called by JobStart when the -t flag was   *      Touch the given target. Called by JobStart when the -t flag was
  *      given   *      given
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      The data modification of the file is changed. In addition, if the   *      The data modification of the file is changed. In addition, if the
  *      file did not exist, it is created.   *      file did not exist, it is created.
Line 1005 
Line 981 
  */   */
 void  void
 Job_Touch(gn, silent)  Job_Touch(gn, silent)
     GNode         *gn;          /* the node of the file to touch */      GNode         *gn;          /* the node of the file to touch */
     Boolean       silent;       /* TRUE if should not print messages */      Boolean       silent;       /* TRUE if should not print messages */
 {  {
     int           streamID;     /* ID of stream opened to do the touch */      int           streamID;     /* ID of stream opened to do the touch */
   
     if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {      if (gn->type & (OP_JOIN|OP_USE|OP_EXEC|OP_OPTIONAL)) {
         /*          /*
Line 1019 
Line 995 
     }      }
   
     if (!silent) {      if (!silent) {
         (void) fprintf(stdout, "touch %s\n", gn->name);          (void)fprintf(stdout, "touch %s\n", gn->name);
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
   
     if (noExecute) {      if (noExecute) {
Line 1032 
Line 1008 
     } else if (gn->type & OP_LIB) {      } else if (gn->type & OP_LIB) {
         Arch_TouchLib(gn);          Arch_TouchLib(gn);
     } else {      } else {
         char    *file = gn->path ? gn->path : gn->name;          const char *file = gn->path != NULL ? gn->path : gn->name;
   
         if (set_times(file) == -1) {          if (set_times(file) == -1){
             streamID = open(file, O_RDWR | O_CREAT, 0666);              streamID = open(file, O_RDWR | O_CREAT, 0666);
   
             if (streamID >= 0) {              if (streamID >= 0) {
Line 1045 
Line 1021 
                  * modification time, then close the file.                   * modification time, then close the file.
                  */                   */
                 if (read(streamID, &c, 1) == 1) {                  if (read(streamID, &c, 1) == 1) {
                     (void) lseek(streamID, 0, SEEK_SET);                      (void)lseek(streamID, 0, SEEK_SET);
                     (void) write(streamID, &c, 1);                      (void)write(streamID, &c, 1);
                 }                  }
   
                 (void) close(streamID);                  (void)close(streamID);
             } else {              } else {
                 (void) fprintf(stdout, "*** couldn't touch %s: %s",                  (void)fprintf(stdout, "*** couldn't touch %s: %s",
                                file, strerror(errno));                                 file, strerror(errno));
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
         }          }
     }      }
Line 1074 
Line 1050 
  */   */
 Boolean  Boolean
 Job_CheckCommands(gn, abortProc)  Job_CheckCommands(gn, abortProc)
     GNode          *gn;             /* The target whose commands need      GNode          *gn;             /* The target whose commands need
                                      * verifying */                                       * verifying */
     void         (*abortProc) __P((char *, ...));      void         (*abortProc)(char *, ...);
                         /* Function to abort with message */                          /* Function to abort with message */
 {  {
     if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&      if (OP_NOP(gn->type) && Lst_IsEmpty(&gn->commands) &&
Line 1085 
Line 1061 
          * No commands. Look for .DEFAULT rule from which we might infer           * No commands. Look for .DEFAULT rule from which we might infer
          * commands           * commands
          */           */
         if ((DEFAULT != NULL) && !Lst_IsEmpty(&DEFAULT->commands)) {          if (DEFAULT != NULL && !Lst_IsEmpty(&DEFAULT->commands)) {
             /*              /*
              * Make only looks for a .DEFAULT if the node was never the               * Make only looks for a .DEFAULT if the node was never the
              * target of an operator, so that's what we do too. If               * target of an operator, so that's what we do too. If
Line 1108 
Line 1084 
             static const char msg[] = "make: don't know how to make";              static const char msg[] = "make: don't know how to make";
   
             if (gn->type & OP_OPTIONAL) {              if (gn->type & OP_OPTIONAL) {
                 (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);                  (void)fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             } else if (keepgoing) {              } else if (keepgoing) {
                 (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);                  (void)fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
                 (void) fflush(stdout);                  (void)fflush(stdout);
                 return FALSE;                  return FALSE;
             } else {              } else {
                 (*abortProc)("%s %s. Stop in %s.", msg, gn->name,                  (*abortProc)("%s %s. Stop in %s.", msg, gn->name,
                         Var_Value(".CURDIR", VAR_GLOBAL));                          Var_Value(".CURDIR"));
                 return FALSE;                  return FALSE;
             }              }
         }          }
Line 1129 
Line 1105 
  * JobLocalInput --   * JobLocalInput --
  *      Handle a pipe becoming readable. Callback function for Rmt_Watch   *      Handle a pipe becoming readable. Callback function for Rmt_Watch
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      JobDoOutput is called.   *      JobDoOutput is called.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 /*ARGSUSED*/  /*ARGSUSED*/
 static void  static void
 JobLocalInput(stream, job)  JobLocalInput(stream, job)
     int     stream;     /* Stream that's ready (ignored) */      int     stream;     /* Stream that's ready (ignored) */
     Job     *job;       /* Job to which the stream belongs */      Job     *job;       /* Job to which the stream belongs */
 {  {
     JobDoOutput(job, FALSE);      JobDoOutput(job, FALSE);
 }  }
Line 1153 
Line 1125 
  *      Execute the shell for the given job. Called from JobStart and   *      Execute the shell for the given job. Called from JobStart and
  *      JobRestart.   *      JobRestart.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      A shell is executed, outputs is altered and the Job structure added   *      A shell is executed, outputs is altered and the Job structure added
  *      to the job table.   *      to the job table.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobExec(job, argv)  JobExec(job, argv)
     Job           *job;         /* Job to execute */      Job           *job;         /* Job to execute */
     char          **argv;      char          **argv;
 {  {
     int           cpid;         /* ID of new child */      int           cpid;         /* ID of new child */
   
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         int       i;          int       i;
   
         (void) fprintf(stdout, "Running %s %sly\n", job->node->name,          (void)fprintf(stdout, "Running %s %sly\n", job->node->name,
                        job->flags&JOB_REMOTE?"remote":"local");                         job->flags&JOB_REMOTE?"remote":"local");
         (void) fprintf(stdout, "\tCommand: ");          (void)fprintf(stdout, "\tCommand: ");
         for (i = 0; argv[i] != NULL; i++) {          for (i = 0; argv[i] != NULL; i++) {
             (void) fprintf(stdout, "%s ", argv[i]);              (void)fprintf(stdout, "%s ", argv[i]);
         }          }
         (void) fprintf(stdout, "\n");          (void)fprintf(stdout, "\n");
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
   
     /*      /*
Line 1188 
Line 1156 
      * banner with their name in it never appears). This is an attempt to       * banner with their name in it never appears). This is an attempt to
      * provide that feedback, even if nothing follows it.       * provide that feedback, even if nothing follows it.
      */       */
     if ((lastNode != job->node) && (job->flags & JOB_FIRST) &&      if (lastNode != job->node && (job->flags & JOB_FIRST) &&
         !(job->flags & JOB_SILENT)) {          !(job->flags & JOB_SILENT)) {
         MESSAGE(stdout, job->node);          MESSAGE(stdout, job->node);
         lastNode = job->node;          lastNode = job->node;
Line 1211 
Line 1179 
          */           */
         if (dup2(FILENO(job->cmdFILE), 0) == -1)          if (dup2(FILENO(job->cmdFILE), 0) == -1)
             Punt("Cannot dup2: %s", strerror(errno));              Punt("Cannot dup2: %s", strerror(errno));
         (void) fcntl(0, F_SETFD, 0);          (void)fcntl(0, F_SETFD, 0);
         (void) lseek(0, 0, SEEK_SET);          (void)lseek(0, 0, SEEK_SET);
   
         if (usePipes) {          if (usePipes) {
             /*              /*
Line 1236 
Line 1204 
          * it before routing the shell's error output to the same place as           * it before routing the shell's error output to the same place as
          * its standard output.           * its standard output.
          */           */
         (void) fcntl(1, F_SETFD, 0);          (void)fcntl(1, F_SETFD, 0);
         if (dup2(1, 2) == -1)          if (dup2(1, 2) == -1)
             Punt("Cannot dup2: %s", strerror(errno));              Punt("Cannot dup2: %s", strerror(errno));
   
Line 1247 
Line 1215 
          * by killing its process family, but not commit suicide.           * by killing its process family, but not commit suicide.
          */           */
 # if defined(SYSV)  # if defined(SYSV)
         (void) setsid();          (void)setsid();
 # else  # else
         (void) setpgid(0, getpid());          (void)setpgid(0, getpid());
 # endif  # endif
 #endif /* USE_PGRP */  #endif /* USE_PGRP */
   
Line 1258 
Line 1226 
             Rmt_Exec(shellPath, argv, FALSE);              Rmt_Exec(shellPath, argv, FALSE);
         } else          } else
 #endif /* REMOTE */  #endif /* REMOTE */
            (void) execv(shellPath, argv);             (void)execv(shellPath, argv);
   
         (void) write(2, "Could not execute shell\n",          (void)write(2, "Could not execute shell\n",
                      sizeof("Could not execute shell"));                       sizeof("Could not execute shell"));
         _exit(1);          _exit(1);
     } else {      } else {
Line 1308 
Line 1276 
              * XXX: Used to not happen if REMOTE. Why?               * XXX: Used to not happen if REMOTE. Why?
              */               */
             if (job->cmdFILE != NULL && job->cmdFILE != stdout) {              if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
                 (void) fclose(job->cmdFILE);                  (void)fclose(job->cmdFILE);
                 job->cmdFILE = NULL;                  job->cmdFILE = NULL;
             }              }
         }          }
 #ifdef REMOTE  #ifdef REMOTE
         (void) sigsetmask(omask);          (void)sigsetmask(omask);
 #endif  #endif
     }      }
   
Line 1334 
Line 1302 
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * JobMakeArgv --   * JobMakeArgv --
  *      Create the argv needed to execute the shell for a given job.   *      Create the argv needed to execute the shell for a given job.
  *  
  *  
  * Results:  
  *  
  * Side Effects:  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobMakeArgv(job, argv)  JobMakeArgv(job, argv)
     Job           *job;      Job           *job;
     char          **argv;      char          **argv;
 {  {
     int           argc;      int           argc;
     static char   args[10];     /* For merged arguments */      static char   args[10];     /* For merged arguments */
   
     argv[0] = shellName;      argv[0] = shellName;
     argc = 1;      argc = 1;
   
     if ((commandShell->exit && (*commandShell->exit != '-')) ||      if ((commandShell->exit && *commandShell->exit != '-') ||
         (commandShell->echo && (*commandShell->echo != '-')))          (commandShell->echo && *commandShell->echo != '-'))
     {      {
         /*          /*
          * At least one of the flags doesn't have a minus before it, so           * At least one of the flags doesn't have a minus before it, so
Line 1390 
Line 1352 
  * JobRestart --   * JobRestart --
  *      Restart a job that stopped for some reason.   *      Restart a job that stopped for some reason.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      jobFull will be set if the job couldn't be run.   *      jobFull will be set if the job couldn't be run.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
 JobRestart(job)  JobRestart(job)
     Job           *job;         /* Job to restart */      Job           *job;         /* Job to restart */
 {  {
 #ifdef REMOTE  #ifdef REMOTE
     int host;      int host;
Line 1412 
Line 1370 
             verboseRemigrates ||              verboseRemigrates ||
 #endif  #endif
             DEBUG(JOB)) {              DEBUG(JOB)) {
            (void) fprintf(stdout, "*** remigrating %x(%s)\n",             (void)fprintf(stdout, "*** remigrating %x(%s)\n",
                            job->pid, job->node->name);                             job->pid, job->node->name);
            (void) fflush(stdout);             (void)fflush(stdout);
         }          }
   
 #ifdef REMOTE  #ifdef REMOTE
         if (!Rmt_ReExport(job->pid, job->node, &host)) {          if (!Rmt_ReExport(job->pid, job->node, &host)) {
             if (verboseRemigrates || DEBUG(JOB)) {              if (verboseRemigrates || DEBUG(JOB)) {
                 (void) fprintf(stdout, "*** couldn't migrate...\n");                  (void)fprintf(stdout, "*** couldn't migrate...\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
 #endif  #endif
             if (nLocal != maxLocal) {              if (nLocal != maxLocal) {
Line 1435 
Line 1393 
                     verboseRemigrates ||                      verboseRemigrates ||
 #endif  #endif
                     DEBUG(JOB)) {                      DEBUG(JOB)) {
                     (void) fprintf(stdout, "*** resuming on local machine\n");                      (void)fprintf(stdout, "*** resuming on local machine\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 KILL(job->pid, SIGCONT);                  KILL(job->pid, SIGCONT);
                 nLocal +=1;                  nLocal +=1;
Line 1456 
Line 1414 
                     verboseRemigrates ||                      verboseRemigrates ||
 #endif  #endif
                     DEBUG(JOB)) {                      DEBUG(JOB)) {
                    (void) fprintf(stdout, "*** holding\n");                     (void)fprintf(stdout, "*** holding\n");
                    (void) fflush(stdout);                     (void)fflush(stdout);
                 }                  }
                 Lst_AtFront(&stoppedJobs, job);                  Lst_AtFront(&stoppedJobs, job);
                 jobFull = TRUE;                  jobFull = TRUE;
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                    (void) fprintf(stdout, "Job queue is full.\n");                     (void)fprintf(stdout, "Job queue is full.\n");
                    (void) fflush(stdout);                     (void)fflush(stdout);
                 }                  }
                 return;                  return;
             }              }
Line 1485 
Line 1443 
         if (nJobs == maxJobs) {          if (nJobs == maxJobs) {
             jobFull = TRUE;              jobFull = TRUE;
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "Job queue is full.\n");                  (void)fprintf(stdout, "Job queue is full.\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
         }          }
     } else if (job->flags & JOB_RESTART) {      } else if (job->flags & JOB_RESTART) {
Line 1503 
Line 1461 
         JobMakeArgv(job, argv);          JobMakeArgv(job, argv);
   
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
             (void) fprintf(stdout, "Restarting %s...", job->node->name);              (void)fprintf(stdout, "Restarting %s...", job->node->name);
             (void) fflush(stdout);              (void)fflush(stdout);
         }          }
 #ifdef REMOTE  #ifdef REMOTE
         if ((job->node->type&OP_NOEXPORT) ||          if ((job->node->type&OP_NOEXPORT) ||
             (nLocal < maxLocal && runLocalFirst)              (nLocal < maxLocal && runLocalFirst)
 # ifdef RMT_NO_EXEC  # ifdef RMT_NO_EXEC
             || !Rmt_Export(shellPath, argv, job)              || !Rmt_Export(shellPath, argv, job)
 # else  # else
Line 1516 
Line 1474 
 # endif  # endif
 #endif  #endif
         {          {
             if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) {              if (nLocal >= maxLocal && !(job->flags & JOB_SPECIAL)) {
                 /*                  /*
                  * Can't be exported and not allowed to run locally -- put it                   * Can't be exported and not allowed to run locally -- put it
                  * back on the hold queue and mark the table full                   * back on the hold queue and mark the table full
                  */                   */
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout, "holding\n");                      (void)fprintf(stdout, "holding\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 Lst_AtFront(&stoppedJobs, job);                  Lst_AtFront(&stoppedJobs, job);
                 jobFull = TRUE;                  jobFull = TRUE;
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout, "Job queue is full.\n");                      (void)fprintf(stdout, "Job queue is full.\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 return;                  return;
             } else {              } else {
Line 1537 
Line 1495 
                  * Job may be run locally.                   * Job may be run locally.
                  */                   */
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout, "running locally\n");                      (void)fprintf(stdout, "running locally\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 job->flags &= ~JOB_REMOTE;                  job->flags &= ~JOB_REMOTE;
             }              }
Line 1549 
Line 1507 
              * Can be exported. Hooray!               * Can be exported. Hooray!
              */               */
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "exporting\n");                  (void)fprintf(stdout, "exporting\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             job->flags |= JOB_REMOTE;              job->flags |= JOB_REMOTE;
         }          }
Line 1562 
Line 1520 
          * we don't know...           * we don't know...
          */           */
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
            (void) fprintf(stdout, "Resuming %s...", job->node->name);             (void)fprintf(stdout, "Resuming %s...", job->node->name);
            (void) fflush(stdout);             (void)fflush(stdout);
         }          }
         if (((job->flags & JOB_REMOTE) ||          if (((job->flags & JOB_REMOTE) ||
             (nLocal < maxLocal) ||              nLocal < maxLocal ||
 #ifdef REMOTE  #ifdef REMOTE
             (((job->flags & JOB_SPECIAL) &&              ((job->flags & JOB_SPECIAL) &&
               (job->node->type & OP_NOEXPORT)) &&                (job->node->type & OP_NOEXPORT) &&
              (maxLocal == 0))) &&               maxLocal == 0)
 #else  #else
             ((job->flags & JOB_SPECIAL) &&              ((job->flags & JOB_SPECIAL) &&
              (maxLocal == 0))) &&               maxLocal == 0)
 #endif  #endif
            (nJobs != maxJobs))             ) && nJobs != maxJobs)
         {          {
             /*              /*
              * If the job is remote, it's ok to resume it as long as the               * If the job is remote, it's ok to resume it as long as the
Line 1592 
Line 1550 
                 error = !Rmt_Signal(job, SIGCONT);                  error = !Rmt_Signal(job, SIGCONT);
             } else              } else
 #endif  /* RMT_WANTS_SIGNALS */  #endif  /* RMT_WANTS_SIGNALS */
                 error = (KILL(job->pid, SIGCONT) != 0);                  error = KILL(job->pid, SIGCONT) != 0;
   
             if (!error) {              if (!error) {
                 /*                  /*
Line 1605 
Line 1563 
   
                 job->flags &= ~(JOB_RESUME|JOB_CONTINUING);                  job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                    (void) fprintf(stdout, "done\n");                     (void)fprintf(stdout, "done\n");
                    (void) fflush(stdout);                     (void)fflush(stdout);
                 }                  }
             } else {              } else {
                 Error("couldn't resume %s: %s",                  Error("couldn't resume %s: %s",
Line 1621 
Line 1579 
              * place the job back on the list of stopped jobs.               * place the job back on the list of stopped jobs.
              */               */
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "table full\n");                  (void)fprintf(stdout, "table full\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             Lst_AtFront(&stoppedJobs, job);              Lst_AtFront(&stoppedJobs, job);
             jobFull = TRUE;              jobFull = TRUE;
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "Job queue is full.\n");                  (void)fprintf(stdout, "Job queue is full.\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
         }          }
     }      }
Line 1652 
Line 1610 
  */   */
 static int  static int
 JobStart(gn, flags, previous)  JobStart(gn, flags, previous)
     GNode         *gn;        /* target to create */      GNode         *gn;        /* target to create */
     int            flags;      /* flags for the job to override normal ones.      int            flags;      /* flags for the job to override normal ones.
                                * e.g. JOB_SPECIAL or JOB_IGNDOTS */                                 * e.g. JOB_SPECIAL or JOB_IGNDOTS */
     Job           *previous;  /* The previous Job structure for this node,      Job           *previous;  /* The previous Job structure for this node,
                                * if any. */                                 * if any. */
 {  {
     register Job  *job;       /* new job descriptor */      Job           *job;       /* new job descriptor */
     char          *argv[4];   /* Argument vector to shell */      char          *argv[4];   /* Argument vector to shell */
     Boolean       cmdsOK;     /* true if the nodes commands were all right */      Boolean       cmdsOK;     /* true if the nodes commands were all right */
     Boolean       local;      /* Set true if the job was run locally */      Boolean       local;      /* Set true if the job was run locally */
     Boolean       noExec;     /* Set true if we decide not to run the job */      Boolean       noExec;     /* Set true if we decide not to run the job */
     int           tfd;        /* where to stash those pesky commands */  
   
     if (previous != NULL) {      if (previous != NULL) {
         previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);          previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
         job = previous;          job = previous;
     } else {      } else {
         job = (Job *) emalloc(sizeof(Job));          job = emalloc(sizeof(Job));
         if (job == NULL) {          if (job == NULL) {
             Punt("JobStart out of memory");              Punt("JobStart out of memory");
         }          }
Line 1718 
Line 1675 
             DieHorribly();              DieHorribly();
         }          }
   
         (void) strcpy(tfile, TMPPAT);          job->cmdFILE = fopen(tfile, "w+");
         if ((tfd = mkstemp(tfile)) == -1)  
             Punt("Cannot create temp file: %s", strerror(errno));  
         job->cmdFILE = fdopen(tfd, "w+");  
         eunlink(tfile);  
         if (job->cmdFILE == NULL) {          if (job->cmdFILE == NULL) {
             close(tfd);  
             Punt("Could not open %s", tfile);              Punt("Could not open %s", tfile);
         }          }
         (void) fcntl(FILENO(job->cmdFILE), F_SETFD, 1);          (void)fcntl(FILENO(job->cmdFILE), F_SETFD, 1);
         /*          /*
          * Send the commands to the command file, flush all its buffers then           * Send the commands to the command file, flush all its buffers then
          * rewind and remove the thing.           * rewind and remove the thing.
Line 1739 
Line 1691 
          * per shell.           * per shell.
          */           */
         if (compatMake) {          if (compatMake) {
             LstNode ln;  
             /*              /*
              * Be compatible: If this is the first time for this node,               * Be compatible: If this is the first time for this node,
              * verify its commands are ok and open the commands list for               * verify its commands are ok and open the commands list for
Line 1749 
Line 1700 
              * ellipsis, note that there's nothing more to execute.               * ellipsis, note that there's nothing more to execute.
              */               */
             if ((job->flags&JOB_FIRST))              if ((job->flags&JOB_FIRST))
                 Lst_Open(&gn->commands);                  gn->current = Lst_First(&gn->commands);
             ln = Lst_Next(&gn->commands);              else
                   gn->current = Lst_Succ(gn->current);
   
             if ((ln == NULL) || !JobPrintCommand(Lst_Datum(ln), job)) {              if (gn->current == NULL ||
                   !JobPrintCommand(Lst_Datum(gn->current), job)) {
                 noExec = TRUE;                  noExec = TRUE;
                 Lst_Close(&gn->commands);                  gn->current = NULL;
             }              }
             if (noExec && !(job->flags & JOB_FIRST)) {              if (noExec && !(job->flags & JOB_FIRST)) {
                 /*                  /*
Line 1800 
Line 1753 
          * not -- just let the user know they're bad and keep going. It           * not -- just let the user know they're bad and keep going. It
          * doesn't do any harm in this case and may do some good.           * doesn't do any harm in this case and may do some good.
          */           */
         if (cmdsOK)          if (cmdsOK) {
             Lst_Find(&gn->commands, JobPrintCommand, job);              Lst_Find(&gn->commands, JobPrintCommand, job);
           }
         /*          /*
          * Don't execute the shell, thank you.           * Don't execute the shell, thank you.
          */           */
Line 1814 
Line 1768 
          * up the graph.           * up the graph.
          */           */
         job->cmdFILE = stdout;          job->cmdFILE = stdout;
         Job_Touch(gn, job->flags&JOB_SILENT);          Job_Touch(gn, job->flags&JOB_SILENT);
         noExec = TRUE;          noExec = TRUE;
     }      }
   
Line 1826 
Line 1780 
          * Unlink and close the command file if we opened one           * Unlink and close the command file if we opened one
          */           */
         if (job->cmdFILE != stdout) {          if (job->cmdFILE != stdout) {
               (void)eunlink(tfile);
             if (job->cmdFILE != NULL)              if (job->cmdFILE != NULL)
                 (void) fclose(job->cmdFILE);                  (void)fclose(job->cmdFILE);
         } else {          } else {
              (void) fflush(stdout);               (void)fflush(stdout);
         }          }
   
         /*          /*
Line 1838 
Line 1793 
          */           */
         if (cmdsOK) {          if (cmdsOK) {
             if (aborting == 0) {              if (aborting == 0) {
                 Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node);                  Lst_ForEachFrom(job->tailCmds, JobSaveCommand, job->node);
                 Make_Update(job->node);                  Make_Update(job->node);
             }              }
             free(job);              free(job);
Line 1848 
Line 1803 
             return JOB_ERROR;              return JOB_ERROR;
         }          }
     } else {      } else {
         (void) fflush(job->cmdFILE);          (void)fflush(job->cmdFILE);
           (void)eunlink(tfile);
     }      }
   
     /*      /*
Line 1869 
Line 1825 
                 Punt("Cannot create pipe: %s", strerror(errno));                  Punt("Cannot create pipe: %s", strerror(errno));
             job->inPipe = fd[0];              job->inPipe = fd[0];
             job->outPipe = fd[1];              job->outPipe = fd[1];
             (void) fcntl(job->inPipe, F_SETFD, 1);              (void)fcntl(job->inPipe, F_SETFD, 1);
             (void) fcntl(job->outPipe, F_SETFD, 1);              (void)fcntl(job->outPipe, F_SETFD, 1);
         } else {          } else {
             (void) fprintf(stdout, "Remaking `%s'\n", gn->name);              (void)fprintf(stdout, "Remaking `%s'\n", gn->name);
             (void) fflush(stdout);              (void)fflush(stdout);
             (void) strcpy(job->outFile, TMPPAT);              (void)strcpy(job->outFile, TMPPAT);
             if ((job->outFd = mkstemp(job->outFile)) == -1)              if ((job->outFd = mkstemp(job->outFile)) == -1)
                 Punt("Cannot create temp file: %s", strerror(errno));                  Punt("Cannot create temp file: %s", strerror(errno));
             (void) fcntl(job->outFd, F_SETFD, 1);              (void)fcntl(job->outFd, F_SETFD, 1);
         }          }
     }      }
   
Line 1895 
Line 1851 
 #endif  #endif
         local = TRUE;          local = TRUE;
   
     if (local && (((nLocal >= maxLocal) &&      if (local && nLocal >= maxLocal &&
         !(job->flags & JOB_SPECIAL) &&          !(job->flags & JOB_SPECIAL) &&
 #ifdef REMOTE  #ifdef REMOTE
         (!(gn->type & OP_NOEXPORT) || (maxLocal != 0))          (!(gn->type & OP_NOEXPORT) || maxLocal != 0)
 #else  #else
         (maxLocal != 0)          maxLocal != 0
 #endif  #endif
         )))          )
     {      {
         /*          /*
          * The job can only be run locally, but we've hit the limit of           * The job can only be run locally, but we've hit the limit of
Line 1916 
Line 1872 
         jobFull = TRUE;          jobFull = TRUE;
   
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
            (void) fprintf(stdout, "Can only run job locally.\n");             (void)fprintf(stdout, "Can only run job locally.\n");
            (void) fflush(stdout);             (void)fflush(stdout);
         }          }
         job->flags |= JOB_RESTART;          job->flags |= JOB_RESTART;
         Lst_AtEnd(&stoppedJobs, job);          Lst_AtEnd(&stoppedJobs, job);
     } else {      } else {
         if ((nLocal >= maxLocal) && local) {          if (nLocal >= maxLocal && local) {
             /*              /*
              * If we're running this job locally as a special case (see above),               * If we're running this job locally as a special case (see above),
              * at least say the table is full.               * at least say the table is full.
              */               */
             jobFull = TRUE;              jobFull = TRUE;
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "Local job queue is full.\n");                  (void)fprintf(stdout, "Local job queue is full.\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
         }          }
         JobExec(job, argv);          JobExec(job, argv);
     }      }
     return(JOB_RUNNING);      return JOB_RUNNING;
 }  }
   
 static char *  static char *
 JobOutput(job, cp, endp, msg)  JobOutput(job, cp, endp, msg)
     register Job *job;      Job *job;
     register char *cp, *endp;      char *cp, *endp;
     int msg;      int msg;
 {  {
     register char *ecp;      char *ecp;
   
     if (commandShell->noPrint) {      if (commandShell->noPrint) {
         ecp = strstr(cp, commandShell->noPrint);          ecp = strstr(cp, commandShell->noPrint);
Line 1961 
Line 1917 
                  * however, since the non-printable comes after it,                   * however, since the non-printable comes after it,
                  * there must be a newline, so we don't print one.                   * there must be a newline, so we don't print one.
                  */                   */
                 (void) fprintf(stdout, "%s", cp);                  (void)fprintf(stdout, "%s", cp);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             cp = ecp + commandShell->noPLen;              cp = ecp + commandShell->noPLen;
             if (cp != endp) {              if (cp != endp) {
Line 1986 
Line 1942 
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * JobDoOutput  --   * JobDoOutput  --
  *      This function is called at different times depending on   *      This function is called at different times depending on
  *      whether the user has specified that output is to be collected   *      whether the user has specified that output is to be collected
  *      via pipes or temporary files. In the former case, we are called   *      via pipes or temporary files. In the former case, we are called
Line 2004 
Line 1960 
  *      alone on the line (the character after it is not \0 or \n), we   *      alone on the line (the character after it is not \0 or \n), we
  *      do print whatever follows it.   *      do print whatever follows it.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      curPos may be shifted as may the contents of outBuf.   *      curPos may be shifted as may the contents of outBuf.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 STATIC void  STATIC void
 JobDoOutput(job, finish)  JobDoOutput(job, finish)
     register Job   *job;          /* the job whose output needs printing */      Job           *job;   /* the job whose output needs printing */
     Boolean        finish;        /* TRUE if this is the last time we'll be      Boolean        finish;        /* TRUE if this is the last time we'll be
                                    * called for this job */                                     * called for this job */
 {  {
     Boolean       gotNL = FALSE;  /* true if got a newline */      Boolean       gotNL = FALSE;  /* true if got a newline */
     Boolean       fbuf;           /* true if our buffer filled up */      Boolean       fbuf;           /* true if our buffer filled up */
     register int  nr;             /* number of bytes read */      int           nr;             /* number of bytes read */
     register int  i;              /* auxiliary index into outBuf */      int           i;              /* auxiliary index into outBuf */
     register int  max;            /* limit for i (end of current data) */      int           max;            /* limit for i (end of current data) */
     int           nRead;          /* (Temporary) number of bytes read */      int           nRead;          /* (Temporary) number of bytes read */
   
     FILE          *oFILE;         /* Stream pointer to shell's output file */      FILE          *oFILE;         /* Stream pointer to shell's output file */
     char          inLine[132];      char          inLine[132];
   
   
     if (usePipes) {      if (usePipes) {
Line 2038 
Line 1991 
   
         nRead = read(job->inPipe, &job->outBuf[job->curPos],          nRead = read(job->inPipe, &job->outBuf[job->curPos],
                          JOB_BUFSIZE - job->curPos);                           JOB_BUFSIZE - job->curPos);
         if (nRead < 0) {          if (nRead == -1) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 perror("JobDoOutput(piperead)");                  perror("JobDoOutput(piperead)");
             }              }
Line 2053 
Line 2006 
          * output remaining in the buffer.           * output remaining in the buffer.
          * Also clear the 'finish' flag so we stop looping.           * Also clear the 'finish' flag so we stop looping.
          */           */
         if ((nr == 0) && (job->curPos != 0)) {          if (nr == 0 && job->curPos != 0) {
             job->outBuf[job->curPos] = '\n';              job->outBuf[job->curPos] = '\n';
             nr = 1;              nr = 1;
             finish = FALSE;              finish = FALSE;
Line 2117 
Line 2070 
                         MESSAGE(stdout, job->node);                          MESSAGE(stdout, job->node);
                         lastNode = job->node;                          lastNode = job->node;
                     }                      }
                     (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");                      (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
             }              }
             if (i < max - 1) {              if (i < max - 1) {
                 /* shift the remaining characters down */                  /* shift the remaining characters down */
                 (void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));                  (void)memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
                 job->curPos = max - (i + 1);                  job->curPos = max - (i + 1);
   
             } else {              } else {
Line 2158 
Line 2111 
          */           */
         oFILE = fopen(job->outFile, "r");          oFILE = fopen(job->outFile, "r");
         if (oFILE != NULL) {          if (oFILE != NULL) {
             (void) fprintf(stdout, "Results of making %s:\n", job->node->name);              (void)fprintf(stdout, "Results of making %s:\n", job->node->name);
             (void) fflush(stdout);              (void)fflush(stdout);
             while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {              while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {
                 register char   *cp, *endp, *oendp;                  char    *cp, *endp, *oendp;
   
                 cp = inLine;                  cp = inLine;
                 oendp = endp = inLine + strlen(inLine);                  oendp = endp = inLine + strlen(inLine);
Line 2175 
Line 2128 
                  * we know there's no newline at the end, so we add one of                   * we know there's no newline at the end, so we add one of
                  * our own free will.                   * our own free will.
                  */                   */
                 (void) fprintf(stdout, "%s", cp);                  (void)fprintf(stdout, "%s", cp);
                 (void) fflush(stdout);                  (void)fflush(stdout);
                 if (endp != oendp) {                  if (endp != oendp) {
                     (void) fprintf(stdout, "\n");                      (void)fprintf(stdout, "\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
             }              }
             (void) fclose(oFILE);              (void)fclose(oFILE);
             (void) eunlink(job->outFile);              (void)eunlink(job->outFile);
         }          }
     }      }
 }  }
Line 2193 
Line 2146 
  * Job_CatchChildren --   * Job_CatchChildren --
  *      Handle the exit of a child. Called from Make_Make.   *      Handle the exit of a child. Called from Make_Make.
  *   *
  * Results:  
  *      none.  
  *  
  * Side Effects:   * Side Effects:
  *      The job descriptor is removed from the list of children.   *      The job descriptor is removed from the list of children.
  *   *
Line 2204 
Line 2154 
  *      caller, until there are no more children to report. For each   *      caller, until there are no more children to report. For each
  *      job, call JobFinish to finish things off. This will take care of   *      job, call JobFinish to finish things off. This will take care of
  *      putting jobs on the stoppedJobs queue.   *      putting jobs on the stoppedJobs queue.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Job_CatchChildren(block)  Job_CatchChildren(block)
     Boolean       block;        /* TRUE if should block on the wait. */      Boolean       block;        /* TRUE if should block on the wait. */
 {  {
     int           pid;          /* pid of dead child */      int           pid;          /* pid of dead child */
     register Job  *job;         /* job descriptor for dead child */      Job           *job;         /* job descriptor for dead child */
     LstNode       jnode;        /* list element for finding job */      LstNode       jnode;        /* list element for finding job */
     int           status;       /* Exit/termination status */      int           status;       /* Exit/termination status */
   
     /*      /*
      * Don't even bother if we know there's no one around.       * Don't even bother if we know there's no one around.
Line 2227 
Line 2176 
                           (block?0:WNOHANG)|WUNTRACED)) > 0)                            (block?0:WNOHANG)|WUNTRACED)) > 0)
     {      {
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
             (void) fprintf(stdout, "Process %d exited or stopped.\n", pid);              (void)fprintf(stdout, "Process %d exited or stopped.\n", pid);
             (void) fflush(stdout);              (void)fflush(stdout);
         }          }
   
   
Line 2252 
Line 2201 
             Lst_Remove(&jobs, jnode);              Lst_Remove(&jobs, jnode);
             nJobs -= 1;              nJobs -= 1;
             if (jobFull && DEBUG(JOB)) {              if (jobFull && DEBUG(JOB)) {
                 (void) fprintf(stdout, "Job queue is no longer full.\n");                  (void)fprintf(stdout, "Job queue is no longer full.\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             jobFull = FALSE;              jobFull = FALSE;
 #ifdef REMOTE  #ifdef REMOTE
             if (!(job->flags & JOB_REMOTE)) {              if (!(job->flags & JOB_REMOTE)) {
                 if (DEBUG(JOB)) {                  if (DEBUG(JOB)) {
                     (void) fprintf(stdout,                      (void)fprintf(stdout,
                                    "Job queue has one fewer local process.\n");                                     "Job queue has one fewer local process.\n");
                     (void) fflush(stdout);                      (void)fflush(stdout);
                 }                  }
                 nLocal -= 1;                  nLocal -= 1;
             }              }
Line 2283 
Line 2232 
  *      just spinning when there's nothing to do and the reaping   *      just spinning when there's nothing to do and the reaping
  *      of a child can wait for a while.   *      of a child can wait for a while.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      Output is read from pipes if we're piping.   *      Output is read from pipes if we're piping.
  * -----------------------------------------------------------------------   * -----------------------------------------------------------------------
Line 2293 
Line 2239 
 void  void
 Job_CatchOutput()  Job_CatchOutput()
 {  {
     int                   nfds;      int                   nfds;
     struct timeval        timeout;      struct timeval        timeout;
     register LstNode      ln;      LstNode               ln;
     register Job          *job;      Job                   *job;
 #ifdef RMT_WILL_WATCH  #ifdef RMT_WILL_WATCH
     int                   pnJobs;       /* Previous nJobs */      int                   pnJobs;       /* Previous nJobs */
 #endif  #endif
   
     (void) fflush(stdout);      (void)fflush(stdout);
 #ifdef RMT_WILL_WATCH  #ifdef RMT_WILL_WATCH
     pnJobs = nJobs;      pnJobs = nJobs;
   
Line 2340 
Line 2286 
             free(readfdsp);              free(readfdsp);
             return;              return;
         } else {          } else {
             Lst_Open(&jobs);              for (ln = Lst_First(&jobs); nfds && ln != NULL; ln = Lst_Adv(ln)) {
             while (nfds && (ln = Lst_Next(&jobs)) != NULL) {  
                 job = (Job *)Lst_Datum(ln);                  job = (Job *)Lst_Datum(ln);
                 if (FD_ISSET(job->inPipe, readfdsp)) {                  if (FD_ISSET(job->inPipe, readfdsp)) {
                     JobDoOutput(job, FALSE);                      JobDoOutput(job, FALSE);
                     nfds -= 1;                      nfds -= 1;
                 }                  }
             }              }
             Lst_Close(&jobs);  
         }          }
         free(readfdsp);          free(readfdsp);
     }      }
Line 2361 
Line 2305 
  *      Start the creation of a target. Basically a front-end for   *      Start the creation of a target. Basically a front-end for
  *      JobStart used by the Make module.   *      JobStart used by the Make module.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Another job is started.   *      Another job is started.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Job_Make(gn)  Job_Make(gn)
     GNode   *gn;      GNode   *gn;
 {  {
     (void) JobStart(gn, 0, NULL);      (void)JobStart(gn, 0, NULL);
 }  }
   
 /*-  /*-
Line 2381 
Line 2321 
  * Job_Init --   * Job_Init --
  *      Initialize the process module   *      Initialize the process module
  *   *
  * Results:  
  *      none  
  *  
  * Side Effects:   * Side Effects:
  *      lists and counters are initialized   *      lists and counters are initialized
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 Job_Init(maxproc, maxlocal)  Job_Init(maxproc, maxlocal)
     int           maxproc;  /* the greatest number of jobs which may be      int           maxproc;  /* the greatest number of jobs which may be
                              * running at one time */                               * running at one time */
     int           maxlocal; /* the greatest number of local jobs which may      int           maxlocal; /* the greatest number of local jobs which may
                              * be running at once. */                               * be running at once. */
 {  {
     GNode         *begin;     /* node for commands to do at the very start */      GNode         *begin;     /* node for commands to do at the very start */
       int           tfd;
   
       (void)strcpy(tfile, TMPPAT);
       if ((tfd = mkstemp(tfile)) == -1)
           Punt("Cannot create temp file: %s", strerror(errno));
       else
           (void)close(tfd);
   
     Lst_Init(&jobs);      Lst_Init(&jobs);
     Lst_Init(&stoppedJobs);      Lst_Init(&stoppedJobs);
     maxJobs =     maxproc;      maxJobs =     maxproc;
     maxLocal =    maxlocal;      maxLocal =    maxlocal;
     nJobs =       0;      nJobs =       0;
     nLocal =      0;      nLocal =      0;
     jobFull =     FALSE;      jobFull =     FALSE;
   
     aborting =    0;      aborting =    0;
     errors =      0;      errors =      0;
   
     lastNode =    NULL;      lastNode =    NULL;
   
Line 2448 
Line 2392 
      * JobPassSig will take care of calling JobInterrupt if appropriate.       * JobPassSig will take care of calling JobInterrupt if appropriate.
      */       */
     if (signal(SIGINT, SIG_IGN) != SIG_IGN) {      if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGINT, JobPassSig);          (void)signal(SIGINT, JobPassSig);
     }      }
     if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {      if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGHUP, JobPassSig);          (void)signal(SIGHUP, JobPassSig);
     }      }
     if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {      if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGQUIT, JobPassSig);          (void)signal(SIGQUIT, JobPassSig);
     }      }
     if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {      if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGTERM, JobPassSig);          (void)signal(SIGTERM, JobPassSig);
     }      }
     /*      /*
      * There are additional signals that need to be caught and passed if       * There are additional signals that need to be caught and passed if
Line 2467 
Line 2411 
      */       */
 #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)  #if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)
     if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) {      if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGTSTP, JobPassSig);          (void)signal(SIGTSTP, JobPassSig);
     }      }
     if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) {      if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGTTOU, JobPassSig);          (void)signal(SIGTTOU, JobPassSig);
     }      }
     if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) {      if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGTTIN, JobPassSig);          (void)signal(SIGTTIN, JobPassSig);
     }      }
     if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) {      if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) {
         (void) signal(SIGWINCH, JobPassSig);          (void)signal(SIGWINCH, JobPassSig);
     }      }
 #endif  #endif
   
     begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);      begin = Targ_FindNode(".BEGIN", NULL, TARG_NOCREATE);
   
     if (begin != NULL) {      if (begin != NULL) {
         JobStart(begin, JOB_SPECIAL, (Job *)0);          JobStart(begin, JOB_SPECIAL, (Job *)0);
Line 2491 
Line 2435 
 #endif /* RMT_WILL_WATCH */  #endif /* RMT_WILL_WATCH */
         }          }
     }      }
     postCommands = Targ_FindNode(".END", TARG_CREATE);      postCommands = Targ_FindNode(".END", NULL, TARG_CREATE);
 }  }
   
 /*-  /*-
Line 2504 
Line 2448 
  *   *
  * Results:   * Results:
  *      TRUE if the job table is full, FALSE otherwise   *      TRUE if the job table is full, FALSE otherwise
  * Side Effects:  
  *      None.  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 Boolean  Boolean
 Job_Full()  Job_Full()
 {  {
     return(aborting || jobFull);      return aborting || jobFull;
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Job_Empty --   * Job_Empty --
  *      See if the job table is empty.  Because the local concurrency may   *      See if the job table is empty.  Because the local concurrency may
  *      be set to 0, it is possible for the job table to become empty,   *      be set to 0, it is possible for the job table to become empty,
  *      while the list of stoppedJobs remains non-empty. In such a case,   *      while the list of stoppedJobs remains non-empty. In such a case,
  *      we want to restart as many jobs as we can.   *      we want to restart as many jobs as we can.
  *   *
  * Results:   * Results:
  *      TRUE if it is. FALSE if it ain't.   *      TRUE if it is. FALSE if it ain't.
  *  
  * Side Effects:  
  *      None.  
  *  
  * -----------------------------------------------------------------------   * -----------------------------------------------------------------------
  */   */
 Boolean  Boolean
Line 2541 
Line 2479 
              */               */
             jobFull = FALSE;              jobFull = FALSE;
             JobRestartJobs();              JobRestartJobs();
             return(FALSE);              return FALSE;
         } else {          } else {
             return(TRUE);              return TRUE;
         }          }
     } else {      } else {
         return(FALSE);          return FALSE;
     }      }
 }  }
   
Line 2557 
Line 2495 
  *   *
  * Results:   * Results:
  *      A pointer to the Shell structure.   *      A pointer to the Shell structure.
  *  
  * Side Effects:  
  *      None.  
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static Shell *  static Shell *
 JobMatchShell(name)  JobMatchShell(name)
     char          *name;      /* Final component of shell path */      char          *name;      /* Final component of shell path */
 {  {
     register Shell *sh;       /* Pointer into shells table */      Shell         *sh;        /* Pointer into shells table */
     Shell          *match;    /* Longest-matching shell */      Shell         *match;     /* Longest-matching shell */
     register char *cp1,      char          *cp1,
                   *cp2;                    *cp2;
     char          *eoname;      char          *eoname;
   
Line 2589 
Line 2523 
            match = sh;             match = sh;
         }          }
     }      }
     return(match == NULL ? sh : match);      return match == NULL ? sh : match;
 }  }
   
 /*-  /*-
Line 2615 
Line 2549 
  *      provides the functionality it does in C. Each word consists of   *      provides the functionality it does in C. Each word consists of
  *      keyword and value separated by an equal sign. There should be no   *      keyword and value separated by an equal sign. There should be no
  *      unnecessary spaces in the word. The keywords are as follows:   *      unnecessary spaces in the word. The keywords are as follows:
  *          name            Name of shell.   *          name            Name of shell.
  *          path            Location of shell. Overrides "name" if given   *          path            Location of shell. Overrides "name" if given
  *          quiet           Command to turn off echoing.   *          quiet           Command to turn off echoing.
  *          echo            Command to turn echoing on   *          echo            Command to turn echoing on
  *          filter          Result of turning off echoing that shouldn't be   *          filter          Result of turning off echoing that shouldn't be
  *                          printed.   *                          printed.
  *          echoFlag        Flag to turn echoing on at the start   *          echoFlag        Flag to turn echoing on at the start
  *          errFlag         Flag to turn error checking on at the start   *          errFlag         Flag to turn error checking on at the start
  *          hasErrCtl       True if shell has error checking control   *          hasErrCtl       True if shell has error checking control
  *          check           Command to turn on error checking if hasErrCtl   *          check           Command to turn on error checking if hasErrCtl
  *                          is TRUE or template of command to echo a command   *                          is TRUE or template of command to echo a command
  *                          for which error checking is off if hasErrCtl is   *                          for which error checking is off if hasErrCtl is
  *                          FALSE.   *                          FALSE.
  *          ignore          Command to turn off error checking if hasErrCtl   *          ignore          Command to turn off error checking if hasErrCtl
  *                          is TRUE or template of command to execute a   *                          is TRUE or template of command to execute a
  *                          command so as to ignore any errors it returns if   *                          command so as to ignore any errors it returns if
  *                          hasErrCtl is FALSE.   *                          hasErrCtl is FALSE.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 ReturnStatus  ReturnStatus
 Job_ParseShell(line)  Job_ParseShell(line)
     char          *line;  /* The shell spec */      char          *line;  /* The shell spec */
 {  {
     char          **words;      char          **words;
     int           wordCount;      int           wordCount;
     register char **argv;      char          **argv;
     register int  argc;      int           argc;
     char          *path;      char          *path;
     Shell         newShell;      Shell         newShell;
     Boolean       fullSpec = FALSE;      Boolean       fullSpec = FALSE;
   
     while (isspace(*line)) {      while (isspace(*line)) {
         line++;          line++;
     }      }
   
     efree(shellArgv);      efree(shellArgv);
   
     words = brk_string(line, &wordCount, TRUE, &shellArgv);  
   
       words = brk_string(line, &wordCount, &shellArgv);
   
     memset(&newShell, 0, sizeof(newShell));      memset(&newShell, 0, sizeof(newShell));
   
     /*      /*
Line 2681 
Line 2614 
                      newShell.exit = &argv[0][8];                       newShell.exit = &argv[0][8];
                  } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) {                   } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) {
                      char c = argv[0][10];                       char c = argv[0][10];
                      newShell.hasErrCtl = !((c != 'Y') && (c != 'y') &&                       newShell.hasErrCtl = !(c != 'Y' && c != 'y' &&
                                            (c != 'T') && (c != 't'));                                             c != 'T' && c != 't');
                  } else if (strncmp(*argv, "check=", 6) == 0) {                   } else if (strncmp(*argv, "check=", 6) == 0) {
                      newShell.errCheck = &argv[0][6];                       newShell.errCheck = &argv[0][6];
                  } else if (strncmp(*argv, "ignore=", 7) == 0) {                   } else if (strncmp(*argv, "ignore=", 7) == 0) {
Line 2691 
Line 2624 
                      Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",                       Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",
                                   *argv);                                    *argv);
                      free(words);                       free(words);
                      return(FAILURE);                       return FAILURE;
                  }                   }
                  fullSpec = TRUE;                   fullSpec = TRUE;
              }               }
Line 2706 
Line 2639 
          */           */
         if (newShell.name == NULL) {          if (newShell.name == NULL) {
             Parse_Error(PARSE_FATAL, "Neither path nor name specified");              Parse_Error(PARSE_FATAL, "Neither path nor name specified");
             return(FAILURE);              return FAILURE;
         } else {          } else {
             commandShell = JobMatchShell(newShell.name);              commandShell = JobMatchShell(newShell.name);
             shellName = newShell.name;              shellName = newShell.name;
Line 2734 
Line 2667 
         if (!fullSpec) {          if (!fullSpec) {
             commandShell = JobMatchShell(shellName);              commandShell = JobMatchShell(shellName);
         } else {          } else {
             commandShell = (Shell *) emalloc(sizeof(Shell));              commandShell = emalloc(sizeof(Shell));
             *commandShell = newShell;              *commandShell = newShell;
         }          }
     }      }
Line 2765 
Line 2698 
  * JobInterrupt --   * JobInterrupt --
  *      Handle the receipt of an interrupt.   *      Handle the receipt of an interrupt.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      All children are killed. Another job will be started if the   *      All children are killed. Another job will be started if the
  *      .INTERRUPT target was given.   *      .INTERRUPT target was given.
Line 2775 
Line 2705 
  */   */
 static void  static void
 JobInterrupt(runINTERRUPT, signo)  JobInterrupt(runINTERRUPT, signo)
     int     runINTERRUPT;       /* Non-zero if commands for the .INTERRUPT      int     runINTERRUPT;       /* Non-zero if commands for the .INTERRUPT
                                  * target should be executed */                                   * target should be executed */
     int     signo;              /* signal received */      int     signo;              /* signal received */
 {  {
     LstNode       ln;           /* element in job table */      LstNode       ln;           /* element in job table */
     Job           *job;         /* job descriptor in that element */      Job           *job;         /* job descriptor in that element */
     GNode         *interrupt;   /* the node describing the .INTERRUPT target */      GNode         *interrupt;   /* the node describing the .INTERRUPT target */
   
     aborting = ABORT_INTERRUPT;      aborting = ABORT_INTERRUPT;
   
     Lst_Open(&jobs);      for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Adv(ln)) {
     while ((ln = Lst_Next(&jobs)) != NULL) {  
         job = (Job *)Lst_Datum(ln);          job = (Job *)Lst_Datum(ln);
   
         if (!Targ_Precious(job->node)) {          if (!Targ_Precious(job->node)) {
             char        *file = (job->node->path == NULL ?              const char  *file = job->node->path == NULL ?
                                  job->node->name :                                   job->node->name :
                                  job->node->path);                                   job->node->path;
             if (!noExecute && eunlink(file) != -1) {              if (!noExecute && eunlink(file) != -1) {
                 Error("*** %s removed", file);                  Error("*** %s removed", file);
             }              }
Line 2819 
Line 2748 
 #else  #else
         if (job->pid) {          if (job->pid) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout,                  (void)fprintf(stdout,
                                "JobInterrupt passing signal to child %d.\n",                                 "JobInterrupt passing signal to child %d.\n",
                                job->pid);                                 job->pid);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             KILL(job->pid, signo);              KILL(job->pid, signo);
         }          }
Line 2830 
Line 2759 
     }      }
   
 #ifdef REMOTE  #ifdef REMOTE
     Lst_Open(&stoppedJobs);      for (ln = Lst_First(&stoppedJobs); ln != NULL; ln = Lst_Adv(ln)) {
     while ((ln = Lst_Next(&stoppedJobs)) != NULL) {  
         job = (Job *)Lst_Datum(ln);          job = (Job *)Lst_Datum(ln);
   
         if (job->flags & JOB_RESTART) {          if (job->flags & JOB_RESTART) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout, "%s%s",                  (void)fprintf(stdout, "%s%s",
                                "JobInterrupt skipping job on stopped queue",                                 "JobInterrupt skipping job on stopped queue",
                                "-- it was waiting to be restarted.\n");                                 "-- it was waiting to be restarted.\n");
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             continue;              continue;
         }          }
         if (!Targ_Precious(job->node)) {          if (!Targ_Precious(job->node)) {
             char        *file = (job->node->path == NULL ?              char        *file = job->node->path == NULL ?
                                  job->node->name :                                   job->node->name :
                                  job->node->path);                                   job->node->path;
             if (eunlink(file) == 0) {              if (eunlink(file) == 0) {
                 Error("*** %s removed", file);                  Error("*** %s removed", file);
             }              }
Line 2855 
Line 2783 
          * Resume the thing so it will take the signal.           * Resume the thing so it will take the signal.
          */           */
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
             (void) fprintf(stdout,              (void)fprintf(stdout,
                            "JobInterrupt passing CONT to stopped child %d.\n",                             "JobInterrupt passing CONT to stopped child %d.\n",
                            job->pid);                             job->pid);
             (void) fflush(stdout);              (void)fflush(stdout);
         }          }
         KILL(job->pid, SIGCONT);          KILL(job->pid, SIGCONT);
 #ifdef RMT_WANTS_SIGNALS  #ifdef RMT_WANTS_SIGNALS
Line 2878 
Line 2806 
             }              }
         } else if (job->pid) {          } else if (job->pid) {
             if (DEBUG(JOB)) {              if (DEBUG(JOB)) {
                 (void) fprintf(stdout,                  (void)fprintf(stdout,
                        "JobInterrupt passing interrupt to stopped child %d.\n",                         "JobInterrupt passing interrupt to stopped child %d.\n",
                                job->pid);                                 job->pid);
                 (void) fflush(stdout);                  (void)fflush(stdout);
             }              }
             KILL(job->pid, SIGINT);              KILL(job->pid, SIGINT);
         }          }
 #endif /* RMT_WANTS_SIGNALS */  #endif /* RMT_WANTS_SIGNALS */
     }      }
 #endif  #endif
     Lst_Close(&stoppedJobs);  
   
     if (runINTERRUPT && !touchFlag) {      if (runINTERRUPT && !touchFlag) {
         interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);          interrupt = Targ_FindNode(".INTERRUPT", NULL, TARG_NOCREATE);
         if (interrupt != NULL) {          if (interrupt != NULL) {
             ignoreErrors = FALSE;              ignoreErrors = FALSE;
   
Line 2904 
Line 2831 
             }              }
         }          }
     }      }
       (void)eunlink(tfile);
     exit(signo);      exit(signo);
 }  }
   
Line 2915 
Line 2843 
  *   *
  * Results:   * Results:
  *      Number of errors reported.   *      Number of errors reported.
    *
    * Side Effects:
    *      The process' temporary file (tfile) is removed if it still
    *      existed.
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 int  int
Line 2934 
Line 2866 
             }              }
         }          }
     }      }
     return(errors);      (void)eunlink(tfile);
       return errors;
 }  }
   
 /*-  /*-
Line 2942 
Line 2875 
  * Job_End --   * Job_End --
  *      Cleanup any memory used by the jobs module   *      Cleanup any memory used by the jobs module
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Memory is freed   *      Memory is freed
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
Line 2956 
Line 2886 
     efree(shellArgv);      efree(shellArgv);
 #endif  #endif
 }  }
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * Job_Wait --   * Job_Wait --
  *      Waits for all running jobs to finish and returns. Sets 'aborting'   *      Waits for all running jobs to finish and returns. Sets 'aborting'
  *      to ABORT_WAIT to prevent other jobs from starting.   *      to ABORT_WAIT to prevent other jobs from starting.
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Currently running jobs finish.   *      Currently running jobs finish.
  *   *
Line 2991 
Line 2918 
  *      This function is to be called only in the event of a major   *      This function is to be called only in the event of a major
  *      error. Most definitely NOT to be called from JobInterrupt.   *      error. Most definitely NOT to be called from JobInterrupt.
  *   *
  * Results:  
  *      None  
  *  
  * Side Effects:   * Side Effects:
  *      All children are killed, not just the firstborn   *      All children are killed, not just the firstborn
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
Line 3001 
Line 2925 
 void  void
 Job_AbortAll()  Job_AbortAll()
 {  {
     LstNode             ln;     /* element in job table */      LstNode             ln;     /* element in job table */
     Job                 *job;   /* the job descriptor in that element */      Job                 *job;   /* the job descriptor in that element */
     int                 foo;      int                 foo;
   
     aborting = ABORT_ERROR;      aborting = ABORT_ERROR;
   
     if (nJobs) {      if (nJobs) {
           for (ln = Lst_First(&jobs); ln != NULL; ln = Lst_Adv(ln)) {
         Lst_Open(&jobs);  
         while ((ln = Lst_Next(&jobs)) != NULL) {  
             job = (Job *)Lst_Datum(ln);              job = (Job *)Lst_Datum(ln);
   
             /*              /*
Line 3037 
Line 2959 
      */       */
     while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)      while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
         continue;          continue;
       (void)eunlink(tfile);
 }  }
   
 #ifdef REMOTE  #ifdef REMOTE
Line 3046 
Line 2969 
  *      Handle the eviction of a child. Called from RmtStatusChange.   *      Handle the eviction of a child. Called from RmtStatusChange.
  *      Flags the child as remigratable and then suspends it.   *      Flags the child as remigratable and then suspends it.
  *   *
  * Results:  
  *      none.  
  *  
  * Side Effects:   * Side Effects:
  *      The job descriptor is flagged for remigration.   *      The job descriptor is flagged for remigration.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 void  void
 JobFlagForMigration(hostID)  JobFlagForMigration(hostID)
     int           hostID;       /* ID of host we used, for matching children. */      int           hostID;       /* ID of host we used, for matching children. */
 {  {
     register Job  *job;         /* job descriptor for dead child */      Job           *job;         /* job descriptor for dead child */
     LstNode       jnode;        /* list element for finding job */      LstNode       jnode;        /* list element for finding job */
   
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID);          (void)fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID);
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
     jnode = Lst_Find(&jobs, JobCmpRmtID, &hostID);      jnode = Lst_Find(&jobs, JobCmpRmtID, &hostID);
   
Line 3079 
Line 2998 
     job = (Job *)Lst_Datum(jnode);      job = (Job *)Lst_Datum(jnode);
   
     if (DEBUG(JOB)) {      if (DEBUG(JOB)) {
         (void) fprintf(stdout,          (void)fprintf(stdout,
                        "JobFlagForMigration(%d) found job '%s'.\n", hostID,                         "JobFlagForMigration(%d) found job '%s'.\n", hostID,
                        job->node->name);                         job->node->name);
         (void) fflush(stdout);          (void)fflush(stdout);
     }      }
   
     KILL(job->pid, SIGSTOP);      KILL(job->pid, SIGSTOP);
Line 3091 
Line 3010 
 }  }
   
 #endif  #endif
   
 /*-  /*-
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  * JobRestartJobs --   * JobRestartJobs --
Line 3099 
Line 3018 
  *      Note that this tries to restart them regardless of pending errors.   *      Note that this tries to restart them regardless of pending errors.
  *      It's not good to leave stopped jobs lying around!   *      It's not good to leave stopped jobs lying around!
  *   *
  * Results:  
  *      None.  
  *  
  * Side Effects:   * Side Effects:
  *      Resumes(and possibly migrates) jobs.   *      Resumes(and possibly migrates) jobs.
  *  
  *-----------------------------------------------------------------------   *-----------------------------------------------------------------------
  */   */
 static void  static void
Line 3112 
Line 3027 
 {  {
     Job *job;      Job *job;
   
     while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL)  {      while (!jobFull && (job = (Job *)Lst_DeQueue(&stoppedJobs)) != NULL) {
         if (DEBUG(JOB)) {          if (DEBUG(JOB)) {
             (void) fprintf(stdout,              (void)fprintf(stdout,
                        "Job queue is not full. Restarting a stopped job.\n");                         "Job queue is not full. Restarting a stopped job.\n");
             (void) fflush(stdout);              (void)fflush(stdout);
         }          }
         JobRestart(job);          JobRestart(job);
     }      }

Legend:
Removed from v.1.39  
changed lines
  Added in v.1.40