job.c revision 1.517 1 /* $NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $ */
2
3 /*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
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. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 */
34
35 /*
36 * Copyright (c) 1988, 1989 by Adam de Boor
37 * Copyright (c) 1989 by Berkeley Softworks
38 * All rights reserved.
39 *
40 * This code is derived from software contributed to Berkeley by
41 * Adam de Boor.
42 *
43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions
45 * are met:
46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement:
53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission.
58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE.
70 */
71
72 /*
73 * Create child processes and collect their output.
74 *
75 * Interface:
76 * Job_Init Initialize this module and make the .BEGIN target.
77 *
78 * Job_End Clean up any memory used.
79 *
80 * Job_Make Start making the given target.
81 *
82 * Job_CatchChildren
83 * Handle the termination of any children.
84 *
85 * Job_CatchOutput
86 * Print any output the child processes have produced.
87 *
88 * Job_ParseShell Given a special dependency line with target '.SHELL',
89 * define the shell that is used for the creation
90 * commands in jobs mode.
91 *
92 * Job_MakeDotEnd Make the .END target. Must only be called when the
93 * job table is empty.
94 *
95 * Job_AbortAll Kill all currently running jobs, in an emergency.
96 *
97 * Job_CheckCommands
98 * Add fallback commands to a target, if necessary.
99 *
100 * Job_Touch Update a target without really updating it.
101 *
102 * Job_Wait Wait for all currently-running jobs to finish.
103 */
104
105 #include <sys/types.h>
106 #include <sys/stat.h>
107 #include <sys/time.h>
108 #include <sys/wait.h>
109
110 #include <errno.h>
111 #ifndef USE_SELECT
112 #include <poll.h>
113 #endif
114 #include <signal.h>
115 #include <utime.h>
116
117 #include "make.h"
118 #include "dir.h"
119 #include "job.h"
120 #ifdef USE_META
121 # include "meta.h"
122 #endif
123 #include "pathnames.h"
124 #include "trace.h"
125
126 /* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
127 MAKE_RCSID("$NetBSD: job.c,v 1.517 2025/07/06 07:11:31 rillig Exp $");
128
129
130 #ifdef USE_SELECT
131 /*
132 * Emulate poll() in terms of select(). This is not a complete
133 * emulation but it is sufficient for make's purposes.
134 */
135
136 #define poll emul_poll
137 #define pollfd emul_pollfd
138
139 struct emul_pollfd {
140 int fd;
141 short events;
142 short revents;
143 };
144
145 #define POLLIN 0x0001
146 #define POLLOUT 0x0004
147
148 int emul_poll(struct pollfd *, int, int);
149 #endif
150
151 struct pollfd;
152
153
154 enum JobStatus {
155 JOB_ST_FREE, /* Job is available */
156 JOB_ST_SET_UP, /* Job is allocated but otherwise invalid */
157 JOB_ST_RUNNING, /* Job is running, pid valid */
158 JOB_ST_FINISHED /* Job is done (i.e. after SIGCHLD) */
159 };
160
161 static const char JobStatus_Name[][9] = {
162 "free",
163 "set-up",
164 "running",
165 "finished",
166 };
167
168 /*
169 * A Job manages the shell commands that are run to create a single target.
170 * Each job is run in a separate subprocess by a shell. Several jobs can run
171 * in parallel.
172 *
173 * The shell commands for the target are written to a temporary file,
174 * then the shell is run with the temporary file as stdin, and the output
175 * of that shell is captured via a pipe.
176 *
177 * When a job is finished, Make_Update updates all parents of the node
178 * that was just remade, marking them as ready to be made next if all
179 * other dependencies are finished as well.
180 */
181 struct Job {
182 /* The process ID of the shell running the commands */
183 int pid;
184
185 /* The target the child is making */
186 GNode *node;
187
188 /*
189 * If one of the shell commands is "...", all following commands are
190 * delayed until the .END node is made. This list node points to the
191 * first of these commands, if any.
192 */
193 StringListNode *tailCmds;
194
195 /* This is where the shell commands go. */
196 FILE *cmdFILE;
197
198 int exit_status; /* from wait4() in signal handler */
199
200 enum JobStatus status;
201
202 bool suspended;
203
204 /* Ignore non-zero exits */
205 bool ignerr;
206 /* Output the command before or instead of running it. */
207 bool echo;
208 /* Target is a special one. */
209 bool special;
210
211 int inPipe; /* Pipe for reading output from job */
212 int outPipe; /* Pipe for writing control commands */
213 struct pollfd *inPollfd; /* pollfd associated with inPipe */
214
215 #define JOB_BUFSIZE 1024
216 /* Buffer for storing the output of the job, line by line. */
217 char outBuf[JOB_BUFSIZE + 1];
218 size_t outBufLen;
219
220 #ifdef USE_META
221 struct BuildMon bm;
222 #endif
223 };
224
225
226 /*
227 * A shell defines how the commands are run. All commands for a target are
228 * written into a single file, which is then given to the shell to execute
229 * the commands from it. The commands are written to the file using a few
230 * templates for echo control and error control.
231 *
232 * The name of the shell is the basename for the predefined shells, such as
233 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its
234 * basename is used to select the type of shell; the longest match wins.
235 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh.
236 *
237 * The echoing of command lines is controlled using hasEchoCtl, echoOff,
238 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it
239 * still outputs something, but this something is not interesting, therefore
240 * it is filtered out using noPrint and noPrintLen.
241 *
242 * The error checking for individual commands is controlled using hasErrCtl,
243 * errOn, errOff and runChkTmpl.
244 *
245 * In case a shell doesn't have error control, echoTmpl is a printf template
246 * for echoing the command, should echoing be on; runIgnTmpl is another
247 * printf template for executing the command while ignoring the return
248 * status. Finally runChkTmpl is a printf template for running the command and
249 * causing the shell to exit on error. If any of these strings are empty when
250 * hasErrCtl is false, the command will be executed anyway as is, and if it
251 * causes an error, so be it. Any templates set up to echo the command will
252 * escape any '$ ` \ "' characters in the command string to avoid unwanted
253 * shell code injection, the escaped command is safe to use in double quotes.
254 *
255 * The command-line flags "echo" and "exit" also control the behavior. The
256 * "echo" flag causes the shell to start echoing commands right away. The
257 * "exit" flag causes the shell to exit when an error is detected in one of
258 * the commands.
259 */
260 typedef struct Shell {
261
262 /*
263 * The name of the shell. For Bourne and C shells, this is used only
264 * to find the shell description when used as the single source of a
265 * .SHELL target. For user-defined shells, this is the full path of
266 * the shell.
267 */
268 const char *name;
269
270 bool hasEchoCtl; /* whether both echoOff and echoOn are there */
271 const char *echoOff; /* command to turn echoing off */
272 const char *echoOn; /* command to turn echoing back on */
273 const char *noPrint; /* text to skip when printing output from the
274 * shell. This is usually the same as echoOff */
275 size_t noPrintLen; /* length of noPrint command */
276
277 bool hasErrCtl; /* whether error checking can be controlled
278 * for individual commands */
279 const char *errOn; /* command to turn on error checking */
280 const char *errOff; /* command to turn off error checking */
281
282 const char *echoTmpl; /* template to echo a command */
283 const char *runIgnTmpl; /* template to run a command without error
284 * checking */
285 const char *runChkTmpl; /* template to run a command with error
286 * checking */
287
288 /*
289 * A string literal that results in a newline character when it
290 * occurs outside of any 'quote' or "quote" characters.
291 */
292 const char *newline;
293 char commentChar; /* character used by shell for comment lines */
294
295 const char *echoFlag; /* shell flag to echo commands */
296 const char *errFlag; /* shell flag to exit on error */
297 } Shell;
298
299 typedef struct CommandFlags {
300 /* Whether to echo the command before or instead of running it. */
301 bool echo;
302
303 /* Run the command even in -n or -N mode. */
304 bool always;
305
306 /*
307 * true if we turned error checking off before writing the command to
308 * the commands file and need to turn it back on
309 */
310 bool ignerr;
311 } CommandFlags;
312
313 /*
314 * Write shell commands to a file.
315 *
316 * TODO: keep track of whether commands are echoed.
317 * TODO: keep track of whether error checking is active.
318 */
319 typedef struct ShellWriter {
320 FILE *f;
321
322 /* we've sent 'set -x' */
323 bool xtraced;
324
325 } ShellWriter;
326
327 /* error handling variables */
328 static int job_errors = 0; /* number of errors reported */
329 static enum { /* Why is the make aborting? */
330 ABORT_NONE,
331 ABORT_ERROR, /* Aborted because of an error */
332 ABORT_INTERRUPT, /* Aborted because it was interrupted */
333 ABORT_WAIT /* Waiting for jobs to finish */
334 } aborting = ABORT_NONE;
335 #define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
336
337 static const char aborting_name[][6] = { "NONE", "ERROR", "INTR", "WAIT" };
338
339 /* Tracks the number of tokens currently "out" to build jobs. */
340 int jobTokensRunning = 0;
341
342 /*
343 * Descriptions for various shells.
344 *
345 * The build environment may set DEFSHELL_INDEX to one of
346 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
347 * select one of the predefined shells as the default shell.
348 *
349 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
350 * name or the full path of a sh-compatible shell, which will be used as
351 * the default shell.
352 *
353 * ".SHELL" lines in Makefiles can choose the default shell from the
354 * set defined here, or add additional shells.
355 */
356
357 #ifdef DEFSHELL_CUSTOM
358 #define DEFSHELL_INDEX_CUSTOM 0
359 #define DEFSHELL_INDEX_SH 1
360 #define DEFSHELL_INDEX_KSH 2
361 #define DEFSHELL_INDEX_CSH 3
362 #else
363 #define DEFSHELL_INDEX_SH 0
364 #define DEFSHELL_INDEX_KSH 1
365 #define DEFSHELL_INDEX_CSH 2
366 #endif
367
368 #ifndef DEFSHELL_INDEX
369 #define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
370 #endif
371
372 static Shell shells[] = {
373 #ifdef DEFSHELL_CUSTOM
374 /*
375 * An sh-compatible shell with a non-standard name.
376 *
377 * Keep this in sync with the "sh" description below, but avoid
378 * non-portable features that might not be supplied by all
379 * sh-compatible shells.
380 */
381 {
382 DEFSHELL_CUSTOM, /* .name */
383 false, /* .hasEchoCtl */
384 "", /* .echoOff */
385 "", /* .echoOn */
386 "", /* .noPrint */
387 0, /* .noPrintLen */
388 false, /* .hasErrCtl */
389 "", /* .errOn */
390 "", /* .errOff */
391 "echo \"%s\"\n", /* .echoTmpl */
392 "%s\n", /* .runIgnTmpl */
393 "{ %s \n} || exit $?\n", /* .runChkTmpl */
394 "'\n'", /* .newline */
395 '#', /* .commentChar */
396 "", /* .echoFlag */
397 "", /* .errFlag */
398 },
399 #endif /* DEFSHELL_CUSTOM */
400 /*
401 * SH description. Echo control is also possible and, under
402 * sun UNIX anyway, one can even control error checking.
403 */
404 {
405 "sh", /* .name */
406 false, /* .hasEchoCtl */
407 "", /* .echoOff */
408 "", /* .echoOn */
409 "", /* .noPrint */
410 0, /* .noPrintLen */
411 false, /* .hasErrCtl */
412 "", /* .errOn */
413 "", /* .errOff */
414 "echo \"%s\"\n", /* .echoTmpl */
415 "%s\n", /* .runIgnTmpl */
416 "{ %s \n} || exit $?\n", /* .runChkTmpl */
417 "'\n'", /* .newline */
418 '#', /* .commentChar*/
419 #if defined(MAKE_NATIVE) && defined(__NetBSD__)
420 /* XXX: -q is not really echoFlag, it's more like noEchoInSysFlag. */
421 "q", /* .echoFlag */
422 #else
423 "", /* .echoFlag */
424 #endif
425 "", /* .errFlag */
426 },
427 /*
428 * KSH description.
429 */
430 {
431 "ksh", /* .name */
432 true, /* .hasEchoCtl */
433 "set +v", /* .echoOff */
434 "set -v", /* .echoOn */
435 "set +v", /* .noPrint */
436 6, /* .noPrintLen */
437 false, /* .hasErrCtl */
438 "", /* .errOn */
439 "", /* .errOff */
440 "echo \"%s\"\n", /* .echoTmpl */
441 "%s\n", /* .runIgnTmpl */
442 "{ %s \n} || exit $?\n", /* .runChkTmpl */
443 "'\n'", /* .newline */
444 '#', /* .commentChar */
445 "v", /* .echoFlag */
446 "", /* .errFlag */
447 },
448 /*
449 * CSH description. The csh can do echo control by playing
450 * with the setting of the 'echo' shell variable. Sadly,
451 * however, it is unable to do error control nicely.
452 */
453 {
454 "csh", /* .name */
455 true, /* .hasEchoCtl */
456 "unset verbose", /* .echoOff */
457 "set verbose", /* .echoOn */
458 "unset verbose", /* .noPrint */
459 13, /* .noPrintLen */
460 false, /* .hasErrCtl */
461 "", /* .errOn */
462 "", /* .errOff */
463 "echo \"%s\"\n", /* .echoTmpl */
464 "csh -c \"%s || exit 0\"\n", /* .runIgnTmpl */
465 "", /* .runChkTmpl */
466 "'\\\n'", /* .newline */
467 '#', /* .commentChar */
468 "v", /* .echoFlag */
469 "e", /* .errFlag */
470 }
471 };
472
473 /*
474 * This is the shell to which we pass all commands in the Makefile.
475 * It is set by the Job_ParseShell function.
476 */
477 static Shell *shell = &shells[DEFSHELL_INDEX];
478 char *shellPath; /* full pathname of executable image */
479 const char *shellName = NULL; /* last component of shellPath */
480 char *shellErrFlag = NULL;
481 static char *shell_freeIt = NULL; /* Allocated memory for custom .SHELL */
482
483
484 static Job *job_table; /* The structures that describe them */
485 static Job *job_table_end; /* job_table + maxJobs */
486 static bool wantToken;
487 static bool lurking_children = false;
488 static bool make_suspended = false; /* Whether we've seen a SIGTSTP (etc) */
489
490 /*
491 * Set of descriptors of pipes connected to
492 * the output channels of children
493 */
494 static struct pollfd *fds = NULL;
495 static Job **jobByFdIndex = NULL;
496 static nfds_t fdsLen = 0;
497 static void watchfd(Job *);
498 static void clearfd(Job *);
499
500 static char *targPrefix = NULL; /* To identify a job change in the output. */
501
502 static Job tokenPoolJob; /* token wait pseudo-job */
503
504 static Job childExitJob; /* child exit pseudo-job */
505 #define CEJ_CHILD_EXITED '.'
506 #define CEJ_RESUME_JOBS 'R'
507
508 enum {
509 npseudojobs = 2 /* number of pseudo-jobs */
510 };
511
512 static sigset_t caught_signals; /* Set of signals we handle */
513 static volatile sig_atomic_t caught_sigchld;
514
515 static void CollectOutput(Job *, bool);
516 static void JobInterrupt(bool, int) MAKE_ATTR_DEAD;
517 static void JobSigReset(void);
518
519 static void
520 SwitchOutputTo(GNode *gn)
521 {
522 /* The node for which output was most recently produced. */
523 static GNode *lastNode = NULL;
524
525 if (gn == lastNode)
526 return;
527 lastNode = gn;
528
529 if (opts.maxJobs != 1 && targPrefix != NULL && targPrefix[0] != '\0')
530 (void)fprintf(stdout, "%s %s ---\n", targPrefix, gn->name);
531 }
532
533 static unsigned
534 nfds_per_job(void)
535 {
536 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
537 if (useMeta)
538 return 2;
539 #endif
540 return 1;
541 }
542
543 void
544 Job_FlagsToString(const Job *job, char *buf, size_t bufsize)
545 {
546 snprintf(buf, bufsize, "%c%c%c",
547 job->ignerr ? 'i' : '-',
548 !job->echo ? 's' : '-',
549 job->special ? 'S' : '-');
550 }
551
552 #ifdef USE_META
553 struct BuildMon *
554 Job_BuildMon(Job *job)
555 {
556 return &job->bm;
557 }
558 #endif
559
560 GNode *
561 Job_Node(Job *job)
562 {
563 return job->node;
564 }
565
566 int
567 Job_Pid(Job *job)
568 {
569 return job->pid;
570 }
571
572 static void
573 JobTable_Dump(const char *where)
574 {
575 const Job *job;
576 char flags[4];
577
578 debug_printf("%s, job table:\n", where);
579 for (job = job_table; job < job_table_end; job++) {
580 Job_FlagsToString(job, flags, sizeof flags);
581 debug_printf("job %d, status %s, flags %s, pid %d\n",
582 (int)(job - job_table), JobStatus_Name[job->status],
583 flags, job->pid);
584 }
585 }
586
587 /*
588 * Delete the target of a failed, interrupted, or otherwise
589 * unsuccessful job unless inhibited by .PRECIOUS.
590 */
591 static void
592 JobDeleteTarget(GNode *gn)
593 {
594 const char *file;
595
596 if (gn->type & OP_JOIN)
597 return;
598 if (gn->type & OP_PHONY)
599 return;
600 if (GNode_IsPrecious(gn))
601 return;
602 if (opts.noExecute)
603 return;
604
605 file = GNode_Path(gn);
606 if (unlink_file(file) == 0)
607 Error("*** %s removed", file);
608 }
609
610 /* Lock the jobs table and the jobs therein. */
611 static void
612 JobsTable_Lock(sigset_t *omaskp)
613 {
614 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0)
615 Punt("JobsTable_Lock: %s", strerror(errno));
616 }
617
618 /* Unlock the jobs table and the jobs therein. */
619 static void
620 JobsTable_Unlock(sigset_t *omaskp)
621 {
622 (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
623 }
624
625 static void
626 SetNonblocking(int fd)
627 {
628 int flags = fcntl(fd, F_GETFL, 0);
629 if (flags == -1)
630 Punt("SetNonblocking.get: %s", strerror(errno));
631 flags |= O_NONBLOCK;
632 if (fcntl(fd, F_SETFL, flags) == -1)
633 Punt("SetNonblocking.set: %s", strerror(errno));
634 }
635
636 static void
637 SetCloseOnExec(int fd)
638 {
639 if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
640 Punt("SetCloseOnExec: %s", strerror(errno));
641 }
642
643 static void
644 JobCreatePipe(Job *job, int minfd)
645 {
646 int i;
647 int pipe_fds[2];
648
649 if (pipe(pipe_fds) == -1)
650 Punt("JobCreatePipe: %s", strerror(errno));
651
652 for (i = 0; i < 2; i++) {
653 /* Avoid using low-numbered fds */
654 int fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
655 if (fd != -1) {
656 close(pipe_fds[i]);
657 pipe_fds[i] = fd;
658 }
659 }
660
661 job->inPipe = pipe_fds[0];
662 job->outPipe = pipe_fds[1];
663
664 SetCloseOnExec(job->inPipe);
665 SetCloseOnExec(job->outPipe);
666
667 /*
668 * We mark the input side of the pipe non-blocking; we poll(2) the
669 * pipe when we're waiting for a job token, but we might lose the
670 * race for the token when a new one becomes available, so the read
671 * from the pipe should not block.
672 */
673 SetNonblocking(job->inPipe);
674 }
675
676 /* Pass the signal to each running job. */
677 static void
678 JobCondPassSig(int signo)
679 {
680 Job *job;
681
682 DEBUG1(JOB, "JobCondPassSig: signal %d\n", signo);
683
684 for (job = job_table; job < job_table_end; job++) {
685 if (job->status != JOB_ST_RUNNING)
686 continue;
687 DEBUG2(JOB, "JobCondPassSig passing signal %d to pid %d\n",
688 signo, job->pid);
689 KILLPG(job->pid, signo);
690 }
691 }
692
693 static void
694 WriteOrDie(int fd, char ch)
695 {
696 if (write(fd, &ch, 1) != 1)
697 execDie("write", "child");
698 }
699
700 static void
701 HandleSIGCHLD(int signo MAKE_ATTR_UNUSED)
702 {
703 caught_sigchld = 1;
704 /* Wake up from poll(). */
705 WriteOrDie(childExitJob.outPipe, CEJ_CHILD_EXITED);
706 }
707
708 static void
709 HandleSIGCONT(int signo MAKE_ATTR_UNUSED)
710 {
711 WriteOrDie(childExitJob.outPipe, CEJ_RESUME_JOBS);
712 }
713
714 /*
715 * Pass a signal on to all jobs, then resend to ourselves.
716 * We die by the same signal.
717 */
718 MAKE_ATTR_DEAD static void
719 JobPassSig_int(int signo)
720 {
721 /* Run .INTERRUPT target then exit */
722 JobInterrupt(true, signo);
723 }
724
725 /*
726 * Pass a signal on to all jobs, then resend to ourselves.
727 * We die by the same signal.
728 */
729 MAKE_ATTR_DEAD static void
730 JobPassSig_term(int signo)
731 {
732 /* Dont run .INTERRUPT target then exit */
733 JobInterrupt(false, signo);
734 }
735
736 static void
737 JobPassSig_suspend(int signo)
738 {
739 sigset_t nmask, omask;
740 struct sigaction act;
741
742 /* Suppress job started/continued messages */
743 make_suspended = true;
744
745 /* Pass the signal onto every job */
746 JobCondPassSig(signo);
747
748 /*
749 * Send ourselves the signal now we've given the message to everyone
750 * else. Note we block everything else possible while we're getting
751 * the signal. This ensures that all our jobs get continued when we
752 * wake up before we take any other signal.
753 */
754 sigfillset(&nmask);
755 sigdelset(&nmask, signo);
756 (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
757
758 act.sa_handler = SIG_DFL;
759 sigemptyset(&act.sa_mask);
760 act.sa_flags = 0;
761 (void)sigaction(signo, &act, NULL);
762
763 DEBUG1(JOB, "JobPassSig_suspend passing signal %d to self\n", signo);
764
765 (void)kill(getpid(), signo);
766
767 /*
768 * We've been continued.
769 *
770 * A whole host of signals is going to happen!
771 * SIGCHLD for any processes that actually suspended themselves.
772 * SIGCHLD for any processes that exited while we were asleep.
773 * The SIGCONT that actually caused us to wake up.
774 *
775 * Since we defer passing the SIGCONT on to our children until
776 * the main processing loop, we can be sure that all the SIGCHLD
777 * events will have happened by then - and that the waitpid() will
778 * collect the child 'suspended' events.
779 * For correct sequencing we just need to ensure we process the
780 * waitpid() before passing on the SIGCONT.
781 *
782 * In any case nothing else is needed here.
783 */
784
785 /* Restore handler and signal mask */
786 act.sa_handler = JobPassSig_suspend;
787 (void)sigaction(signo, &act, NULL);
788 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
789 }
790
791 static Job *
792 JobFindPid(int pid, enum JobStatus status, bool isJobs)
793 {
794 Job *job;
795
796 for (job = job_table; job < job_table_end; job++) {
797 if (job->status == status && job->pid == pid)
798 return job;
799 }
800 if (DEBUG(JOB) && isJobs)
801 JobTable_Dump("no pid");
802 return NULL;
803 }
804
805 /* Parse leading '@', '-' and '+', which control the exact execution mode. */
806 static void
807 ParseCommandFlags(char **pp, CommandFlags *out_cmdFlags)
808 {
809 char *p = *pp;
810 out_cmdFlags->echo = true;
811 out_cmdFlags->ignerr = false;
812 out_cmdFlags->always = false;
813
814 for (;;) {
815 if (*p == '@')
816 out_cmdFlags->echo = DEBUG(LOUD);
817 else if (*p == '-')
818 out_cmdFlags->ignerr = true;
819 else if (*p == '+')
820 out_cmdFlags->always = true;
821 else if (!ch_isspace(*p))
822 /* Ignore whitespace for compatibility with GNU make */
823 break;
824 p++;
825 }
826
827 *pp = p;
828 }
829
830 /* Escape a string for a double-quoted string literal in sh, csh and ksh. */
831 static char *
832 EscapeShellDblQuot(const char *cmd)
833 {
834 size_t i, j;
835
836 /* Worst that could happen is every char needs escaping. */
837 char *esc = bmake_malloc(strlen(cmd) * 2 + 1);
838 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) {
839 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' ||
840 cmd[i] == '"')
841 esc[j++] = '\\';
842 esc[j] = cmd[i];
843 }
844 esc[j] = '\0';
845
846 return esc;
847 }
848
849 static void
850 ShellWriter_WriteFmt(ShellWriter *wr, const char *fmt, const char *arg)
851 {
852 DEBUG1(JOB, fmt, arg);
853
854 (void)fprintf(wr->f, fmt, arg);
855 if (wr->f == stdout)
856 (void)fflush(wr->f);
857 }
858
859 static void
860 ShellWriter_WriteLine(ShellWriter *wr, const char *line)
861 {
862 ShellWriter_WriteFmt(wr, "%s\n", line);
863 }
864
865 static void
866 ShellWriter_EchoOff(ShellWriter *wr)
867 {
868 if (shell->hasEchoCtl)
869 ShellWriter_WriteLine(wr, shell->echoOff);
870 }
871
872 static void
873 ShellWriter_EchoCmd(ShellWriter *wr, const char *escCmd)
874 {
875 ShellWriter_WriteFmt(wr, shell->echoTmpl, escCmd);
876 }
877
878 static void
879 ShellWriter_EchoOn(ShellWriter *wr)
880 {
881 if (shell->hasEchoCtl)
882 ShellWriter_WriteLine(wr, shell->echoOn);
883 }
884
885 static void
886 ShellWriter_TraceOn(ShellWriter *wr)
887 {
888 if (!wr->xtraced) {
889 ShellWriter_WriteLine(wr, "set -x");
890 wr->xtraced = true;
891 }
892 }
893
894 static void
895 ShellWriter_ErrOff(ShellWriter *wr, bool echo)
896 {
897 if (echo)
898 ShellWriter_EchoOff(wr);
899 ShellWriter_WriteLine(wr, shell->errOff);
900 if (echo)
901 ShellWriter_EchoOn(wr);
902 }
903
904 static void
905 ShellWriter_ErrOn(ShellWriter *wr, bool echo)
906 {
907 if (echo)
908 ShellWriter_EchoOff(wr);
909 ShellWriter_WriteLine(wr, shell->errOn);
910 if (echo)
911 ShellWriter_EchoOn(wr);
912 }
913
914 /*
915 * The shell has no built-in error control, so emulate error control by
916 * enclosing each shell command in a template like "{ %s \n } || exit $?"
917 * (configurable per shell).
918 */
919 static void
920 JobWriteSpecialsEchoCtl(Job *job, ShellWriter *wr, CommandFlags *inout_cmdFlags,
921 const char *escCmd, const char **inout_cmdTemplate)
922 {
923 /* XXX: Why is the whole job modified at this point? */
924 job->ignerr = true;
925
926 if (job->echo && inout_cmdFlags->echo) {
927 ShellWriter_EchoOff(wr);
928 ShellWriter_EchoCmd(wr, escCmd);
929
930 /*
931 * Leave echoing off so the user doesn't see the commands
932 * for toggling the error checking.
933 */
934 inout_cmdFlags->echo = false;
935 }
936 *inout_cmdTemplate = shell->runIgnTmpl;
937
938 /*
939 * The template runIgnTmpl already takes care of ignoring errors,
940 * so pretend error checking is still on.
941 * XXX: What effects does this have, and why is it necessary?
942 */
943 inout_cmdFlags->ignerr = false;
944 }
945
946 static void
947 JobWriteSpecials(Job *job, ShellWriter *wr, const char *escCmd, bool run,
948 CommandFlags *inout_cmdFlags, const char **inout_cmdTemplate)
949 {
950 if (!run)
951 inout_cmdFlags->ignerr = false;
952 else if (shell->hasErrCtl)
953 ShellWriter_ErrOff(wr, job->echo && inout_cmdFlags->echo);
954 else if (shell->runIgnTmpl != NULL && shell->runIgnTmpl[0] != '\0') {
955 JobWriteSpecialsEchoCtl(job, wr, inout_cmdFlags, escCmd,
956 inout_cmdTemplate);
957 } else
958 inout_cmdFlags->ignerr = false;
959 }
960
961 /*
962 * Write a shell command to the job's commands file, to be run later.
963 *
964 * If the command starts with '@' and neither the -s nor the -n flag was
965 * given to make, stick a shell-specific echoOff command in the script.
966 *
967 * If the command starts with '-' and the shell has no error control (none
968 * of the predefined shells has that), ignore errors for the rest of the job.
969 *
970 * XXX: Why ignore errors for the entire job? This is documented in the
971 * manual page, but without giving a rationale.
972 *
973 * If the command is just "...", attach all further commands of this job to
974 * the .END node instead, see Job_Finish.
975 */
976 static void
977 JobWriteCommand(Job *job, ShellWriter *wr, StringListNode *ln, const char *ucmd)
978 {
979 bool run;
980
981 CommandFlags cmdFlags;
982 /* Template for writing a command to the shell file */
983 const char *cmdTemplate;
984 char *xcmd; /* The expanded command */
985 char *xcmdStart;
986 char *escCmd; /* xcmd escaped to be used in double quotes */
987
988 run = GNode_ShouldExecute(job->node);
989
990 xcmd = Var_SubstInTarget(ucmd, job->node);
991 /* TODO: handle errors */
992 xcmdStart = xcmd;
993
994 cmdTemplate = "%s\n";
995
996 ParseCommandFlags(&xcmd, &cmdFlags);
997
998 /* The '+' command flag overrides the -n or -N options. */
999 if (cmdFlags.always && !run) {
1000 /*
1001 * We're not actually executing anything...
1002 * but this one needs to be - use compat mode just for it.
1003 */
1004 (void)Compat_RunCommand(ucmd, job->node, ln);
1005 free(xcmdStart);
1006 return;
1007 }
1008
1009 /*
1010 * If the shell doesn't have error control, the alternate echoing
1011 * will be done (to avoid showing additional error checking code)
1012 * and this needs some characters escaped.
1013 */
1014 escCmd = shell->hasErrCtl ? NULL : EscapeShellDblQuot(xcmd);
1015
1016 if (!cmdFlags.echo) {
1017 if (job->echo && run && shell->hasEchoCtl)
1018 ShellWriter_EchoOff(wr);
1019 else if (shell->hasErrCtl)
1020 cmdFlags.echo = true;
1021 }
1022
1023 if (cmdFlags.ignerr) {
1024 JobWriteSpecials(job, wr, escCmd, run, &cmdFlags, &cmdTemplate);
1025 } else {
1026
1027 /*
1028 * If errors are being checked and the shell doesn't have
1029 * error control but does supply an runChkTmpl template, then
1030 * set up commands to run through it.
1031 */
1032
1033 if (!shell->hasErrCtl && shell->runChkTmpl != NULL &&
1034 shell->runChkTmpl[0] != '\0') {
1035 if (job->echo && cmdFlags.echo) {
1036 ShellWriter_EchoOff(wr);
1037 ShellWriter_EchoCmd(wr, escCmd);
1038 cmdFlags.echo = false;
1039 }
1040 /*
1041 * If it's a comment line or blank, avoid the possible
1042 * syntax error generated by "{\n} || exit $?".
1043 */
1044 cmdTemplate = escCmd[0] == shell->commentChar ||
1045 escCmd[0] == '\0'
1046 ? shell->runIgnTmpl
1047 : shell->runChkTmpl;
1048 cmdFlags.ignerr = false;
1049 }
1050 }
1051
1052 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0)
1053 ShellWriter_TraceOn(wr);
1054
1055 ShellWriter_WriteFmt(wr, cmdTemplate, xcmd);
1056 free(xcmdStart);
1057 free(escCmd);
1058
1059 if (cmdFlags.ignerr)
1060 ShellWriter_ErrOn(wr, cmdFlags.echo && job->echo);
1061
1062 if (!cmdFlags.echo)
1063 ShellWriter_EchoOn(wr);
1064 }
1065
1066 /*
1067 * Write all commands to the shell file that is later executed.
1068 *
1069 * The special command "..." stops writing and saves the remaining commands
1070 * to be executed later, when the target '.END' is made.
1071 *
1072 * Return whether at least one command was written to the shell file.
1073 */
1074 static bool
1075 JobWriteCommands(Job *job)
1076 {
1077 StringListNode *ln;
1078 bool seen = false;
1079 ShellWriter wr;
1080
1081 wr.f = job->cmdFILE;
1082 wr.xtraced = false;
1083
1084 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) {
1085 const char *cmd = ln->datum;
1086
1087 if (strcmp(cmd, "...") == 0) {
1088 job->node->type |= OP_SAVE_CMDS;
1089 job->tailCmds = ln->next;
1090 break;
1091 }
1092
1093 JobWriteCommand(job, &wr, ln, ln->datum);
1094 seen = true;
1095 }
1096
1097 return seen;
1098 }
1099
1100 /*
1101 * Save the delayed commands (those after '...'), to be executed later in
1102 * the '.END' node, when everything else is done.
1103 */
1104 static void
1105 JobSaveCommands(Job *job)
1106 {
1107 StringListNode *ln;
1108
1109 for (ln = job->tailCmds; ln != NULL; ln = ln->next) {
1110 const char *cmd = ln->datum;
1111 char *expanded_cmd;
1112 /*
1113 * XXX: This Var_Subst is only intended to expand the dynamic
1114 * variables such as .TARGET, .IMPSRC. It is not intended to
1115 * expand the other variables as well; see deptgt-end.mk.
1116 */
1117 expanded_cmd = Var_SubstInTarget(cmd, job->node);
1118 /* TODO: handle errors */
1119 Lst_Append(&Targ_GetEndNode()->commands, expanded_cmd);
1120 Parse_RegisterCommand(expanded_cmd);
1121 }
1122 }
1123
1124
1125 /* Close both input and output pipes when a job is finished. */
1126 static void
1127 JobClosePipes(Job *job)
1128 {
1129 clearfd(job);
1130 (void)close(job->outPipe);
1131 job->outPipe = -1;
1132
1133 CollectOutput(job, true);
1134 (void)close(job->inPipe);
1135 job->inPipe = -1;
1136 }
1137
1138 static void
1139 DebugFailedJob(const Job *job)
1140 {
1141 const StringListNode *ln;
1142
1143 if (!DEBUG(ERROR))
1144 return;
1145
1146 debug_printf("\n");
1147 debug_printf("*** Failed target: %s\n", job->node->name);
1148 debug_printf("*** In directory: %s\n", curdir);
1149 debug_printf("*** Failed commands:\n");
1150 for (ln = job->node->commands.first; ln != NULL; ln = ln->next) {
1151 const char *cmd = ln->datum;
1152 debug_printf("\t%s\n", cmd);
1153
1154 if (strchr(cmd, '$') != NULL) {
1155 char *xcmd = Var_Subst(cmd, job->node, VARE_EVAL);
1156 debug_printf("\t=> %s\n", xcmd);
1157 free(xcmd);
1158 }
1159 }
1160 }
1161
1162 static void
1163 JobFinishDoneExitedError(Job *job, int *inout_status)
1164 {
1165 SwitchOutputTo(job->node);
1166 #ifdef USE_META
1167 if (useMeta) {
1168 meta_job_error(job, job->node,
1169 job->ignerr, WEXITSTATUS(*inout_status));
1170 }
1171 #endif
1172 if (!shouldDieQuietly(job->node, -1)) {
1173 DebugFailedJob(job);
1174 (void)printf("*** [%s] Error code %d%s\n",
1175 job->node->name, WEXITSTATUS(*inout_status),
1176 job->ignerr ? " (ignored)" : "");
1177 }
1178
1179 if (job->ignerr)
1180 *inout_status = 0;
1181 else {
1182 if (deleteOnError)
1183 JobDeleteTarget(job->node);
1184 PrintOnError(job->node, "\n");
1185 }
1186 }
1187
1188 static void
1189 JobFinishDoneExited(Job *job, int *inout_status)
1190 {
1191 DEBUG2(JOB, "Target %s, pid %d exited\n",
1192 job->node->name, job->pid);
1193
1194 if (WEXITSTATUS(*inout_status) != 0)
1195 JobFinishDoneExitedError(job, inout_status);
1196 else if (DEBUG(JOB)) {
1197 SwitchOutputTo(job->node);
1198 (void)printf("Target %s, pid %d exited successfully\n",
1199 job->node->name, job->pid);
1200 }
1201 }
1202
1203 static void
1204 JobFinishDoneSignaled(Job *job, int status)
1205 {
1206 SwitchOutputTo(job->node);
1207 DebugFailedJob(job);
1208 (void)printf("*** [%s] Signal %d\n", job->node->name, WTERMSIG(status));
1209 if (deleteOnError)
1210 JobDeleteTarget(job->node);
1211 }
1212
1213 static void
1214 JobFinishDone(Job *job, int *inout_status)
1215 {
1216 if (WIFEXITED(*inout_status))
1217 JobFinishDoneExited(job, inout_status);
1218 else
1219 JobFinishDoneSignaled(job, *inout_status);
1220
1221 (void)fflush(stdout);
1222 }
1223
1224 /*
1225 * Finish the job, add deferred commands to the .END node, mark the job as
1226 * free, update parent nodes and start new jobs as available/necessary.
1227 */
1228 static void
1229 JobFinish(Job *job, int status)
1230 {
1231 bool done, return_job_token;
1232
1233 DEBUG3(JOB, "JobFinish: target %s, pid %d, status %#x\n",
1234 job->node->name, job->pid, status);
1235
1236 if ((WIFEXITED(status) &&
1237 ((WEXITSTATUS(status) != 0 && !job->ignerr))) ||
1238 WIFSIGNALED(status)) {
1239 /* Finished because of an error. */
1240
1241 JobClosePipes(job);
1242 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1243 if (fclose(job->cmdFILE) != 0)
1244 Punt("Cannot write shell script for \"%s\": %s",
1245 job->node->name, strerror(errno));
1246 job->cmdFILE = NULL;
1247 }
1248 done = true;
1249
1250 } else if (WIFEXITED(status)) {
1251 /*
1252 * Deal with ignored errors in -B mode. We need to print a
1253 * message telling of the ignored error as well as to run
1254 * the next command.
1255 */
1256 done = WEXITSTATUS(status) != 0;
1257
1258 JobClosePipes(job);
1259
1260 } else {
1261 /* No need to close things down or anything. */
1262 done = false;
1263 }
1264
1265 if (done)
1266 JobFinishDone(job, &status);
1267
1268 #ifdef USE_META
1269 if (useMeta) {
1270 int meta_status = meta_job_finish(job);
1271 if (meta_status != 0 && status == 0)
1272 status = meta_status;
1273 }
1274 #endif
1275
1276 return_job_token = false;
1277
1278 Trace_Log(JOBEND, job);
1279 if (!job->special) {
1280 if (status != 0 ||
1281 (aborting == ABORT_ERROR) || aborting == ABORT_INTERRUPT)
1282 return_job_token = true;
1283 }
1284
1285 if (aborting != ABORT_ERROR && aborting != ABORT_INTERRUPT &&
1286 status == 0) {
1287 JobSaveCommands(job);
1288 job->node->made = MADE;
1289 if (!job->special)
1290 return_job_token = true;
1291 Make_Update(job->node);
1292 job->status = JOB_ST_FREE;
1293 } else if (status != 0) {
1294 job_errors++;
1295 job->status = JOB_ST_FREE;
1296 }
1297
1298 if (job_errors > 0 && !opts.keepgoing && aborting != ABORT_INTERRUPT) {
1299 /* Prevent more jobs from getting started. */
1300 aborting = ABORT_ERROR;
1301 }
1302
1303 if (return_job_token)
1304 TokenPool_Return();
1305
1306 if (aborting == ABORT_ERROR && jobTokensRunning == 0) {
1307 if (shouldDieQuietly(NULL, -1))
1308 exit(2);
1309 Fatal("%d error%s", job_errors, job_errors == 1 ? "" : "s");
1310 }
1311 }
1312
1313 static void
1314 TouchRegular(GNode *gn)
1315 {
1316 const char *file = GNode_Path(gn);
1317 struct utimbuf times;
1318 int fd;
1319 char c;
1320
1321 times.actime = now;
1322 times.modtime = now;
1323 if (utime(file, ×) >= 0)
1324 return;
1325
1326 fd = open(file, O_RDWR | O_CREAT, 0666);
1327 if (fd < 0) {
1328 (void)fprintf(stderr, "*** couldn't touch %s: %s\n",
1329 file, strerror(errno));
1330 (void)fflush(stderr);
1331 return; /* XXX: What about propagating the error? */
1332 }
1333
1334 /*
1335 * Last resort: update the file's time stamps in the traditional way.
1336 * XXX: This doesn't work for empty files, which are sometimes used
1337 * as marker files.
1338 */
1339 if (read(fd, &c, 1) == 1) {
1340 (void)lseek(fd, 0, SEEK_SET);
1341 while (write(fd, &c, 1) == -1 && errno == EAGAIN)
1342 continue;
1343 }
1344 (void)close(fd); /* XXX: What about propagating the error? */
1345 }
1346
1347 /*
1348 * Touch the given target. Called by Job_Make when the -t flag was given.
1349 *
1350 * The modification date of the file is changed.
1351 * If the file did not exist, it is created.
1352 */
1353 void
1354 Job_Touch(GNode *gn, bool echo)
1355 {
1356 if (gn->type &
1357 (OP_JOIN | OP_USE | OP_USEBEFORE | OP_EXEC | OP_OPTIONAL |
1358 OP_SPECIAL | OP_PHONY)) {
1359 /*
1360 * These are "virtual" targets and should not really be
1361 * created.
1362 */
1363 return;
1364 }
1365
1366 if (echo || !GNode_ShouldExecute(gn)) {
1367 (void)fprintf(stdout, "touch %s\n", gn->name);
1368 (void)fflush(stdout);
1369 }
1370
1371 if (!GNode_ShouldExecute(gn))
1372 return;
1373
1374 if (gn->type & OP_ARCHV)
1375 Arch_Touch(gn);
1376 else if (gn->type & OP_LIB)
1377 Arch_TouchLib(gn);
1378 else
1379 TouchRegular(gn);
1380 }
1381
1382 /*
1383 * Make sure the given node has all the commands it needs.
1384 *
1385 * The node will have commands from the .DEFAULT rule added to it if it
1386 * needs them.
1387 *
1388 * Input:
1389 * gn The target whose commands need verifying
1390 * abortProc Function to abort with message
1391 *
1392 * Results:
1393 * true if the commands are ok.
1394 */
1395 bool
1396 Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
1397 {
1398 if (GNode_IsTarget(gn))
1399 return true;
1400 if (!Lst_IsEmpty(&gn->commands))
1401 return true;
1402 if ((gn->type & OP_LIB) && !Lst_IsEmpty(&gn->children))
1403 return true;
1404
1405 /*
1406 * No commands. Look for .DEFAULT rule from which we might infer
1407 * commands.
1408 */
1409 if (defaultNode != NULL && !Lst_IsEmpty(&defaultNode->commands) &&
1410 !(gn->type & OP_SPECIAL)) {
1411 /*
1412 * The traditional Make only looks for a .DEFAULT if the node
1413 * was never the target of an operator, so that's what we do
1414 * too.
1415 *
1416 * The .DEFAULT node acts like a transformation rule, in that
1417 * gn also inherits any attributes or sources attached to
1418 * .DEFAULT itself.
1419 */
1420 Make_HandleUse(defaultNode, gn);
1421 Var_Set(gn, IMPSRC, GNode_VarTarget(gn));
1422 return true;
1423 }
1424
1425 Dir_UpdateMTime(gn, false);
1426 if (gn->mtime != 0 || (gn->type & OP_SPECIAL))
1427 return true;
1428
1429 /*
1430 * The node wasn't the target of an operator. We have no .DEFAULT
1431 * rule to go on and the target doesn't already exist. There's
1432 * nothing more we can do for this branch. If the -k flag wasn't
1433 * given, we stop in our tracks, otherwise we just don't update
1434 * this node's parents so they never get examined.
1435 */
1436
1437 if (gn->flags.fromDepend) {
1438 if (!Job_RunTarget(".STALE", gn->fname))
1439 fprintf(stdout,
1440 "%s: %s:%u: ignoring stale %s for %s\n",
1441 progname, gn->fname, gn->lineno, makeDependfile,
1442 gn->name);
1443 return true;
1444 }
1445
1446 if (gn->type & OP_OPTIONAL) {
1447 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1448 progname, gn->name, "ignored");
1449 (void)fflush(stdout);
1450 return true;
1451 }
1452
1453 if (opts.keepgoing) {
1454 (void)fprintf(stdout, "%s: don't know how to make %s (%s)\n",
1455 progname, gn->name, "continuing");
1456 (void)fflush(stdout);
1457 return false;
1458 }
1459
1460 abortProc("don't know how to make %s. Stop", gn->name);
1461 return false;
1462 }
1463
1464 /*
1465 * Execute the shell for the given job.
1466 *
1467 * See Job_CatchOutput for handling the output of the shell.
1468 */
1469 static void
1470 JobExec(Job *job, char **argv)
1471 {
1472 int cpid; /* ID of new child */
1473 sigset_t mask;
1474
1475 if (DEBUG(JOB)) {
1476 int i;
1477
1478 debug_printf("Running %s\n", job->node->name);
1479 debug_printf("\tCommand:");
1480 for (i = 0; argv[i] != NULL; i++) {
1481 debug_printf(" %s", argv[i]);
1482 }
1483 debug_printf("\n");
1484 }
1485
1486 /*
1487 * Some jobs produce no output, and it's disconcerting to have
1488 * no feedback of their running (since they produce no output, the
1489 * banner with their name in it never appears). This is an attempt to
1490 * provide that feedback, even if nothing follows it.
1491 */
1492 if (job->echo)
1493 SwitchOutputTo(job->node);
1494
1495 /* No interruptions until this job is in the jobs table. */
1496 JobsTable_Lock(&mask);
1497
1498 /* Pre-emptively mark job running, pid still zero though */
1499 job->status = JOB_ST_RUNNING;
1500
1501 Var_ReexportVars(job->node);
1502 Var_ExportStackTrace(job->node->name, NULL);
1503
1504 cpid = FORK_FUNCTION();
1505 if (cpid == -1)
1506 Punt("fork: %s", strerror(errno));
1507
1508 if (cpid == 0) {
1509 /* Child */
1510 sigset_t tmask;
1511
1512 #ifdef USE_META
1513 if (useMeta)
1514 meta_job_child(job);
1515 #endif
1516 /*
1517 * Reset all signal handlers; this is necessary because we
1518 * also need to unblock signals before we exec(2).
1519 */
1520 JobSigReset();
1521
1522 sigemptyset(&tmask);
1523 JobsTable_Unlock(&tmask);
1524
1525 if (dup2(fileno(job->cmdFILE), STDIN_FILENO) == -1)
1526 execDie("dup2", "job->cmdFILE");
1527 if (fcntl(STDIN_FILENO, F_SETFD, 0) == -1)
1528 execDie("clear close-on-exec", "stdin");
1529 if (lseek(STDIN_FILENO, 0, SEEK_SET) == -1)
1530 execDie("lseek to 0", "stdin");
1531
1532 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
1533 /* Pass job token pipe to submakes. */
1534 if (fcntl(tokenPoolJob.inPipe, F_SETFD, 0) == -1)
1535 execDie("clear close-on-exec",
1536 "tokenPoolJob.inPipe");
1537 if (fcntl(tokenPoolJob.outPipe, F_SETFD, 0) == -1)
1538 execDie("clear close-on-exec",
1539 "tokenPoolJob.outPipe");
1540 }
1541
1542 if (dup2(job->outPipe, STDOUT_FILENO) == -1)
1543 execDie("dup2", "job->outPipe");
1544
1545 /*
1546 * The output channels are marked close on exec. This bit
1547 * was duplicated by dup2 (on some systems), so we have
1548 * to clear it before routing the shell's error output to
1549 * the same place as its standard output.
1550 */
1551 if (fcntl(STDOUT_FILENO, F_SETFD, 0) == -1)
1552 execDie("clear close-on-exec", "stdout");
1553 if (dup2(STDOUT_FILENO, STDERR_FILENO) == -1)
1554 execDie("dup2", "1, 2");
1555
1556 /*
1557 * We want to switch the child into a different process
1558 * family so we can kill it and all its descendants in
1559 * one fell swoop, by killing its process family, but not
1560 * commit suicide.
1561 */
1562 #if defined(MAKE_NATIVE) || defined(HAVE_SETPGID)
1563 # if defined(SYSV)
1564 /* XXX: dsl - I'm sure this should be setpgrp()... */
1565 (void)setsid();
1566 # else
1567 (void)setpgid(0, getpid());
1568 # endif
1569 #endif
1570
1571 (void)execv(shellPath, argv);
1572 execDie("exec", shellPath);
1573 }
1574
1575 /* Parent, continuing after the child exec */
1576 job->pid = cpid;
1577
1578 Trace_Log(JOBSTART, job);
1579
1580 #ifdef USE_META
1581 if (useMeta)
1582 meta_job_parent(job, cpid);
1583 #endif
1584
1585 job->outBufLen = 0;
1586
1587 watchfd(job);
1588
1589 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1590 if (fclose(job->cmdFILE) != 0)
1591 Punt("Cannot write shell script for \"%s\": %s",
1592 job->node->name, strerror(errno));
1593 job->cmdFILE = NULL;
1594 }
1595
1596 if (DEBUG(JOB)) {
1597 debug_printf(
1598 "JobExec: target %s, pid %d added to jobs table\n",
1599 job->node->name, job->pid);
1600 JobTable_Dump("job started");
1601 }
1602 JobsTable_Unlock(&mask);
1603 }
1604
1605 static void
1606 BuildArgv(Job *job, char **argv)
1607 {
1608 int argc;
1609 static char args[10];
1610
1611 argv[0] = UNCONST(shellName);
1612 argc = 1;
1613
1614 if ((shell->errFlag != NULL && shell->errFlag[0] != '-') ||
1615 (shell->echoFlag != NULL && shell->echoFlag[0] != '-')) {
1616 /*
1617 * At least one of the flags doesn't have a minus before it,
1618 * so merge them together. Have to do this because the Bourne
1619 * shell thinks its second argument is a file to source.
1620 * Grrrr. Note the ten-character limitation on the combined
1621 * arguments.
1622 *
1623 * TODO: Research until when the above comments were
1624 * practically relevant.
1625 */
1626 (void)snprintf(args, sizeof args, "-%s%s",
1627 !job->ignerr && shell->errFlag != NULL
1628 ? shell->errFlag : "",
1629 job->echo && shell->echoFlag != NULL
1630 ? shell->echoFlag : "");
1631 if (args[1] != '\0') {
1632 argv[argc] = args;
1633 argc++;
1634 }
1635 } else {
1636 if (!job->ignerr && shell->errFlag != NULL) {
1637 argv[argc] = UNCONST(shell->errFlag);
1638 argc++;
1639 }
1640 if (job->echo && shell->echoFlag != NULL) {
1641 argv[argc] = UNCONST(shell->echoFlag);
1642 argc++;
1643 }
1644 }
1645 argv[argc] = NULL;
1646 }
1647
1648 static void
1649 JobWriteShellCommands(Job *job, GNode *gn, bool *out_run)
1650 {
1651 char fname[MAXPATHLEN];
1652 int fd;
1653
1654 fd = Job_TempFile(NULL, fname, sizeof fname);
1655
1656 job->cmdFILE = fdopen(fd, "w+");
1657 if (job->cmdFILE == NULL)
1658 Punt("Could not fdopen %s", fname);
1659
1660 (void)fcntl(fd, F_SETFD, FD_CLOEXEC);
1661
1662 #ifdef USE_META
1663 if (useMeta) {
1664 meta_job_start(job, gn);
1665 if (gn->type & OP_SILENT) /* might have changed */
1666 job->echo = false;
1667 }
1668 #endif
1669
1670 *out_run = JobWriteCommands(job);
1671 }
1672
1673 void
1674 Job_Make(GNode *gn)
1675 {
1676 Job *job;
1677 char *argv[10];
1678 bool cmdsOK; /* true if the nodes commands were all right */
1679 bool run;
1680
1681 for (job = job_table; job < job_table_end; job++) {
1682 if (job->status == JOB_ST_FREE)
1683 break;
1684 }
1685 if (job >= job_table_end)
1686 Punt("Job_Make no job slots vacant");
1687
1688 memset(job, 0, sizeof *job);
1689 job->node = gn;
1690 job->tailCmds = NULL;
1691 job->status = JOB_ST_SET_UP;
1692
1693 job->special = (gn->type & OP_SPECIAL) != OP_NONE;
1694 job->ignerr = opts.ignoreErrors || gn->type & OP_IGNORE;
1695 job->echo = !(opts.silent || gn->type & OP_SILENT);
1696
1697 /*
1698 * Check the commands now so any attributes from .DEFAULT have a
1699 * chance to migrate to the node.
1700 */
1701 cmdsOK = Job_CheckCommands(gn, Error);
1702
1703 job->inPollfd = NULL;
1704
1705 if (Lst_IsEmpty(&gn->commands)) {
1706 job->cmdFILE = stdout;
1707 run = false;
1708
1709 if (!cmdsOK) {
1710 PrintOnError(gn, "\n");
1711 DieHorribly();
1712 }
1713 } else if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) ||
1714 (!opts.noExecute && !opts.touch)) {
1715 int parseErrorsBefore;
1716
1717 if (!cmdsOK) {
1718 PrintOnError(gn, "\n");
1719 DieHorribly();
1720 }
1721
1722 parseErrorsBefore = parseErrors;
1723 JobWriteShellCommands(job, gn, &run);
1724 if (parseErrors != parseErrorsBefore)
1725 run = false;
1726 (void)fflush(job->cmdFILE);
1727 } else if (!GNode_ShouldExecute(gn)) {
1728 SwitchOutputTo(gn);
1729 job->cmdFILE = stdout;
1730 if (cmdsOK)
1731 JobWriteCommands(job);
1732 run = false;
1733 (void)fflush(job->cmdFILE);
1734 } else {
1735 Job_Touch(gn, job->echo);
1736 run = false;
1737 }
1738
1739 if (!run) {
1740 if (!job->special)
1741 TokenPool_Return();
1742
1743 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1744 (void)fclose(job->cmdFILE);
1745 job->cmdFILE = NULL;
1746 }
1747
1748 if (cmdsOK && aborting == ABORT_NONE) {
1749 JobSaveCommands(job);
1750 job->node->made = MADE;
1751 Make_Update(job->node);
1752 }
1753 job->status = JOB_ST_FREE;
1754 return;
1755 }
1756
1757 BuildArgv(job, argv);
1758 JobCreatePipe(job, 3);
1759 JobExec(job, argv);
1760 }
1761
1762 /*
1763 * If the shell has an output filter (which only csh and ksh have by default),
1764 * print the output of the child process, skipping the noPrint text of the
1765 * shell.
1766 *
1767 * Return the part of the output that the calling function needs to output by
1768 * itself.
1769 */
1770 static const char *
1771 PrintFilteredOutput(Job *job, size_t len)
1772 {
1773 const char *p = job->outBuf, *ep, *endp;
1774
1775 if (shell->noPrint == NULL || shell->noPrint[0] == '\0')
1776 return p;
1777
1778 endp = p + len;
1779 while ((ep = strstr(p, shell->noPrint)) != NULL && ep < endp) {
1780 if (ep > p) {
1781 if (!opts.silent)
1782 SwitchOutputTo(job->node);
1783 (void)fwrite(p, 1, (size_t)(ep - p), stdout);
1784 (void)fflush(stdout);
1785 }
1786 p = ep + shell->noPrintLen;
1787 if (p == endp)
1788 break;
1789 p++; /* skip over the (XXX: assumed) newline */
1790 cpp_skip_whitespace(&p);
1791 }
1792 return p;
1793 }
1794
1795 /*
1796 * Collect output from the job. Print any complete lines.
1797 *
1798 * In the output of the shell, the 'noPrint' lines are removed. If the
1799 * command is not alone on the line (the character after it is not \0 or
1800 * \n), we do print whatever follows it.
1801 *
1802 * If finish is true, collect all remaining output for the job.
1803 */
1804 static void
1805 CollectOutput(Job *job, bool finish)
1806 {
1807 const char *p;
1808 size_t nr; /* number of bytes read */
1809 size_t i; /* auxiliary index into outBuf */
1810 size_t max; /* limit for i (end of current data) */
1811
1812 again:
1813 nr = (size_t)read(job->inPipe, job->outBuf + job->outBufLen,
1814 JOB_BUFSIZE - job->outBufLen);
1815 if (nr == (size_t)-1) {
1816 if (errno == EAGAIN)
1817 return;
1818 if (DEBUG(JOB))
1819 perror("CollectOutput(piperead)");
1820 nr = 0;
1821 }
1822
1823 if (nr == 0)
1824 finish = false; /* stop looping */
1825
1826 if (nr == 0 && job->outBufLen > 0) {
1827 job->outBuf[job->outBufLen] = '\n';
1828 nr = 1;
1829 }
1830
1831 max = job->outBufLen + nr;
1832 job->outBuf[max] = '\0';
1833
1834 for (i = job->outBufLen; i < max; i++)
1835 if (job->outBuf[i] == '\0')
1836 job->outBuf[i] = ' ';
1837
1838 for (i = max; i > job->outBufLen; i--)
1839 if (job->outBuf[i - 1] == '\n')
1840 break;
1841
1842 if (i == job->outBufLen) {
1843 job->outBufLen = max;
1844 if (max < JOB_BUFSIZE)
1845 goto unfinished_line;
1846 i = max;
1847 }
1848
1849 p = PrintFilteredOutput(job, i);
1850 if (*p != '\0') {
1851 if (!opts.silent)
1852 SwitchOutputTo(job->node);
1853 #ifdef USE_META
1854 if (useMeta)
1855 meta_job_output(job, p);
1856 #endif
1857 (void)fwrite(p, 1, (size_t)(job->outBuf + i - p), stdout);
1858 (void)fflush(stdout);
1859 }
1860 memmove(job->outBuf, job->outBuf + i, max - i);
1861 job->outBufLen = max - i;
1862
1863 unfinished_line:
1864 if (finish)
1865 goto again;
1866 }
1867
1868 static void
1869 JobRun(GNode *target)
1870 {
1871 /* Don't let these special jobs overlap with other unrelated jobs. */
1872 Compat_Make(target, target);
1873 if (GNode_IsError(target)) {
1874 PrintOnError(target, "\n\nStop.\n");
1875 exit(1);
1876 }
1877 }
1878
1879 void
1880 Job_CatchChildren(void)
1881 {
1882 int pid;
1883 int status;
1884
1885 if (jobTokensRunning == 0)
1886 return;
1887 if (caught_sigchld == 0)
1888 return;
1889 caught_sigchld = 0;
1890
1891 while ((pid = waitpid((pid_t)-1, &status, WNOHANG | WUNTRACED)) > 0) {
1892 DEBUG2(JOB,
1893 "Process with pid %d exited/stopped with status %#x.\n",
1894 pid, status);
1895 JobReapChild(pid, status, true);
1896 }
1897 }
1898
1899 /*
1900 * It is possible that wait[pid]() was called from elsewhere,
1901 * this lets us reap jobs regardless.
1902 */
1903 void
1904 JobReapChild(pid_t pid, int status, bool isJobs)
1905 {
1906 Job *job;
1907
1908 if (jobTokensRunning == 0)
1909 return;
1910
1911 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs);
1912 if (job == NULL) {
1913 if (isJobs && !lurking_children)
1914 Error("Child with pid %d and status %#x not in table?",
1915 pid, status);
1916 return;
1917 }
1918
1919 if (WIFSTOPPED(status)) {
1920 DEBUG2(JOB, "Process for target %s, pid %d stopped\n",
1921 job->node->name, job->pid);
1922 if (!make_suspended) {
1923 switch (WSTOPSIG(status)) {
1924 case SIGTSTP:
1925 (void)printf("*** [%s] Suspended\n",
1926 job->node->name);
1927 break;
1928 case SIGSTOP:
1929 (void)printf("*** [%s] Stopped\n",
1930 job->node->name);
1931 break;
1932 default:
1933 (void)printf("*** [%s] Stopped -- signal %d\n",
1934 job->node->name, WSTOPSIG(status));
1935 }
1936 job->suspended = true;
1937 }
1938 (void)fflush(stdout);
1939 return;
1940 }
1941
1942 job->status = JOB_ST_FINISHED;
1943 job->exit_status = status;
1944 if (WIFEXITED(status))
1945 job->node->exit_status = WEXITSTATUS(status);
1946
1947 JobFinish(job, status);
1948 }
1949
1950 static void
1951 Job_Continue(Job *job)
1952 {
1953 DEBUG1(JOB, "Continuing pid %d\n", job->pid);
1954 if (job->suspended) {
1955 (void)printf("*** [%s] Continued\n", job->node->name);
1956 (void)fflush(stdout);
1957 job->suspended = false;
1958 }
1959 if (KILLPG(job->pid, SIGCONT) != 0)
1960 DEBUG1(JOB, "Failed to send SIGCONT to pid %d\n", job->pid);
1961 }
1962
1963 static void
1964 ContinueJobs(void)
1965 {
1966 Job *job;
1967
1968 for (job = job_table; job < job_table_end; job++) {
1969 if (job->status == JOB_ST_RUNNING &&
1970 (make_suspended || job->suspended))
1971 Job_Continue(job);
1972 else if (job->status == JOB_ST_FINISHED)
1973 JobFinish(job, job->exit_status);
1974 }
1975 make_suspended = false;
1976 }
1977
1978 void
1979 Job_CatchOutput(void)
1980 {
1981 int nready;
1982 Job *job;
1983 unsigned i;
1984
1985 (void)fflush(stdout);
1986
1987 do {
1988 /* Maybe skip the job token pipe. */
1989 nfds_t skip = wantToken ? 0 : 1;
1990 nready = poll(fds + skip, fdsLen - skip, -1);
1991 } while (nready < 0 && errno == EINTR);
1992
1993 if (nready < 0)
1994 Punt("poll: %s", strerror(errno));
1995
1996 if (nready > 0 && childExitJob.inPollfd->revents & POLLIN) {
1997 char token;
1998 ssize_t count = read(childExitJob.inPipe, &token, 1);
1999 if (count != 1)
2000 Punt("childExitJob.read: %s",
2001 count == 0 ? "EOF" : strerror(errno));
2002 if (token == CEJ_RESUME_JOBS)
2003 ContinueJobs();
2004 nready--;
2005 }
2006
2007 Job_CatchChildren();
2008 if (nready == 0)
2009 return;
2010
2011 for (i = npseudojobs * nfds_per_job(); i < fdsLen; i++) {
2012 if (fds[i].revents == 0)
2013 continue;
2014 job = jobByFdIndex[i];
2015 if (job->status == JOB_ST_RUNNING)
2016 CollectOutput(job, false);
2017 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2018 /*
2019 * With meta mode, we may have activity on the job's filemon
2020 * descriptor too, which at the moment is any pollfd other
2021 * than job->inPollfd.
2022 */
2023 if (useMeta && job->inPollfd != &fds[i]) {
2024 if (meta_job_event(job) <= 0)
2025 fds[i].events = 0; /* never mind */
2026 }
2027 #endif
2028 if (--nready == 0)
2029 return;
2030 }
2031 }
2032
2033 static void
2034 InitShellNameAndPath(void)
2035 {
2036 shellName = shell->name;
2037
2038 #ifdef DEFSHELL_CUSTOM
2039 if (shellName[0] == '/') {
2040 shellPath = bmake_strdup(shellName);
2041 shellName = str_basename(shellPath);
2042 return;
2043 }
2044 #endif
2045
2046 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
2047 }
2048
2049 void
2050 Shell_Init(void)
2051 {
2052 if (shellPath == NULL)
2053 InitShellNameAndPath();
2054
2055 Var_SetWithFlags(SCOPE_CMDLINE, ".SHELL", shellPath,
2056 VAR_SET_INTERNAL|VAR_SET_READONLY);
2057 if (shell->errFlag == NULL)
2058 shell->errFlag = "";
2059 if (shell->echoFlag == NULL)
2060 shell->echoFlag = "";
2061 if (shell->hasErrCtl && shell->errFlag[0] != '\0') {
2062 if (shellErrFlag != NULL &&
2063 strcmp(shell->errFlag, &shellErrFlag[1]) != 0) {
2064 free(shellErrFlag);
2065 shellErrFlag = NULL;
2066 }
2067 if (shellErrFlag == NULL)
2068 shellErrFlag = str_concat2("-", shell->errFlag);
2069 } else if (shellErrFlag != NULL) {
2070 free(shellErrFlag);
2071 shellErrFlag = NULL;
2072 }
2073 }
2074
2075 /* Return the shell string literal that results in a newline character. */
2076 const char *
2077 Shell_GetNewline(void)
2078 {
2079 return shell->newline;
2080 }
2081
2082 void
2083 Job_SetPrefix(void)
2084 {
2085 if (targPrefix != NULL)
2086 free(targPrefix);
2087 else if (!Var_Exists(SCOPE_GLOBAL, ".MAKE.JOB.PREFIX"))
2088 Global_Set(".MAKE.JOB.PREFIX", "---");
2089
2090 targPrefix = Var_Subst("${.MAKE.JOB.PREFIX}",
2091 SCOPE_GLOBAL, VARE_EVAL);
2092 /* TODO: handle errors */
2093 }
2094
2095 static void
2096 AddSig(int sig, SignalProc handler)
2097 {
2098 if (bmake_signal(sig, SIG_IGN) != SIG_IGN) {
2099 sigaddset(&caught_signals, sig);
2100 (void)bmake_signal(sig, handler);
2101 }
2102 }
2103
2104 void
2105 Job_Init(void)
2106 {
2107 Job_SetPrefix();
2108
2109 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table);
2110 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table);
2111 job_table_end = job_table + opts.maxJobs;
2112 wantToken = false;
2113 caught_sigchld = 0;
2114
2115 aborting = ABORT_NONE;
2116 job_errors = 0;
2117
2118 /*
2119 * There is a non-zero chance that we already have children,
2120 * e.g. after 'make -f- <<EOF'.
2121 * Since their termination causes a 'Child (pid) not in table'
2122 * message, Collect the status of any that are already dead, and
2123 * suppress the error message if there are any undead ones.
2124 */
2125 for (;;) {
2126 int rval, status;
2127 rval = waitpid((pid_t)-1, &status, WNOHANG);
2128 if (rval > 0)
2129 continue;
2130 if (rval == 0)
2131 lurking_children = true;
2132 break;
2133 }
2134
2135 Shell_Init();
2136
2137 JobCreatePipe(&childExitJob, 3);
2138
2139 {
2140 size_t nfds = (npseudojobs + (size_t)opts.maxJobs) *
2141 nfds_per_job();
2142 fds = bmake_malloc(sizeof *fds * nfds);
2143 jobByFdIndex = bmake_malloc(sizeof *jobByFdIndex * nfds);
2144 }
2145
2146 /* These are permanent entries and take slots 0 and 1 */
2147 watchfd(&tokenPoolJob);
2148 watchfd(&childExitJob);
2149
2150 sigemptyset(&caught_signals);
2151 (void)bmake_signal(SIGCHLD, HandleSIGCHLD);
2152 sigaddset(&caught_signals, SIGCHLD);
2153
2154 /* Handle the signals specified by POSIX. */
2155 AddSig(SIGINT, JobPassSig_int);
2156 AddSig(SIGHUP, JobPassSig_term);
2157 AddSig(SIGTERM, JobPassSig_term);
2158 AddSig(SIGQUIT, JobPassSig_term);
2159
2160 /*
2161 * These signals need to be passed to the jobs, as each job has its
2162 * own process group and thus the terminal driver doesn't forward the
2163 * signals itself.
2164 */
2165 AddSig(SIGTSTP, JobPassSig_suspend);
2166 AddSig(SIGTTOU, JobPassSig_suspend);
2167 AddSig(SIGTTIN, JobPassSig_suspend);
2168 AddSig(SIGWINCH, JobCondPassSig);
2169 AddSig(SIGCONT, HandleSIGCONT);
2170
2171 (void)Job_RunTarget(".BEGIN", NULL);
2172 /* Create the .END node, see Targ_GetEndNode in Compat_MakeAll. */
2173 (void)Targ_GetEndNode();
2174 }
2175
2176 static void
2177 DelSig(int sig)
2178 {
2179 if (sigismember(&caught_signals, sig) != 0)
2180 (void)bmake_signal(sig, SIG_DFL);
2181 }
2182
2183 static void
2184 JobSigReset(void)
2185 {
2186 DelSig(SIGINT);
2187 DelSig(SIGHUP);
2188 DelSig(SIGQUIT);
2189 DelSig(SIGTERM);
2190 DelSig(SIGTSTP);
2191 DelSig(SIGTTOU);
2192 DelSig(SIGTTIN);
2193 DelSig(SIGWINCH);
2194 DelSig(SIGCONT);
2195 (void)bmake_signal(SIGCHLD, SIG_DFL);
2196 }
2197
2198 static Shell *
2199 FindShellByName(const char *name)
2200 {
2201 Shell *sh = shells;
2202 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0];
2203
2204 for (sh = shells; sh < shellsEnd; sh++) {
2205 if (strcmp(name, sh->name) == 0)
2206 return sh;
2207 }
2208 return NULL;
2209 }
2210
2211 /*
2212 * Parse a shell specification and set up 'shell', shellPath and
2213 * shellName appropriately.
2214 *
2215 * Input:
2216 * line The shell spec
2217 *
2218 * Results:
2219 * Returns false if the specification was incorrect.
2220 * If successful, 'shell' is usable, shellPath is the full path of the
2221 * shell described by 'shell', and shellName is the final component of
2222 * shellPath.
2223 *
2224 * Notes:
2225 * A shell specification has the form ".SHELL: keyword=value...". Double
2226 * quotes can be used to enclose blanks in words. A backslash escapes
2227 * anything (most notably a double-quote and a space) and
2228 * provides the usual escape sequences from C. There should be no
2229 * unnecessary spaces in the word. The keywords are:
2230 * name Name of shell.
2231 * path Location of shell.
2232 * quiet Command to turn off echoing.
2233 * echo Command to turn echoing on
2234 * filter The output from the shell command that turns off
2235 * echoing, to be filtered from the final output.
2236 * echoFlag Flag to turn echoing on at the start.
2237 * errFlag Flag to turn error checking on at the start.
2238 * hasErrCtl True if the shell has error checking control.
2239 * newline String literal to represent a newline character.
2240 * check If hasErrCtl is true: The command to turn on error
2241 * checking. If hasErrCtl is false: The template for a
2242 * shell command that echoes a command for which error
2243 * checking is off.
2244 * ignore If hasErrCtl is true: The command to turn off error
2245 * checking. If hasErrCtl is false: The template for a
2246 * shell command that executes a command so as to ignore
2247 * any errors it returns.
2248 */
2249 bool
2250 Job_ParseShell(char *line)
2251 {
2252 Words wordsList;
2253 char **words;
2254 char **argv;
2255 size_t argc;
2256 char *path;
2257 Shell newShell;
2258 bool fullSpec = false;
2259 Shell *sh;
2260
2261 /* XXX: don't use line as an iterator variable */
2262 pp_skip_whitespace(&line);
2263
2264 free(shell_freeIt);
2265
2266 memset(&newShell, 0, sizeof newShell);
2267
2268 wordsList = Str_Words(line, true);
2269 words = wordsList.words;
2270 argc = wordsList.len;
2271 path = wordsList.freeIt;
2272 if (words == NULL) {
2273 Error("Unterminated quoted string [%s]", line);
2274 return false;
2275 }
2276 shell_freeIt = path;
2277
2278 for (path = NULL, argv = words; argc != 0; argc--, argv++) {
2279 char *arg = *argv;
2280 if (strncmp(arg, "path=", 5) == 0) {
2281 path = arg + 5;
2282 } else if (strncmp(arg, "name=", 5) == 0) {
2283 newShell.name = arg + 5;
2284 } else {
2285 if (strncmp(arg, "quiet=", 6) == 0) {
2286 newShell.echoOff = arg + 6;
2287 } else if (strncmp(arg, "echo=", 5) == 0) {
2288 newShell.echoOn = arg + 5;
2289 } else if (strncmp(arg, "filter=", 7) == 0) {
2290 newShell.noPrint = arg + 7;
2291 newShell.noPrintLen = strlen(newShell.noPrint);
2292 } else if (strncmp(arg, "echoFlag=", 9) == 0) {
2293 newShell.echoFlag = arg + 9;
2294 } else if (strncmp(arg, "errFlag=", 8) == 0) {
2295 newShell.errFlag = arg + 8;
2296 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) {
2297 char c = arg[10];
2298 newShell.hasErrCtl = c == 'Y' || c == 'y' ||
2299 c == 'T' || c == 't';
2300 } else if (strncmp(arg, "newline=", 8) == 0) {
2301 newShell.newline = arg + 8;
2302 } else if (strncmp(arg, "check=", 6) == 0) {
2303 /*
2304 * Before 2020-12-10, these two variables had
2305 * been a single variable.
2306 */
2307 newShell.errOn = arg + 6;
2308 newShell.echoTmpl = arg + 6;
2309 } else if (strncmp(arg, "ignore=", 7) == 0) {
2310 /*
2311 * Before 2020-12-10, these two variables had
2312 * been a single variable.
2313 */
2314 newShell.errOff = arg + 7;
2315 newShell.runIgnTmpl = arg + 7;
2316 } else if (strncmp(arg, "errout=", 7) == 0) {
2317 newShell.runChkTmpl = arg + 7;
2318 } else if (strncmp(arg, "comment=", 8) == 0) {
2319 newShell.commentChar = arg[8];
2320 } else {
2321 Parse_Error(PARSE_FATAL,
2322 "Unknown keyword \"%s\"", arg);
2323 free(words);
2324 return false;
2325 }
2326 fullSpec = true;
2327 }
2328 }
2329
2330 if (path == NULL) {
2331 if (newShell.name == NULL) {
2332 Parse_Error(PARSE_FATAL,
2333 "Neither path nor name specified");
2334 free(words);
2335 return false;
2336 } else {
2337 if ((sh = FindShellByName(newShell.name)) == NULL) {
2338 Parse_Error(PARSE_WARNING,
2339 "%s: No matching shell", newShell.name);
2340 free(words);
2341 return false;
2342 }
2343 shell = sh;
2344 shellName = newShell.name;
2345 if (shellPath != NULL) {
2346 free(shellPath);
2347 shellPath = NULL;
2348 Shell_Init();
2349 }
2350 }
2351 } else {
2352 free(shellPath);
2353 shellPath = bmake_strdup(path);
2354 shellName = newShell.name != NULL ? newShell.name
2355 : str_basename(path);
2356 if (!fullSpec) {
2357 if ((sh = FindShellByName(shellName)) == NULL) {
2358 Parse_Error(PARSE_WARNING,
2359 "%s: No matching shell", shellName);
2360 free(words);
2361 return false;
2362 }
2363 shell = sh;
2364 } else {
2365 shell = bmake_malloc(sizeof *shell);
2366 *shell = newShell;
2367 }
2368 /* This will take care of shellErrFlag. */
2369 Shell_Init();
2370 }
2371
2372 if (shell->echoOn != NULL && shell->echoOff != NULL)
2373 shell->hasEchoCtl = true;
2374
2375 if (!shell->hasErrCtl) {
2376 if (shell->echoTmpl == NULL)
2377 shell->echoTmpl = "";
2378 if (shell->runIgnTmpl == NULL)
2379 shell->runIgnTmpl = "%s\n";
2380 }
2381
2382 /*
2383 * Do not free up the words themselves, since they may be in use
2384 * by the shell specification.
2385 */
2386 free(words);
2387 return true;
2388 }
2389
2390 /*
2391 * After receiving an interrupt signal, terminate all child processes and if
2392 * necessary make the .INTERRUPT target.
2393 */
2394 static void
2395 JobInterrupt(bool runINTERRUPT, int signo)
2396 {
2397 Job *job;
2398 sigset_t mask;
2399
2400 aborting = ABORT_INTERRUPT;
2401
2402 JobsTable_Lock(&mask);
2403
2404 for (job = job_table; job < job_table_end; job++) {
2405 if (job->status == JOB_ST_RUNNING && job->pid != 0) {
2406 DEBUG2(JOB,
2407 "JobInterrupt passing signal %d to child %d.\n",
2408 signo, job->pid);
2409 KILLPG(job->pid, signo);
2410 }
2411 }
2412
2413 for (job = job_table; job < job_table_end; job++) {
2414 if (job->status == JOB_ST_RUNNING && job->pid != 0) {
2415 int status;
2416 (void)waitpid(job->pid, &status, 0);
2417 JobDeleteTarget(job->node);
2418 }
2419 }
2420
2421 JobsTable_Unlock(&mask);
2422
2423 if (runINTERRUPT && !opts.touch) {
2424 GNode *dotInterrupt = Targ_FindNode(".INTERRUPT");
2425 if (dotInterrupt != NULL) {
2426 opts.ignoreErrors = false;
2427 JobRun(dotInterrupt);
2428 }
2429 }
2430 Trace_Log(MAKEINTR, NULL);
2431 exit(signo); /* XXX: why signo? */
2432 }
2433
2434 /* Make the .END target, returning the number of job-related errors. */
2435 int
2436 Job_MakeDotEnd(void)
2437 {
2438 GNode *dotEnd = Targ_GetEndNode();
2439 if (!Lst_IsEmpty(&dotEnd->commands) ||
2440 !Lst_IsEmpty(&dotEnd->children)) {
2441 if (job_errors != 0)
2442 Error("Errors reported so .END ignored");
2443 else
2444 JobRun(dotEnd);
2445 }
2446 return job_errors;
2447 }
2448
2449 #ifdef CLEANUP
2450 void
2451 Job_End(void)
2452 {
2453 free(shell_freeIt);
2454 }
2455 #endif
2456
2457 /* Waits for all running jobs to finish. */
2458 void
2459 Job_Wait(void)
2460 {
2461 aborting = ABORT_WAIT; /* Prevent other jobs from starting. */
2462 while (jobTokensRunning != 0)
2463 Job_CatchOutput();
2464 aborting = ABORT_NONE;
2465 }
2466
2467 /*
2468 * Abort all currently running jobs without handling output or anything.
2469 * This function is to be called only in the event of a major error.
2470 * Most definitely NOT to be called from JobInterrupt.
2471 */
2472 void
2473 Job_AbortAll(void)
2474 {
2475 Job *job;
2476 int status;
2477
2478 aborting = ABORT_ERROR;
2479
2480 if (jobTokensRunning != 0) {
2481 for (job = job_table; job < job_table_end; job++) {
2482 if (job->status != JOB_ST_RUNNING)
2483 continue;
2484 KILLPG(job->pid, SIGINT);
2485 KILLPG(job->pid, SIGKILL);
2486 }
2487 }
2488
2489 while (waitpid((pid_t)-1, &status, WNOHANG) > 0)
2490 continue;
2491 }
2492
2493 static void
2494 watchfd(Job *job)
2495 {
2496 if (job->inPollfd != NULL)
2497 Punt("Watching watched job");
2498
2499 fds[fdsLen].fd = job->inPipe;
2500 fds[fdsLen].events = POLLIN;
2501 jobByFdIndex[fdsLen] = job;
2502 job->inPollfd = &fds[fdsLen];
2503 fdsLen++;
2504 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2505 if (useMeta) {
2506 fds[fdsLen].fd = meta_job_fd(job);
2507 fds[fdsLen].events = fds[fdsLen].fd == -1 ? 0 : POLLIN;
2508 jobByFdIndex[fdsLen] = job;
2509 fdsLen++;
2510 }
2511 #endif
2512 }
2513
2514 static void
2515 clearfd(Job *job)
2516 {
2517 size_t i;
2518 if (job->inPollfd == NULL)
2519 Punt("Unwatching unwatched job");
2520 i = (size_t)(job->inPollfd - fds);
2521 fdsLen--;
2522 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2523 if (useMeta) {
2524 assert(nfds_per_job() == 2);
2525 if (i % 2 != 0)
2526 Punt("odd-numbered fd with meta");
2527 fdsLen--;
2528 }
2529 #endif
2530 /* Move last job in table into hole made by dead job. */
2531 if (fdsLen != i) {
2532 fds[i] = fds[fdsLen];
2533 jobByFdIndex[i] = jobByFdIndex[fdsLen];
2534 jobByFdIndex[i]->inPollfd = &fds[i];
2535 #if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2536 if (useMeta) {
2537 fds[i + 1] = fds[fdsLen + 1];
2538 jobByFdIndex[i + 1] = jobByFdIndex[fdsLen + 1];
2539 }
2540 #endif
2541 }
2542 job->inPollfd = NULL;
2543 }
2544
2545 int
2546 Job_TempFile(const char *pattern, char *tfile, size_t tfile_sz)
2547 {
2548 int fd;
2549 sigset_t mask;
2550
2551 JobsTable_Lock(&mask);
2552 fd = mkTempFile(pattern, tfile, tfile_sz);
2553 if (tfile != NULL && !DEBUG(SCRIPT))
2554 unlink(tfile);
2555 JobsTable_Unlock(&mask);
2556
2557 return fd;
2558 }
2559
2560 static void
2561 TokenPool_Write(char tok)
2562 {
2563 if (write(tokenPoolJob.outPipe, &tok, 1) != 1)
2564 Punt("Cannot write \"%c\" to the token pool: %s",
2565 tok, strerror(errno));
2566 }
2567
2568 /*
2569 * Put a token (back) into the job token pool.
2570 * This allows a make process to start a build job.
2571 */
2572 static void
2573 TokenPool_Add(void)
2574 {
2575 char tok = JOB_TOKENS[aborting], tok1;
2576
2577 /* If we are depositing an error token, flush everything else. */
2578 while (tok != '+' && read(tokenPoolJob.inPipe, &tok1, 1) == 1)
2579 continue;
2580
2581 DEBUG3(JOB, "TokenPool_Add: pid %d, aborting %s, token %c\n",
2582 getpid(), aborting_name[aborting], tok);
2583 TokenPool_Write(tok);
2584 }
2585
2586 static void
2587 TokenPool_InitClient(int tokenPoolReader, int tokenPoolWriter)
2588 {
2589 tokenPoolJob.inPipe = tokenPoolReader;
2590 tokenPoolJob.outPipe = tokenPoolWriter;
2591 (void)fcntl(tokenPoolReader, F_SETFD, FD_CLOEXEC);
2592 (void)fcntl(tokenPoolWriter, F_SETFD, FD_CLOEXEC);
2593 }
2594
2595 /* Prepare the job token pipe in the root make process. */
2596 static void
2597 TokenPool_InitServer(int maxJobTokens)
2598 {
2599 int i;
2600 char jobarg[64];
2601
2602 JobCreatePipe(&tokenPoolJob, 15);
2603
2604 snprintf(jobarg, sizeof jobarg, "%d,%d",
2605 tokenPoolJob.inPipe, tokenPoolJob.outPipe);
2606
2607 Global_Append(MAKEFLAGS, "-J");
2608 Global_Append(MAKEFLAGS, jobarg);
2609
2610 /*
2611 * Preload the job pipe with one token per job, save the one
2612 * "extra" token for the primary job.
2613 */
2614 SetNonblocking(tokenPoolJob.outPipe);
2615 for (i = 1; i < maxJobTokens; i++)
2616 TokenPool_Add();
2617 }
2618
2619 void
2620 TokenPool_Init(int maxJobTokens, int tokenPoolReader, int tokenPoolWriter)
2621 {
2622 if (tokenPoolReader >= 0 && tokenPoolWriter >= 0)
2623 TokenPool_InitClient(tokenPoolReader, tokenPoolWriter);
2624 else
2625 TokenPool_InitServer(maxJobTokens);
2626 }
2627
2628 /* Return a taken token to the pool. */
2629 void
2630 TokenPool_Return(void)
2631 {
2632 jobTokensRunning--;
2633 if (jobTokensRunning < 0)
2634 Punt("token botch");
2635 if (jobTokensRunning != 0 || JOB_TOKENS[aborting] != '+')
2636 TokenPool_Add();
2637 }
2638
2639 /*
2640 * Attempt to take a token from the pool.
2641 *
2642 * If the pool is empty, set wantToken so that we wake up when a token is
2643 * released.
2644 *
2645 * Returns true if a token was taken, and false if the pool is currently
2646 * empty.
2647 */
2648 bool
2649 TokenPool_Take(void)
2650 {
2651 char tok, tok1;
2652 ssize_t count;
2653
2654 wantToken = false;
2655 DEBUG3(JOB, "TokenPool_Take: pid %d, aborting %s, running %d\n",
2656 getpid(), aborting_name[aborting], jobTokensRunning);
2657
2658 if (aborting != ABORT_NONE || jobTokensRunning >= opts.maxJobs)
2659 return false;
2660
2661 count = read(tokenPoolJob.inPipe, &tok, 1);
2662 if (count == 0)
2663 Fatal("eof on job pipe");
2664 if (count < 0 && jobTokensRunning != 0) {
2665 if (errno != EAGAIN)
2666 Fatal("job pipe read: %s", strerror(errno));
2667 DEBUG1(JOB, "TokenPool_Take: pid %d blocked for token\n",
2668 getpid());
2669 wantToken = true;
2670 return false;
2671 }
2672
2673 if (count == 1 && tok != '+') {
2674 /* make being aborted - remove any other job tokens */
2675 DEBUG2(JOB, "TokenPool_Take: pid %d aborted by token %c\n",
2676 getpid(), tok);
2677 while (read(tokenPoolJob.inPipe, &tok1, 1) == 1)
2678 continue;
2679 /* And put the stopper back */
2680 TokenPool_Write(tok);
2681 if (shouldDieQuietly(NULL, 1)) {
2682 Job_Wait();
2683 exit(6);
2684 }
2685 Fatal("A failure has been detected "
2686 "in another branch of the parallel make");
2687 }
2688
2689 if (count == 1 && jobTokensRunning == 0)
2690 /* We didn't want the token really */
2691 TokenPool_Write(tok);
2692
2693 jobTokensRunning++;
2694 DEBUG1(JOB, "TokenPool_Take: pid %d took a token\n", getpid());
2695 return true;
2696 }
2697
2698 /* Make the named target if found, exit if the target fails. */
2699 bool
2700 Job_RunTarget(const char *target, const char *fname)
2701 {
2702 GNode *gn = Targ_FindNode(target);
2703 if (gn == NULL)
2704 return false;
2705
2706 if (fname != NULL)
2707 Var_Set(gn, ALLSRC, fname);
2708
2709 JobRun(gn);
2710 return true;
2711 }
2712
2713 #ifdef USE_SELECT
2714 int
2715 emul_poll(struct pollfd *fd, int nfd, int timeout)
2716 {
2717 fd_set rfds, wfds;
2718 int i, maxfd, nselect, npoll;
2719 struct timeval tv, *tvp;
2720 long usecs;
2721
2722 FD_ZERO(&rfds);
2723 FD_ZERO(&wfds);
2724
2725 maxfd = -1;
2726 for (i = 0; i < nfd; i++) {
2727 fd[i].revents = 0;
2728
2729 if (fd[i].events & POLLIN)
2730 FD_SET(fd[i].fd, &rfds);
2731
2732 if (fd[i].events & POLLOUT)
2733 FD_SET(fd[i].fd, &wfds);
2734
2735 if (fd[i].fd > maxfd)
2736 maxfd = fd[i].fd;
2737 }
2738
2739 if (maxfd >= FD_SETSIZE) {
2740 Punt("Ran out of fd_set slots; "
2741 "recompile with a larger FD_SETSIZE.");
2742 }
2743
2744 if (timeout < 0) {
2745 tvp = NULL;
2746 } else {
2747 usecs = timeout * 1000;
2748 tv.tv_sec = usecs / 1000000;
2749 tv.tv_usec = usecs % 1000000;
2750 tvp = &tv;
2751 }
2752
2753 nselect = select(maxfd + 1, &rfds, &wfds, NULL, tvp);
2754
2755 if (nselect <= 0)
2756 return nselect;
2757
2758 npoll = 0;
2759 for (i = 0; i < nfd; i++) {
2760 if (FD_ISSET(fd[i].fd, &rfds))
2761 fd[i].revents |= POLLIN;
2762
2763 if (FD_ISSET(fd[i].fd, &wfds))
2764 fd[i].revents |= POLLOUT;
2765
2766 if (fd[i].revents)
2767 npoll++;
2768 }
2769
2770 return npoll;
2771 }
2772 #endif /* USE_SELECT */
2773