VirtualBox

source: kBuild/trunk/src/kmk/job.c@ 46

Last change on this file since 46 was 46, checked in by bird, 22 years ago

kMk changes. Made extensions configurable from config.h. fixed parents.

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette