version 1.14.4.1, 1997/01/26 05:51:39 |
version 1.15, 1996/05/29 15:28:05 |
|
|
|
|
#ifndef lint |
#ifndef lint |
#if 0 |
#if 0 |
static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; |
static char sccsid[] = "@(#)job.c 5.15 (Berkeley) 3/1/91"; |
#else |
#else |
static char rcsid[] = "$NetBSD$"; |
static char rcsid[] = "$NetBSD$"; |
#endif |
#endif |
Line 110 static char rcsid[] = "$NetBSD$"; |
|
Line 110 static char rcsid[] = "$NetBSD$"; |
|
#include <fcntl.h> |
#include <fcntl.h> |
#include <errno.h> |
#include <errno.h> |
#include <utime.h> |
#include <utime.h> |
|
#include <signal.h> |
#include <stdio.h> |
#include <stdio.h> |
#include <string.h> |
#include <string.h> |
#include <signal.h> |
#include <signal.h> |
Line 120 static char rcsid[] = "$NetBSD$"; |
|
Line 121 static char rcsid[] = "$NetBSD$"; |
|
#include "pathnames.h" |
#include "pathnames.h" |
#ifdef REMOTE |
#ifdef REMOTE |
#include "rmt.h" |
#include "rmt.h" |
# define STATIC |
# define STATIC |
#else |
#else |
# define STATIC static |
# define STATIC static |
#endif |
#endif |
Line 128 static char rcsid[] = "$NetBSD$"; |
|
Line 129 static char rcsid[] = "$NetBSD$"; |
|
extern int errno; |
extern int errno; |
|
|
/* |
/* |
* error handling variables |
* error handling variables |
*/ |
*/ |
static int errors = 0; /* number of errors reported */ |
static int errors = 0; /* number of errors reported */ |
static int aborting = 0; /* why is the make aborting? */ |
static int aborting = 0; /* why is the make aborting? */ |
Line 136 static int aborting = 0; /* why |
|
Line 137 static int aborting = 0; /* why |
|
#define ABORT_INTERRUPT 2 /* Because it was interrupted */ |
#define ABORT_INTERRUPT 2 /* Because it was interrupted */ |
#define ABORT_WAIT 3 /* Waiting for jobs to finish */ |
#define ABORT_WAIT 3 /* Waiting for jobs to finish */ |
|
|
/* |
/* |
* XXX: Avoid SunOS bug... FILENO() is fp->_file, and file |
* XXX: Avoid SunOS bug... FILENO() is fp->_file, and file |
* is a char! So when we go above 127 we turn negative! |
* is a char! So when we go above 127 we turn negative! |
*/ |
*/ |
Line 165 static int numCommands; /* T |
|
Line 166 static int numCommands; /* T |
|
* tfile is the name of a file into which all shell commands are put. It is |
* tfile is the name of a file into which all shell commands are put. It is |
* used over by removing it before the child shell is executed. The XXXXX in |
* used over by removing it before the child shell is executed. The XXXXX in |
* the string are replaced by the pid of the make process in a 5-character |
* the string are replaced by the pid of the make process in a 5-character |
* field with leading zeroes. |
* field with leading zeroes. |
*/ |
*/ |
static char tfile[] = TMPPAT; |
static char tfile[] = TMPPAT; |
|
|
Line 253 STATIC char *targFmt; /* Format s |
|
Line 254 STATIC char *targFmt; /* Format s |
|
* When JobStart attempts to run a job remotely but can't, and isn't allowed |
* When JobStart attempts to run a job remotely but can't, and isn't allowed |
* to run the job locally, or when Job_CatchChildren detects a job that has |
* to run the job locally, or when Job_CatchChildren detects a job that has |
* been migrated home, the job is placed on the stoppedJobs queue to be run |
* been migrated home, the job is placed on the stoppedJobs queue to be run |
* when the next job finishes. |
* when the next job finishes. |
*/ |
*/ |
STATIC Lst stoppedJobs; /* Lst of Job structures describing |
STATIC Lst stoppedJobs; /* Lst of Job structures describing |
* jobs that were stopped due to concurrency |
* jobs that were stopped due to concurrency |
Line 270 STATIC Lst stoppedJobs; /* Lst of Job st |
|
Line 271 STATIC Lst stoppedJobs; /* Lst of Job st |
|
# endif |
# endif |
#endif |
#endif |
|
|
/* |
/* |
* Grmpf... There is no way to set bits of the wait structure |
* Grmpf... There is no way to set bits of the wait structure |
* anymore with the stupid W*() macros. I liked the union wait |
* anymore with the stupid W*() macros. I liked the union wait |
* stuff much more. So, we devise our own macros... This is |
* stuff much more. So, we devise our own macros... This is |
Line 308 static void JobExec __P((Job *, char **) |
|
Line 309 static void JobExec __P((Job *, char **) |
|
static void JobMakeArgv __P((Job *, char **)); |
static void JobMakeArgv __P((Job *, char **)); |
static void JobRestart __P((Job *)); |
static void JobRestart __P((Job *)); |
static int JobStart __P((GNode *, int, Job *)); |
static int JobStart __P((GNode *, int, Job *)); |
static char *JobOutput __P((Job *, char *, char *, int)); |
|
static void JobDoOutput __P((Job *, Boolean)); |
static void JobDoOutput __P((Job *, Boolean)); |
static Shell *JobMatchShell __P((char *)); |
static Shell *JobMatchShell __P((char *)); |
static void JobInterrupt __P((int, int)); |
static void JobInterrupt __P((int, int)); |
Line 347 JobCondPassSig(jobp, signop) |
|
Line 347 JobCondPassSig(jobp, signop) |
|
* job as well. |
* job as well. |
*/ |
*/ |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, |
(void) fprintf(stdout, |
"JobCondPassSig passing signal %d to child %d.\n", |
"JobCondPassSig passing signal %d to child %d.\n", |
signo, job->pid); |
signo, job->pid); |
(void) fflush(stdout); |
(void) fflush(stdout); |
Line 368 JobCondPassSig(jobp, signop) |
|
Line 368 JobCondPassSig(jobp, signop) |
|
* |
* |
* Side Effects: |
* Side Effects: |
* We die by the same signal. |
* We die by the same signal. |
* |
* |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
static void |
static void |
Line 377 JobPassSig(signo) |
|
Line 377 JobPassSig(signo) |
|
{ |
{ |
sigset_t nmask, omask; |
sigset_t nmask, omask; |
struct sigaction act; |
struct sigaction act; |
|
|
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); |
(void) fprintf(stdout, "JobPassSig(%d) called.\n", signo); |
(void) fflush(stdout); |
(void) fflush(stdout); |
Line 394 JobPassSig(signo) |
|
Line 394 JobPassSig(signo) |
|
} else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { |
} else if ((signo == SIGHUP) || (signo == SIGTERM) || (signo == SIGQUIT)) { |
JobInterrupt(FALSE, signo); |
JobInterrupt(FALSE, signo); |
} |
} |
|
|
/* |
/* |
* Leave gracefully if SIGQUIT, rather than core dumping. |
* Leave gracefully if SIGQUIT, rather than core dumping. |
*/ |
*/ |
if (signo == SIGQUIT) { |
if (signo == SIGQUIT) { |
Finish(0); |
Finish(0); |
} |
} |
|
|
/* |
/* |
* Send ourselves the signal now we've given the message to everyone else. |
* Send ourselves the signal now we've given the message to everyone else. |
* Note we block everything else possible while we're getting the signal. |
* Note we block everything else possible while we're getting the signal. |
Line 454 JobCmpPid(job, pid) |
|
Line 454 JobCmpPid(job, pid) |
|
ClientData job; /* job to examine */ |
ClientData job; /* job to examine */ |
ClientData pid; /* process id desired */ |
ClientData pid; /* process id desired */ |
{ |
{ |
return *(int *) pid - ((Job *) job)->pid; |
return( *(int *) pid - ((Job *) job)->pid); |
} |
} |
|
|
#ifdef REMOTE |
#ifdef REMOTE |
Line 462 JobCmpPid(job, pid) |
|
Line 462 JobCmpPid(job, pid) |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* JobCmpRmtID -- |
* JobCmpRmtID -- |
* Compare the rmtID of the job with the given rmtID and return 0 if they |
* Compare the rmtID of the job with the given rmtID and return 0 if they |
* are equal. |
* are equal. |
* |
* |
* Results: |
* Results: |
* 0 if the rmtID's match |
* 0 if the rmtID's match |
Line 525 JobPrintCommand(cmdp, jobp) |
|
Line 525 JobPrintCommand(cmdp, jobp) |
|
char *cmdStart; /* Start of expanded command */ |
char *cmdStart; /* Start of expanded command */ |
LstNode cmdNode; /* Node for replacing the command */ |
LstNode cmdNode; /* Node for replacing the command */ |
char *cmd = (char *) cmdp; |
char *cmd = (char *) cmdp; |
Job *job = (Job *) jobp; |
Job *job = (Job *) jobp; |
|
|
noSpecials = (noExecute && !(job->node->type & OP_MAKE)); |
noSpecials = (noExecute && !(job->node->type & OP_MAKE)); |
|
|
if (strcmp(cmd, "...") == 0) { |
if (strcmp(cmd, "...") == 0) { |
job->node->type |= OP_SAVE_CMDS; |
job->node->type |= OP_SAVE_CMDS; |
if ((job->flags & JOB_IGNDOTS) == 0) { |
if ((job->flags & JOB_IGNDOTS) == 0) { |
job->tailCmds = Lst_Succ(Lst_Member(job->node->commands, |
job->tailCmds = Lst_Succ(Lst_Member(job->node->commands, |
(ClientData)cmd)); |
(ClientData)cmd)); |
return 1; |
return(1); |
} |
} |
return 0; |
return(0); |
} |
} |
|
|
#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ |
#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ |
Line 621 JobPrintCommand(cmdp, jobp) |
|
Line 621 JobPrintCommand(cmdp, jobp) |
|
} |
} |
cmdTemplate = commandShell->ignErr; |
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 |
* of by the ignErr template, so pretend error checking |
* is still on. |
* is still on. |
*/ |
*/ |
Line 633 JobPrintCommand(cmdp, jobp) |
|
Line 633 JobPrintCommand(cmdp, jobp) |
|
errOff = FALSE; |
errOff = FALSE; |
} |
} |
} |
} |
|
|
DBPRINTF(cmdTemplate, cmd); |
DBPRINTF(cmdTemplate, cmd); |
|
|
if (errOff) { |
if (errOff) { |
/* |
/* |
* If echoing is already off, there's no point in issuing the |
* If echoing is already off, there's no point in issuing the |
|
|
* Some nodes may be put on the toBeMade queue. |
* Some nodes may be put on the toBeMade queue. |
* Final commands for the job are placed on postCommands. |
* Final commands for the job are placed on postCommands. |
* |
* |
* 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. |
* 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. |
* to ABORT_ERROR so no more jobs will be started. |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
Line 776 JobFinish(job, status) |
|
Line 776 JobFinish(job, status) |
|
* TRUE if in -B mode and the job exited non-zero. |
* TRUE if in -B mode and the job exited non-zero. |
*/ |
*/ |
done = WEXITSTATUS(*status) != 0; |
done = WEXITSTATUS(*status) != 0; |
/* |
/* |
* Old comment said: "Note we don't |
* Old comment said: "Note we don't |
* want to close down any of the streams until we know we're at the |
* want to close down any of the streams until we know we're at the |
* end." |
* end." |
Line 794 JobFinish(job, status) |
|
Line 794 JobFinish(job, status) |
|
*/ |
*/ |
done = FALSE; |
done = FALSE; |
} |
} |
|
|
if (done || |
if (done || |
WIFSTOPPED(*status) || |
WIFSTOPPED(*status) || |
(WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) || |
(WIFSIGNALED(*status) && (WTERMSIG(*status) == SIGCONT)) || |
DEBUG(JOB)) |
DEBUG(JOB)) |
{ |
{ |
FILE *out; |
FILE *out; |
|
|
if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { |
if (compatMake && !usePipes && (job->flags & JOB_IGNERR)) { |
/* |
/* |
* If output is going to a file and this job is ignoring |
* If output is going to a file and this job is ignoring |
Line 847 JobFinish(job, status) |
|
Line 847 JobFinish(job, status) |
|
lastNode = job->node; |
lastNode = job->node; |
} |
} |
if (!(job->flags & JOB_REMIGRATE)) { |
if (!(job->flags & JOB_REMIGRATE)) { |
(void) fprintf(out, "*** Stopped -- signal %d\n", |
fprintf(out, "*** Stopped -- signal %d\n", WSTOPSIG(*status)); |
WSTOPSIG(*status)); |
|
} |
} |
job->flags |= JOB_RESUME; |
job->flags |= JOB_RESUME; |
(void)Lst_AtEnd(stoppedJobs, (ClientData)job); |
(void)Lst_AtEnd(stoppedJobs, (ClientData)job); |
Line 861 JobFinish(job, status) |
|
Line 860 JobFinish(job, status) |
|
} else if (WTERMSIG(*status) == SIGCONT) { |
} else if (WTERMSIG(*status) == SIGCONT) { |
/* |
/* |
* If the beastie has continued, shift the Job from the stopped |
* 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. |
* exceeded) and go and get another child. |
*/ |
*/ |
if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) { |
if (job->flags & (JOB_RESUME|JOB_REMIGRATE|JOB_RESTART)) { |
Line 949 JobFinish(job, status) |
|
Line 948 JobFinish(job, status) |
|
} else { |
} else { |
done = TRUE; |
done = TRUE; |
} |
} |
|
|
|
|
if (done && |
if (done && |
(aborting != ABORT_ERROR) && |
(aborting != ABORT_ERROR) && |
Line 988 JobFinish(job, status) |
|
Line 987 JobFinish(job, status) |
|
*/ |
*/ |
aborting = ABORT_ERROR; |
aborting = ABORT_ERROR; |
} |
} |
|
|
if ((aborting == ABORT_ERROR) && Job_Empty()) { |
if ((aborting == ABORT_ERROR) && Job_Empty()) { |
/* |
/* |
* If we are aborting and the job table is now empty, we finish. |
* If we are aborting and the job table is now empty, we finish. |
Line 1027 Job_Touch(gn, silent) |
|
Line 1026 Job_Touch(gn, silent) |
|
*/ |
*/ |
return; |
return; |
} |
} |
|
|
if (!silent) { |
if (!silent) { |
(void) fprintf(stdout, "touch %s\n", gn->name); |
(void) fprintf(stdout, "touch %s\n", gn->name); |
(void) fflush(stdout); |
(void) fflush(stdout); |
Line 1059 Job_Touch(gn, silent) |
|
Line 1058 Job_Touch(gn, silent) |
|
(void) lseek(streamID, 0L, L_SET); |
(void) lseek(streamID, 0L, L_SET); |
(void) write(streamID, &c, 1); |
(void) write(streamID, &c, 1); |
} |
} |
|
|
(void) close(streamID); |
(void) close(streamID); |
} else { |
} else { |
(void) fprintf(stdout, "*** couldn't touch %s: %s", |
(void) fprintf(stdout, "*** couldn't touch %s: %s", |
Line 1073 Job_Touch(gn, silent) |
|
Line 1072 Job_Touch(gn, silent) |
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Job_CheckCommands -- |
* Job_CheckCommands -- |
* Make sure the given node has all the commands it needs. |
* Make sure the given node has all the commands it needs. |
* |
* |
* Results: |
* Results: |
* TRUE if the commands list is/was ok. |
* TRUE if the commands list is/was ok. |
|
|
Job_CheckCommands(gn, abortProc) |
Job_CheckCommands(gn, abortProc) |
GNode *gn; /* The target whose commands need |
GNode *gn; /* The target whose commands need |
* verifying */ |
* verifying */ |
void (*abortProc) __P((char *, ...)); |
void (*abortProc) __P((char *, ...)); |
/* Function to abort with message */ |
/* Function to abort with message */ |
{ |
{ |
if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) && |
if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) && |
(gn->type & OP_LIB) == 0) { |
(gn->type & OP_LIB) == 0) { |
/* |
/* |
* No commands. Look for .DEFAULT rule from which we might infer |
* No commands. Look for .DEFAULT rule from which we might infer |
* commands |
* commands |
*/ |
*/ |
if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) { |
if ((DEFAULT != NILGNODE) && !Lst_IsEmpty(DEFAULT->commands)) { |
char *p1; |
char *p1; |
Line 1117 Job_CheckCommands(gn, abortProc) |
|
Line 1116 Job_CheckCommands(gn, abortProc) |
|
* rule to go on and the target doesn't already exist. There's |
* rule to go on and the target doesn't already exist. There's |
* nothing more we can do for this branch. If the -k flag wasn't |
* nothing more we can do for this branch. If the -k flag wasn't |
* given, we stop in our tracks, otherwise we just don't update |
* given, we stop in our tracks, otherwise we just don't update |
* this node's parents so they never get examined. |
* this node's parents so they never get examined. |
*/ |
*/ |
static const char msg[] = "make: don't know how to make"; |
static const char msg[] = "make: don't know how to make"; |
|
|
Line 1147 Job_CheckCommands(gn, abortProc) |
|
Line 1146 Job_CheckCommands(gn, abortProc) |
|
* |
* |
* Side Effects: |
* Side Effects: |
* JobDoOutput is called. |
* JobDoOutput is called. |
* |
* |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
/*ARGSUSED*/ |
/*ARGSUSED*/ |
static void |
static void |
JobLocalInput(stream, job) |
JobLocalInput(stream, job) |
int stream; /* Stream that's ready (ignored) */ |
int stream; /* Stream that's ready(ignored) */ |
Job *job; /* Job to which the stream belongs */ |
Job *job; /* Job to which the stream belongs */ |
{ |
{ |
JobDoOutput(job, FALSE); |
JobDoOutput(job, FALSE); |
Line 1181 JobExec(job, argv) |
|
Line 1180 JobExec(job, argv) |
|
char **argv; |
char **argv; |
{ |
{ |
int cpid; /* ID of new child */ |
int cpid; /* ID of new child */ |
|
|
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
int i; |
int i; |
|
|
(void) fprintf(stdout, "Running %s %sly\n", job->node->name, |
(void) fprintf(stdout, "Running %s %sly\n", job->node->name, |
job->flags&JOB_REMOTE?"remote":"local"); |
job->flags&JOB_REMOTE?"remote":"local"); |
(void) fprintf(stdout, "\tCommand: "); |
(void) fprintf(stdout, "\tCommand: "); |
Line 1194 JobExec(job, argv) |
|
Line 1193 JobExec(job, argv) |
|
(void) fprintf(stdout, "\n"); |
(void) fprintf(stdout, "\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
|
|
/* |
/* |
* Some jobs produce no output and it's disconcerting to have |
* 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 |
* banner with their name in it never appears). This is an attempt to |
* provide that feedback, even if nothing follows it. |
* provide that feedback, even if nothing follows it. |
*/ |
*/ |
Line 1206 JobExec(job, argv) |
|
Line 1205 JobExec(job, argv) |
|
MESSAGE(stdout, job->node); |
MESSAGE(stdout, job->node); |
lastNode = job->node; |
lastNode = job->node; |
} |
} |
|
|
#ifdef RMT_NO_EXEC |
#ifdef RMT_NO_EXEC |
if (job->flags & JOB_REMOTE) { |
if (job->flags & JOB_REMOTE) { |
goto jobExecFinish; |
goto jobExecFinish; |
Line 1219 JobExec(job, argv) |
|
Line 1218 JobExec(job, argv) |
|
|
|
/* |
/* |
* Must duplicate the input stream down to the child's input and |
* 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. |
* close-on-exec, we must clear that bit in the new input. |
*/ |
*/ |
if (dup2(FILENO(job->cmdFILE), 0) == -1) |
if (dup2(FILENO(job->cmdFILE), 0) == -1) |
Punt("Cannot dup2: %s", strerror(errno)); |
Punt("Cannot dup2: %s", strerror(errno)); |
(void) fcntl(0, F_SETFD, 0); |
(void) fcntl(0, F_SETFD, 0); |
(void) lseek(0, 0, L_SET); |
(void) lseek(0, 0, L_SET); |
|
|
if (usePipes) { |
if (usePipes) { |
/* |
/* |
* Set up the child's output to be routed through the pipe |
* Set up the child's output to be routed through the pipe |
Line 1245 JobExec(job, argv) |
|
Line 1244 JobExec(job, argv) |
|
} |
} |
/* |
/* |
* The output channels are marked close on exec. This bit was |
* 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 |
* it before routing the shell's error output to the same place as |
* its standard output. |
* its standard output. |
*/ |
*/ |
Line 1269 JobExec(job, argv) |
|
Line 1268 JobExec(job, argv) |
|
#ifdef REMOTE |
#ifdef REMOTE |
if (job->flags & JOB_REMOTE) { |
if (job->flags & JOB_REMOTE) { |
Rmt_Exec(shellPath, argv, FALSE); |
Rmt_Exec(shellPath, argv, FALSE); |
} else |
} else |
#endif /* REMOTE */ |
#endif /* REMOTE */ |
(void) execv(shellPath, argv); |
(void) execv(shellPath, argv); |
|
|
Line 1289 JobExec(job, argv) |
|
Line 1288 JobExec(job, argv) |
|
* stream to watch in the outputs mask |
* stream to watch in the outputs mask |
*/ |
*/ |
job->curPos = 0; |
job->curPos = 0; |
|
|
#ifdef RMT_WILL_WATCH |
#ifdef RMT_WILL_WATCH |
Rmt_Watch(job->inPipe, JobLocalInput, job); |
Rmt_Watch(job->inPipe, JobLocalInput, job); |
#else |
#else |
Line 1319 JobExec(job, argv) |
|
Line 1318 JobExec(job, argv) |
|
} |
} |
|
|
#ifdef RMT_NO_EXEC |
#ifdef RMT_NO_EXEC |
jobExecFinish: |
jobExecFinish: |
#endif |
#endif |
/* |
/* |
* Now the job is actually running, add it to the table. |
* Now the job is actually running, add it to the table. |
|
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* JobMakeArgv -- |
* JobMakeArgv -- |
* Create the argv needed to execute the shell for a given job. |
* Create the argv needed to execute the shell for a given job. |
* |
* |
* |
* |
* Results: |
* Results: |
* |
* |
Line 1350 JobMakeArgv(job, argv) |
|
Line 1349 JobMakeArgv(job, argv) |
|
{ |
{ |
int argc; |
int argc; |
static char args[10]; /* For merged arguments */ |
static char args[10]; /* For merged arguments */ |
|
|
argv[0] = shellName; |
argv[0] = shellName; |
argc = 1; |
argc = 1; |
|
|
Line 1389 JobMakeArgv(job, argv) |
|
Line 1388 JobMakeArgv(job, argv) |
|
/*- |
/*- |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* JobRestart -- |
* JobRestart -- |
* Restart a job that stopped for some reason. |
* Restart a job that stopped for some reason. |
* |
* |
* Results: |
* Results: |
* None. |
* None. |
Line 1406 JobRestart(job) |
|
Line 1405 JobRestart(job) |
|
#ifdef REMOTE |
#ifdef REMOTE |
int host; |
int host; |
#endif |
#endif |
|
|
if (job->flags & JOB_REMIGRATE) { |
if (job->flags & JOB_REMIGRATE) { |
if ( |
if ( |
#ifdef REMOTE |
#ifdef REMOTE |
Line 1480 JobRestart(job) |
|
Line 1479 JobRestart(job) |
|
job->rmtID = host; |
job->rmtID = host; |
} |
} |
#endif |
#endif |
|
|
(void)Lst_AtEnd(jobs, (ClientData)job); |
(void)Lst_AtEnd(jobs, (ClientData)job); |
nJobs += 1; |
nJobs += 1; |
if (nJobs == maxJobs) { |
if (nJobs == maxJobs) { |
Line 1497 JobRestart(job) |
|
Line 1496 JobRestart(job) |
|
* the 'exit' flag of the commandShell is used to cause it to exit |
* the 'exit' flag of the commandShell is used to cause it to exit |
* upon receiving an error. If the JOB_SILENT flag is clear, the |
* upon receiving an error. If the JOB_SILENT flag is clear, the |
* 'echo' flag of the commandShell is used to get it to start echoing |
* 'echo' flag of the commandShell is used to get it to start echoing |
* as soon as it starts processing commands. |
* as soon as it starts processing commands. |
*/ |
*/ |
char *argv[4]; |
char *argv[4]; |
|
|
JobMakeArgv(job, argv); |
JobMakeArgv(job, argv); |
|
|
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
Line 1509 JobRestart(job) |
|
Line 1508 JobRestart(job) |
|
} |
} |
#ifdef REMOTE |
#ifdef REMOTE |
if ((job->node->type&OP_NOEXPORT) || |
if ((job->node->type&OP_NOEXPORT) || |
(nLocal < maxLocal && runLocalFirst) |
(nLocal < maxLocal && runLocalFirst) |
# ifdef RMT_NO_EXEC |
# ifdef RMT_NO_EXEC |
|| !Rmt_Export(shellPath, argv, job) |
|| !Rmt_Export(shellPath, argv, job) |
# else |
# else |
Line 1581 JobRestart(job) |
|
Line 1580 JobRestart(job) |
|
/* |
/* |
* If the job is remote, it's ok to resume it as long as the |
* If the job is remote, it's ok to resume it as long as the |
* maximum concurrency won't be exceeded. If it's local and |
* 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 |
* job must be run locally and maxLocal is 0), it's also ok to |
* resume it. |
* resume it. |
*/ |
*/ |
Boolean error; |
Boolean error; |
extern int errno; |
extern int errno; |
int status; |
int status; |
|
|
#ifdef RMT_WANTS_SIGNALS |
#ifdef RMT_WANTS_SIGNALS |
if (job->flags & JOB_REMOTE) { |
if (job->flags & JOB_REMOTE) { |
error = !Rmt_Signal(job, SIGCONT); |
error = !Rmt_Signal(job, SIGCONT); |
Line 1604 JobRestart(job) |
|
Line 1603 JobRestart(job) |
|
job->flags |= JOB_CONTINUING; |
job->flags |= JOB_CONTINUING; |
W_SETTERMSIG(&status, SIGCONT); |
W_SETTERMSIG(&status, SIGCONT); |
JobFinish(job, &status); |
JobFinish(job, &status); |
|
|
job->flags &= ~(JOB_RESUME|JOB_CONTINUING); |
job->flags &= ~(JOB_RESUME|JOB_CONTINUING); |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "done\n"); |
(void) fprintf(stdout, "done\n"); |
Line 1640 JobRestart(job) |
|
Line 1639 JobRestart(job) |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* JobStart -- |
* JobStart -- |
* Start a target-creation process going for the target described |
* Start a target-creation process going for the target described |
* by the graph node gn. |
* by the graph node gn. |
* |
* |
* Results: |
* Results: |
* JOB_ERROR if there was an error in the commands, JOB_FINISHED |
* JOB_ERROR if there was an error in the commands, JOB_FINISHED |
Line 1704 JobStart(gn, flags, previous) |
|
Line 1703 JobStart(gn, flags, previous) |
|
} else { |
} else { |
cmdsOK = TRUE; |
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 |
* 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, |
* 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? |
* we just set the file to be stdout. Cute, huh? |
Line 1719 JobStart(gn, flags, previous) |
|
Line 1718 JobStart(gn, flags, previous) |
|
if (!cmdsOK) { |
if (!cmdsOK) { |
DieHorribly(); |
DieHorribly(); |
} |
} |
|
|
job->cmdFILE = fopen(tfile, "w+"); |
job->cmdFILE = fopen(tfile, "w+"); |
if (job->cmdFILE == NULL) { |
if (job->cmdFILE == NULL) { |
Punt("Could not open %s", tfile); |
Punt("Could not open %s", tfile); |
Line 1748 JobStart(gn, flags, previous) |
|
Line 1747 JobStart(gn, flags, previous) |
|
cmdsOK = FALSE; |
cmdsOK = FALSE; |
} else { |
} else { |
LstNode ln = Lst_Next(gn->commands); |
LstNode ln = Lst_Next(gn->commands); |
|
|
if ((ln == NILLNODE) || |
if ((ln == NILLNODE) || |
JobPrintCommand((ClientData) Lst_Datum(ln), |
JobPrintCommand((ClientData) Lst_Datum(ln), |
(ClientData) job)) |
(ClientData) job)) |
Line 1777 JobStart(gn, flags, previous) |
|
Line 1776 JobStart(gn, flags, previous) |
|
*/ |
*/ |
numCommands = 0; |
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, |
* If we didn't print out any commands to the shell script, |
* there's not much point in executing the shell, is there? |
* there's not much point in executing the shell, is there? |
Line 1821 JobStart(gn, flags, previous) |
|
Line 1820 JobStart(gn, flags, previous) |
|
} |
} |
|
|
/* |
/* |
* If we're not supposed to execute a shell, don't. |
* If we're not supposed to execute a shell, don't. |
*/ |
*/ |
if (noExec) { |
if (noExec) { |
/* |
/* |
Line 1916 JobStart(gn, flags, previous) |
|
Line 1915 JobStart(gn, flags, previous) |
|
/* |
/* |
* The job can only be run locally, but we've hit the limit of |
* The job can only be run locally, but we've hit the limit of |
* local concurrency, so put the job on hold until some other job |
* 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 |
* may be run locally even when the local limit has been reached |
* (e.g. when maxLocal == 0), though they will be exported if at |
*(e.g. when maxLocal == 0), though they will be exported if at |
* all possible. In addition, any target marked with .NOEXPORT will |
* all possible. In addition, any target marked with .NOEXPORT will |
* be run locally if maxLocal is 0. |
* be run locally if maxLocal is 0. |
*/ |
*/ |
jobFull = TRUE; |
jobFull = TRUE; |
|
|
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, "Can only run job locally.\n"); |
(void) fprintf(stdout, "Can only run job locally.\n"); |
(void) fflush(stdout); |
(void) fflush(stdout); |
Line 1933 JobStart(gn, flags, previous) |
|
Line 1932 JobStart(gn, flags, previous) |
|
} else { |
} else { |
if ((nLocal >= maxLocal) && local) { |
if ((nLocal >= maxLocal) && local) { |
/* |
/* |
* If we're running this job locally as a special case (see above), |
* If we're running this job locally as a special case(see above), |
* at least say the table is full. |
* at least say the table is full. |
*/ |
*/ |
jobFull = TRUE; |
jobFull = TRUE; |
Line 1947 JobStart(gn, flags, previous) |
|
Line 1946 JobStart(gn, flags, previous) |
|
return(JOB_RUNNING); |
return(JOB_RUNNING); |
} |
} |
|
|
static char * |
static char * |
JobOutput(job, cp, endp, msg) |
JobOutput(job, cp, endp, msg) |
register Job *job; |
register Job *job; |
register char *cp, *endp; |
register char *cp, *endp; |
Line 2010 JobOutput(job, cp, endp, msg) |
|
Line 2009 JobOutput(job, cp, endp, msg) |
|
* In both cases, however, we keep our figurative eye out for the |
* In both cases, however, we keep our figurative eye out for the |
* 'noPrint' line for the shell from which the output came. If |
* '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 |
* 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. |
* do print whatever follows it. |
* |
* |
* Results: |
* Results: |
Line 2030 JobDoOutput(job, finish) |
|
Line 2029 JobDoOutput(job, finish) |
|
Boolean fbuf; /* true if our buffer filled up */ |
Boolean fbuf; /* true if our buffer filled up */ |
register int nr; /* number of bytes read */ |
register int nr; /* number of bytes read */ |
register int i; /* auxiliary index into outBuf */ |
register int i; /* auxiliary index into outBuf */ |
register int max; /* limit for i (end of current data) */ |
register int max; /* limit for i(end of current data) */ |
int nRead; /* (Temporary) number of bytes read */ |
int nRead; /*(Temporary) number of bytes read */ |
|
|
FILE *oFILE; /* Stream pointer to shell's output file */ |
FILE *oFILE; /* Stream pointer to shell's output file */ |
char inLine[132]; |
char inLine[132]; |
|
|
|
|
if (usePipes) { |
if (usePipes) { |
/* |
/* |
* Read as many bytes as will fit in the buffer. |
* Read as many bytes as will fit in the buffer. |
Line 2044 JobDoOutput(job, finish) |
|
Line 2043 JobDoOutput(job, finish) |
|
end_loop: |
end_loop: |
gotNL = FALSE; |
gotNL = FALSE; |
fbuf = FALSE; |
fbuf = FALSE; |
|
|
nRead = read(job->inPipe, &job->outBuf[job->curPos], |
nRead = read(job->inPipe, &job->outBuf[job->curPos], |
JOB_BUFSIZE - job->curPos); |
JOB_BUFSIZE - job->curPos); |
if (nRead < 0) { |
if (nRead < 0) { |
|
|
} |
} |
|
|
/* |
/* |
* 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 |
* remaining output, so pretend we read a newline if there's any |
* output remaining in the buffer. |
* output remaining in the buffer. |
* Also clear the 'finish' flag so we stop looping. |
* Also clear the 'finish' flag so we stop looping. |
|
|
} else if (nr == 0) { |
} else if (nr == 0) { |
finish = FALSE; |
finish = FALSE; |
} |
} |
|
|
/* |
/* |
* Look for the last newline in the bytes we just got. If there is |
* Look for the last newline in the bytes we just got. If there is |
* one, break out of the loop with 'i' as its index and gotNL set |
* one, break out of the loop with 'i' as its index and gotNL set |
* TRUE. |
* TRUE. |
*/ |
*/ |
max = job->curPos + nr; |
max = job->curPos + nr; |
for (i = job->curPos + nr - 1; i >= job->curPos; i--) { |
for (i = job->curPos + nr - 1; i >= job->curPos; i--) { |
|
|
job->outBuf[i] = ' '; |
job->outBuf[i] = ' '; |
} |
} |
} |
} |
|
|
if (!gotNL) { |
if (!gotNL) { |
job->curPos += nr; |
job->curPos += nr; |
if (job->curPos == JOB_BUFSIZE) { |
if (job->curPos == JOB_BUFSIZE) { |
/* |
/* |
* If we've run out of buffer space, we have no choice |
* If we've run out of buffer space, we have no choice |
* but to print the stuff. sigh. |
* but to print the stuff. sigh. |
*/ |
*/ |
fbuf = TRUE; |
fbuf = TRUE; |
i = job->curPos; |
i = job->curPos; |
|
|
/* |
/* |
* Need to send the output to the screen. Null terminate it |
* Need to send the output to the screen. Null terminate it |
* first, overwriting the newline character if there was one. |
* 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 |
* to the shell description), we print the line, preceeded |
* by a target banner if this target isn't the same as the |
* by a target banner if this target isn't the same as the |
* one for which we last printed something. |
* one for which we last printed something. |
* The rest of the data in the buffer are then shifted down |
* The rest of the data in the buffer are then shifted down |
* to the start of the buffer and curPos is set accordingly. |
* to the start of the buffer and curPos is set accordingly. |
*/ |
*/ |
job->outBuf[i] = '\0'; |
job->outBuf[i] = '\0'; |
if (i >= job->curPos) { |
if (i >= job->curPos) { |
char *cp; |
char *cp; |
|
|
cp = JobOutput(job, job->outBuf, &job->outBuf[i], FALSE); |
cp = JobOutput(job, job->outBuf, &job->outBuf[i]); |
|
|
/* |
/* |
* There's still more in that thar buffer. This time, though, |
* There's still more in that thar buffer. This time, though, |
|
|
} |
} |
if (i < max - 1) { |
if (i < max - 1) { |
/* shift the remaining characters down */ |
/* shift the remaining characters down */ |
(void) memcpy(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); |
(void) memcpy(job->outBuf, &job->outBuf[i + 1], max -(i + 1)); |
job->curPos = max - (i + 1); |
job->curPos = max -(i + 1); |
|
|
} else { |
} else { |
/* |
/* |
* We have written everything out, so we just start over |
* We have written everything out, so we just start over |
|
|
if (finish) { |
if (finish) { |
/* |
/* |
* If the finish flag is true, we must loop until we hit |
* If the finish flag is true, we must loop until we hit |
* end-of-file on the pipe. This is guaranteed to happen |
* end-of-file on the pipe. This is guaranteed to happen eventually |
* eventually since the other end of the pipe is now closed |
* since the other end of the pipe is now closed(we closed it |
* (we closed it explicitly and the child has exited). When |
* explicitly and the child has exited). When we do get an EOF, |
* we do get an EOF, finish will be set FALSE and we'll fall |
* finish will be set FALSE and we'll fall through and out. |
* through and out. |
|
*/ |
*/ |
goto end_loop; |
goto end_loop; |
} |
} |
Line 2231 Job_CatchChildren(block) |
|
Line 2229 Job_CatchChildren(block) |
|
if (nLocal == 0) { |
if (nLocal == 0) { |
return; |
return; |
} |
} |
|
|
while ((pid = waitpid((pid_t) -1, &status, |
while ((pid = waitpid((pid_t) -1, &status, |
(block?0:WNOHANG)|WUNTRACED)) > 0) |
(block?0:WNOHANG)|WUNTRACED)) > 0) |
{ |
{ |
Line 2239 Job_CatchChildren(block) |
|
Line 2237 Job_CatchChildren(block) |
|
(void) fprintf(stdout, "Process %d exited or stopped.\n", pid); |
(void) fprintf(stdout, "Process %d exited or stopped.\n", pid); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
|
|
|
|
jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid); |
jnode = Lst_Find(jobs, (ClientData)&pid, JobCmpPid); |
|
|
Line 2247 Job_CatchChildren(block) |
|
Line 2245 Job_CatchChildren(block) |
|
if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { |
if (WIFSIGNALED(status) && (WTERMSIG(status) == SIGCONT)) { |
jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid); |
jnode = Lst_Find(stoppedJobs, (ClientData) &pid, JobCmpPid); |
if (jnode == NILLNODE) { |
if (jnode == NILLNODE) { |
Error("Resumed child (%d) not in table", pid); |
Error("Resumed child(%d) not in table", pid); |
continue; |
continue; |
} |
} |
job = (Job *)Lst_Datum(jnode); |
job = (Job *)Lst_Datum(jnode); |
(void) Lst_Remove(stoppedJobs, jnode); |
(void) Lst_Remove(stoppedJobs, jnode); |
} else { |
} else { |
Error("Child (%d) not in table?", pid); |
Error("Child(%d) not in table?", pid); |
continue; |
continue; |
} |
} |
} else { |
} else { |
Line 2288 Job_CatchChildren(block) |
|
Line 2286 Job_CatchChildren(block) |
|
* Job_CatchOutput -- |
* Job_CatchOutput -- |
* Catch the output from our children, if we're using |
* Catch the output from our children, if we're using |
* pipes do so. Otherwise just block time until we get a |
* 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 |
* just spinning when there's nothing to do and the reaping |
* of a child can wait for a while. |
* of a child can wait for a while. |
* |
* |
* Results: |
* Results: |
* None |
* None |
* |
* |
* Side Effects: |
* Side Effects: |
* Output is read from pipes if we're piping. |
* Output is read from pipes if we're piping. |
Line 2328 Job_CatchOutput() |
|
Line 2326 Job_CatchOutput() |
|
* NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren |
* NOTE: IT IS THE RESPONSIBILITY OF Rmt_Wait TO CALL Job_CatchChildren |
* IN A TIMELY FASHION TO CATCH ANY LOCALLY RUNNING JOBS THAT EXIT. |
* 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 |
* 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...) |
* wait...) |
*/ |
*/ |
while (nJobs != 0 && pnJobs == nJobs) { |
while (nJobs != 0 && pnJobs == nJobs) { |
Line 2430 Job_Init(maxproc, maxlocal) |
|
Line 2428 Job_Init(maxproc, maxlocal) |
|
} else { |
} else { |
targFmt = TARG_FMT; |
targFmt = TARG_FMT; |
} |
} |
|
|
if (shellPath == NULL) { |
if (shellPath == NULL) { |
/* |
/* |
* The user didn't specify a shell to use, so we are using the |
* The user didn't specify a shell to use, so we are using the |
Line 2469 Job_Init(maxproc, maxlocal) |
|
Line 2467 Job_Init(maxproc, maxlocal) |
|
/* |
/* |
* There are additional signals that need to be caught and passed if |
* 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 |
* 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) |
* signals from the terminal driver as we own the terminal) |
*/ |
*/ |
#if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP) |
#if defined(RMT_WANTS_SIGNALS) || defined(USE_PGRP) |
Line 2486 Job_Init(maxproc, maxlocal) |
|
Line 2484 Job_Init(maxproc, maxlocal) |
|
(void) signal(SIGWINCH, JobPassSig); |
(void) signal(SIGWINCH, JobPassSig); |
} |
} |
#endif |
#endif |
|
|
begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); |
begin = Targ_FindNode(".BEGIN", TARG_NOCREATE); |
|
|
if (begin != NILGNODE) { |
if (begin != NILGNODE) { |
Line 2660 Job_ParseShell(line) |
|
Line 2658 Job_ParseShell(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 |
* Parse the specification by keyword |
*/ |
*/ |
Line 2716 Job_ParseShell(line) |
|
Line 2714 Job_ParseShell(line) |
|
} |
} |
} else { |
} 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. |
* 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 |
* Else we just take the specification at its word and copy it |
* to a new location. In either case, we need to record the |
* to a new location. In either case, we need to record the |
Line 2745 Job_ParseShell(line) |
|
Line 2743 Job_ParseShell(line) |
|
if (commandShell->echoOn && commandShell->echoOff) { |
if (commandShell->echoOn && commandShell->echoOff) { |
commandShell->hasEchoCtl = TRUE; |
commandShell->hasEchoCtl = TRUE; |
} |
} |
|
|
if (!commandShell->hasErrCtl) { |
if (!commandShell->hasErrCtl) { |
if (commandShell->errCheck == NULL) { |
if (commandShell->errCheck == NULL) { |
commandShell->errCheck = ""; |
commandShell->errCheck = ""; |
Line 2754 Job_ParseShell(line) |
|
Line 2752 Job_ParseShell(line) |
|
commandShell->ignErr = "%s\n"; |
commandShell->ignErr = "%s\n"; |
} |
} |
} |
} |
|
|
/* |
/* |
* Do not free up the words themselves, since they might be in use by the |
* Do not free up the words themselves, since they might be in use by the |
* shell specification... |
* shell specification... |
Line 2785 JobInterrupt(runINTERRUPT, signo) |
|
Line 2783 JobInterrupt(runINTERRUPT, signo) |
|
LstNode ln; /* element in job table */ |
LstNode ln; /* element in job table */ |
Job *job; /* job descriptor in that element */ |
Job *job; /* job descriptor in that element */ |
GNode *interrupt; /* the node describing the .INTERRUPT target */ |
GNode *interrupt; /* the node describing the .INTERRUPT target */ |
|
|
aborting = ABORT_INTERRUPT; |
aborting = ABORT_INTERRUPT; |
|
|
(void) Lst_Open(jobs); |
(void) Lst_Open(jobs); |
Line 2823 JobInterrupt(runINTERRUPT, signo) |
|
Line 2821 JobInterrupt(runINTERRUPT, signo) |
|
if (job->pid) { |
if (job->pid) { |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, |
(void) fprintf(stdout, |
"JobInterrupt passing signal to child %d.\n", |
"JobInterrupt passing signal to child %d.\n", |
job->pid); |
job->pid); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Line 2859 JobInterrupt(runINTERRUPT, signo) |
|
Line 2857 JobInterrupt(runINTERRUPT, signo) |
|
*/ |
*/ |
if (DEBUG(JOB)) { |
if (DEBUG(JOB)) { |
(void) fprintf(stdout, |
(void) fprintf(stdout, |
"JobInterrupt passing CONT to stopped child %d.\n", |
"JobInterrupt passing CONT to stopped child %d.\n", |
job->pid); |
job->pid); |
(void) fflush(stdout); |
(void) fflush(stdout); |
} |
} |
Line 2915 JobInterrupt(runINTERRUPT, signo) |
|
Line 2913 JobInterrupt(runINTERRUPT, signo) |
|
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
* Job_End -- |
* Job_End -- |
* Do final processing such as the running of the commands |
* Do final processing such as the running of the commands |
* attached to the .END target. |
* attached to the .END target. |
* |
* |
* Results: |
* Results: |
* Number of errors reported. |
* Number of errors reported. |
* |
* |
* Side Effects: |
* Side Effects: |
* The process' temporary file (tfile) is removed if it still |
* The process' temporary file(tfile) is removed if it still |
* existed. |
* existed. |
*----------------------------------------------------------------------- |
*----------------------------------------------------------------------- |
*/ |
*/ |
|
|
LstNode ln; /* element in job table */ |
LstNode ln; /* element in job table */ |
Job *job; /* the job descriptor in that element */ |
Job *job; /* the job descriptor in that element */ |
int foo; |
int foo; |
|
|
aborting = ABORT_ERROR; |
aborting = ABORT_ERROR; |
|
|
if (nJobs) { |
if (nJobs) { |
|
|
(void) Lst_Open(jobs); |
(void) Lst_Open(jobs); |
|
|
|
|
/* |
/* |
* kill the child process with increasingly drastic signals to make |
* kill the child process with increasingly drastic signals to make |
* darn sure it's dead. |
* darn sure it's dead. |
*/ |
*/ |
#ifdef RMT_WANTS_SIGNALS |
#ifdef RMT_WANTS_SIGNALS |
if (job->flags & JOB_REMOTE) { |
if (job->flags & JOB_REMOTE) { |
|
|
#endif /* RMT_WANTS_SIGNALS */ |
#endif /* RMT_WANTS_SIGNALS */ |
} |
} |
} |
} |
|
|
/* |
/* |
* Catch as many children as want to report in at first, then give up |
* Catch as many children as want to report in at first, then give up |
*/ |
*/ |