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