-/* $NetBSD: job.c,v 1.11 1995/09/27 18:44:40 jtc Exp $ */
+/* $NetBSD: job.c,v 1.13 1995/11/22 17:40:09 christos Exp $ */
/*
* Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
#if 0
static char sccsid[] = "@(#)job.c 5.15 (Berkeley) 3/1/91";
#else
-static char rcsid[] = "$NetBSD: job.c,v 1.11 1995/09/27 18:44:40 jtc Exp $";
+static char rcsid[] = "$NetBSD: job.c,v 1.13 1995/11/22 17:40:09 christos Exp $";
#endif
#endif /* not lint */
#include "dir.h"
#include "job.h"
#include "pathnames.h"
+#ifdef REMOTE
+#include "rmt.h"
+# define STATIC
+#else
+# define STATIC static
+#endif
extern int errno;
#define ABORT_INTERRUPT 2 /* Because it was interrupted */
#define ABORT_WAIT 3 /* Waiting for jobs to finish */
+/*
+ * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file
+ * is a char! So when we go above 127 we turn negative!
+ */
+#define FILENO(a) ((unsigned) fileno(a))
/*
* post-make command processing. The node postCommands is really just the
* for a target. Should this number be
* 0, no shell will be executed. */
-
/*
* Return values from JobStart.
*/
{
"sh",
TRUE, "set -", "set -v", "set -", 5,
+ TRUE, "set -e", "set +e",
+#ifdef OLDBOURNESHELL
FALSE, "echo \"%s\"\n", "sh -c '%s || exit 0'\n",
+#endif
"v", "e",
},
/*
* UNKNOWN.
*/
{
- (char *)0,
- FALSE, (char *)0, (char *)0, (char *)0, 0,
- FALSE, (char *)0, (char *)0,
- (char *)0, (char *)0,
+ (char *) 0,
+ FALSE, (char *) 0, (char *) 0, (char *) 0, 0,
+ FALSE, (char *) 0, (char *) 0,
+ (char *) 0, (char *) 0,
}
};
static Shell *commandShell = &shells[DEFSHELL];/* this is the shell to
* commands in the Makefile.
* It is set by the
* Job_ParseShell function */
-static char *shellPath = (char *) NULL, /* full pathname of
+static char *shellPath = NULL, /* full pathname of
* executable image */
*shellName; /* last component of shell */
static int maxJobs; /* The most children we can run at once */
static int maxLocal; /* The most local ones we can have */
-int nJobs; /* The number of children currently running */
-int nLocal; /* The number of local children */
-Lst jobs; /* The structures that describe them */
-Boolean jobFull; /* Flag to tell when the job table is full. It
+STATIC int nJobs; /* The number of children currently running */
+STATIC int nLocal; /* The number of local children */
+STATIC Lst jobs; /* The structures that describe them */
+STATIC Boolean jobFull; /* Flag to tell when the job table is full. It
* is set TRUE when (1) the total number of
* running jobs equals the maximum allowed or
* (2) a job can only be run locally, but
* the output channels of children */
#endif
-GNode *lastNode; /* The node for which output was most recently
+STATIC GNode *lastNode; /* The node for which output was most recently
* produced. */
-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
* from */
-#define TARG_FMT "--- %s ---\n" /* Default format */
+
+#ifdef REMOTE
+# define TARG_FMT "--- %s at %s ---\n" /* Default format */
+# define MESSAGE(fp, gn) \
+ (void) fprintf(fp, targFmt, gn->name, gn->rem.hname);
+#else
+# define TARG_FMT "--- %s ---\n" /* Default format */
+# define MESSAGE(fp, gn) \
+ (void) fprintf(fp, targFmt, gn->name);
+#endif
/*
* When JobStart attempts to run a job remotely but can't, and isn't allowed
* been migrated home, the job is placed on the stoppedJobs queue to be run
* when the next job finishes.
*/
-Lst stoppedJobs; /* Lst of Job structures describing
+STATIC Lst stoppedJobs; /* Lst of Job structures describing
* jobs that were stopped due to concurrency
* limits or migration home */
#if defined(USE_PGRP) && defined(SYSV)
-#define KILL(pid,sig) killpg (-(pid),(sig))
+# define KILL(pid, sig) killpg(-(pid), (sig))
#else
# if defined(USE_PGRP)
-#define KILL(pid,sig) killpg ((pid),(sig))
+# define KILL(pid, sig) killpg((pid), (sig))
# else
-#define KILL(pid,sig) kill ((pid),(sig))
+# define KILL(pid, sig) kill((pid), (sig))
# endif
#endif
+/*
+ * Grmpf... There is no way to set bits of the wait structure
+ * anymore with the stupid W*() macros. I liked the union wait
+ * stuff much more. So, we devise our own macros... This is
+ * really ugly, use dramamine sparingly. You have been warned.
+ */
+#define W_SETMASKED(st, val, fun) \
+ { \
+ int sh = (int) ~0; \
+ int mask = fun(sh); \
+ \
+ for (sh = 0; ((mask >> sh) & 1) == 0; sh++) \
+ continue; \
+ *(st) = (*(st) & ~mask) | ((val) << sh); \
+ }
+
+#define W_SETTERMSIG(st, val) W_SETMASKED(st, val, WTERMSIG)
+#define W_SETEXITSTATUS(st, val) W_SETMASKED(st, val, WEXITSTATUS)
+
+
static int JobCondPassSig __P((ClientData, ClientData));
static void JobPassSig __P((int));
static int JobCmpPid __P((ClientData, ClientData));
static int JobPrintCommand __P((ClientData, ClientData));
static int JobSaveCommand __P((ClientData, ClientData));
-static void JobFinish __P((Job *, union wait));
+static void JobClose __P((Job *));
+#ifdef REMOTE
+static int JobCmpRmtID __P((Job *, int));
+# ifdef RMT_WILL_WATCH
+static void JobLocalInput __P((int, Job *));
+# endif
+#else
+static void JobFinish __P((Job *, int *));
static void JobExec __P((Job *, char **));
+#endif
static void JobMakeArgv __P((Job *, char **));
static void JobRestart __P((Job *));
static int JobStart __P((GNode *, int, Job *));
static void JobDoOutput __P((Job *, Boolean));
static Shell *JobMatchShell __P((char *));
-static void JobInterrupt __P((int));
+static void JobInterrupt __P((int, int));
+static void JobRestartJobs __P((void));
/*-
*-----------------------------------------------------------------------
int signo = *(int *) signop;
#ifdef RMT_WANTS_SIGNALS
if (job->flags & JOB_REMOTE) {
- (void)Rmt_Signal(job, signo);
+ (void) Rmt_Signal(job, signo);
} else {
KILL(job->pid, signo);
}
* Assume that sending the signal to job->pid will signal any remote
* job as well.
*/
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobCondPassSig passing signal %d to child %d.\n",
+ signo, job->pid);
+ (void) fflush(stdout);
+ }
KILL(job->pid, signo);
#endif
- return(0);
+ return 0;
}
/*-
JobPassSig(signo)
int signo; /* The signal number we've received */
{
- int mask;
+ sigset_t nmask, omask;
- Lst_ForEach(jobs, JobCondPassSig, (ClientData)(long)signo);
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "JobPassSig(%d) called.\n", signo);
+ (void) fflush(stdout);
+ }
+ Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
/*
* Deal with proper cleanup based on the signal received. We only run
* three termination signals are more of a "get out *now*" command.
*/
if (signo == SIGINT) {
- JobInterrupt(TRUE);
+ JobInterrupt(TRUE, signo);
} else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) {
- JobInterrupt(FALSE);
+ JobInterrupt(FALSE, signo);
}
/*
* This ensures that all our jobs get continued when we wake up before
* we take any other signal.
*/
- mask = sigblock(0);
- (void) sigsetmask(~0 & ~(1 << (signo-1)));
- signal(signo, SIG_DFL);
+ sigfillset(&nmask);
+ (void) sigprocmask(SIG_BLOCK, &nmask, &omask);
- kill(getpid(), signo);
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobPassSig passing signal to self, mask = %x.\n",
+ ~0 & ~(1 << (signo-1)));
+ (void) fflush(stdout);
+ }
+ (void) signal(signo, SIG_DFL);
+
+ (void) KILL(getpid(), signo);
signo = SIGCONT;
Lst_ForEach(jobs, JobCondPassSig, (ClientData) &signo);
- sigsetmask(mask);
- signal(signo, JobPassSig);
+ (void) sigprocmask(SIG_SETMASK, &omask, NULL);
+ (void) signal(signo, JobPassSig);
}
*-----------------------------------------------------------------------
*/
static int
-JobCmpPid (job, pid)
+JobCmpPid(job, pid)
ClientData job; /* job to examine */
ClientData pid; /* process id desired */
{
- return ( *(int *) pid - ((Job *) job)->pid);
+ return( *(int *) pid - ((Job *) job)->pid);
}
+#ifdef REMOTE
+/*-
+ *-----------------------------------------------------------------------
+ * JobCmpRmtID --
+ * Compare the rmtID of the job with the given rmtID and return 0 if they
+ * are equal.
+ *
+ * Results:
+ * 0 if the rmtID's match
+ *
+ * Side Effects:
+ * None.
+ *-----------------------------------------------------------------------
+ */
+static int
+JobCmpRmtID(job, rmtID)
+ ClientData job; /* job to examine */
+ ClientData rmtID; /* remote id desired */
+{
+ return(*(int *) rmtID - *(int *) job->rmtID);
+}
+#endif
+
/*-
*-----------------------------------------------------------------------
* JobPrintCommand --
*-----------------------------------------------------------------------
*/
static int
-JobPrintCommand (cmdp, jobp)
+JobPrintCommand(cmdp, jobp)
ClientData cmdp; /* command string to print */
ClientData jobp; /* job for which to print it */
{
char *cmd = (char *) cmdp;
Job *job = (Job *) jobp;
- noSpecials = (noExecute && ! (job->node->type & OP_MAKE));
+ noSpecials = (noExecute && !(job->node->type & OP_MAKE));
- if (strcmp (cmd, "...") == 0) {
+ if (strcmp(cmd, "...") == 0) {
job->node->type |= OP_SAVE_CMDS;
if ((job->flags & JOB_IGNDOTS) == 0) {
- job->tailCmds = Lst_Succ (Lst_Member (job->node->commands,
- (ClientData)cmd));
- return (1);
+ job->tailCmds = Lst_Succ(Lst_Member(job->node->commands,
+ (ClientData)cmd));
+ return(1);
}
- return (0);
+ return(0);
}
-#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) printf (fmt, arg); fprintf (job->cmdFILE, fmt, arg)
+#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \
+ (void) fprintf(stdout, fmt, arg); \
+ (void) fflush(stdout); \
+ } \
+ (void) fprintf(job->cmdFILE, fmt, arg); \
+ (void) fflush(job->cmdFILE);
numCommands += 1;
* For debugging, we replace each command with the result of expanding
* the variables in the command.
*/
- cmdNode = Lst_Member (job->node->commands, (ClientData)cmd);
- cmdStart = cmd = Var_Subst (NULL, cmd, job->node, FALSE);
- Lst_Replace (cmdNode, (ClientData)cmdStart);
+ cmdNode = Lst_Member(job->node->commands, (ClientData)cmd);
+ cmdStart = cmd = Var_Subst(NULL, cmd, job->node, FALSE);
+ Lst_Replace(cmdNode, (ClientData)cmdStart);
cmdTemplate = "%s\n";
cmd++;
if (shutUp) {
- if (! (job->flags & JOB_SILENT) && !noSpecials &&
+ if (!(job->flags & JOB_SILENT) && !noSpecials &&
commandShell->hasEchoCtl) {
- DBPRINTF ("%s\n", commandShell->echoOff);
+ DBPRINTF("%s\n", commandShell->echoOff);
} else {
shutUp = FALSE;
}
}
if (errOff) {
- if ( ! (job->flags & JOB_IGNERR) && !noSpecials) {
+ if ( !(job->flags & JOB_IGNERR) && !noSpecials) {
if (commandShell->hasErrCtl) {
/*
* we don't want the error-control commands showing
* string too, but why make it any more complex than
* it already is?
*/
- if (! (job->flags & JOB_SILENT) && !shutUp &&
+ if (!(job->flags & JOB_SILENT) && !shutUp &&
commandShell->hasEchoCtl) {
- DBPRINTF ("%s\n", commandShell->echoOff);
- DBPRINTF ("%s\n", commandShell->ignErr);
- DBPRINTF ("%s\n", commandShell->echoOn);
+ DBPRINTF("%s\n", commandShell->echoOff);
+ DBPRINTF("%s\n", commandShell->ignErr);
+ DBPRINTF("%s\n", commandShell->echoOn);
} else {
- DBPRINTF ("%s\n", commandShell->ignErr);
+ DBPRINTF("%s\n", commandShell->ignErr);
}
} else if (commandShell->ignErr &&
- (*commandShell->ignErr != '\0'))
+ (*commandShell->ignErr != '\0'))
{
/*
* The shell has no error control, so we need to be
* to ignore errors. Set cmdTemplate to use the weirdness
* instead of the simple "%s\n" template.
*/
- if (! (job->flags & JOB_SILENT) && !shutUp &&
+ if (!(job->flags & JOB_SILENT) && !shutUp &&
commandShell->hasEchoCtl) {
- DBPRINTF ("%s\n", commandShell->echoOff);
- DBPRINTF (commandShell->errCheck, cmd);
+ DBPRINTF("%s\n", commandShell->echoOff);
+ DBPRINTF(commandShell->errCheck, cmd);
shutUp = TRUE;
}
cmdTemplate = commandShell->ignErr;
/*
- * The error ignoration (hee hee) is already taken care
+ * The error ignoration(hee hee) is already taken care
* of by the ignErr template, so pretend error checking
* is still on.
*/
}
}
- DBPRINTF (cmdTemplate, cmd);
+ DBPRINTF(cmdTemplate, cmd);
if (errOff) {
/*
* for the whole command...
*/
if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
- DBPRINTF ("%s\n", commandShell->echoOff);
+ DBPRINTF("%s\n", commandShell->echoOff);
shutUp = TRUE;
}
- DBPRINTF ("%s\n", commandShell->errCheck);
+ DBPRINTF("%s\n", commandShell->errCheck);
}
if (shutUp) {
- DBPRINTF ("%s\n", commandShell->echoOn);
+ DBPRINTF("%s\n", commandShell->echoOn);
}
- return (0);
+ return 0;
}
/*-
*-----------------------------------------------------------------------
*/
static int
-JobSaveCommand (cmd, gn)
+JobSaveCommand(cmd, gn)
ClientData cmd;
ClientData gn;
{
- cmd = (ClientData) Var_Subst (NULL, (char *) cmd, (GNode *) gn, FALSE);
- (void)Lst_AtEnd (postCommands->commands, cmd);
- return (0);
+ cmd = (ClientData) Var_Subst(NULL, (char *) cmd, (GNode *) gn, FALSE);
+ (void) Lst_AtEnd(postCommands->commands, cmd);
+ return(0);
+}
+
+
+/*-
+ *-----------------------------------------------------------------------
+ * JobClose --
+ * Called to close both input and output pipes when a job is finished.
+ *
+ * Results:
+ * Nada
+ *
+ * Side Effects:
+ * The file descriptors associated with the job are closed.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+JobClose(job)
+ Job *job;
+{
+ if (usePipes) {
+#ifdef RMT_WILL_WATCH
+ Rmt_Ignore(job->inPipe);
+#else
+ FD_CLR(job->inPipe, &outputs);
+#endif
+ if (job->outPipe != job->inPipe) {
+ (void) close(job->outPipe);
+ }
+ JobDoOutput(job, TRUE);
+ (void) close(job->inPipe);
+ } else {
+ (void) close(job->outFd);
+ JobDoOutput(job, TRUE);
+ }
}
/*-
* Some nodes may be put on the toBeMade queue.
* Final commands for the job are placed on postCommands.
*
- * If we got an error and are aborting (aborting == ABORT_ERROR) and
+ * 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
+ * If we recognized an error(errors !=0), we set the aborting flag
* to ABORT_ERROR so no more jobs will be started.
*-----------------------------------------------------------------------
*/
/*ARGSUSED*/
static void
-JobFinish (job, status)
- Job *job; /* job to finish */
- union wait status; /* sub-why job went away */
+JobFinish(job, status)
+ Job *job; /* job to finish */
+ int *status; /* sub-why job went away */
{
- Boolean done;
+ Boolean done;
- if ((WIFEXITED(status) &&
- (((status.w_retcode != 0) && !(job->flags & JOB_IGNERR)))) ||
- (WIFSIGNALED(status) && (status.w_termsig != SIGCONT)))
+ if ((WIFEXITED(*status) &&
+ (((WEXITSTATUS(*status) != 0) && !(job->flags & JOB_IGNERR)))) ||
+ (WIFSIGNALED(*status) && (WTERMSIG(*status) != SIGCONT)))
{
/*
* If it exited non-zero and either we're doing things our
* cases, finish out the job's output before printing the exit
* status...
*/
- if (usePipes) {
-#ifdef RMT_WILL_WATCH
- Rmt_Ignore(job->inPipe);
-#else
- FD_CLR(job->inPipe, &outputs);
-#endif /* RMT_WILL_WATCH */
- if (job->outPipe != job->inPipe) {
- (void)close (job->outPipe);
- }
- JobDoOutput (job, TRUE);
- (void)close (job->inPipe);
- } else {
- (void)close (job->outFd);
- JobDoOutput (job, TRUE);
- }
-
+#ifdef REMOTE
+ KILL(job->pid, SIGCONT);
+#endif
+ JobClose(job);
if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
- fclose(job->cmdFILE);
+ (void) fclose(job->cmdFILE);
}
done = TRUE;
- } else if (WIFEXITED(status) && status.w_retcode != 0) {
+#ifdef REMOTE
+ if (job->flags & JOB_REMOTE)
+ Rmt_Done(job->rmtID, job->node);
+#endif
+ } 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. Note we don't
+ * TRUE if in -B mode and the job exited non-zero.
+ */
+ 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.
+ * end."
+ * But we do. Otherwise when are we going to print the rest of the
+ * stuff?
*/
- done = TRUE;
+ JobClose(job);
+#ifdef REMOTE
+ if (job->flags & JOB_REMOTE)
+ Rmt_Done(job->rmtID, job->node);
+#endif /* REMOTE */
} else {
/*
* No need to close things down or anything.
}
if (done ||
- WIFSTOPPED(status) ||
- (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) ||
+ WIFSTOPPED(*status) ||
+ (WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) ||
DEBUG(JOB))
{
FILE *out;
- if (!usePipes && (job->flags & JOB_IGNERR)) {
+ if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) {
/*
* If output is going to a file and this job is ignoring
* errors, arrange to have the exit status sent to the
* output file as well.
*/
- out = fdopen (job->outFd, "w");
+ out = fdopen(job->outFd, "w");
} else {
out = stdout;
}
- if (WIFEXITED(status)) {
- if (status.w_retcode != 0) {
+ if (WIFEXITED(*status)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "Process %d exited.\n", job->pid);
+ (void) fflush(stdout);
+ }
+ if (WEXITSTATUS(*status) != 0) {
if (usePipes && job->node != lastNode) {
- fprintf (out, targFmt, job->node->name);
+ MESSAGE(out, job->node);
lastNode = job->node;
}
- fprintf (out, "*** Error code %d%s\n", status.w_retcode,
- (job->flags & JOB_IGNERR) ? " (ignored)" : "");
+ (void) fprintf(out, "*** Error code %d%s\n",
+ WEXITSTATUS(*status),
+ (job->flags & JOB_IGNERR) ? "(ignored)" : "");
if (job->flags & JOB_IGNERR) {
- status.w_status = 0;
+ *status = 0;
}
} else if (DEBUG(JOB)) {
if (usePipes && job->node != lastNode) {
- fprintf (out, targFmt, job->node->name);
+ MESSAGE(out, job->node);
lastNode = job->node;
}
- fprintf (out, "*** Completed successfully\n");
+ (void) fprintf(out, "*** Completed successfully\n");
+ }
+ } else if (WIFSTOPPED(*status)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "Process %d stopped.\n", job->pid);
+ (void) fflush(stdout);
}
- } else if (WIFSTOPPED(status)) {
if (usePipes && job->node != lastNode) {
- fprintf (out, targFmt, job->node->name);
+ MESSAGE(out, job->node);
lastNode = job->node;
}
- if (! (job->flags & JOB_REMIGRATE)) {
- fprintf (out, "*** Stopped -- signal %d\n", status.w_stopsig);
+ if (!(job->flags & JOB_REMIGRATE)) {
+ fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status));
}
job->flags |= JOB_RESUME;
(void)Lst_AtEnd(stoppedJobs, (ClientData)job);
- fflush(out);
+#ifdef REMOTE
+ if (job->flags & JOB_REMIGRATE)
+ JobRestart(job);
+#endif
+ (void) fflush(out);
return;
- } else if (status.w_termsig == SIGCONT) {
+ } else if (WTERMSIG(*status) == SIGCONT) {
/*
* If the beastie has continued, shift the Job from the stopped
- * list to the running one (or re-stop it if concurrency is
+ * list to the running one(or re-stop it if concurrency is
* exceeded) and go and get another child.
*/
if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) {
if (usePipes && job->node != lastNode) {
- fprintf (out, targFmt, job->node->name);
+ MESSAGE(out, job->node);
lastNode = job->node;
}
- fprintf (out, "*** Continued\n");
+ (void) fprintf(out, "*** Continued\n");
}
- if (! (job->flags & JOB_CONTINUING)) {
- JobRestart(job);
- } else {
- Lst_AtEnd(jobs, (ClientData)job);
- nJobs += 1;
- if (! (job->flags & JOB_REMOTE)) {
- nLocal += 1;
- }
- if (nJobs == maxJobs) {
- jobFull = TRUE;
- if (DEBUG(JOB)) {
- printf("Job queue is full.\n");
- }
+ if (!(job->flags & JOB_CONTINUING)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "Warning: process %d was not continuing.\n",
+ job->pid);
+ (void) fflush(stdout);
}
+#ifdef notdef
+ /*
+ * We don't really want to restart a job from scratch just
+ * because it continued, especially not without killing the
+ * continuing process! That's why this is ifdef'ed out.
+ * FD - 9/17/90
+ */
+ JobRestart(job);
+#endif
}
- fflush(out);
- return;
+ job->flags &= ~JOB_CONTINUING;
+ Lst_AtEnd(jobs, (ClientData)job);
+ nJobs += 1;
+ if (!(job->flags & JOB_REMOTE)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "Process %d is continuing locally.\n",
+ job->pid);
+ (void) fflush(stdout);
+ }
+ nLocal += 1;
+ }
+ if (nJobs == maxJobs) {
+ jobFull = TRUE;
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "Job queue is full.\n");
+ (void) fflush(stdout);
+ }
+ }
+ (void) fflush(out);
+ return;
} else {
if (usePipes && job->node != lastNode) {
- fprintf (out, targFmt, job->node->name);
+ MESSAGE(out, job->node);
lastNode = job->node;
}
- fprintf (out, "*** Signal %d\n", status.w_termsig);
+ (void) fprintf(out, "*** Signal %d\n", WTERMSIG(*status));
}
- fflush (out);
+ (void) fflush(out);
}
/*
* 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.
*/
- if ((status.w_status == 0) &&
- !Lst_IsAtEnd (job->node->commands))
- {
- switch (JobStart (job->node,
- job->flags & JOB_IGNDOTS,
- job))
- {
- case JOB_RUNNING:
- done = FALSE;
- break;
- case JOB_ERROR:
- done = TRUE;
- status.w_retcode = 1;
- break;
- case JOB_FINISHED:
- /*
- * If we got back a JOB_FINISHED code, JobStart has already
- * called Make_Update and freed the job descriptor. We set
- * done to false here to avoid fake cycles and double frees.
- * JobStart needs to do the update so we can proceed up the
- * graph when given the -n flag..
- */
- done = FALSE;
- break;
+ if (compatMake && (WIFEXITED(*status) &&
+ !Lst_IsAtEnd(job->node->commands))) {
+ switch (JobStart(job->node, job->flags & JOB_IGNDOTS, job)) {
+ case JOB_RUNNING:
+ done = FALSE;
+ break;
+ case JOB_ERROR:
+ done = TRUE;
+ W_SETEXITSTATUS(status, 1);
+ break;
+ case JOB_FINISHED:
+ /*
+ * If we got back a JOB_FINISHED code, JobStart has already
+ * called Make_Update and freed the job descriptor. We set
+ * done to false here to avoid fake cycles and double frees.
+ * JobStart needs to do the update so we can proceed up the
+ * graph when given the -n flag..
+ */
+ done = FALSE;
+ break;
}
} else {
done = TRUE;
if (done &&
(aborting != ABORT_ERROR) &&
(aborting != ABORT_INTERRUPT) &&
- (status.w_status == 0))
+ (*status == 0))
{
/*
* As long as we aren't aborting and the job didn't return a non-zero
* on the .END target.
*/
if (job->tailCmds != NILLNODE) {
- Lst_ForEachFrom (job->node->commands, job->tailCmds,
+ Lst_ForEachFrom(job->node->commands, job->tailCmds,
JobSaveCommand,
- (ClientData)job->node);
+ (ClientData)job->node);
}
job->node->made = MADE;
- Make_Update (job->node);
+ Make_Update(job->node);
free((Address)job);
- } else if (status.w_status) {
+ } else if (*status == 0) {
errors += 1;
free((Address)job);
}
- while (!errors && !jobFull && !Lst_IsEmpty(stoppedJobs)) {
- JobRestart((Job *)Lst_DeQueue(stoppedJobs));
- }
+ JobRestartJobs();
/*
* Set aborting if any error.
/*
* If we are aborting and the job table is now empty, we finish.
*/
- (void) unlink (tfile);
- Finish (errors);
+ (void) eunlink(tfile);
+ Finish(errors);
}
}
*-----------------------------------------------------------------------
*/
void
-Job_Touch (gn, silent)
+Job_Touch(gn, silent)
GNode *gn; /* the node of the file to touch */
Boolean silent; /* TRUE if should not print messages */
{
}
if (!silent) {
- printf ("touch %s\n", gn->name);
+ (void) fprintf(stdout, "touch %s\n", gn->name);
+ (void) fflush(stdout);
}
if (noExecute) {
}
if (gn->type & OP_ARCHV) {
- Arch_Touch (gn);
+ Arch_Touch(gn);
} else if (gn->type & OP_LIB) {
- Arch_TouchLib (gn);
+ Arch_TouchLib(gn);
} else {
char *file = gn->path ? gn->path : gn->name;
times[0].tv_sec = times[1].tv_sec = now;
times[0].tv_usec = times[1].tv_usec = 0;
if (utimes(file, times) < 0){
- streamID = open (file, O_RDWR | O_CREAT, 0666);
+ streamID = open(file, O_RDWR | O_CREAT, 0666);
if (streamID >= 0) {
char c;
* modification time, then close the file.
*/
if (read(streamID, &c, 1) == 1) {
- lseek(streamID, (off_t) 0, SEEK_SET);
- write(streamID, &c, 1);
+ (void) lseek(streamID, 0L, L_SET);
+ (void) write(streamID, &c, 1);
}
- (void)close (streamID);
- } else
- printf("*** couldn't touch %s: %s", file, strerror(errno));
+ (void) close(streamID);
+ } else {
+ (void) fprintf(stdout, "*** couldn't touch %s: %s",
+ file, strerror(errno));
+ (void) fflush(stdout);
+ }
}
}
}
*-----------------------------------------------------------------------
*/
Boolean
-Job_CheckCommands (gn, abortProc)
+Job_CheckCommands(gn, abortProc)
GNode *gn; /* The target whose commands need
* verifying */
- void (*abortProc) __P((char *, ...));
+ void (*abortProc) __P((char *, ...));
/* Function to abort with message */
{
- if (OP_NOP(gn->type) && Lst_IsEmpty (gn->commands) &&
+ if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) &&
(gn->type & OP_LIB) == 0) {
/*
* No commands. Look for .DEFAULT rule from which we might infer
* .DEFAULT itself.
*/
Make_HandleUse(DEFAULT, gn);
- Var_Set (IMPSRC, Var_Value (TARGET, gn, &p1), gn);
+ Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn);
if (p1)
free(p1);
- } else if (Dir_MTime (gn) == 0) {
+ } else if (Dir_MTime(gn) == 0) {
/*
* The node wasn't the target of an operator we have no .DEFAULT
* rule to go on and the target doesn't already exist. There's
* given, we stop in our tracks, otherwise we just don't update
* this node's parents so they never get examined.
*/
+ static const char msg[] = "make: don't know how to make";
+
if (gn->type & OP_OPTIONAL) {
- printf ("make: don't know how to make %s (ignored)\n",
- gn->name);
+ (void) fprintf(stdout, "%s %s(ignored)\n", msg, gn->name);
+ (void) fflush(stdout);
} else if (keepgoing) {
- printf ("make: don't know how to make %s (continuing)\n",
- gn->name);
- return (FALSE);
+ (void) fprintf(stdout, "%s %s(continuing)\n", msg, gn->name);
+ (void) fflush(stdout);
+ return FALSE;
} else {
- (*abortProc) ("make: don't know how to make %s. Stop",
- gn->name);
- return(FALSE);
+ (*abortProc)("%s %s. Stop", msg, gn->name);
+ return FALSE;
}
}
}
- return (TRUE);
+ return TRUE;
}
#ifdef RMT_WILL_WATCH
/*-
/*ARGSUSED*/
static void
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 */
{
JobDoOutput(job, FALSE);
if (DEBUG(JOB)) {
int i;
- printf("Running %s %sly\n", job->node->name,
- job->flags&JOB_REMOTE?"remote":"local");
- printf("\tCommand: ");
- for (i = 0; argv[i] != (char *)NULL; i++) {
- printf("%s ", argv[i]);
+ (void) fprintf(stdout, "Running %s %sly\n", job->node->name,
+ job->flags&JOB_REMOTE?"remote":"local");
+ (void) fprintf(stdout, "\tCommand: ");
+ for (i = 0; argv[i] != NULL; i++) {
+ (void) fprintf(stdout, "%s ", argv[i]);
}
- printf("\n");
+ (void) fprintf(stdout, "\n");
+ (void) fflush(stdout);
}
/*
* Some jobs produce no output and it's disconcerting to have
- * no feedback of their running (since they produce no output, the
+ * no feedback of their running(since they produce no output, the
* banner with their name in it never appears). This is an attempt to
* provide that feedback, even if nothing follows it.
*/
if ((lastNode != job->node) && (job->flags & JOB_FIRST) &&
- !(job->flags & JOB_SILENT))
- {
- printf(targFmt, job->node->name);
+ !(job->flags & JOB_SILENT)) {
+ MESSAGE(stdout, job->node);
lastNode = job->node;
}
}
#endif /* RMT_NO_EXEC */
- if ((cpid = vfork()) == -1) {
- Punt ("Cannot fork");
+ if ((cpid = vfork()) == -1) {
+ Punt("Cannot fork");
} else if (cpid == 0) {
/*
* Must duplicate the input stream down to the child's input and
- * reset it to the beginning (again). Since the stream was marked
+ * reset it to the beginning(again). Since the stream was marked
* close-on-exec, we must clear that bit in the new input.
*/
- (void) dup2(fileno(job->cmdFILE), 0);
- fcntl(0, F_SETFD, 0);
- lseek(0, (off_t) 0, SEEK_SET);
+ if (dup2(FILENO(job->cmdFILE), 0) == -1)
+ Punt("Cannot dup2: %s", strerror(errno));
+ (void) fcntl(0, F_SETFD, 0);
+ (void) lseek(0, 0, L_SET);
if (usePipes) {
/*
* Set up the child's output to be routed through the pipe
* we've created for it.
*/
- (void) dup2 (job->outPipe, 1);
+ if (dup2(job->outPipe, 1) == -1)
+ Punt("Cannot dup2: %s", strerror(errno));
} else {
/*
* We're capturing output in a file, so we duplicate the
* descriptor to the temporary file into the standard
* output.
*/
- (void) dup2 (job->outFd, 1);
+ if (dup2(job->outFd, 1) == -1)
+ Punt("Cannot dup2: %s", strerror(errno));
}
/*
* The output channels are marked close on exec. This bit was
- * duplicated by the dup2 (on some systems), so we have to clear
+ * duplicated by the dup2(on some systems), so we have to clear
* it before routing the shell's error output to the same place as
* its standard output.
*/
- fcntl(1, F_SETFD, 0);
- (void) dup2 (1, 2);
+ (void) fcntl(1, F_SETFD, 0);
+ if (dup2(1, 2) == -1)
+ Punt("Cannot dup2: %s", strerror(errno));
#ifdef USE_PGRP
/*
* we can kill it and all its descendants in one fell swoop,
* by killing its process family, but not commit suicide.
*/
-
- (void) setpgrp(0, getpid());
-#endif USE_PGRP
+# if defined(SYSV)
+ (void) setsid();
+# else
+ (void) setpgid(0, getpid());
+# endif
+#endif /* USE_PGRP */
- (void) execv (shellPath, argv);
- (void) write (2, "Could not execute shell\n",
- sizeof ("Could not execute shell"));
- _exit (1);
+#ifdef REMOTE
+ if (job->flags & JOB_REMOTE) {
+ Rmt_Exec(shellPath, argv, FALSE);
+ } else
+#endif /* REMOTE */
+ (void) execv(shellPath, argv);
+
+ (void) write(2, "Could not execute shell\n",
+ sizeof("Could not execute shell"));
+ _exit(1);
} else {
+#ifdef REMOTE
+ long omask = sigblock(sigmask(SIGCHLD));
+#endif
job->pid = cpid;
if (usePipes && (job->flags & JOB_FIRST) ) {
}
if (job->flags & JOB_REMOTE) {
+#ifndef REMOTE
job->rmtID = 0;
+#else
+ job->rmtID = Rmt_LastID(job->pid);
+#endif /* REMOTE */
} else {
nLocal += 1;
/*
- * XXX: Used to not happen if CUSTOMS. Why?
+ * XXX: Used to not happen if REMOTE. Why?
*/
- if (job->cmdFILE != stdout) {
- fclose(job->cmdFILE);
+ if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
+ (void) fclose(job->cmdFILE);
job->cmdFILE = NULL;
}
}
+#ifdef REMOTE
+ (void) sigsetmask(omask);
+#endif
}
#ifdef RMT_NO_EXEC
* Now the job is actually running, add it to the table.
*/
nJobs += 1;
- (void)Lst_AtEnd (jobs, (ClientData)job);
+ (void) Lst_AtEnd(jobs, (ClientData)job);
if (nJobs == maxJobs) {
jobFull = TRUE;
}
argc++;
}
}
- argv[argc] = (char *)NULL;
+ argv[argc] = NULL;
}
/*-
JobRestart(job)
Job *job; /* Job to restart */
{
+#ifdef REMOTE
+ int host;
+#endif
+
if (job->flags & JOB_REMIGRATE) {
- if (DEBUG(JOB)) {
- printf("Remigrating %x\n", job->pid);
+ if (
+#ifdef REMOTE
+ verboseRemigrates ||
+#endif
+ DEBUG(JOB)) {
+ (void) fprintf(stdout, "*** remigrating %x(%s)\n",
+ job->pid, job->node->name);
+ (void) fflush(stdout);
}
- if (nLocal != maxLocal) {
+
+#ifdef REMOTE
+ if (!Rmt_ReExport(job->pid, job->node, &host)) {
+ if (verboseRemigrates || DEBUG(JOB)) {
+ (void) fprintf(stdout, "*** couldn't migrate...\n");
+ (void) fflush(stdout);
+ }
+#endif
+ if (nLocal != maxLocal) {
/*
* Job cannot be remigrated, but there's room on the local
* machine, so resume the job and note that another
* local job has started.
*/
- if (DEBUG(JOB)) {
- printf("resuming on local machine\n");
- }
+ if (
+#ifdef REMOTE
+ verboseRemigrates ||
+#endif
+ DEBUG(JOB)) {
+ (void) fprintf(stdout, "*** resuming on local machine\n");
+ (void) fflush(stdout);
+ }
KILL(job->pid, SIGCONT);
nLocal +=1;
+#ifdef REMOTE
+ job->flags &= ~(JOB_REMIGRATE|JOB_RESUME|JOB_REMOTE);
+ job->flags |= JOB_CONTINUING;
+#else
job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
+#endif
} else {
/*
* Job cannot be restarted. Mark the table as full and
* place the job back on the list of stopped jobs.
*/
- if (DEBUG(JOB)) {
- printf("holding\n");
- }
+ if (
+#ifdef REMOTE
+ verboseRemigrates ||
+#endif
+ DEBUG(JOB)) {
+ (void) fprintf(stdout, "*** holding\n");
+ (void) fflush(stdout);
+ }
(void)Lst_AtFront(stoppedJobs, (ClientData)job);
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Job queue is full.\n");
+ (void) fprintf(stdout, "Job queue is full.\n");
+ (void) fflush(stdout);
}
return;
+ }
+#ifdef REMOTE
+ } else {
+ /*
+ * Clear out the remigrate and resume flags. Set the continuing
+ * flag so we know later on that the process isn't exiting just
+ * because of a signal.
+ */
+ job->flags &= ~(JOB_REMIGRATE|JOB_RESUME);
+ job->flags |= JOB_CONTINUING;
+ job->rmtID = host;
}
+#endif
(void)Lst_AtEnd(jobs, (ClientData)job);
nJobs += 1;
if (nJobs == maxJobs) {
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Job queue is full.\n");
+ (void) fprintf(stdout, "Job queue is full.\n");
+ (void) fflush(stdout);
}
}
} else if (job->flags & JOB_RESTART) {
char *argv[4];
JobMakeArgv(job, argv);
-
+
if (DEBUG(JOB)) {
- printf("Restarting %s...", job->node->name);
+ (void) fprintf(stdout, "Restarting %s...", job->node->name);
+ (void) fflush(stdout);
}
- if (((nLocal >= maxLocal) && ! (job->flags & JOB_SPECIAL))) {
+#ifdef REMOTE
+ if ((job->node->type&OP_NOEXPORT) ||
+ (nLocal < maxLocal && runLocalFirst)
+# ifdef RMT_NO_EXEC
+ || !Rmt_Export(shellPath, argv, job)
+# else
+ || !Rmt_Begin(shellPath, argv, job->node)
+# endif
+#endif
+ {
+ if (((nLocal >= maxLocal) && !(job->flags & JOB_SPECIAL))) {
/*
* Can't be exported and not allowed to run locally -- put it
* back on the hold queue and mark the table full
*/
if (DEBUG(JOB)) {
- printf("holding\n");
+ (void) fprintf(stdout, "holding\n");
+ (void) fflush(stdout);
}
(void)Lst_AtFront(stoppedJobs, (ClientData)job);
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Job queue is full.\n");
+ (void) fprintf(stdout, "Job queue is full.\n");
+ (void) fflush(stdout);
}
return;
- } else {
+ } else {
/*
* Job may be run locally.
*/
if (DEBUG(JOB)) {
- printf("running locally\n");
+ (void) fprintf(stdout, "running locally\n");
+ (void) fflush(stdout);
}
job->flags &= ~JOB_REMOTE;
+ }
+ }
+#ifdef REMOTE
+ else {
+ /*
+ * Can be exported. Hooray!
+ */
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "exporting\n");
+ (void) fflush(stdout);
+ }
+ job->flags |= JOB_REMOTE;
}
+#endif
JobExec(job, argv);
} else {
/*
* we don't know...
*/
if (DEBUG(JOB)) {
- printf("Resuming %s...", job->node->name);
+ (void) fprintf(stdout, "Resuming %s...", job->node->name);
+ (void) fflush(stdout);
}
if (((job->flags & JOB_REMOTE) ||
- (nLocal < maxLocal) ||
- (((job->flags & JOB_SPECIAL)) &&
- (maxLocal == 0))) &&
- (nJobs != maxJobs))
+ (nLocal < maxLocal) ||
+#ifdef REMOTE
+ (((job->flags & JOB_SPECIAL) &&
+ (job->node->type & OP_NOEXPORT)) &&
+ (maxLocal == 0))) &&
+#else
+ ((job->flags & JOB_SPECIAL) &&
+ (maxLocal == 0))) &&
+#endif
+ (nJobs != maxJobs))
{
/*
* If the job is remote, it's ok to resume it as long as the
* maximum concurrency won't be exceeded. If it's local and
- * we haven't reached the local concurrency limit already (or the
+ * we haven't reached the local concurrency limit already(or the
* job must be run locally and maxLocal is 0), it's also ok to
* resume it.
*/
Boolean error;
extern int errno;
- union wait status;
+ int status;
#ifdef RMT_WANTS_SIGNALS
if (job->flags & JOB_REMOTE) {
* actually put the thing in the job table.
*/
job->flags |= JOB_CONTINUING;
- status.w_termsig = SIGCONT;
- JobFinish(job, status);
+ W_SETTERMSIG(&status, SIGCONT);
+ JobFinish(job, &status);
job->flags &= ~(JOB_RESUME|JOB_CONTINUING);
if (DEBUG(JOB)) {
- printf("done\n");
+ (void) fprintf(stdout, "done\n");
+ (void) fflush(stdout);
}
} else {
Error("couldn't resume %s: %s",
job->node->name, strerror(errno));
- status.w_status = 0;
- status.w_retcode = 1;
- JobFinish(job, status);
+ status = 0;
+ W_SETEXITSTATUS(&status, 1);
+ JobFinish(job, &status);
}
} else {
/*
* place the job back on the list of stopped jobs.
*/
if (DEBUG(JOB)) {
- printf("table full\n");
+ (void) fprintf(stdout, "table full\n");
+ (void) fflush(stdout);
}
- (void)Lst_AtFront(stoppedJobs, (ClientData)job);
+ (void) Lst_AtFront(stoppedJobs, (ClientData)job);
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Job queue is full.\n");
+ (void) fprintf(stdout, "Job queue is full.\n");
+ (void) fflush(stdout);
}
}
}
*-----------------------------------------------------------------------
*/
static int
-JobStart (gn, flags, previous)
+JobStart(gn, flags, previous)
GNode *gn; /* target to create */
int flags; /* flags for the job to override normal ones.
* e.g. JOB_SPECIAL or JOB_IGNDOTS */
Boolean local; /* Set true if the job was run locally */
Boolean noExec; /* Set true if we decide not to run the job */
- if (previous != (Job *)NULL) {
- previous->flags &= ~ (JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
+ if (previous != NULL) {
+ previous->flags &= ~(JOB_FIRST|JOB_IGNERR|JOB_SILENT|JOB_REMOTE);
job = previous;
} else {
- job = (Job *) emalloc (sizeof (Job));
- if (job == (Job *)NULL) {
+ job = (Job *) emalloc(sizeof(Job));
+ if (job == NULL) {
Punt("JobStart out of memory");
}
flags |= JOB_FIRST;
* are also added to the field.
*/
job->flags = 0;
- if (Targ_Ignore (gn)) {
+ if (Targ_Ignore(gn)) {
job->flags |= JOB_IGNERR;
}
- if (Targ_Silent (gn)) {
+ if (Targ_Silent(gn)) {
job->flags |= JOB_SILENT;
}
job->flags |= flags;
* Check the commands now so any attributes from .DEFAULT have a chance
* to migrate to the node
*/
- if (job->flags & JOB_FIRST) {
+ if (!compatMake && job->flags & JOB_FIRST) {
cmdsOK = Job_CheckCommands(gn, Error);
} else {
cmdsOK = TRUE;
}
/*
- * If the -n flag wasn't given, we open up OUR (not the child's)
+ * If the -n flag wasn't given, we open up OUR(not the child's)
* temporary file to stuff commands in it. The thing is rd/wr so we don't
* need to reopen it to feed it to the shell. If the -n flag *was* given,
* we just set the file to be stdout. Cute, huh?
DieHorribly();
}
- job->cmdFILE = fopen (tfile, "w+");
- if (job->cmdFILE == (FILE *) NULL) {
- Punt ("Could not open %s", tfile);
+ job->cmdFILE = fopen(tfile, "w+");
+ if (job->cmdFILE == NULL) {
+ Punt("Could not open %s", tfile);
}
- 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
* rewind and remove the thing.
if ((job->flags&JOB_FIRST) && (Lst_Open(gn->commands) != SUCCESS)){
cmdsOK = FALSE;
} else {
- LstNode ln = Lst_Next (gn->commands);
+ LstNode ln = Lst_Next(gn->commands);
if ((ln == NILLNODE) ||
- JobPrintCommand ((char *)Lst_Datum (ln), job))
+ JobPrintCommand((ClientData) Lst_Datum(ln),
+ (ClientData) job))
{
noExec = TRUE;
- Lst_Close (gn->commands);
+ Lst_Close(gn->commands);
}
if (noExec && !(job->flags & JOB_FIRST)) {
/*
* Job_CatchChildren b/c it wasn't clear if there were
* more commands to execute or not...
*/
- if (usePipes) {
-#ifdef RMT_WILL_WATCH
- Rmt_Ignore(job->inPipe);
-#else
- FD_CLR(job->inPipe, &outputs);
-#endif
- if (job->outPipe != job->inPipe) {
- (void)close (job->outPipe);
- }
- JobDoOutput (job, TRUE);
- (void)close (job->inPipe);
- } else {
- (void)close (job->outFd);
- JobDoOutput (job, TRUE);
- }
+ JobClose(job);
}
}
} else {
* We can do all the commands at once. hooray for sanity
*/
numCommands = 0;
- Lst_ForEach (gn->commands, JobPrintCommand, (ClientData)job);
+ Lst_ForEach(gn->commands, JobPrintCommand, (ClientData)job);
/*
* If we didn't print out any commands to the shell script,
* in one fell swoop. This will still set up job->tailCmds correctly.
*/
if (lastNode != gn) {
- printf (targFmt, gn->name);
+ MESSAGE(stdout, gn);
lastNode = gn;
}
job->cmdFILE = stdout;
* up the graph.
*/
job->cmdFILE = stdout;
- Job_Touch (gn, job->flags&JOB_SILENT);
+ Job_Touch(gn, job->flags&JOB_SILENT);
noExec = TRUE;
}
* Unlink and close the command file if we opened one
*/
if (job->cmdFILE != stdout) {
- (void) unlink (tfile);
- fclose(job->cmdFILE);
+ (void) eunlink(tfile);
+ if (job->cmdFILE != NULL)
+ (void) fclose(job->cmdFILE);
} else {
- fflush (stdout);
+ (void) fflush(stdout);
}
/*
if (job->tailCmds != NILLNODE) {
Lst_ForEachFrom(job->node->commands, job->tailCmds,
JobSaveCommand,
- (ClientData)job->node);
+ (ClientData)job->node);
}
Make_Update(job->node);
}
return(JOB_ERROR);
}
} else {
- fflush (job->cmdFILE);
- (void) unlink (tfile);
+ (void) fflush(job->cmdFILE);
+ (void) eunlink(tfile);
}
/*
* starting a job and then set up its temporary-file name. This is just
* tfile with two extra digits tacked on -- jobno.
*/
- if (job->flags & JOB_FIRST) {
+ if (!compatMake || (job->flags & JOB_FIRST)) {
if (usePipes) {
int fd[2];
- (void) pipe(fd);
+ if (pipe(fd) == -1)
+ Punt("Cannot create pipe: %s", strerror(errno));
job->inPipe = fd[0];
job->outPipe = fd[1];
- (void)fcntl (job->inPipe, F_SETFD, 1);
- (void)fcntl (job->outPipe, F_SETFD, 1);
+ (void) fcntl(job->inPipe, F_SETFD, 1);
+ (void) fcntl(job->outPipe, F_SETFD, 1);
} else {
- printf ("Remaking `%s'\n", gn->name);
- fflush (stdout);
- sprintf (job->outFile, "%s%02d", tfile, jobno);
+ (void) fprintf(stdout, "Remaking `%s'\n", gn->name);
+ (void) fflush(stdout);
+ sprintf(job->outFile, "%s%02d", tfile, jobno);
jobno = (jobno + 1) % 100;
job->outFd = open(job->outFile,O_WRONLY|O_CREAT|O_APPEND,0600);
- (void)fcntl (job->outFd, F_SETFD, 1);
+ (void) fcntl(job->outFd, F_SETFD, 1);
}
}
- local = TRUE;
+#ifdef REMOTE
+ if (!(gn->type & OP_NOEXPORT) && !(runLocalFirst && nLocal < maxLocal)) {
+#ifdef RMT_NO_EXEC
+ local = !Rmt_Export(shellPath, argv, job);
+#else
+ local = !Rmt_Begin(shellPath, argv, job->node);
+#endif /* RMT_NO_EXEC */
+ if (!local) {
+ job->flags |= JOB_REMOTE;
+ }
+ } else
+#endif
+ local = TRUE;
if (local && (((nLocal >= maxLocal) &&
- !(job->flags & JOB_SPECIAL) &&
- (maxLocal != 0))))
+ !(job->flags & JOB_SPECIAL) &&
+#ifdef REMOTE
+ (!(gn->type & OP_NOEXPORT) || (maxLocal != 0))
+#else
+ (maxLocal != 0)
+#endif
+ )))
{
/*
* The job can only be run locally, but we've hit the limit of
* local concurrency, so put the job on hold until some other job
- * finishes. Note that the special jobs (.BEGIN, .INTERRUPT and .END)
+ * finishes. Note that the special jobs(.BEGIN, .INTERRUPT and .END)
* may be run locally even when the local limit has been reached
- * (e.g. when maxLocal == 0), though they will be exported if at
- * all possible.
+ *(e.g. when maxLocal == 0), though they will be exported if at
+ * all possible. In addition, any target marked with .NOEXPORT will
+ * be run locally if maxLocal is 0.
*/
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Can only run job locally.\n");
+ (void) fprintf(stdout, "Can only run job locally.\n");
+ (void) fflush(stdout);
}
job->flags |= JOB_RESTART;
- (void)Lst_AtEnd(stoppedJobs, (ClientData)job);
+ (void) Lst_AtEnd(stoppedJobs, (ClientData)job);
} else {
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.
*/
jobFull = TRUE;
if (DEBUG(JOB)) {
- printf("Local job queue is full.\n");
+ (void) fprintf(stdout, "Local job queue is full.\n");
+ (void) fflush(stdout);
}
}
JobExec(job, argv);
return(JOB_RUNNING);
}
+static char *
+JobOutput(job, cp, endp, msg)
+ register Job *job;
+ register char *cp, *endp;
+ int msg;
+{
+ register char *ecp;
+
+ if (commandShell->noPrint) {
+ ecp = Str_FindSubstring(cp, commandShell->noPrint);
+ while (ecp != NULL) {
+ if (cp != ecp) {
+ *ecp = '\0';
+ if (msg && job->node != lastNode) {
+ MESSAGE(stdout, job->node);
+ lastNode = job->node;
+ }
+ /*
+ * 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->noPLen;
+ 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++;
+ }
+ ecp = Str_FindSubstring(cp, commandShell->noPrint);
+ } else {
+ return cp;
+ }
+ }
+ }
+ return cp;
+}
+
/*-
*-----------------------------------------------------------------------
* JobDoOutput --
* 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
+ * alone on the line(the character after it is not \0 or \n), we
* do print whatever follows it.
*
* Results:
* curPos may be shifted as may the contents of outBuf.
*-----------------------------------------------------------------------
*/
-static void
-JobDoOutput (job, finish)
+STATIC void
+JobDoOutput(job, finish)
register Job *job; /* the job whose output needs printing */
Boolean finish; /* TRUE if this is the last time we'll be
* called for this job */
{
Boolean gotNL = FALSE; /* true if got a newline */
+ Boolean fbuf; /* true if our buffer filled up */
register int nr; /* number of bytes read */
register int i; /* auxiliary index into outBuf */
- register int max; /* limit for i (end of current data) */
- int nRead; /* (Temporary) number of bytes read */
+ register int max; /* limit for i(end of current data) */
+ int nRead; /*(Temporary) number of bytes read */
FILE *oFILE; /* Stream pointer to shell's output file */
char inLine[132];
* Read as many bytes as will fit in the buffer.
*/
end_loop:
+ gotNL = FALSE;
+ fbuf = FALSE;
- nRead = read (job->inPipe, &job->outBuf[job->curPos],
+ nRead = read(job->inPipe, &job->outBuf[job->curPos],
JOB_BUFSIZE - job->curPos);
if (nRead < 0) {
if (DEBUG(JOB)) {
}
/*
- * If we hit the end-of-file (the job is dead), we must flush its
+ * If we hit the end-of-file(the job is dead), we must flush its
* remaining output, so pretend we read a newline if there's any
* output remaining in the buffer.
* Also clear the 'finish' flag so we stop looping.
* If we've run out of buffer space, we have no choice
* but to print the stuff. sigh.
*/
- gotNL = TRUE;
+ fbuf = TRUE;
i = job->curPos;
}
}
- if (gotNL) {
+ if (gotNL || fbuf) {
/*
* Need to send the output to the screen. Null terminate it
* first, overwriting the newline character if there was one.
- * So long as the line isn't one we should filter (according
+ * So long as the line isn't one we should filter(according
* to the shell description), we print the line, preceeded
* by a target banner if this target isn't the same as the
* one for which we last printed something.
*/
job->outBuf[i] = '\0';
if (i >= job->curPos) {
- register char *cp, *ecp;
-
- cp = job->outBuf;
- if (commandShell->noPrint) {
- ecp = Str_FindSubstring(job->outBuf,
- commandShell->noPrint);
- while (ecp != (char *)NULL) {
- if (cp != ecp) {
- *ecp = '\0';
- if (job->node != lastNode) {
- printf (targFmt, job->node->name);
- lastNode = job->node;
- }
- /*
- * 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.
- */
- printf ("%s", cp);
- }
- cp = ecp + commandShell->noPLen;
- if (cp != &job->outBuf[i]) {
- /*
- * Still more to print, look again after skipping
- * the whitespace following the non-printable
- * command....
- */
- cp++;
- while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
- cp++;
- }
- ecp = Str_FindSubstring (cp,
- commandShell->noPrint);
- } else {
- break;
- }
- }
- }
+ char *cp;
+
+ cp = JobOutput(job, job->outBuf, &job->outBuf[i]);
/*
* There's still more in that thar buffer. This time, though,
*/
if (*cp != '\0') {
if (job->node != lastNode) {
- printf (targFmt, job->node->name);
+ MESSAGE(stdout, job->node);
lastNode = job->node;
}
- printf ("%s\n", cp);
+ (void) fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
+ (void) fflush(stdout);
}
-
- fflush (stdout);
}
if (i < max - 1) {
/* shift the remaining characters down */
- memcpy ( job->outBuf, &job->outBuf[i + 1], max - (i + 1));
- job->curPos = max - (i + 1);
+ (void) memcpy(job->outBuf, &job->outBuf[i + 1], max -(i + 1));
+ job->curPos = max -(i + 1);
} else {
/*
/*
* If the finish flag is true, we must loop until we hit
* end-of-file on the pipe. This is guaranteed to happen eventually
- * since the other end of the pipe is now closed (we closed it
+ * since the other end of the pipe is now closed(we closed it
* explicitly and the child has exited). When we do get an EOF,
* finish will be set FALSE and we'll fall through and out.
*/
* Change to read in blocks and do FindSubString type things as for
* pipes? That would allow for "@echo -n..."
*/
- oFILE = fopen (job->outFile, "r");
- if (oFILE != (FILE *) NULL) {
- printf ("Results of making %s:\n", job->node->name);
- while (fgets (inLine, sizeof(inLine), oFILE) != NULL) {
- register char *cp, *ecp, *endp;
+ oFILE = fopen(job->outFile, "r");
+ if (oFILE != NULL) {
+ (void) fprintf(stdout, "Results of making %s:\n", job->node->name);
+ (void) fflush(stdout);
+ while (fgets(inLine, sizeof(inLine), oFILE) != NULL) {
+ register char *cp, *endp, *oendp;
cp = inLine;
- endp = inLine + strlen(inLine);
+ oendp = endp = inLine + strlen(inLine);
if (endp[-1] == '\n') {
*--endp = '\0';
}
- if (commandShell->noPrint) {
- ecp = Str_FindSubstring(cp, commandShell->noPrint);
- while (ecp != (char *)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.
- */
- printf ("%s", cp);
- }
- cp = ecp + commandShell->noPLen;
- 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++;
- }
- ecp = Str_FindSubstring(cp, commandShell->noPrint);
- } else {
- break;
- }
- }
- }
+ cp = JobOutput(job, inLine, endp, FALSE);
/*
* There's still more in that thar buffer. This time, though,
* we know there's no newline at the end, so we add one of
* our own free will.
*/
- if (*cp != '\0') {
- printf ("%s\n", cp);
+ (void) fprintf(stdout, "%s", cp);
+ (void) fflush(stdout);
+ if (endp != oendp) {
+ (void) fprintf(stdout, "\n");
+ (void) fflush(stdout);
}
}
- fclose (oFILE);
- (void) unlink (job->outFile);
+ (void) fclose(oFILE);
+ (void) eunlink(job->outFile);
}
}
- fflush(stdout);
}
/*-
*-----------------------------------------------------------------------
*/
void
-Job_CatchChildren (block)
+Job_CatchChildren(block)
Boolean block; /* TRUE if should block on the wait. */
{
int pid; /* pid of dead child */
register Job *job; /* job descriptor for dead child */
LstNode jnode; /* list element for finding job */
- union wait status; /* Exit/termination status */
+ int status; /* Exit/termination status */
/*
* Don't even bother if we know there's no one around.
return;
}
- while ((pid = wait3((int *)&status, (block?0:WNOHANG)|WUNTRACED,
- (struct rusage *)0)) > 0)
+ while ((pid = waitpid((pid_t) -1, &status,
+ (block?0:WNOHANG)|WUNTRACED)) > 0)
{
- if (DEBUG(JOB))
- printf("Process %d exited or stopped.\n", pid);
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "Process %d exited or stopped.\n", pid);
+ (void) fflush(stdout);
+ }
- jnode = Lst_Find (jobs, (ClientData)&pid, JobCmpPid);
+ jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid);
if (jnode == NILLNODE) {
- if (WIFSIGNALED(status) && (status.w_termsig == SIGCONT)) {
+ if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) {
jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid);
if (jnode == NILLNODE) {
- Error("Resumed child (%d) not in table", pid);
+ Error("Resumed child(%d) not in table", pid);
continue;
}
job = (Job *)Lst_Datum(jnode);
- (void)Lst_Remove(stoppedJobs, jnode);
+ (void) Lst_Remove(stoppedJobs, jnode);
} else {
- Error ("Child (%d) not in table?", pid);
+ Error("Child(%d) not in table?", pid);
continue;
}
} else {
- job = (Job *) Lst_Datum (jnode);
- (void)Lst_Remove (jobs, jnode);
+ job = (Job *) Lst_Datum(jnode);
+ (void) Lst_Remove(jobs, jnode);
nJobs -= 1;
if (jobFull && DEBUG(JOB)) {
- printf("Job queue is no longer full.\n");
+ (void) fprintf(stdout, "Job queue is no longer full.\n");
+ (void) fflush(stdout);
}
jobFull = FALSE;
+#ifdef REMOTE
+ if (!(job->flags & JOB_REMOTE)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "Job queue has one fewer local process.\n");
+ (void) fflush(stdout);
+ }
+ nLocal -= 1;
+ }
+#else
nLocal -= 1;
+#endif
}
- JobFinish (job, status);
+ JobFinish(job, &status);
}
}
* Job_CatchOutput --
* Catch the output from our children, if we're using
* pipes do so. Otherwise just block time until we get a
- * signal (most likely a SIGCHLD) since there's no point in
+ * signal(most likely a SIGCHLD) since there's no point in
* just spinning when there's nothing to do and the reaping
* of a child can wait for a while.
*
* -----------------------------------------------------------------------
*/
void
-Job_CatchOutput ()
+Job_CatchOutput()
{
int nfds;
struct timeval timeout;
int pnJobs; /* Previous nJobs */
#endif
- fflush(stdout);
+ (void) fflush(stdout);
#ifdef RMT_WILL_WATCH
pnJobs = nJobs;
* NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren
* IN A TIMELY FASHION TO CATCH ANY LOCALLY RUNNING JOBS THAT EXIT.
* It may use the variable nLocal to determine if it needs to call
- * Job_CatchChildren (if nLocal is 0, there's nothing for which to
+ * Job_CatchChildren(if nLocal is 0, there's nothing for which to
* wait...)
*/
while (nJobs != 0 && pnJobs == nJobs) {
timeout.tv_sec = SEL_SEC;
timeout.tv_usec = SEL_USEC;
- if ((nfds = select (FD_SETSIZE, &readfds, (fd_set *) 0, (fd_set *) 0, &timeout)) < 0)
- {
+ if ((nfds = select(FD_SETSIZE, &readfds, (fd_set *) 0,
+ (fd_set *) 0, &timeout)) <= 0)
return;
- } else {
- if (Lst_Open (jobs) == FAILURE) {
- Punt ("Cannot open job table");
+ else {
+ if (Lst_Open(jobs) == FAILURE) {
+ Punt("Cannot open job table");
}
- while (nfds && (ln = Lst_Next (jobs)) != NILLNODE) {
- job = (Job *) Lst_Datum (ln);
+ while (nfds && (ln = Lst_Next(jobs)) != NILLNODE) {
+ job = (Job *) Lst_Datum(ln);
if (FD_ISSET(job->inPipe, &readfds)) {
- JobDoOutput (job, FALSE);
+ JobDoOutput(job, FALSE);
nfds -= 1;
}
}
- Lst_Close (jobs);
+ Lst_Close(jobs);
}
}
#endif /* RMT_WILL_WATCH */
*-----------------------------------------------------------------------
*/
void
-Job_Make (gn)
+Job_Make(gn)
GNode *gn;
{
- (void)JobStart (gn, 0, (Job *)NULL);
+ (void) JobStart(gn, 0, NULL);
}
/*-
*-----------------------------------------------------------------------
*/
void
-Job_Init (maxproc, maxlocal)
+Job_Init(maxproc, maxlocal)
int maxproc; /* the greatest number of jobs which may be
* running at one time */
int maxlocal; /* the greatest number of local jobs which may
{
GNode *begin; /* node for commands to do at the very start */
- sprintf (tfile, "/tmp/make%05d", getpid());
+ (void) sprintf(tfile, "/tmp/make%05d", getpid());
- jobs = Lst_Init (FALSE);
+ jobs = Lst_Init(FALSE);
stoppedJobs = Lst_Init(FALSE);
maxJobs = maxproc;
maxLocal = maxlocal;
lastNode = NILGNODE;
- if (maxJobs == 1) {
+ if (maxJobs == 1
+#ifdef REMOTE
+ || noMessages
+#endif
+ ) {
/*
* If only one job can run at a time, there's no need for a banner,
* no is there?
targFmt = TARG_FMT;
}
- if (shellPath == (char *) NULL) {
+ if (shellPath == NULL) {
/*
* The user didn't specify a shell to use, so we are using the
* default one... Both the absolute path and the last component
* All default shells are located in _PATH_DEFSHELLDIR.
*/
shellName = commandShell->name;
- shellPath = str_concat (_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
+ shellPath = str_concat(_PATH_DEFSHELLDIR, shellName, STR_ADDSLASH);
}
- if (commandShell->exit == (char *)NULL) {
+ if (commandShell->exit == NULL) {
commandShell->exit = "";
}
- if (commandShell->echo == (char *)NULL) {
+ if (commandShell->echo == NULL) {
commandShell->echo = "";
}
* Catch the four signals that POSIX specifies if they aren't ignored.
* JobPassSig will take care of calling JobInterrupt if appropriate.
*/
- if (signal (SIGINT, SIG_IGN) != SIG_IGN) {
- signal (SIGINT, JobPassSig);
+ if (signal(SIGINT, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGINT, JobPassSig);
}
- if (signal (SIGHUP, SIG_IGN) != SIG_IGN) {
- signal (SIGHUP, JobPassSig);
+ if (signal(SIGHUP, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGHUP, JobPassSig);
}
- if (signal (SIGQUIT, SIG_IGN) != SIG_IGN) {
- signal (SIGQUIT, JobPassSig);
+ if (signal(SIGQUIT, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGQUIT, JobPassSig);
}
- if (signal (SIGTERM, SIG_IGN) != SIG_IGN) {
- signal (SIGTERM, JobPassSig);
+ if (signal(SIGTERM, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGTERM, JobPassSig);
}
/*
* There are additional signals that need to be caught and passed if
* either the export system wants to be told directly of signals or if
- * we're giving each job its own process group (since then it won't get
+ * we're giving each job its own process group(since then it won't get
* signals from the terminal driver as we own the terminal)
*/
#if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP)
- if (signal (SIGTSTP, SIG_IGN) != SIG_IGN) {
- signal (SIGTSTP, JobPassSig);
+ if (signal(SIGTSTP, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGTSTP, JobPassSig);
}
- if (signal (SIGTTOU, SIG_IGN) != SIG_IGN) {
- signal (SIGTTOU, JobPassSig);
+ if (signal(SIGTTOU, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGTTOU, JobPassSig);
}
- if (signal (SIGTTIN, SIG_IGN) != SIG_IGN) {
- signal (SIGTTIN, JobPassSig);
+ if (signal(SIGTTIN, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGTTIN, JobPassSig);
}
- if (signal (SIGWINCH, SIG_IGN) != SIG_IGN) {
- signal (SIGWINCH, JobPassSig);
+ if (signal(SIGWINCH, SIG_IGN) != SIG_IGN) {
+ (void) signal(SIGWINCH, JobPassSig);
}
#endif
- begin = Targ_FindNode (".BEGIN", TARG_NOCREATE);
+ begin = Targ_FindNode(".BEGIN", TARG_NOCREATE);
if (begin != NILGNODE) {
- JobStart (begin, JOB_SPECIAL, (Job *)0);
+ JobStart(begin, JOB_SPECIAL, (Job *)0);
while (nJobs) {
Job_CatchOutput();
#ifndef RMT_WILL_WATCH
- Job_CatchChildren (!usePipes);
+ Job_CatchChildren(!usePipes);
#endif /* RMT_WILL_WATCH */
}
}
- postCommands = Targ_FindNode (".END", TARG_CREATE);
+ postCommands = Targ_FindNode(".END", TARG_CREATE);
}
/*-
*-----------------------------------------------------------------------
*/
Boolean
-Job_Full ()
+Job_Full()
{
- return (aborting || jobFull);
+ return(aborting || jobFull);
}
/*-
* -----------------------------------------------------------------------
*/
Boolean
-Job_Empty ()
+Job_Empty()
{
if (nJobs == 0) {
if (!Lst_IsEmpty(stoppedJobs) && !aborting) {
* it...Try and restart the stopped jobs.
*/
jobFull = FALSE;
- while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {
- JobRestart((Job *)Lst_DeQueue(stoppedJobs));
- }
+ JobRestartJobs();
return(FALSE);
} else {
return(TRUE);
*-----------------------------------------------------------------------
*/
static Shell *
-JobMatchShell (name)
+JobMatchShell(name)
char *name; /* Final component of shell path */
{
register Shell *sh; /* Pointer into shells table */
*cp2;
char *eoname;
- eoname = name + strlen (name);
+ eoname = name + strlen(name);
- match = (Shell *) NULL;
+ match = NULL;
for (sh = shells; sh->name != NULL; sh++) {
- for (cp1 = eoname - strlen (sh->name), cp2 = sh->name;
+ for (cp1 = eoname - strlen(sh->name), cp2 = sh->name;
*cp1 != '\0' && *cp1 == *cp2;
cp1++, cp2++) {
continue;
}
if (*cp1 != *cp2) {
continue;
- } else if (match == (Shell *) NULL ||
- strlen (match->name) < strlen (sh->name)) {
- match = sh;
+ } else if (match == NULL || strlen(match->name) < strlen(sh->name)) {
+ match = sh;
}
}
- return (match == (Shell *) NULL ? sh : match);
+ return(match == NULL ? sh : match);
}
/*-
*-----------------------------------------------------------------------
*/
ReturnStatus
-Job_ParseShell (line)
+Job_ParseShell(line)
char *line; /* The shell spec */
{
char **words;
Shell newShell;
Boolean fullSpec = FALSE;
- while (isspace (*line)) {
+ while (isspace(*line)) {
line++;
}
- words = brk_string (line, &wordCount, TRUE);
+ words = brk_string(line, &wordCount, TRUE);
- memset ((Address)&newShell, 0, sizeof(newShell));
+ memset((Address)&newShell, 0, sizeof(newShell));
/*
* Parse the specification by keyword
*/
- for (path = (char *)NULL, argc = wordCount - 1, argv = words + 1;
+ for (path = NULL, argc = wordCount - 1, argv = words + 1;
argc != 0;
argc--, argv++) {
- if (strncmp (*argv, "path=", 5) == 0) {
+ if (strncmp(*argv, "path=", 5) == 0) {
path = &argv[0][5];
- } else if (strncmp (*argv, "name=", 5) == 0) {
+ } else if (strncmp(*argv, "name=", 5) == 0) {
newShell.name = &argv[0][5];
} else {
- if (strncmp (*argv, "quiet=", 6) == 0) {
+ if (strncmp(*argv, "quiet=", 6) == 0) {
newShell.echoOff = &argv[0][6];
- } else if (strncmp (*argv, "echo=", 5) == 0) {
+ } else if (strncmp(*argv, "echo=", 5) == 0) {
newShell.echoOn = &argv[0][5];
- } else if (strncmp (*argv, "filter=", 7) == 0) {
+ } else if (strncmp(*argv, "filter=", 7) == 0) {
newShell.noPrint = &argv[0][7];
newShell.noPLen = strlen(newShell.noPrint);
- } else if (strncmp (*argv, "echoFlag=", 9) == 0) {
+ } else if (strncmp(*argv, "echoFlag=", 9) == 0) {
newShell.echo = &argv[0][9];
- } else if (strncmp (*argv, "errFlag=", 8) == 0) {
+ } else if (strncmp(*argv, "errFlag=", 8) == 0) {
newShell.exit = &argv[0][8];
- } else if (strncmp (*argv, "hasErrCtl=", 10) == 0) {
+ } else if (strncmp(*argv, "hasErrCtl=", 10) == 0) {
char c = argv[0][10];
newShell.hasErrCtl = !((c != 'Y') && (c != 'y') &&
- (c != 'T') && (c != 't'));
- } else if (strncmp (*argv, "check=", 6) == 0) {
+ (c != 'T') && (c != 't'));
+ } else if (strncmp(*argv, "check=", 6) == 0) {
newShell.errCheck = &argv[0][6];
- } else if (strncmp (*argv, "ignore=", 7) == 0) {
+ } else if (strncmp(*argv, "ignore=", 7) == 0) {
newShell.ignErr = &argv[0][7];
} else {
- Parse_Error (PARSE_FATAL, "Unknown keyword \"%s\"",
+ Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"",
*argv);
- return (FAILURE);
+ return(FAILURE);
}
fullSpec = TRUE;
}
}
- if (path == (char *)NULL) {
+ if (path == NULL) {
/*
* If no path was given, the user wants one of the pre-defined shells,
* yes? So we find the one s/he wants with the help of JobMatchShell
* and set things up the right way. shellPath will be set up by
* Job_Init.
*/
- if (newShell.name == (char *)NULL) {
- Parse_Error (PARSE_FATAL, "Neither path nor name specified");
- return (FAILURE);
+ if (newShell.name == NULL) {
+ Parse_Error(PARSE_FATAL, "Neither path nor name specified");
+ return(FAILURE);
} else {
- commandShell = JobMatchShell (newShell.name);
+ commandShell = JobMatchShell(newShell.name);
shellName = newShell.name;
}
} else {
/*
- * The user provided a path. If s/he gave nothing else (fullSpec is
+ * The user provided a path. If s/he gave nothing else(fullSpec is
* FALSE), try and find a matching shell in the ones we know of.
* Else we just take the specification at its word and copy it
* to a new location. In either case, we need to record the
* path the user gave for the shell.
*/
shellPath = path;
- path = strrchr (path, '/');
- if (path == (char *)NULL) {
+ path = strrchr(path, '/');
+ if (path == NULL) {
path = shellPath;
} else {
path += 1;
}
- if (newShell.name != (char *)NULL) {
+ if (newShell.name != NULL) {
shellName = newShell.name;
} else {
shellName = path;
}
if (!fullSpec) {
- commandShell = JobMatchShell (shellName);
+ commandShell = JobMatchShell(shellName);
} else {
commandShell = (Shell *) emalloc(sizeof(Shell));
*commandShell = newShell;
}
if (!commandShell->hasErrCtl) {
- if (commandShell->errCheck == (char *)NULL) {
+ if (commandShell->errCheck == NULL) {
commandShell->errCheck = "";
}
- if (commandShell->ignErr == (char *)NULL) {
+ if (commandShell->ignErr == NULL) {
commandShell->ignErr = "%s\n";
}
}
* Do not free up the words themselves, since they might be in use by the
* shell specification...
*/
- free (words);
+ free(words);
return SUCCESS;
}
*-----------------------------------------------------------------------
*/
static void
-JobInterrupt (runINTERRUPT)
+JobInterrupt(runINTERRUPT, signo)
int runINTERRUPT; /* Non-zero if commands for the .INTERRUPT
* target should be executed */
+ int signo; /* signal received */
{
LstNode ln; /* element in job table */
Job *job; /* job descriptor in that element */
aborting = ABORT_INTERRUPT;
- (void)Lst_Open (jobs);
- while ((ln = Lst_Next (jobs)) != NILLNODE) {
- job = (Job *) Lst_Datum (ln);
+ (void) Lst_Open(jobs);
+ while ((ln = Lst_Next(jobs)) != NILLNODE) {
+ job = (Job *) Lst_Datum(ln);
- if (!Targ_Precious (job->node)) {
- char *file = (job->node->path == (char *)NULL ?
+ if (!Targ_Precious(job->node)) {
+ char *file = (job->node->path == NULL ?
job->node->name :
job->node->path);
- struct stat st;
- if (!noExecute && lstat(file, &st) != -1 && !S_ISDIR(st.st_mode) &&
- unlink(file) != -1) {
- Error ("*** %s removed", file);
+ if (!noExecute && eunlink(file) != -1) {
+ Error("*** %s removed", file);
}
}
#ifdef RMT_WANTS_SIGNALS
/*
* If job is remote, let the Rmt module do the killing.
*/
- if (!Rmt_Signal(job, SIGINT)) {
+ if (!Rmt_Signal(job, signo)) {
/*
* If couldn't kill the thing, finish it out now with an
* error code, since no exit report will come in likely.
*/
- union wait status;
+ int status;
status.w_status = 0;
status.w_retcode = 1;
- JobFinish(job, status);
+ JobFinish(job, &status);
}
} else if (job->pid) {
- KILL(job->pid, SIGINT);
+ KILL(job->pid, signo);
}
#else
if (job->pid) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobInterrupt passing signal to child %d.\n",
+ job->pid);
+ (void) fflush(stdout);
+ }
+ KILL(job->pid, signo);
+ }
+#endif /* RMT_WANTS_SIGNALS */
+ }
+
+#ifdef REMOTE
+ (void)Lst_Open(stoppedJobs);
+ while ((ln = Lst_Next(stoppedJobs)) != NILLNODE) {
+ job = (Job *) Lst_Datum(ln);
+
+ if (job->flags & JOB_RESTART) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "%s%s",
+ "JobInterrupt skipping job on stopped queue",
+ "-- it was waiting to be restarted.\n");
+ (void) fflush(stdout);
+ }
+ continue;
+ }
+ if (!Targ_Precious(job->node)) {
+ char *file = (job->node->path == NULL ?
+ job->node->name :
+ job->node->path);
+ if (eunlink(file) == 0) {
+ Error("*** %s removed", file);
+ }
+ }
+ /*
+ * Resume the thing so it will take the signal.
+ */
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobInterrupt passing CONT to stopped child %d.\n",
+ job->pid);
+ (void) fflush(stdout);
+ }
+ KILL(job->pid, SIGCONT);
+#ifdef RMT_WANTS_SIGNALS
+ if (job->flags & JOB_REMOTE) {
+ /*
+ * If job is remote, let the Rmt module do the killing.
+ */
+ if (!Rmt_Signal(job, SIGINT)) {
+ /*
+ * If couldn't kill the thing, finish it out now with an
+ * error code, since no exit report will come in likely.
+ */
+ int status;
+ status.w_status = 0;
+ status.w_retcode = 1;
+ JobFinish(job, &status);
+ }
+ } else if (job->pid) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobInterrupt passing interrupt to stopped child %d.\n",
+ job->pid);
+ (void) fflush(stdout);
+ }
KILL(job->pid, SIGINT);
}
#endif /* RMT_WANTS_SIGNALS */
}
- Lst_Close (jobs);
+#endif
+ Lst_Close(stoppedJobs);
if (runINTERRUPT && !touchFlag) {
- interrupt = Targ_FindNode (".INTERRUPT", TARG_NOCREATE);
+ interrupt = Targ_FindNode(".INTERRUPT", TARG_NOCREATE);
if (interrupt != NILGNODE) {
ignoreErrors = FALSE;
- JobStart (interrupt, JOB_IGNDOTS, (Job *)0);
+ JobStart(interrupt, JOB_IGNDOTS, (Job *)0);
while (nJobs) {
Job_CatchOutput();
#ifndef RMT_WILL_WATCH
- Job_CatchChildren (!usePipes);
+ Job_CatchChildren(!usePipes);
#endif /* RMT_WILL_WATCH */
}
}
}
- (void) unlink (tfile);
- exit (0);
+ (void) eunlink(tfile);
+ exit(signo);
}
/*
* Number of errors reported.
*
* Side Effects:
- * The process' temporary file (tfile) is removed if it still
+ * The process' temporary file(tfile) is removed if it still
* existed.
*-----------------------------------------------------------------------
*/
int
-Job_End ()
+Job_End()
{
- if (postCommands != NILGNODE && !Lst_IsEmpty (postCommands->commands)) {
+ if (postCommands != NILGNODE && !Lst_IsEmpty(postCommands->commands)) {
if (errors) {
- Error ("Errors reported so .END ignored");
+ Error("Errors reported so .END ignored");
} else {
- JobStart (postCommands, JOB_SPECIAL | JOB_IGNDOTS,
- (Job *)0);
+ JobStart(postCommands, JOB_SPECIAL | JOB_IGNDOTS, NULL);
while (nJobs) {
Job_CatchOutput();
#ifndef RMT_WILL_WATCH
- Job_CatchChildren (!usePipes);
+ Job_CatchChildren(!usePipes);
#endif /* RMT_WILL_WATCH */
}
}
}
- (void) unlink (tfile);
+ (void) eunlink(tfile);
return(errors);
}
*-----------------------------------------------------------------------
*/
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 */
int foo;
if (nJobs) {
- (void)Lst_Open (jobs);
- while ((ln = Lst_Next (jobs)) != NILLNODE) {
- job = (Job *) Lst_Datum (ln);
+ (void) Lst_Open(jobs);
+ while ((ln = Lst_Next(jobs)) != NILLNODE) {
+ job = (Job *) Lst_Datum(ln);
/*
* kill the child process with increasingly drastic signals to make
/*
* Catch as many children as want to report in at first, then give up
*/
- while (wait3(&foo, WNOHANG, (struct rusage *)0) > 0)
+ while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
continue;
- (void) unlink (tfile);
+ (void) eunlink(tfile);
+}
+
+#ifdef REMOTE
+/*-
+ *-----------------------------------------------------------------------
+ * JobFlagForMigration --
+ * Handle the eviction of a child. Called from RmtStatusChange.
+ * Flags the child as remigratable and then suspends it.
+ *
+ * Results:
+ * none.
+ *
+ * Side Effects:
+ * The job descriptor is flagged for remigration.
+ *
+ *-----------------------------------------------------------------------
+ */
+void
+JobFlagForMigration(hostID)
+ int hostID; /* ID of host we used, for matching children. */
+{
+ register Job *job; /* job descriptor for dead child */
+ LstNode jnode; /* list element for finding job */
+
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout, "JobFlagForMigration(%d) called.\n", hostID);
+ (void) fflush(stdout);
+ }
+ jnode = Lst_Find(jobs, (ClientData)hostID, JobCmpRmtID);
+
+ if (jnode == NILLNODE) {
+ jnode = Lst_Find(stoppedJobs, (ClientData)hostID, JobCmpRmtID);
+ if (jnode == NILLNODE) {
+ if (DEBUG(JOB)) {
+ Error("Evicting host(%d) not in table", hostID);
+ }
+ return;
+ }
+ }
+ job = (Job *) Lst_Datum(jnode);
+
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "JobFlagForMigration(%d) found job '%s'.\n", hostID,
+ job->node->name);
+ (void) fflush(stdout);
+ }
+
+ KILL(job->pid, SIGSTOP);
+
+ job->flags |= JOB_REMIGRATE;
+}
+
+#endif
+\f
+/*-
+ *-----------------------------------------------------------------------
+ * JobRestartJobs --
+ * Tries to restart stopped jobs if there are slots available.
+ * Note that this tries to restart them regardless of pending errors.
+ * It's not good to leave stopped jobs lying around!
+ *
+ * Results:
+ * None.
+ *
+ * Side Effects:
+ * Resumes(and possibly migrates) jobs.
+ *
+ *-----------------------------------------------------------------------
+ */
+static void
+JobRestartJobs()
+{
+ while (!jobFull && !Lst_IsEmpty(stoppedJobs)) {
+ if (DEBUG(JOB)) {
+ (void) fprintf(stdout,
+ "Job queue is not full. Restarting a stopped job.\n");
+ (void) fflush(stdout);
+ }
+ JobRestart((Job *)Lst_DeQueue(stoppedJobs));
+ }
}