aboutsummaryrefslogtreecommitdiff
path: root/contrib/bmake/job.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bmake/job.c')
-rw-r--r--contrib/bmake/job.c544
1 files changed, 243 insertions, 301 deletions
diff --git a/contrib/bmake/job.c b/contrib/bmake/job.c
index 694739f37b33..052b9290f9f3 100644
--- a/contrib/bmake/job.c
+++ b/contrib/bmake/job.c
@@ -1,4 +1,4 @@
-/* $NetBSD: job.c,v 1.302 2020/11/01 18:45:49 rillig Exp $ */
+/* $NetBSD: job.c,v 1.326 2020/11/16 18:28:27 rillig Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
@@ -156,7 +156,7 @@
#include "trace.h"
/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
-MAKE_RCSID("$NetBSD: job.c,v 1.302 2020/11/01 18:45:49 rillig Exp $");
+MAKE_RCSID("$NetBSD: job.c,v 1.326 2020/11/16 18:28:27 rillig Exp $");
/* A shell defines how the commands are run. All commands for a target are
* written into a single file, which is then given to the shell to execute
@@ -182,7 +182,7 @@ MAKE_RCSID("$NetBSD: job.c,v 1.302 2020/11/01 18:45:49 rillig Exp $");
* status. Finally errExit is a printf template for running the command and
* causing the shell to exit on error. If any of these strings are empty when
* hasErrCtl is FALSE, the command will be executed anyway as is, and if it
- * causes an error, so be it. Any templates setup to echo the command will
+ * causes an error, so be it. Any templates set up to echo the command will
* escape any '$ ` \ "' characters in the command string to avoid common
* problems with echo "%s\n" as a template.
*
@@ -404,8 +404,8 @@ static char *shellArgv = NULL; /* Custom shell args */
static Job *job_table; /* The structures that describe them */
static Job *job_table_end; /* job_table + maxJobs */
static unsigned int wantToken; /* we want a token */
-static int lurking_children = 0;
-static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */
+static Boolean lurking_children = FALSE;
+static Boolean make_suspended = FALSE; /* Whether we've seen a SIGTSTP (etc) */
/*
* Set of descriptors of pipes connected to
@@ -459,7 +459,7 @@ job_table_dump(const char *where)
debug_printf("job table @ %s\n", where);
for (job = job_table; job < job_table_end; job++) {
debug_printf("job %d, status %d, flags %d, pid %d\n",
- (int)(job - job_table), job->job_state, job->flags, job->pid);
+ (int)(job - job_table), job->status, job->flags, job->pid);
}
}
@@ -555,7 +555,7 @@ JobCondPassSig(int signo)
DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo);
for (job = job_table; job < job_table_end; job++) {
- if (job->job_state != JOB_ST_RUNNING)
+ if (job->status != JOB_ST_RUNNING)
continue;
DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n",
signo, job->pid);
@@ -612,7 +612,7 @@ JobPassSig_suspend(int signo)
struct sigaction act;
/* Suppress job started/continued messages */
- make_suspended = 1;
+ make_suspended = TRUE;
/* Pass the signal onto every job */
JobCondPassSig(signo);
@@ -662,12 +662,12 @@ JobPassSig_suspend(int signo)
}
static Job *
-JobFindPid(int pid, JobState status, Boolean isJobs)
+JobFindPid(int pid, JobStatus status, Boolean isJobs)
{
Job *job;
for (job = job_table; job < job_table_end; job++) {
- if ((job->job_state == status) && job->pid == pid)
+ if (job->status == status && job->pid == pid)
return job;
}
if (DEBUG(JOB) && isJobs)
@@ -721,6 +721,22 @@ EscapeShellDblQuot(const char *cmd)
return esc;
}
+static void
+JobPrintf(Job *job, const char *fmt, const char *arg)
+{
+ if (DEBUG(JOB))
+ debug_printf(fmt, arg);
+
+ (void)fprintf(job->cmdFILE, fmt, arg);
+ (void)fflush(job->cmdFILE);
+}
+
+static void
+JobPrintln(Job *job, const char *line)
+{
+ JobPrintf(job, "%s\n", line);
+}
+
/*-
*-----------------------------------------------------------------------
* JobPrintCommand --
@@ -733,7 +749,7 @@ EscapeShellDblQuot(const char *cmd)
* If the command is just "..." we take all future commands for this
* job to be commands to be executed once the entire graph has been
* 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 .END
* node and executed by Job_End when all things are done.
*
* Side Effects:
@@ -762,12 +778,6 @@ JobPrintCommand(Job *job, char *cmd)
noSpecials = !GNode_ShouldExecute(job->node);
-#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \
- debug_printf(fmt, arg); \
- } \
- (void)fprintf(job->cmdFILE, fmt, arg); \
- (void)fflush(job->cmdFILE);
-
numCommands++;
Var_Subst(cmd, job->node, VARE_WANTRES, &cmd);
@@ -799,8 +809,8 @@ JobPrintCommand(Job *job, char *cmd)
if (shutUp) {
if (!(job->flags & JOB_SILENT) && !noSpecials &&
- commandShell->hasEchoCtl) {
- DBPRINTF("%s\n", commandShell->echoOff);
+ (commandShell->hasEchoCtl)) {
+ JobPrintln(job, commandShell->echoOff);
} else {
if (commandShell->hasErrCtl)
shutUp = FALSE;
@@ -819,16 +829,15 @@ JobPrintCommand(Job *job, char *cmd)
* it already is?
*/
if (!(job->flags & JOB_SILENT) && !shutUp &&
- commandShell->hasEchoCtl) {
- DBPRINTF("%s\n", commandShell->echoOff);
- DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
- DBPRINTF("%s\n", commandShell->echoOn);
+ (commandShell->hasEchoCtl)) {
+ JobPrintln(job, commandShell->echoOff);
+ JobPrintln(job, commandShell->errOffOrExecIgnore);
+ JobPrintln(job, commandShell->echoOn);
} else {
- DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
+ JobPrintln(job, commandShell->errOffOrExecIgnore);
}
} else if (commandShell->errOffOrExecIgnore &&
- commandShell->errOffOrExecIgnore[0] != '\0')
- {
+ commandShell->errOffOrExecIgnore[0] != '\0') {
/*
* The shell has no error control, so we need to be
* weird to get it to ignore any errors from the command.
@@ -840,15 +849,14 @@ JobPrintCommand(Job *job, char *cmd)
*/
job->flags |= JOB_IGNERR;
if (!(job->flags & JOB_SILENT) && !shutUp) {
- if (commandShell->hasEchoCtl) {
- DBPRINTF("%s\n", commandShell->echoOff);
- }
- DBPRINTF(commandShell->errOnOrEcho, escCmd);
- shutUp = TRUE;
+ if (commandShell->hasEchoCtl) {
+ JobPrintln(job, commandShell->echoOff);
+ }
+ JobPrintf(job, commandShell->errOnOrEcho, escCmd);
+ shutUp = TRUE;
} else {
- if (!shutUp) {
- DBPRINTF(commandShell->errOnOrEcho, escCmd);
- }
+ if (!shutUp)
+ JobPrintf(job, commandShell->errOnOrEcho, escCmd);
}
cmdTemplate = commandShell->errOffOrExecIgnore;
/*
@@ -867,36 +875,35 @@ JobPrintCommand(Job *job, char *cmd)
/*
* If errors are being checked and the shell doesn't have error control
- * but does supply an errExit template, then setup commands to run
+ * but does supply an errExit template, then set up commands to run
* through it.
*/
if (!commandShell->hasErrCtl && commandShell->errExit &&
commandShell->errExit[0] != '\0') {
- if (!(job->flags & JOB_SILENT) && !shutUp) {
- if (commandShell->hasEchoCtl) {
- DBPRINTF("%s\n", commandShell->echoOff);
- }
- DBPRINTF(commandShell->errOnOrEcho, escCmd);
- shutUp = TRUE;
- }
- /* If it's a comment line or blank, treat as an ignored error */
- if ((escCmd[0] == commandShell->commentChar) ||
- (escCmd[0] == 0))
- cmdTemplate = commandShell->errOffOrExecIgnore;
- else
- cmdTemplate = commandShell->errExit;
- errOff = FALSE;
+ if (!(job->flags & JOB_SILENT) && !shutUp) {
+ if (commandShell->hasEchoCtl)
+ JobPrintln(job, commandShell->echoOff);
+ JobPrintf(job, commandShell->errOnOrEcho, escCmd);
+ shutUp = TRUE;
+ }
+ /* If it's a comment line or blank, treat as an ignored error */
+ if (escCmd[0] == commandShell->commentChar ||
+ (escCmd[0] == '\0'))
+ cmdTemplate = commandShell->errOffOrExecIgnore;
+ else
+ cmdTemplate = commandShell->errExit;
+ errOff = FALSE;
}
}
if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 &&
- (job->flags & JOB_TRACED) == 0) {
- DBPRINTF("set -%s\n", "x");
- job->flags |= JOB_TRACED;
+ !(job->flags & JOB_TRACED)) {
+ JobPrintln(job, "set -x");
+ job->flags |= JOB_TRACED;
}
- DBPRINTF(cmdTemplate, cmd);
+ JobPrintf(job, cmdTemplate, cmd);
free(cmdStart);
free(escCmd);
if (errOff) {
@@ -905,15 +912,14 @@ JobPrintCommand(Job *job, char *cmd)
* echoOff command. Otherwise we issue it and pretend it was on
* for the whole command...
*/
- if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
- DBPRINTF("%s\n", commandShell->echoOff);
+ if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl) {
+ JobPrintln(job, commandShell->echoOff);
shutUp = TRUE;
}
- DBPRINTF("%s\n", commandShell->errOnOrEcho);
- }
- if (shutUp && commandShell->hasEchoCtl) {
- DBPRINTF("%s\n", commandShell->echoOn);
+ JobPrintln(job, commandShell->errOnOrEcho);
}
+ if (shutUp && commandShell->hasEchoCtl)
+ JobPrintln(job, commandShell->echoOn);
}
/* Print all commands to the shell file that is later executed.
@@ -930,12 +936,11 @@ JobPrintCommands(Job *job)
if (strcmp(cmd, "...") == 0) {
job->node->type |= OP_SAVE_CMDS;
- if ((job->flags & JOB_IGNDOTS) == 0) {
- job->tailCmds = ln->next;
- break;
- }
- } else
- JobPrintCommand(job, ln->datum);
+ job->tailCmds = ln->next;
+ break;
+ }
+
+ JobPrintCommand(job, ln->datum);
}
}
@@ -960,7 +965,7 @@ JobSaveCommands(Job *job)
/* Called to close both input and output pipes when a job is finished. */
static void
-JobClose(Job *job)
+JobClosePipes(Job *job)
{
clearfd(job);
(void)close(job->outPipe);
@@ -971,28 +976,17 @@ JobClose(Job *job)
job->inPipe = -1;
}
-/*-
- *-----------------------------------------------------------------------
- * JobFinish --
- * Do final processing for the given job including updating
- * parents and starting new jobs as available/necessary. Note
- * that we pay no attention to the JOB_IGNERR flag here.
- * This is because when we're called because of a noexecute flag
- * or something, jstat.w_status is 0 and when called from
- * Job_CatchChildren, the status is zeroed if it s/b ignored.
+/* Do final processing for the given job including updating parent nodes and
+ * starting new jobs as available/necessary.
+ *
+ * Deferred commands for the job are placed on the .END node.
+ *
+ * If there was a serious error (errors != 0; not an ignored one), no more
+ * jobs will be started.
*
* Input:
* job job to finish
* status sub-why job went away
- *
- * Side Effects:
- * Final commands for the job are placed on postCommands.
- *
- * If we got an error and are aborting (aborting == ABORT_ERROR) and
- * the job list is now empty, we are done for the day.
- * If we recognized an error (errors !=0), we set the aborting flag
- * to ABORT_ERROR so no more jobs will be started.
- *-----------------------------------------------------------------------
*/
static void
JobFinish (Job *job, WAIT_T status)
@@ -1003,7 +997,7 @@ JobFinish (Job *job, WAIT_T status)
job->pid, job->node->name, status);
if ((WIFEXITED(status) &&
- (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) ||
+ ((WEXITSTATUS(status) != 0 && !(job->flags & JOB_IGNERR)))) ||
WIFSIGNALED(status))
{
/*
@@ -1014,7 +1008,7 @@ JobFinish (Job *job, WAIT_T status)
* cases, finish out the job's output before printing the exit
* status...
*/
- JobClose(job);
+ JobClosePipes(job);
if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
(void)fclose(job->cmdFILE);
job->cmdFILE = NULL;
@@ -1023,19 +1017,11 @@ JobFinish (Job *job, WAIT_T status)
} else if (WIFEXITED(status)) {
/*
* Deal with ignored errors in -B mode. We need to print a message
- * telling of the ignored error as well as setting status.w_status
- * to 0 so the next command gets run. To do this, we set done to be
- * TRUE if in -B mode and the job exited non-zero.
+ * telling of the ignored error as well as to run the next command.
+ *
*/
done = WEXITSTATUS(status) != 0;
- /*
- * Old comment said: "Note we don't
- * want to close down any of the streams until we know we're at the
- * end."
- * But we do. Otherwise when are we going to print the rest of the
- * stuff?
- */
- JobClose(job);
+ JobClosePipes(job);
} else {
/*
* No need to close things down or anything.
@@ -1057,7 +1043,7 @@ JobFinish (Job *job, WAIT_T status)
meta_job_error(job, job->node, job->flags, WEXITSTATUS(status));
}
#endif
- if (!dieQuietly(job->node, -1))
+ if (!shouldDieQuietly(job->node, -1))
(void)printf("*** [%s] Error code %d%s\n",
job->node->name,
WEXITSTATUS(status),
@@ -1094,11 +1080,9 @@ JobFinish (Job *job, WAIT_T status)
#ifdef USE_META
if (useMeta) {
- int x;
-
- if ((x = meta_job_finish(job)) != 0 && status == 0) {
- status = x;
- }
+ int meta_status = meta_job_finish(job);
+ if (meta_status != 0 && status == 0)
+ status = meta_status;
}
#endif
@@ -1106,13 +1090,12 @@ JobFinish (Job *job, WAIT_T status)
Trace_Log(JOBEND, job);
if (!(job->flags & JOB_SPECIAL)) {
- if ((WAIT_STATUS(status) != 0) ||
- (aborting == ABORT_ERROR) ||
- (aborting == ABORT_INTERRUPT))
+ if (WAIT_STATUS(status) != 0 ||
+ (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT)
return_job_token = TRUE;
}
- if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) &&
+ if (aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT &&
(WAIT_STATUS(status) == 0)) {
/*
* As long as we aren't aborting and the job didn't return a non-zero
@@ -1124,33 +1107,50 @@ JobFinish (Job *job, WAIT_T status)
if (!(job->flags & JOB_SPECIAL))
return_job_token = TRUE;
Make_Update(job->node);
- job->job_state = JOB_ST_FREE;
+ job->status = JOB_ST_FREE;
} else if (WAIT_STATUS(status)) {
errors++;
- job->job_state = JOB_ST_FREE;
+ job->status = JOB_ST_FREE;
}
- /*
- * Set aborting if any error.
- */
- if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) {
- /*
- * 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
- * started.
- */
- aborting = ABORT_ERROR;
- }
+ if (errors > 0 && !opts.keepgoing && aborting != ABORT_INTERRUPT)
+ aborting = ABORT_ERROR; /* Prevent more jobs from getting started. */
if (return_job_token)
Job_TokenReturn();
- if (aborting == ABORT_ERROR && jobTokensRunning == 0) {
- /*
- * If we are aborting and the job table is now empty, we finish.
- */
+ if (aborting == ABORT_ERROR && jobTokensRunning == 0)
Finish(errors);
+}
+
+static void
+TouchRegular(GNode *gn)
+{
+ const char *file = GNode_Path(gn);
+ struct utimbuf times = { now, now };
+ int fd;
+ char c;
+
+ if (utime(file, &times) >= 0)
+ return;
+
+ fd = open(file, O_RDWR | O_CREAT, 0666);
+ if (fd < 0) {
+ (void)fprintf(stderr, "*** couldn't touch %s: %s\n",
+ file, strerror(errno));
+ (void)fflush(stderr);
+ return; /* XXX: What about propagating the error? */
}
+
+ /* Last resort: update the file's time stamps in the traditional way.
+ * XXX: This doesn't work for empty files, which are sometimes used
+ * as marker files. */
+ if (read(fd, &c, 1) == 1) {
+ (void)lseek(fd, 0, SEEK_SET);
+ while (write(fd, &c, 1) == -1 && errno == EAGAIN)
+ continue;
+ }
+ (void)close(fd); /* XXX: What about propagating the error? */
}
/* Touch the given target. Called by JobStart when the -t flag was given.
@@ -1160,15 +1160,9 @@ JobFinish (Job *job, WAIT_T status)
void
Job_Touch(GNode *gn, Boolean silent)
{
- int streamID; /* ID of stream opened to do the touch */
- struct utimbuf times; /* Times for utime() call */
-
if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|
OP_SPECIAL|OP_PHONY)) {
- /*
- * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
- * and, as such, shouldn't really be created.
- */
+ /* These are "virtual" targets and should not really be created. */
return;
}
@@ -1177,42 +1171,20 @@ Job_Touch(GNode *gn, Boolean silent)
(void)fflush(stdout);
}
- if (!GNode_ShouldExecute(gn)) {
+ if (!GNode_ShouldExecute(gn))
return;
- }
if (gn->type & OP_ARCHV) {
Arch_Touch(gn);
- } else if (gn->type & OP_LIB) {
- Arch_TouchLib(gn);
- } else {
- const char *file = GNode_Path(gn);
-
- times.actime = times.modtime = now;
- if (utime(file, &times) < 0){
- streamID = open(file, O_RDWR | O_CREAT, 0666);
-
- if (streamID >= 0) {
- char c;
-
- /*
- * Read and write a byte to the file to change the
- * modification time, then close the file.
- */
- if (read(streamID, &c, 1) == 1) {
- (void)lseek(streamID, (off_t)0, SEEK_SET);
- while (write(streamID, &c, 1) == -1 && errno == EAGAIN)
- continue;
- }
+ return;
+ }
- (void)close(streamID);
- } else {
- (void)fprintf(stdout, "*** couldn't touch %s: %s",
- file, strerror(errno));
- (void)fflush(stdout);
- }
- }
+ if (gn->type & OP_LIB) {
+ Arch_TouchLib(gn);
+ return;
}
+
+ TouchRegular(gn);
}
/* Make sure the given node has all the commands it needs.
@@ -1239,25 +1211,25 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
/*
* No commands. Look for .DEFAULT rule from which we might infer
- * commands
+ * commands.
*/
- if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) &&
- (gn->type & OP_SPECIAL) == 0) {
+ if (defaultNode != NULL && !Lst_IsEmpty(defaultNode->commands) &&
+ !(gn->type & OP_SPECIAL)) {
/*
- * Make only looks for a .DEFAULT if the node was never the
- * target of an operator, so that's what we do too. If
- * a .DEFAULT was given, we substitute its commands for gn's
- * commands and set the IMPSRC variable to be the target's name
- * The DEFAULT node acts like a transformation rule, in that
+ * The traditional Make only looks for a .DEFAULT if the node was
+ * never the target of an operator, so that's what we do too.
+ *
+ * The .DEFAULT node acts like a transformation rule, in that
* gn also inherits any attributes or sources attached to
* .DEFAULT itself.
*/
- Make_HandleUse(DEFAULT, gn);
+ Make_HandleUse(defaultNode, gn);
Var_Set(IMPSRC, GNode_VarTarget(gn), gn);
return TRUE;
}
- if (Dir_MTime(gn, 0) != 0 || (gn->type & OP_SPECIAL))
+ Dir_UpdateMTime(gn, FALSE);
+ if (gn->mtime != 0 || (gn->type & OP_SPECIAL))
return TRUE;
/*
@@ -1296,21 +1268,19 @@ Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
/* Execute the shell for the given job.
*
- * A shell is executed, its output is altered and the Job structure added
- * to the job table.
- */
+ * See Job_CatchOutput for handling the output of the shell. */
static void
JobExec(Job *job, char **argv)
{
int cpid; /* ID of new child */
- sigset_t mask;
+ sigset_t mask;
job->flags &= ~JOB_TRACED;
if (DEBUG(JOB)) {
int i;
- debug_printf("Running %s %sly\n", job->node->name, "local");
+ debug_printf("Running %s\n", job->node->name);
debug_printf("\tCommand: ");
for (i = 0; argv[i] != NULL; i++) {
debug_printf("%s ", argv[i]);
@@ -1333,7 +1303,7 @@ JobExec(Job *job, char **argv)
JobSigLock(&mask);
/* Pre-emptively mark job running, pid still zero though */
- job->job_state = JOB_ST_RUNNING;
+ job->status = JOB_ST_RUNNING;
cpid = vFork();
if (cpid == -1)
@@ -1367,18 +1337,18 @@ JobExec(Job *job, char **argv)
execDie("dup2", "job->cmdFILE");
if (fcntl(0, F_SETFD, 0) == -1)
execDie("fcntl clear close-on-exec", "stdin");
- if (lseek(0, (off_t)0, SEEK_SET) == -1)
+ if (lseek(0, 0, SEEK_SET) == -1)
execDie("lseek to 0", "stdin");
if (Always_pass_job_queue ||
(job->node->type & (OP_MAKE | OP_SUBMAKE))) {
- /*
- * Pass job token pipe to submakes.
- */
- if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1)
- execDie("clear close-on-exec", "tokenWaitJob.inPipe");
- if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1)
- execDie("clear close-on-exec", "tokenWaitJob.outPipe");
+ /*
+ * Pass job token pipe to submakes.
+ */
+ if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1)
+ execDie("clear close-on-exec", "tokenWaitJob.inPipe");
+ if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1)
+ execDie("clear close-on-exec", "tokenWaitJob.outPipe");
}
/*
@@ -1475,7 +1445,7 @@ JobMakeArgv(Job *job, char **argv)
* Bourne shell thinks its second argument is a file to source.
* Grrrr. Note the ten-character limitation on the combined arguments.
*/
- (void)snprintf(args, sizeof(args), "-%s%s",
+ (void)snprintf(args, sizeof args, "-%s%s",
((job->flags & JOB_IGNERR) ? "" :
(commandShell->exit ? commandShell->exit : "")),
((job->flags & JOB_SILENT) ? "" :
@@ -1507,7 +1477,6 @@ JobMakeArgv(Job *job, char **argv)
* Input:
* gn target to create
* flags flags for the job to override normal ones.
- * e.g. JOB_SPECIAL or JOB_IGNDOTS
* previous The previous Job structure for this node, if any.
*
* Results:
@@ -1519,13 +1488,11 @@ JobMakeArgv(Job *job, char **argv)
* A new Job node is created and added to the list of running
* jobs. PMake is forked and a child shell created.
*
- * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set
- * JOB_IGNDOTS is never set (dsl)
- * Also the return value is ignored by everyone.
+ * NB: The return value is ignored by everyone.
*-----------------------------------------------------------------------
*/
static JobStartResult
-JobStart(GNode *gn, int flags)
+JobStart(GNode *gn, JobFlags flags)
{
Job *job; /* new job descriptor */
char *argv[10]; /* Argument vector to shell */
@@ -1534,33 +1501,24 @@ JobStart(GNode *gn, int flags)
int tfd; /* File descriptor to the temp file */
for (job = job_table; job < job_table_end; job++) {
- if (job->job_state == JOB_ST_FREE)
+ if (job->status == JOB_ST_FREE)
break;
}
if (job >= job_table_end)
Punt("JobStart no job slots vacant");
memset(job, 0, sizeof *job);
- job->job_state = JOB_ST_SETUP;
- if (gn->type & OP_SPECIAL)
- flags |= JOB_SPECIAL;
-
job->node = gn;
job->tailCmds = NULL;
+ job->status = JOB_ST_SET_UP;
- /*
- * Set the initial value of the flags for this job based on the global
- * ones and the node's attributes... Any flags supplied by the caller
- * are also added to the field.
- */
- job->flags = 0;
- if (Targ_Ignore(gn)) {
- job->flags |= JOB_IGNERR;
- }
- if (Targ_Silent(gn)) {
- job->flags |= JOB_SILENT;
- }
- job->flags |= flags;
+ if (gn->type & OP_SPECIAL)
+ flags |= JOB_SPECIAL;
+ if (Targ_Ignore(gn))
+ flags |= JOB_IGNERR;
+ if (Targ_Silent(gn))
+ flags |= JOB_SILENT;
+ job->flags = flags;
/*
* Check the commands now so any attributes from .DEFAULT have a chance
@@ -1576,7 +1534,7 @@ JobStart(GNode *gn, int flags)
* we just set the file to be stdout. Cute, huh?
*/
if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) ||
- (!opts.noExecute && !opts.touchFlag)) {
+ (!opts.noExecute && !opts.touchFlag)) {
/*
* tfile is the name of a file into which all shell commands are
* put. It is removed before the child shell is executed, unless
@@ -1596,13 +1554,13 @@ JobStart(GNode *gn, int flags)
JobSigLock(&mask);
tfd = mkTempFile(TMPPAT, &tfile);
if (!DEBUG(SCRIPT))
- (void)eunlink(tfile);
+ (void)eunlink(tfile);
JobSigUnlock(&mask);
job->cmdFILE = fdopen(tfd, "w+");
- if (job->cmdFILE == NULL) {
+ if (job->cmdFILE == NULL)
Punt("Could not fdopen %s", tfile);
- }
+
(void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC);
/*
* Send the commands to the command file, flush all its buffers then
@@ -1613,9 +1571,8 @@ JobStart(GNode *gn, int flags)
#ifdef USE_META
if (useMeta) {
meta_job_start(job, gn);
- if (Targ_Silent(gn)) { /* might have changed */
+ if (Targ_Silent(gn)) /* might have changed */
job->flags |= JOB_SILENT;
- }
}
#endif
/*
@@ -1662,7 +1619,7 @@ JobStart(GNode *gn, int flags)
* up the graph.
*/
job->cmdFILE = stdout;
- Job_Touch(gn, job->flags&JOB_SILENT);
+ Job_Touch(gn, job->flags & JOB_SILENT);
noExec = TRUE;
}
/* Just in case it isn't already... */
@@ -1677,11 +1634,9 @@ JobStart(GNode *gn, int flags)
/*
* Unlink and close the command file if we opened one
*/
- if (job->cmdFILE != stdout) {
- if (job->cmdFILE != NULL) {
- (void)fclose(job->cmdFILE);
- job->cmdFILE = NULL;
- }
+ if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
+ (void)fclose(job->cmdFILE);
+ job->cmdFILE = NULL;
}
/*
@@ -1693,7 +1648,7 @@ JobStart(GNode *gn, int flags)
job->node->made = MADE;
Make_Update(job->node);
}
- job->job_state = JOB_ST_FREE;
+ job->status = JOB_ST_FREE;
return cmdsOK ? JOB_FINISHED : JOB_ERROR;
}
@@ -1710,71 +1665,58 @@ JobStart(GNode *gn, int flags)
return JOB_RUNNING;
}
+/* Print the output of the shell command, skipping the noPrint command of
+ * the shell, if any. */
static char *
JobOutput(Job *job, char *cp, char *endp)
{
char *ecp;
- if (commandShell->noPrint && commandShell->noPrint[0] != '\0') {
- while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) {
- if (cp != ecp) {
- *ecp = '\0';
- /*
- * The only way there wouldn't be a newline after
- * this line is if it were the last in the buffer.
- * however, since the non-printable comes after it,
- * there must be a newline, so we don't print one.
- */
- (void)fprintf(stdout, "%s", cp);
- (void)fflush(stdout);
- }
- cp = ecp + commandShell->noPrintLen;
- if (cp != endp) {
- /*
- * Still more to print, look again after skipping
- * the whitespace following the non-printable
- * command....
- */
- cp++;
- while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
- cp++;
- }
- } else {
- return cp;
- }
+ if (commandShell->noPrint == NULL || commandShell->noPrint[0] == '\0')
+ return cp;
+
+ while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) {
+ if (ecp != cp) {
+ *ecp = '\0';
+ /*
+ * The only way there wouldn't be a newline after
+ * this line is if it were the last in the buffer.
+ * however, since the non-printable comes after it,
+ * there must be a newline, so we don't print one.
+ */
+ (void)fprintf(stdout, "%s", cp);
+ (void)fflush(stdout);
+ }
+ cp = ecp + commandShell->noPrintLen;
+ if (cp != endp) {
+ /*
+ * Still more to print, look again after skipping
+ * the whitespace following the non-printable
+ * command....
+ */
+ cp++;
+ pp_skip_whitespace(&cp);
+ } else {
+ return cp;
}
}
return cp;
}
-/*-
- *-----------------------------------------------------------------------
- * JobDoOutput --
- * This function is called at different times depending on
- * whether the user has specified that output is to be collected
- * via pipes or temporary files. In the former case, we are called
- * whenever there is something to read on the pipe. We collect more
- * output from the given job and store it in the job's outBuf. If
- * this makes up a line, we print it tagged by the job's identifier,
- * as necessary.
- * If output has been collected in a temporary file, we open the
- * file and read it line by line, transferring it to our own
- * output channel until the file is empty. At which point we
- * remove the temporary file.
- * In both cases, however, we keep our figurative eye out for the
- * 'noPrint' line for the shell from which the output came. If
- * we recognize a line, we don't print it. If the command is not
- * alone on the line (the character after it is not \0 or \n), we
- * do print whatever follows it.
+/*
+ * This function is called whenever there is something to read on the pipe.
+ * We collect more output from the given job and store it in the job's
+ * outBuf. If this makes up a line, we print it tagged by the job's
+ * identifier, as necessary.
+ *
+ * In the output of the shell, the 'noPrint' lines are removed. If the
+ * command is not alone on the line (the character after it is not \0 or
+ * \n), we do print whatever follows it.
*
* Input:
* job the job whose output needs printing
* finish TRUE if this is the last time we'll be called
* for this job
- *
- * Side Effects:
- * curPos may be shifted as may the contents of outBuf.
- *-----------------------------------------------------------------------
*/
static void
JobDoOutput(Job *job, Boolean finish)
@@ -1789,12 +1731,12 @@ JobDoOutput(Job *job, Boolean finish)
/*
* Read as many bytes as will fit in the buffer.
*/
-end_loop:
+again:
gotNL = FALSE;
fbuf = FALSE;
nRead = read(job->inPipe, &job->outBuf[job->curPos],
- JOB_BUFSIZE - job->curPos);
+ JOB_BUFSIZE - job->curPos);
if (nRead < 0) {
if (errno == EAGAIN)
return;
@@ -1812,7 +1754,7 @@ end_loop:
* output remaining in the buffer.
* 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';
nr = 1;
finish = FALSE;
@@ -1907,7 +1849,7 @@ end_loop:
* we do get an EOF, finish will be set FALSE and we'll fall
* through and out.
*/
- goto end_loop;
+ goto again;
}
}
@@ -2005,13 +1947,13 @@ JobReapChild(pid_t pid, WAIT_T status, Boolean isJobs)
(void)printf("*** [%s] Stopped -- signal %d\n",
job->node->name, WSTOPSIG(status));
}
- job->job_suspended = 1;
+ job->suspended = TRUE;
}
(void)fflush(stdout);
return;
}
- job->job_state = JOB_ST_FINISHED;
+ job->status = JOB_ST_FINISHED;
job->exit_status = WAIT_STATUS(status);
JobFinish(job, status);
@@ -2055,7 +1997,7 @@ Job_CatchOutput(void)
default:
abort();
}
- --nready;
+ nready--;
}
Job_CatchChildren();
@@ -2066,7 +2008,7 @@ Job_CatchOutput(void)
if (!fds[i].revents)
continue;
job = jobfds[i];
- if (job->job_state == JOB_ST_RUNNING)
+ if (job->status == JOB_ST_RUNNING)
JobDoOutput(job, FALSE);
#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
/*
@@ -2090,7 +2032,7 @@ Job_CatchOutput(void)
void
Job_Make(GNode *gn)
{
- (void)JobStart(gn, 0);
+ (void)JobStart(gn, JOB_NONE);
}
void
@@ -2111,7 +2053,7 @@ Shell_Init(void)
#endif
shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
}
- Var_Set_with_flags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY);
+ Var_SetWithFlags(".SHELL", shellPath, VAR_CMDLINE, VAR_SET_READONLY);
if (commandShell->exit == NULL) {
commandShell->exit = "";
}
@@ -2176,10 +2118,10 @@ Job_Init(void)
lastNode = NULL;
- Always_pass_job_queue = getBoolean(MAKE_ALWAYS_PASS_JOB_QUEUE,
+ Always_pass_job_queue = GetBooleanVar(MAKE_ALWAYS_PASS_JOB_QUEUE,
Always_pass_job_queue);
- Job_error_token = getBoolean(MAKE_JOB_ERROR_TOKEN, Job_error_token);
+ Job_error_token = GetBooleanVar(MAKE_JOB_ERROR_TOKEN, Job_error_token);
/*
@@ -2195,7 +2137,7 @@ Job_Init(void)
if (rval > 0)
continue;
if (rval == 0)
- lurking_children = 1;
+ lurking_children = TRUE;
break;
}
@@ -2204,9 +2146,9 @@ Job_Init(void)
JobCreatePipe(&childExitJob, 3);
/* Preallocate enough for the maximum number of jobs. */
- fds = bmake_malloc(sizeof(*fds) *
+ fds = bmake_malloc(sizeof *fds *
(npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
- jobfds = bmake_malloc(sizeof(*jobfds) *
+ jobfds = bmake_malloc(sizeof *jobfds *
(npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
/* These are permanent entries and take slots 0 and 1 */
@@ -2351,7 +2293,7 @@ Job_ParseShell(char *line)
free(shellArgv);
- memset(&newShell, 0, sizeof(newShell));
+ memset(&newShell, 0, sizeof newShell);
/*
* Parse the specification by keyword
@@ -2463,7 +2405,7 @@ Job_ParseShell(char *line)
}
commandShell = sh;
} else {
- commandShell = bmake_malloc(sizeof(Shell));
+ commandShell = bmake_malloc(sizeof *commandShell);
*commandShell = newShell;
}
/* this will take care of shellErrFlag */
@@ -2514,7 +2456,7 @@ JobInterrupt(int runINTERRUPT, int signo)
JobSigLock(&mask);
for (job = job_table; job < job_table_end; job++) {
- if (job->job_state != JOB_ST_RUNNING)
+ if (job->status != JOB_ST_RUNNING)
continue;
gn = job->node;
@@ -2536,7 +2478,7 @@ JobInterrupt(int runINTERRUPT, int signo)
JobRun(interrupt);
}
}
- Trace_Log(MAKEINTR, 0);
+ Trace_Log(MAKEINTR, NULL);
exit(signo);
}
@@ -2593,7 +2535,7 @@ Job_AbortAll(void)
if (jobTokensRunning) {
for (job = job_table; job < job_table_end; job++) {
- if (job->job_state != JOB_ST_RUNNING)
+ if (job->status != JOB_ST_RUNNING)
continue;
/*
* kill the child process with increasingly drastic signals to make
@@ -2619,23 +2561,23 @@ JobRestartJobs(void)
Job *job;
for (job = job_table; job < job_table_end; job++) {
- if (job->job_state == JOB_ST_RUNNING &&
- (make_suspended || job->job_suspended)) {
+ if (job->status == JOB_ST_RUNNING &&
+ (make_suspended || job->suspended)) {
DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid);
- if (job->job_suspended) {
+ if (job->suspended) {
(void)printf("*** [%s] Continued\n", job->node->name);
(void)fflush(stdout);
}
- job->job_suspended = 0;
+ job->suspended = FALSE;
if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) {
debug_printf("Failed to send SIGCONT to %d\n", job->pid);
}
}
- if (job->job_state == JOB_ST_FINISHED)
+ if (job->status == JOB_ST_FINISHED)
/* Job exit deferred after calling waitpid() in a signal handler */
JobFinish(job, job->exit_status);
}
- make_suspended = 0;
+ make_suspended = FALSE;
}
static void
@@ -2745,7 +2687,7 @@ Job_ServerStart(int max_tokens, int jp_0, int jp_1)
JobCreatePipe(&tokenWaitJob, 15);
- snprintf(jobarg, sizeof(jobarg), "%d,%d",
+ snprintf(jobarg, sizeof jobarg, "%d,%d",
tokenWaitJob.inPipe, tokenWaitJob.outPipe);
Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
@@ -2813,7 +2755,7 @@ Job_TokenWithdraw(void)
/* And put the stopper back */
while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
continue;
- if (dieQuietly(NULL, 1))
+ if (shouldDieQuietly(NULL, 1))
exit(2);
Fatal("A failure has been detected in another branch of the parallel make");
}
@@ -2889,7 +2831,7 @@ emul_poll(struct pollfd *fd, int nfd, int timeout)
tvp = &tv;
}
- nselect = select(maxfd + 1, &rfds, &wfds, 0, tvp);
+ nselect = select(maxfd + 1, &rfds, &wfds, NULL, tvp);
if (nselect <= 0)
return nselect;