Mon Oct 26 22:51:56 2020 UTC ()
make(1): remove unnecessary double negation in Job_ParseShell


(rillig)
diff -r1.290 -r1.291 src/usr.bin/make/job.c

cvs diff -r1.290 -r1.291 src/usr.bin/make/job.c (switch to unified diff)

--- src/usr.bin/make/job.c 2020/10/26 21:34:10 1.290
+++ src/usr.bin/make/job.c 2020/10/26 22:51:56 1.291
@@ -1,1145 +1,1145 @@ @@ -1,1145 +1,1145 @@
1/* $NetBSD: job.c,v 1.290 2020/10/26 21:34:10 rillig Exp $ */ 1/* $NetBSD: job.c,v 1.291 2020/10/26 22:51:56 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 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 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1988, 1989 by Adam de Boor 36 * Copyright (c) 1988, 1989 by Adam de Boor
37 * Copyright (c) 1989 by Berkeley Softworks 37 * Copyright (c) 1989 by Berkeley Softworks
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * This code is derived from software contributed to Berkeley by 40 * This code is derived from software contributed to Berkeley by
41 * Adam de Boor. 41 * Adam de Boor.
42 * 42 *
43 * Redistribution and use in source and binary forms, with or without 43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions 44 * modification, are permitted provided that the following conditions
45 * are met: 45 * are met:
46 * 1. Redistributions of source code must retain the above copyright 46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer. 47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright 48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the 49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution. 50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software 51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement: 52 * must display the following acknowledgement:
53 * This product includes software developed by the University of 53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors. 54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of 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 56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission. 57 * without specific prior written permission.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 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 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 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 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 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 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
70 */ 70 */
71 71
72/*- 72/*-
73 * job.c -- 73 * job.c --
74 * handle the creation etc. of our child processes. 74 * handle the creation etc. of our child processes.
75 * 75 *
76 * Interface: 76 * Interface:
77 * Job_Init Called to initialize this module. In addition, 77 * Job_Init Called to initialize this module. In addition,
78 * any commands attached to the .BEGIN target 78 * any commands attached to the .BEGIN target
79 * are executed before this function returns. 79 * are executed before this function returns.
80 * Hence, the makefiles must have been parsed 80 * Hence, the makefiles must have been parsed
81 * before this function is called. 81 * before this function is called.
82 * 82 *
83 * Job_End Clean up any memory used. 83 * Job_End Clean up any memory used.
84 * 84 *
85 * Job_Make Start the creation of the given target. 85 * Job_Make Start the creation of the given target.
86 * 86 *
87 * Job_CatchChildren 87 * Job_CatchChildren
88 * Check for and handle the termination of any 88 * Check for and handle the termination of any
89 * children. This must be called reasonably 89 * children. This must be called reasonably
90 * frequently to keep the whole make going at 90 * frequently to keep the whole make going at
91 * a decent clip, since job table entries aren't 91 * a decent clip, since job table entries aren't
92 * removed until their process is caught this way. 92 * removed until their process is caught this way.
93 * 93 *
94 * Job_CatchOutput 94 * Job_CatchOutput
95 * Print any output our children have produced. 95 * Print any output our children have produced.
96 * Should also be called fairly frequently to 96 * Should also be called fairly frequently to
97 * keep the user informed of what's going on. 97 * keep the user informed of what's going on.
98 * If no output is waiting, it will block for 98 * If no output is waiting, it will block for
99 * a time given by the SEL_* constants, below, 99 * a time given by the SEL_* constants, below,
100 * or until output is ready. 100 * or until output is ready.
101 * 101 *
102 * Job_ParseShell Given the line following a .SHELL target, parse 102 * Job_ParseShell Given the line following a .SHELL target, parse
103 * the line as a shell specification. Returns 103 * the line as a shell specification. Returns
104 * FALSE if the spec was incorrect. 104 * FALSE if the spec was incorrect.
105 * 105 *
106 * Job_Finish Perform any final processing which needs doing. 106 * Job_Finish Perform any final processing which needs doing.
107 * This includes the execution of any commands 107 * This includes the execution of any commands
108 * which have been/were attached to the .END 108 * which have been/were attached to the .END
109 * target. It should only be called when the 109 * target. It should only be called when the
110 * job table is empty. 110 * job table is empty.
111 * 111 *
112 * Job_AbortAll Abort all currently running jobs. It doesn't 112 * Job_AbortAll Abort all currently running jobs. It doesn't
113 * handle output or do anything for the jobs, 113 * handle output or do anything for the jobs,
114 * just kills them. It should only be called in 114 * just kills them. It should only be called in
115 * an emergency. 115 * an emergency.
116 * 116 *
117 * Job_CheckCommands 117 * Job_CheckCommands
118 * Verify that the commands for a target are 118 * Verify that the commands for a target are
119 * ok. Provide them if necessary and possible. 119 * ok. Provide them if necessary and possible.
120 * 120 *
121 * Job_Touch Update a target without really updating it. 121 * Job_Touch Update a target without really updating it.
122 * 122 *
123 * Job_Wait Wait for all currently-running jobs to finish. 123 * Job_Wait Wait for all currently-running jobs to finish.
124 */ 124 */
125 125
126#include <sys/types.h> 126#include <sys/types.h>
127#include <sys/stat.h> 127#include <sys/stat.h>
128#include <sys/file.h> 128#include <sys/file.h>
129#include <sys/time.h> 129#include <sys/time.h>
130#include <sys/wait.h> 130#include <sys/wait.h>
131 131
132#include <errno.h> 132#include <errno.h>
133#ifndef USE_SELECT 133#ifndef USE_SELECT
134#include <poll.h> 134#include <poll.h>
135#endif 135#endif
136#include <signal.h> 136#include <signal.h>
137#include <utime.h> 137#include <utime.h>
138 138
139#include "make.h" 139#include "make.h"
140#include "dir.h" 140#include "dir.h"
141#include "job.h" 141#include "job.h"
142#include "pathnames.h" 142#include "pathnames.h"
143#include "trace.h" 143#include "trace.h"
144 144
145/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */ 145/* "@(#)job.c 8.2 (Berkeley) 3/19/94" */
146MAKE_RCSID("$NetBSD: job.c,v 1.290 2020/10/26 21:34:10 rillig Exp $"); 146MAKE_RCSID("$NetBSD: job.c,v 1.291 2020/10/26 22:51:56 rillig Exp $");
147 147
148/* A shell defines how the commands are run. All commands for a target are 148/* A shell defines how the commands are run. All commands for a target are
149 * written into a single file, which is then given to the shell to execute 149 * written into a single file, which is then given to the shell to execute
150 * the commands from it. The commands are written to the file using a few 150 * the commands from it. The commands are written to the file using a few
151 * templates for echo control and error control. 151 * templates for echo control and error control.
152 * 152 *
153 * The name of the shell is the basename for the predefined shells, such as 153 * The name of the shell is the basename for the predefined shells, such as
154 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its 154 * "sh", "csh", "bash". For custom shells, it is the full pathname, and its
155 * basename is used to select the type of shell; the longest match wins. 155 * basename is used to select the type of shell; the longest match wins.
156 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh. 156 * So /usr/pkg/bin/bash has type sh, /usr/local/bin/tcsh has type csh.
157 * 157 *
158 * The echoing of command lines is controlled using hasEchoCtl, echoOff, 158 * The echoing of command lines is controlled using hasEchoCtl, echoOff,
159 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it 159 * echoOn, noPrint and noPrintLen. When echoOff is executed by the shell, it
160 * still outputs something, but this something is not interesting, therefore 160 * still outputs something, but this something is not interesting, therefore
161 * it is filtered out using noPrint and noPrintLen. 161 * it is filtered out using noPrint and noPrintLen.
162 * 162 *
163 * The error checking for individual commands is controlled using hasErrCtl, 163 * The error checking for individual commands is controlled using hasErrCtl,
164 * errOnOrEcho, errOffOrExecIgnore and errExit. 164 * errOnOrEcho, errOffOrExecIgnore and errExit.
165 * 165 *
166 * If a shell doesn't have error control, errOnOrEcho becomes a printf template 166 * If a shell doesn't have error control, errOnOrEcho becomes a printf template
167 * for echoing the command, should echoing be on; errOffOrExecIgnore becomes 167 * for echoing the command, should echoing be on; errOffOrExecIgnore becomes
168 * another printf template for executing the command while ignoring the return 168 * another printf template for executing the command while ignoring the return
169 * status. Finally errExit is a printf template for running the command and 169 * status. Finally errExit is a printf template for running the command and
170 * causing the shell to exit on error. If any of these strings are empty when 170 * causing the shell to exit on error. If any of these strings are empty when
171 * hasErrCtl is FALSE, the command will be executed anyway as is, and if it 171 * hasErrCtl is FALSE, the command will be executed anyway as is, and if it
172 * causes an error, so be it. Any templates setup to echo the command will 172 * causes an error, so be it. Any templates setup to echo the command will
173 * escape any '$ ` \ "' characters in the command string to avoid common 173 * escape any '$ ` \ "' characters in the command string to avoid common
174 * problems with echo "%s\n" as a template. 174 * problems with echo "%s\n" as a template.
175 * 175 *
176 * The command-line flags "echo" and "exit" also control the behavior. The 176 * The command-line flags "echo" and "exit" also control the behavior. The
177 * "echo" flag causes the shell to start echoing commands right away. The 177 * "echo" flag causes the shell to start echoing commands right away. The
178 * "exit" flag causes the shell to exit when an error is detected in one of 178 * "exit" flag causes the shell to exit when an error is detected in one of
179 * the commands. 179 * the commands.
180 */ 180 */
181typedef struct Shell { 181typedef struct Shell {
182 182
183 /* The name of the shell. For Bourne and C shells, this is used only to 183 /* The name of the shell. For Bourne and C shells, this is used only to
184 * find the shell description when used as the single source of a .SHELL 184 * find the shell description when used as the single source of a .SHELL
185 * target. For user-defined shells, this is the full path of the shell. */ 185 * target. For user-defined shells, this is the full path of the shell. */
186 const char *name; 186 const char *name;
187 187
188 Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */ 188 Boolean hasEchoCtl; /* True if both echoOff and echoOn defined */
189 const char *echoOff; /* command to turn off echo */ 189 const char *echoOff; /* command to turn off echo */
190 const char *echoOn; /* command to turn it back on again */ 190 const char *echoOn; /* command to turn it back on again */
191 const char *noPrint; /* text to skip when printing output from 191 const char *noPrint; /* text to skip when printing output from
192 * shell. This is usually the same as echoOff */ 192 * shell. This is usually the same as echoOff */
193 size_t noPrintLen; /* length of noPrint command */ 193 size_t noPrintLen; /* length of noPrint command */
194 194
195 Boolean hasErrCtl; /* set if can control error checking for 195 Boolean hasErrCtl; /* set if can control error checking for
196 * individual commands */ 196 * individual commands */
197 /* XXX: split into errOn and echoCmd */ 197 /* XXX: split into errOn and echoCmd */
198 const char *errOnOrEcho; /* template to turn on error checking */ 198 const char *errOnOrEcho; /* template to turn on error checking */
199 /* XXX: split into errOff and execIgnore */ 199 /* XXX: split into errOff and execIgnore */
200 const char *errOffOrExecIgnore; /* template to turn off error checking */ 200 const char *errOffOrExecIgnore; /* template to turn off error checking */
201 const char *errExit; /* template to use for testing exit code */ 201 const char *errExit; /* template to use for testing exit code */
202 202
203 /* string literal that results in a newline character when it appears 203 /* string literal that results in a newline character when it appears
204 * outside of any 'quote' or "quote" characters */ 204 * outside of any 'quote' or "quote" characters */
205 const char *newline; 205 const char *newline;
206 char commentChar; /* character used by shell for comment lines */ 206 char commentChar; /* character used by shell for comment lines */
207 207
208 /* 208 /*
209 * command-line flags 209 * command-line flags
210 */ 210 */
211 const char *echo; /* echo commands */ 211 const char *echo; /* echo commands */
212 const char *exit; /* exit on error */ 212 const char *exit; /* exit on error */
213} Shell; 213} Shell;
214 214
215/* 215/*
216 * error handling variables 216 * error handling variables
217 */ 217 */
218static int errors = 0; /* number of errors reported */ 218static int errors = 0; /* number of errors reported */
219typedef enum AbortReason { /* why is the make aborting? */ 219typedef enum AbortReason { /* why is the make aborting? */
220 ABORT_NONE, 220 ABORT_NONE,
221 ABORT_ERROR, /* Because of an error */ 221 ABORT_ERROR, /* Because of an error */
222 ABORT_INTERRUPT, /* Because it was interrupted */ 222 ABORT_INTERRUPT, /* Because it was interrupted */
223 ABORT_WAIT /* Waiting for jobs to finish */ 223 ABORT_WAIT /* Waiting for jobs to finish */
224} AbortReason; 224} AbortReason;
225static AbortReason aborting = ABORT_NONE; 225static AbortReason aborting = ABORT_NONE;
226#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */ 226#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
227 227
228/* 228/*
229 * this tracks the number of tokens currently "out" to build jobs. 229 * this tracks the number of tokens currently "out" to build jobs.
230 */ 230 */
231int jobTokensRunning = 0; 231int jobTokensRunning = 0;
232 232
233/* The number of commands actually printed to the shell commands file for 233/* The number of commands actually printed to the shell commands file for
234 * the current job. Should this number be 0, no shell will be executed. */ 234 * the current job. Should this number be 0, no shell will be executed. */
235static int numCommands; 235static int numCommands;
236 236
237typedef enum JobStartResult { 237typedef enum JobStartResult {
238 JOB_RUNNING, /* Job is running */ 238 JOB_RUNNING, /* Job is running */
239 JOB_ERROR, /* Error in starting the job */ 239 JOB_ERROR, /* Error in starting the job */
240 JOB_FINISHED /* The job is already finished */ 240 JOB_FINISHED /* The job is already finished */
241} JobStartResult; 241} JobStartResult;
242 242
243/* 243/*
244 * Descriptions for various shells. 244 * Descriptions for various shells.
245 * 245 *
246 * The build environment may set DEFSHELL_INDEX to one of 246 * The build environment may set DEFSHELL_INDEX to one of
247 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to 247 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
248 * select one of the predefined shells as the default shell. 248 * select one of the predefined shells as the default shell.
249 * 249 *
250 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the 250 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
251 * name or the full path of a sh-compatible shell, which will be used as 251 * name or the full path of a sh-compatible shell, which will be used as
252 * the default shell. 252 * the default shell.
253 * 253 *
254 * ".SHELL" lines in Makefiles can choose the default shell from the 254 * ".SHELL" lines in Makefiles can choose the default shell from the
255 * set defined here, or add additional shells. 255 * set defined here, or add additional shells.
256 */ 256 */
257 257
258#ifdef DEFSHELL_CUSTOM 258#ifdef DEFSHELL_CUSTOM
259#define DEFSHELL_INDEX_CUSTOM 0 259#define DEFSHELL_INDEX_CUSTOM 0
260#define DEFSHELL_INDEX_SH 1 260#define DEFSHELL_INDEX_SH 1
261#define DEFSHELL_INDEX_KSH 2 261#define DEFSHELL_INDEX_KSH 2
262#define DEFSHELL_INDEX_CSH 3 262#define DEFSHELL_INDEX_CSH 3
263#else /* !DEFSHELL_CUSTOM */ 263#else /* !DEFSHELL_CUSTOM */
264#define DEFSHELL_INDEX_SH 0 264#define DEFSHELL_INDEX_SH 0
265#define DEFSHELL_INDEX_KSH 1 265#define DEFSHELL_INDEX_KSH 1
266#define DEFSHELL_INDEX_CSH 2 266#define DEFSHELL_INDEX_CSH 2
267#endif /* !DEFSHELL_CUSTOM */ 267#endif /* !DEFSHELL_CUSTOM */
268 268
269#ifndef DEFSHELL_INDEX 269#ifndef DEFSHELL_INDEX
270#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */ 270#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
271#endif /* !DEFSHELL_INDEX */ 271#endif /* !DEFSHELL_INDEX */
272 272
273static Shell shells[] = { 273static Shell shells[] = {
274#ifdef DEFSHELL_CUSTOM 274#ifdef DEFSHELL_CUSTOM
275 /* 275 /*
276 * An sh-compatible shell with a non-standard name. 276 * An sh-compatible shell with a non-standard name.
277 * 277 *
278 * Keep this in sync with the "sh" description below, but avoid 278 * Keep this in sync with the "sh" description below, but avoid
279 * non-portable features that might not be supplied by all 279 * non-portable features that might not be supplied by all
280 * sh-compatible shells. 280 * sh-compatible shells.
281 */ 281 */
282{ 282{
283 DEFSHELL_CUSTOM, /* .name */ 283 DEFSHELL_CUSTOM, /* .name */
284 FALSE, /* .hasEchoCtl */ 284 FALSE, /* .hasEchoCtl */
285 "", /* .echoOff */ 285 "", /* .echoOff */
286 "", /* .echoOn */ 286 "", /* .echoOn */
287 "", /* .noPrint */ 287 "", /* .noPrint */
288 0, /* .noPrintLen */ 288 0, /* .noPrintLen */
289 FALSE, /* .hasErrCtl */ 289 FALSE, /* .hasErrCtl */
290 "echo \"%s\"\n", /* .errOnOrEcho */ 290 "echo \"%s\"\n", /* .errOnOrEcho */
291 "%s\n", /* .errOffOrExecIgnore */ 291 "%s\n", /* .errOffOrExecIgnore */
292 "{ %s \n} || exit $?\n", /* .errExit */ 292 "{ %s \n} || exit $?\n", /* .errExit */
293 "'\n'", /* .newline */ 293 "'\n'", /* .newline */
294 '#', /* .commentChar */ 294 '#', /* .commentChar */
295 "", /* .echo */ 295 "", /* .echo */
296 "", /* .exit */ 296 "", /* .exit */
297}, 297},
298#endif /* DEFSHELL_CUSTOM */ 298#endif /* DEFSHELL_CUSTOM */
299 /* 299 /*
300 * SH description. Echo control is also possible and, under 300 * SH description. Echo control is also possible and, under
301 * sun UNIX anyway, one can even control error checking. 301 * sun UNIX anyway, one can even control error checking.
302 */ 302 */
303{ 303{
304 "sh", /* .name */ 304 "sh", /* .name */
305 FALSE, /* .hasEchoCtl */ 305 FALSE, /* .hasEchoCtl */
306 "", /* .echoOff */ 306 "", /* .echoOff */
307 "", /* .echoOn */ 307 "", /* .echoOn */
308 "", /* .noPrint */ 308 "", /* .noPrint */
309 0, /* .noPrintLen */ 309 0, /* .noPrintLen */
310 FALSE, /* .hasErrCtl */ 310 FALSE, /* .hasErrCtl */
311 "echo \"%s\"\n", /* .errOnOrEcho */ 311 "echo \"%s\"\n", /* .errOnOrEcho */
312 "%s\n", /* .errOffOrExecIgnore */ 312 "%s\n", /* .errOffOrExecIgnore */
313 "{ %s \n} || exit $?\n", /* .errExit */ 313 "{ %s \n} || exit $?\n", /* .errExit */
314 "'\n'", /* .newline */ 314 "'\n'", /* .newline */
315 '#', /* .commentChar*/ 315 '#', /* .commentChar*/
316#if defined(MAKE_NATIVE) && defined(__NetBSD__) 316#if defined(MAKE_NATIVE) && defined(__NetBSD__)
317 "q", /* .echo */ 317 "q", /* .echo */
318#else 318#else
319 "", /* .echo */ 319 "", /* .echo */
320#endif 320#endif
321 "", /* .exit */ 321 "", /* .exit */
322}, 322},
323 /* 323 /*
324 * KSH description. 324 * KSH description.
325 */ 325 */
326{ 326{
327 "ksh", /* .name */ 327 "ksh", /* .name */
328 TRUE, /* .hasEchoCtl */ 328 TRUE, /* .hasEchoCtl */
329 "set +v", /* .echoOff */ 329 "set +v", /* .echoOff */
330 "set -v", /* .echoOn */ 330 "set -v", /* .echoOn */
331 "set +v", /* .noPrint */ 331 "set +v", /* .noPrint */
332 6, /* .noPrintLen */ 332 6, /* .noPrintLen */
333 FALSE, /* .hasErrCtl */ 333 FALSE, /* .hasErrCtl */
334 "echo \"%s\"\n", /* .errOnOrEcho */ 334 "echo \"%s\"\n", /* .errOnOrEcho */
335 "%s\n", /* .errOffOrExecIgnore */ 335 "%s\n", /* .errOffOrExecIgnore */
336 "{ %s \n} || exit $?\n", /* .errExit */ 336 "{ %s \n} || exit $?\n", /* .errExit */
337 "'\n'", /* .newline */ 337 "'\n'", /* .newline */
338 '#', /* .commentChar */ 338 '#', /* .commentChar */
339 "v", /* .echo */ 339 "v", /* .echo */
340 "", /* .exit */ 340 "", /* .exit */
341}, 341},
342 /* 342 /*
343 * CSH description. The csh can do echo control by playing 343 * CSH description. The csh can do echo control by playing
344 * with the setting of the 'echo' shell variable. Sadly, 344 * with the setting of the 'echo' shell variable. Sadly,
345 * however, it is unable to do error control nicely. 345 * however, it is unable to do error control nicely.
346 */ 346 */
347{ 347{
348 "csh", /* .name */ 348 "csh", /* .name */
349 TRUE, /* .hasEchoCtl */ 349 TRUE, /* .hasEchoCtl */
350 "unset verbose", /* .echoOff */ 350 "unset verbose", /* .echoOff */
351 "set verbose", /* .echoOn */ 351 "set verbose", /* .echoOn */
352 "unset verbose", /* .noPrint */ 352 "unset verbose", /* .noPrint */
353 13, /* .noPrintLen */ 353 13, /* .noPrintLen */
354 FALSE, /* .hasErrCtl */ 354 FALSE, /* .hasErrCtl */
355 "echo \"%s\"\n", /* .errOnOrEcho */ 355 "echo \"%s\"\n", /* .errOnOrEcho */
356 /* XXX: Mismatch between errOn and execIgnore */ 356 /* XXX: Mismatch between errOn and execIgnore */
357 "csh -c \"%s || exit 0\"\n", /* .errOffOrExecIgnore */ 357 "csh -c \"%s || exit 0\"\n", /* .errOffOrExecIgnore */
358 "", /* .errExit */ 358 "", /* .errExit */
359 "'\\\n'", /* .newline */ 359 "'\\\n'", /* .newline */
360 '#', /* .commentChar */ 360 '#', /* .commentChar */
361 "v", /* .echo */ 361 "v", /* .echo */
362 "e", /* .exit */ 362 "e", /* .exit */
363} 363}
364}; 364};
365 365
366/* This is the shell to which we pass all commands in the Makefile. 366/* This is the shell to which we pass all commands in the Makefile.
367 * It is set by the Job_ParseShell function. */ 367 * It is set by the Job_ParseShell function. */
368static Shell *commandShell = &shells[DEFSHELL_INDEX]; 368static Shell *commandShell = &shells[DEFSHELL_INDEX];
369const char *shellPath = NULL; /* full pathname of executable image */ 369const char *shellPath = NULL; /* full pathname of executable image */
370const char *shellName = NULL; /* last component of shellPath */ 370const char *shellName = NULL; /* last component of shellPath */
371char *shellErrFlag = NULL; 371char *shellErrFlag = NULL;
372static char *shellArgv = NULL; /* Custom shell args */ 372static char *shellArgv = NULL; /* Custom shell args */
373 373
374 374
375static Job *job_table; /* The structures that describe them */ 375static Job *job_table; /* The structures that describe them */
376static Job *job_table_end; /* job_table + maxJobs */ 376static Job *job_table_end; /* job_table + maxJobs */
377static unsigned int wantToken; /* we want a token */ 377static unsigned int wantToken; /* we want a token */
378static int lurking_children = 0; 378static int lurking_children = 0;
379static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */ 379static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */
380 380
381/* 381/*
382 * Set of descriptors of pipes connected to 382 * Set of descriptors of pipes connected to
383 * the output channels of children 383 * the output channels of children
384 */ 384 */
385static struct pollfd *fds = NULL; 385static struct pollfd *fds = NULL;
386static Job **jobfds = NULL; 386static Job **jobfds = NULL;
387static nfds_t nfds = 0; 387static nfds_t nfds = 0;
388static void watchfd(Job *); 388static void watchfd(Job *);
389static void clearfd(Job *); 389static void clearfd(Job *);
390static int readyfd(Job *); 390static int readyfd(Job *);
391 391
392static GNode *lastNode; /* The node for which output was most recently 392static GNode *lastNode; /* The node for which output was most recently
393 * produced. */ 393 * produced. */
394static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */ 394static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */
395static Job tokenWaitJob; /* token wait pseudo-job */ 395static Job tokenWaitJob; /* token wait pseudo-job */
396 396
397static Job childExitJob; /* child exit pseudo-job */ 397static Job childExitJob; /* child exit pseudo-job */
398#define CHILD_EXIT "." 398#define CHILD_EXIT "."
399#define DO_JOB_RESUME "R" 399#define DO_JOB_RESUME "R"
400 400
401enum { npseudojobs = 2 }; /* number of pseudo-jobs */ 401enum { npseudojobs = 2 }; /* number of pseudo-jobs */
402 402
403#define TARG_FMT "%s %s ---\n" /* Default format */ 403#define TARG_FMT "%s %s ---\n" /* Default format */
404#define MESSAGE(fp, gn) \ 404#define MESSAGE(fp, gn) \
405 if (opts.maxJobs != 1 && targPrefix && *targPrefix) \ 405 if (opts.maxJobs != 1 && targPrefix && *targPrefix) \
406 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) 406 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name)
407 407
408static sigset_t caught_signals; /* Set of signals we handle */ 408static sigset_t caught_signals; /* Set of signals we handle */
409 409
410static void JobDoOutput(Job *, Boolean); 410static void JobDoOutput(Job *, Boolean);
411static void JobInterrupt(int, int) MAKE_ATTR_DEAD; 411static void JobInterrupt(int, int) MAKE_ATTR_DEAD;
412static void JobRestartJobs(void); 412static void JobRestartJobs(void);
413static void JobSigReset(void); 413static void JobSigReset(void);
414 414
415static unsigned 415static unsigned
416nfds_per_job(void) 416nfds_per_job(void)
417{ 417{
418#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 418#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
419 if (useMeta) 419 if (useMeta)
420 return 2; 420 return 2;
421#endif 421#endif
422 return 1; 422 return 1;
423} 423}
424 424
425static void 425static void
426job_table_dump(const char *where) 426job_table_dump(const char *where)
427{ 427{
428 Job *job; 428 Job *job;
429 429
430 debug_printf("job table @ %s\n", where); 430 debug_printf("job table @ %s\n", where);
431 for (job = job_table; job < job_table_end; job++) { 431 for (job = job_table; job < job_table_end; job++) {
432 debug_printf("job %d, status %d, flags %d, pid %d\n", 432 debug_printf("job %d, status %d, flags %d, pid %d\n",
433 (int)(job - job_table), job->job_state, job->flags, job->pid); 433 (int)(job - job_table), job->job_state, job->flags, job->pid);
434 } 434 }
435} 435}
436 436
437/* 437/*
438 * Delete the target of a failed, interrupted, or otherwise 438 * Delete the target of a failed, interrupted, or otherwise
439 * unsuccessful job unless inhibited by .PRECIOUS. 439 * unsuccessful job unless inhibited by .PRECIOUS.
440 */ 440 */
441static void 441static void
442JobDeleteTarget(GNode *gn) 442JobDeleteTarget(GNode *gn)
443{ 443{
444 const char *file; 444 const char *file;
445 445
446 if (gn->type & OP_JOIN) 446 if (gn->type & OP_JOIN)
447 return; 447 return;
448 if (gn->type & OP_PHONY) 448 if (gn->type & OP_PHONY)
449 return; 449 return;
450 if (Targ_Precious(gn)) 450 if (Targ_Precious(gn))
451 return; 451 return;
452 if (opts.noExecute) 452 if (opts.noExecute)
453 return; 453 return;
454 454
455 file = GNode_Path(gn); 455 file = GNode_Path(gn);
456 if (eunlink(file) != -1) 456 if (eunlink(file) != -1)
457 Error("*** %s removed", file); 457 Error("*** %s removed", file);
458} 458}
459 459
460/* 460/*
461 * JobSigLock/JobSigUnlock 461 * JobSigLock/JobSigUnlock
462 * 462 *
463 * Signal lock routines to get exclusive access. Currently used to 463 * Signal lock routines to get exclusive access. Currently used to
464 * protect `jobs' and `stoppedJobs' list manipulations. 464 * protect `jobs' and `stoppedJobs' list manipulations.
465 */ 465 */
466static void JobSigLock(sigset_t *omaskp) 466static void JobSigLock(sigset_t *omaskp)
467{ 467{
468 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) { 468 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) {
469 Punt("JobSigLock: sigprocmask: %s", strerror(errno)); 469 Punt("JobSigLock: sigprocmask: %s", strerror(errno));
470 sigemptyset(omaskp); 470 sigemptyset(omaskp);
471 } 471 }
472} 472}
473 473
474static void JobSigUnlock(sigset_t *omaskp) 474static void JobSigUnlock(sigset_t *omaskp)
475{ 475{
476 (void)sigprocmask(SIG_SETMASK, omaskp, NULL); 476 (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
477} 477}
478 478
479static void 479static void
480JobCreatePipe(Job *job, int minfd) 480JobCreatePipe(Job *job, int minfd)
481{ 481{
482 int i, fd, flags; 482 int i, fd, flags;
483 int pipe_fds[2]; 483 int pipe_fds[2];
484 484
485 if (pipe(pipe_fds) == -1) 485 if (pipe(pipe_fds) == -1)
486 Punt("Cannot create pipe: %s", strerror(errno)); 486 Punt("Cannot create pipe: %s", strerror(errno));
487 487
488 for (i = 0; i < 2; i++) { 488 for (i = 0; i < 2; i++) {
489 /* Avoid using low numbered fds */ 489 /* Avoid using low numbered fds */
490 fd = fcntl(pipe_fds[i], F_DUPFD, minfd); 490 fd = fcntl(pipe_fds[i], F_DUPFD, minfd);
491 if (fd != -1) { 491 if (fd != -1) {
492 close(pipe_fds[i]); 492 close(pipe_fds[i]);
493 pipe_fds[i] = fd; 493 pipe_fds[i] = fd;
494 } 494 }
495 } 495 }
496 496
497 job->inPipe = pipe_fds[0]; 497 job->inPipe = pipe_fds[0];
498 job->outPipe = pipe_fds[1]; 498 job->outPipe = pipe_fds[1];
499 499
500 /* Set close-on-exec flag for both */ 500 /* Set close-on-exec flag for both */
501 if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1) 501 if (fcntl(job->inPipe, F_SETFD, FD_CLOEXEC) == -1)
502 Punt("Cannot set close-on-exec: %s", strerror(errno)); 502 Punt("Cannot set close-on-exec: %s", strerror(errno));
503 if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1) 503 if (fcntl(job->outPipe, F_SETFD, FD_CLOEXEC) == -1)
504 Punt("Cannot set close-on-exec: %s", strerror(errno)); 504 Punt("Cannot set close-on-exec: %s", strerror(errno));
505 505
506 /* 506 /*
507 * We mark the input side of the pipe non-blocking; we poll(2) the 507 * We mark the input side of the pipe non-blocking; we poll(2) the
508 * pipe when we're waiting for a job token, but we might lose the 508 * pipe when we're waiting for a job token, but we might lose the
509 * race for the token when a new one becomes available, so the read 509 * race for the token when a new one becomes available, so the read
510 * from the pipe should not block. 510 * from the pipe should not block.
511 */ 511 */
512 flags = fcntl(job->inPipe, F_GETFL, 0); 512 flags = fcntl(job->inPipe, F_GETFL, 0);
513 if (flags == -1) 513 if (flags == -1)
514 Punt("Cannot get flags: %s", strerror(errno)); 514 Punt("Cannot get flags: %s", strerror(errno));
515 flags |= O_NONBLOCK; 515 flags |= O_NONBLOCK;
516 if (fcntl(job->inPipe, F_SETFL, flags) == -1) 516 if (fcntl(job->inPipe, F_SETFL, flags) == -1)
517 Punt("Cannot set flags: %s", strerror(errno)); 517 Punt("Cannot set flags: %s", strerror(errno));
518} 518}
519 519
520/* Pass the signal to each running job. */ 520/* Pass the signal to each running job. */
521static void 521static void
522JobCondPassSig(int signo) 522JobCondPassSig(int signo)
523{ 523{
524 Job *job; 524 Job *job;
525 525
526 DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo); 526 DEBUG1(JOB, "JobCondPassSig(%d) called.\n", signo);
527 527
528 for (job = job_table; job < job_table_end; job++) { 528 for (job = job_table; job < job_table_end; job++) {
529 if (job->job_state != JOB_ST_RUNNING) 529 if (job->job_state != JOB_ST_RUNNING)
530 continue; 530 continue;
531 DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n", 531 DEBUG2(JOB, "JobCondPassSig passing signal %d to child %d.\n",
532 signo, job->pid); 532 signo, job->pid);
533 KILLPG(job->pid, signo); 533 KILLPG(job->pid, signo);
534 } 534 }
535} 535}
536 536
537/* SIGCHLD handler. 537/* SIGCHLD handler.
538 * 538 *
539 * Sends a token on the child exit pipe to wake us up from select()/poll(). */ 539 * Sends a token on the child exit pipe to wake us up from select()/poll(). */
540static void 540static void
541JobChildSig(int signo MAKE_ATTR_UNUSED) 541JobChildSig(int signo MAKE_ATTR_UNUSED)
542{ 542{
543 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN) 543 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN)
544 continue; 544 continue;
545} 545}
546 546
547 547
548/* Resume all stopped jobs. */ 548/* Resume all stopped jobs. */
549static void 549static void
550JobContinueSig(int signo MAKE_ATTR_UNUSED) 550JobContinueSig(int signo MAKE_ATTR_UNUSED)
551{ 551{
552 /* 552 /*
553 * Defer sending SIGCONT to our stopped children until we return 553 * Defer sending SIGCONT to our stopped children until we return
554 * from the signal handler. 554 * from the signal handler.
555 */ 555 */
556 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && 556 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
557 errno == EAGAIN) 557 errno == EAGAIN)
558 continue; 558 continue;
559} 559}
560 560
561/* Pass a signal on to all jobs, then resend to ourselves. 561/* Pass a signal on to all jobs, then resend to ourselves.
562 * We die by the same signal. */ 562 * We die by the same signal. */
563MAKE_ATTR_DEAD static void 563MAKE_ATTR_DEAD static void
564JobPassSig_int(int signo) 564JobPassSig_int(int signo)
565{ 565{
566 /* Run .INTERRUPT target then exit */ 566 /* Run .INTERRUPT target then exit */
567 JobInterrupt(TRUE, signo); 567 JobInterrupt(TRUE, signo);
568} 568}
569 569
570/* Pass a signal on to all jobs, then resend to ourselves. 570/* Pass a signal on to all jobs, then resend to ourselves.
571 * We die by the same signal. */ 571 * We die by the same signal. */
572MAKE_ATTR_DEAD static void 572MAKE_ATTR_DEAD static void
573JobPassSig_term(int signo) 573JobPassSig_term(int signo)
574{ 574{
575 /* Dont run .INTERRUPT target then exit */ 575 /* Dont run .INTERRUPT target then exit */
576 JobInterrupt(FALSE, signo); 576 JobInterrupt(FALSE, signo);
577} 577}
578 578
579static void 579static void
580JobPassSig_suspend(int signo) 580JobPassSig_suspend(int signo)
581{ 581{
582 sigset_t nmask, omask; 582 sigset_t nmask, omask;
583 struct sigaction act; 583 struct sigaction act;
584 584
585 /* Suppress job started/continued messages */ 585 /* Suppress job started/continued messages */
586 make_suspended = 1; 586 make_suspended = 1;
587 587
588 /* Pass the signal onto every job */ 588 /* Pass the signal onto every job */
589 JobCondPassSig(signo); 589 JobCondPassSig(signo);
590 590
591 /* 591 /*
592 * Send ourselves the signal now we've given the message to everyone else. 592 * Send ourselves the signal now we've given the message to everyone else.
593 * Note we block everything else possible while we're getting the signal. 593 * Note we block everything else possible while we're getting the signal.
594 * This ensures that all our jobs get continued when we wake up before 594 * This ensures that all our jobs get continued when we wake up before
595 * we take any other signal. 595 * we take any other signal.
596 */ 596 */
597 sigfillset(&nmask); 597 sigfillset(&nmask);
598 sigdelset(&nmask, signo); 598 sigdelset(&nmask, signo);
599 (void)sigprocmask(SIG_SETMASK, &nmask, &omask); 599 (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
600 600
601 act.sa_handler = SIG_DFL; 601 act.sa_handler = SIG_DFL;
602 sigemptyset(&act.sa_mask); 602 sigemptyset(&act.sa_mask);
603 act.sa_flags = 0; 603 act.sa_flags = 0;
604 (void)sigaction(signo, &act, NULL); 604 (void)sigaction(signo, &act, NULL);
605 605
606 if (DEBUG(JOB)) 606 if (DEBUG(JOB))
607 debug_printf("JobPassSig passing signal %d to self.\n", signo); 607 debug_printf("JobPassSig passing signal %d to self.\n", signo);
608 608
609 (void)kill(getpid(), signo); 609 (void)kill(getpid(), signo);
610 610
611 /* 611 /*
612 * We've been continued. 612 * We've been continued.
613 * 613 *
614 * A whole host of signals continue to happen! 614 * A whole host of signals continue to happen!
615 * SIGCHLD for any processes that actually suspended themselves. 615 * SIGCHLD for any processes that actually suspended themselves.
616 * SIGCHLD for any processes that exited while we were alseep. 616 * SIGCHLD for any processes that exited while we were alseep.
617 * The SIGCONT that actually caused us to wakeup. 617 * The SIGCONT that actually caused us to wakeup.
618 * 618 *
619 * Since we defer passing the SIGCONT on to our children until 619 * Since we defer passing the SIGCONT on to our children until
620 * the main processing loop, we can be sure that all the SIGCHLD 620 * the main processing loop, we can be sure that all the SIGCHLD
621 * events will have happened by then - and that the waitpid() will 621 * events will have happened by then - and that the waitpid() will
622 * collect the child 'suspended' events. 622 * collect the child 'suspended' events.
623 * For correct sequencing we just need to ensure we process the 623 * For correct sequencing we just need to ensure we process the
624 * waitpid() before passing on the SIGCONT. 624 * waitpid() before passing on the SIGCONT.
625 * 625 *
626 * In any case nothing else is needed here. 626 * In any case nothing else is needed here.
627 */ 627 */
628 628
629 /* Restore handler and signal mask */ 629 /* Restore handler and signal mask */
630 act.sa_handler = JobPassSig_suspend; 630 act.sa_handler = JobPassSig_suspend;
631 (void)sigaction(signo, &act, NULL); 631 (void)sigaction(signo, &act, NULL);
632 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 632 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
633} 633}
634 634
635static Job * 635static Job *
636JobFindPid(int pid, JobState status, Boolean isJobs) 636JobFindPid(int pid, JobState status, Boolean isJobs)
637{ 637{
638 Job *job; 638 Job *job;
639 639
640 for (job = job_table; job < job_table_end; job++) { 640 for (job = job_table; job < job_table_end; job++) {
641 if ((job->job_state == status) && job->pid == pid) 641 if ((job->job_state == status) && job->pid == pid)
642 return job; 642 return job;
643 } 643 }
644 if (DEBUG(JOB) && isJobs) 644 if (DEBUG(JOB) && isJobs)
645 job_table_dump("no pid"); 645 job_table_dump("no pid");
646 return NULL; 646 return NULL;
647} 647}
648 648
649/*- 649/*-
650 *----------------------------------------------------------------------- 650 *-----------------------------------------------------------------------
651 * JobPrintCommand -- 651 * JobPrintCommand --
652 * Put out another command for the given job. If the command starts 652 * Put out another command for the given job. If the command starts
653 * with an @ or a - we process it specially. In the former case, 653 * with an @ or a - we process it specially. In the former case,
654 * so long as the -s and -n flags weren't given to make, we stick 654 * so long as the -s and -n flags weren't given to make, we stick
655 * a shell-specific echoOff command in the script. In the latter, 655 * a shell-specific echoOff command in the script. In the latter,
656 * we ignore errors for the entire job, unless the shell has error 656 * we ignore errors for the entire job, unless the shell has error
657 * control. 657 * control.
658 * If the command is just "..." we take all future commands for this 658 * If the command is just "..." we take all future commands for this
659 * job to be commands to be executed once the entire graph has been 659 * job to be commands to be executed once the entire graph has been
660 * made and return non-zero to signal that the end of the commands 660 * made and return non-zero to signal that the end of the commands
661 * was reached. These commands are later attached to the postCommands 661 * was reached. These commands are later attached to the postCommands
662 * node and executed by Job_End when all things are done. 662 * node and executed by Job_End when all things are done.
663 * 663 *
664 * Side Effects: 664 * Side Effects:
665 * If the command begins with a '-' and the shell has no error control, 665 * If the command begins with a '-' and the shell has no error control,
666 * the JOB_IGNERR flag is set in the job descriptor. 666 * the JOB_IGNERR flag is set in the job descriptor.
667 * numCommands is incremented if the command is actually printed. 667 * numCommands is incremented if the command is actually printed.
668 *----------------------------------------------------------------------- 668 *-----------------------------------------------------------------------
669 */ 669 */
670static void 670static void
671JobPrintCommand(Job *job, char *cmd) 671JobPrintCommand(Job *job, char *cmd)
672{ 672{
673 const char *const cmdp = cmd; 673 const char *const cmdp = cmd;
674 Boolean noSpecials; /* true if we shouldn't worry about 674 Boolean noSpecials; /* true if we shouldn't worry about
675 * inserting special commands into 675 * inserting special commands into
676 * the input stream. */ 676 * the input stream. */
677 Boolean shutUp = FALSE; /* true if we put a no echo command 677 Boolean shutUp = FALSE; /* true if we put a no echo command
678 * into the command file */ 678 * into the command file */
679 Boolean errOff = FALSE; /* true if we turned error checking 679 Boolean errOff = FALSE; /* true if we turned error checking
680 * off before printing the command 680 * off before printing the command
681 * and need to turn it back on */ 681 * and need to turn it back on */
682 const char *cmdTemplate; /* Template to use when printing the 682 const char *cmdTemplate; /* Template to use when printing the
683 * command */ 683 * command */
684 char *cmdStart; /* Start of expanded command */ 684 char *cmdStart; /* Start of expanded command */
685 char *escCmd = NULL; /* Command with quotes/backticks escaped */ 685 char *escCmd = NULL; /* Command with quotes/backticks escaped */
686 686
687 noSpecials = NoExecute(job->node); 687 noSpecials = NoExecute(job->node);
688 688
689#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ 689#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \
690 debug_printf(fmt, arg); \ 690 debug_printf(fmt, arg); \
691 } \ 691 } \
692 (void)fprintf(job->cmdFILE, fmt, arg); \ 692 (void)fprintf(job->cmdFILE, fmt, arg); \
693 (void)fflush(job->cmdFILE); 693 (void)fflush(job->cmdFILE);
694 694
695 numCommands++; 695 numCommands++;
696 696
697 Var_Subst(cmd, job->node, VARE_WANTRES, &cmd); 697 Var_Subst(cmd, job->node, VARE_WANTRES, &cmd);
698 /* TODO: handle errors */ 698 /* TODO: handle errors */
699 cmdStart = cmd; 699 cmdStart = cmd;
700 700
701 cmdTemplate = "%s\n"; 701 cmdTemplate = "%s\n";
702 702
703 /* 703 /*
704 * Check for leading @' and -'s to control echoing and error checking. 704 * Check for leading @' and -'s to control echoing and error checking.
705 */ 705 */
706 while (*cmd == '@' || *cmd == '-' || (*cmd == '+')) { 706 while (*cmd == '@' || *cmd == '-' || (*cmd == '+')) {
707 switch (*cmd) { 707 switch (*cmd) {
708 case '@': 708 case '@':
709 shutUp = DEBUG(LOUD) ? FALSE : TRUE; 709 shutUp = DEBUG(LOUD) ? FALSE : TRUE;
710 break; 710 break;
711 case '-': 711 case '-':
712 errOff = TRUE; 712 errOff = TRUE;
713 break; 713 break;
714 case '+': 714 case '+':
715 if (noSpecials) { 715 if (noSpecials) {
716 /* 716 /*
717 * We're not actually executing anything... 717 * We're not actually executing anything...
718 * but this one needs to be - use compat mode just for it. 718 * but this one needs to be - use compat mode just for it.
719 */ 719 */
720 Compat_RunCommand(cmdp, job->node); 720 Compat_RunCommand(cmdp, job->node);
721 free(cmdStart); 721 free(cmdStart);
722 return; 722 return;
723 } 723 }
724 break; 724 break;
725 } 725 }
726 cmd++; 726 cmd++;
727 } 727 }
728 728
729 pp_skip_whitespace(&cmd); 729 pp_skip_whitespace(&cmd);
730 730
731 /* 731 /*
732 * If the shell doesn't have error control the alternate echo'ing will 732 * If the shell doesn't have error control the alternate echo'ing will
733 * be done (to avoid showing additional error checking code) 733 * be done (to avoid showing additional error checking code)
734 * and this will need the characters '$ ` \ "' escaped 734 * and this will need the characters '$ ` \ "' escaped
735 */ 735 */
736 736
737 if (!commandShell->hasErrCtl) { 737 if (!commandShell->hasErrCtl) {
738 int i, j; 738 int i, j;
739 739
740 /* Worst that could happen is every char needs escaping. */ 740 /* Worst that could happen is every char needs escaping. */
741 escCmd = bmake_malloc((strlen(cmd) * 2) + 1); 741 escCmd = bmake_malloc((strlen(cmd) * 2) + 1);
742 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) { 742 for (i = 0, j = 0; cmd[i] != '\0'; i++, j++) {
743 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || 743 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' ||
744 cmd[i] == '"') 744 cmd[i] == '"')
745 escCmd[j++] = '\\'; 745 escCmd[j++] = '\\';
746 escCmd[j] = cmd[i]; 746 escCmd[j] = cmd[i];
747 } 747 }
748 escCmd[j] = '\0'; 748 escCmd[j] = '\0';
749 } 749 }
750 750
751 if (shutUp) { 751 if (shutUp) {
752 if (!(job->flags & JOB_SILENT) && !noSpecials && 752 if (!(job->flags & JOB_SILENT) && !noSpecials &&
753 commandShell->hasEchoCtl) { 753 commandShell->hasEchoCtl) {
754 DBPRINTF("%s\n", commandShell->echoOff); 754 DBPRINTF("%s\n", commandShell->echoOff);
755 } else { 755 } else {
756 if (commandShell->hasErrCtl) 756 if (commandShell->hasErrCtl)
757 shutUp = FALSE; 757 shutUp = FALSE;
758 } 758 }
759 } 759 }
760 760
761 if (errOff) { 761 if (errOff) {
762 if (!noSpecials) { 762 if (!noSpecials) {
763 if (commandShell->hasErrCtl) { 763 if (commandShell->hasErrCtl) {
764 /* 764 /*
765 * we don't want the error-control commands showing 765 * we don't want the error-control commands showing
766 * up either, so we turn off echoing while executing 766 * up either, so we turn off echoing while executing
767 * them. We could put another field in the shell 767 * them. We could put another field in the shell
768 * structure to tell JobDoOutput to look for this 768 * structure to tell JobDoOutput to look for this
769 * string too, but why make it any more complex than 769 * string too, but why make it any more complex than
770 * it already is? 770 * it already is?
771 */ 771 */
772 if (!(job->flags & JOB_SILENT) && !shutUp && 772 if (!(job->flags & JOB_SILENT) && !shutUp &&
773 commandShell->hasEchoCtl) { 773 commandShell->hasEchoCtl) {
774 DBPRINTF("%s\n", commandShell->echoOff); 774 DBPRINTF("%s\n", commandShell->echoOff);
775 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); 775 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
776 DBPRINTF("%s\n", commandShell->echoOn); 776 DBPRINTF("%s\n", commandShell->echoOn);
777 } else { 777 } else {
778 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore); 778 DBPRINTF("%s\n", commandShell->errOffOrExecIgnore);
779 } 779 }
780 } else if (commandShell->errOffOrExecIgnore && 780 } else if (commandShell->errOffOrExecIgnore &&
781 commandShell->errOffOrExecIgnore[0] != '\0') 781 commandShell->errOffOrExecIgnore[0] != '\0')
782 { 782 {
783 /* 783 /*
784 * The shell has no error control, so we need to be 784 * The shell has no error control, so we need to be
785 * weird to get it to ignore any errors from the command. 785 * weird to get it to ignore any errors from the command.
786 * If echoing is turned on, we turn it off and use the 786 * If echoing is turned on, we turn it off and use the
787 * errOnOrEcho template to echo the command. Leave echoing 787 * errOnOrEcho template to echo the command. Leave echoing
788 * off so the user doesn't see the weirdness we go through 788 * off so the user doesn't see the weirdness we go through
789 * to ignore errors. Set cmdTemplate to use the weirdness 789 * to ignore errors. Set cmdTemplate to use the weirdness
790 * instead of the simple "%s\n" template. 790 * instead of the simple "%s\n" template.
791 */ 791 */
792 job->flags |= JOB_IGNERR; 792 job->flags |= JOB_IGNERR;
793 if (!(job->flags & JOB_SILENT) && !shutUp) { 793 if (!(job->flags & JOB_SILENT) && !shutUp) {
794 if (commandShell->hasEchoCtl) { 794 if (commandShell->hasEchoCtl) {
795 DBPRINTF("%s\n", commandShell->echoOff); 795 DBPRINTF("%s\n", commandShell->echoOff);
796 } 796 }
797 DBPRINTF(commandShell->errOnOrEcho, escCmd); 797 DBPRINTF(commandShell->errOnOrEcho, escCmd);
798 shutUp = TRUE; 798 shutUp = TRUE;
799 } else { 799 } else {
800 if (!shutUp) { 800 if (!shutUp) {
801 DBPRINTF(commandShell->errOnOrEcho, escCmd); 801 DBPRINTF(commandShell->errOnOrEcho, escCmd);
802 } 802 }
803 } 803 }
804 cmdTemplate = commandShell->errOffOrExecIgnore; 804 cmdTemplate = commandShell->errOffOrExecIgnore;
805 /* 805 /*
806 * The error ignoration (hee hee) is already taken care 806 * The error ignoration (hee hee) is already taken care
807 * of by the errOffOrExecIgnore template, so pretend error 807 * of by the errOffOrExecIgnore template, so pretend error
808 * checking is still on. 808 * checking is still on.
809 */ 809 */
810 errOff = FALSE; 810 errOff = FALSE;
811 } else { 811 } else {
812 errOff = FALSE; 812 errOff = FALSE;
813 } 813 }
814 } else { 814 } else {
815 errOff = FALSE; 815 errOff = FALSE;
816 } 816 }
817 } else { 817 } else {
818 818
819 /* 819 /*
820 * If errors are being checked and the shell doesn't have error control 820 * If errors are being checked and the shell doesn't have error control
821 * but does supply an errExit template, then setup commands to run 821 * but does supply an errExit template, then setup commands to run
822 * through it. 822 * through it.
823 */ 823 */
824 824
825 if (!commandShell->hasErrCtl && commandShell->errExit && 825 if (!commandShell->hasErrCtl && commandShell->errExit &&
826 commandShell->errExit[0] != '\0') { 826 commandShell->errExit[0] != '\0') {
827 if (!(job->flags & JOB_SILENT) && !shutUp) { 827 if (!(job->flags & JOB_SILENT) && !shutUp) {
828 if (commandShell->hasEchoCtl) { 828 if (commandShell->hasEchoCtl) {
829 DBPRINTF("%s\n", commandShell->echoOff); 829 DBPRINTF("%s\n", commandShell->echoOff);
830 } 830 }
831 DBPRINTF(commandShell->errOnOrEcho, escCmd); 831 DBPRINTF(commandShell->errOnOrEcho, escCmd);
832 shutUp = TRUE; 832 shutUp = TRUE;
833 } 833 }
834 /* If it's a comment line or blank, treat as an ignored error */ 834 /* If it's a comment line or blank, treat as an ignored error */
835 if ((escCmd[0] == commandShell->commentChar) || 835 if ((escCmd[0] == commandShell->commentChar) ||
836 (escCmd[0] == 0)) 836 (escCmd[0] == 0))
837 cmdTemplate = commandShell->errOffOrExecIgnore; 837 cmdTemplate = commandShell->errOffOrExecIgnore;
838 else 838 else
839 cmdTemplate = commandShell->errExit; 839 cmdTemplate = commandShell->errExit;
840 errOff = FALSE; 840 errOff = FALSE;
841 } 841 }
842 } 842 }
843 843
844 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 && 844 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 &&
845 (job->flags & JOB_TRACED) == 0) { 845 (job->flags & JOB_TRACED) == 0) {
846 DBPRINTF("set -%s\n", "x"); 846 DBPRINTF("set -%s\n", "x");
847 job->flags |= JOB_TRACED; 847 job->flags |= JOB_TRACED;
848 } 848 }
849 849
850 DBPRINTF(cmdTemplate, cmd); 850 DBPRINTF(cmdTemplate, cmd);
851 free(cmdStart); 851 free(cmdStart);
852 free(escCmd); 852 free(escCmd);
853 if (errOff) { 853 if (errOff) {
854 /* 854 /*
855 * If echoing is already off, there's no point in issuing the 855 * If echoing is already off, there's no point in issuing the
856 * echoOff command. Otherwise we issue it and pretend it was on 856 * echoOff command. Otherwise we issue it and pretend it was on
857 * for the whole command... 857 * for the whole command...
858 */ 858 */
859 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ 859 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
860 DBPRINTF("%s\n", commandShell->echoOff); 860 DBPRINTF("%s\n", commandShell->echoOff);
861 shutUp = TRUE; 861 shutUp = TRUE;
862 } 862 }
863 DBPRINTF("%s\n", commandShell->errOnOrEcho); 863 DBPRINTF("%s\n", commandShell->errOnOrEcho);
864 } 864 }
865 if (shutUp && commandShell->hasEchoCtl) { 865 if (shutUp && commandShell->hasEchoCtl) {
866 DBPRINTF("%s\n", commandShell->echoOn); 866 DBPRINTF("%s\n", commandShell->echoOn);
867 } 867 }
868} 868}
869 869
870/* Print all commands to the shell file that is later executed. 870/* Print all commands to the shell file that is later executed.
871 * 871 *
872 * The special command "..." stops printing and saves the remaining commands 872 * The special command "..." stops printing and saves the remaining commands
873 * to be executed later. */ 873 * to be executed later. */
874static void 874static void
875JobPrintCommands(Job *job) 875JobPrintCommands(Job *job)
876{ 876{
877 StringListNode *ln; 877 StringListNode *ln;
878 878
879 for (ln = job->node->commands->first; ln != NULL; ln = ln->next) { 879 for (ln = job->node->commands->first; ln != NULL; ln = ln->next) {
880 const char *cmd = ln->datum; 880 const char *cmd = ln->datum;
881 881
882 if (strcmp(cmd, "...") == 0) { 882 if (strcmp(cmd, "...") == 0) {
883 job->node->type |= OP_SAVE_CMDS; 883 job->node->type |= OP_SAVE_CMDS;
884 if ((job->flags & JOB_IGNDOTS) == 0) { 884 if ((job->flags & JOB_IGNDOTS) == 0) {
885 job->tailCmds = ln->next; 885 job->tailCmds = ln->next;
886 break; 886 break;
887 } 887 }
888 } else 888 } else
889 JobPrintCommand(job, ln->datum); 889 JobPrintCommand(job, ln->datum);
890 } 890 }
891} 891}
892 892
893/* Save the delayed commands, to be executed when everything else is done. */ 893/* Save the delayed commands, to be executed when everything else is done. */
894static void 894static void
895JobSaveCommands(Job *job) 895JobSaveCommands(Job *job)
896{ 896{
897 StringListNode *node; 897 StringListNode *node;
898 898
899 for (node = job->tailCmds; node != NULL; node = node->next) { 899 for (node = job->tailCmds; node != NULL; node = node->next) {
900 const char *cmd = node->datum; 900 const char *cmd = node->datum;
901 char *expanded_cmd; 901 char *expanded_cmd;
902 /* XXX: This Var_Subst is only intended to expand the dynamic 902 /* XXX: This Var_Subst is only intended to expand the dynamic
903 * variables such as .TARGET, .IMPSRC. It is not intended to 903 * variables such as .TARGET, .IMPSRC. It is not intended to
904 * expand the other variables as well; see deptgt-end.mk. */ 904 * expand the other variables as well; see deptgt-end.mk. */
905 (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd); 905 (void)Var_Subst(cmd, job->node, VARE_WANTRES, &expanded_cmd);
906 /* TODO: handle errors */ 906 /* TODO: handle errors */
907 Lst_Append(Targ_GetEndNode()->commands, expanded_cmd); 907 Lst_Append(Targ_GetEndNode()->commands, expanded_cmd);
908 } 908 }
909} 909}
910 910
911 911
912/* Called to close both input and output pipes when a job is finished. */ 912/* Called to close both input and output pipes when a job is finished. */
913static void 913static void
914JobClose(Job *job) 914JobClose(Job *job)
915{ 915{
916 clearfd(job); 916 clearfd(job);
917 (void)close(job->outPipe); 917 (void)close(job->outPipe);
918 job->outPipe = -1; 918 job->outPipe = -1;
919 919
920 JobDoOutput(job, TRUE); 920 JobDoOutput(job, TRUE);
921 (void)close(job->inPipe); 921 (void)close(job->inPipe);
922 job->inPipe = -1; 922 job->inPipe = -1;
923} 923}
924 924
925/*- 925/*-
926 *----------------------------------------------------------------------- 926 *-----------------------------------------------------------------------
927 * JobFinish -- 927 * JobFinish --
928 * Do final processing for the given job including updating 928 * Do final processing for the given job including updating
929 * parents and starting new jobs as available/necessary. Note 929 * parents and starting new jobs as available/necessary. Note
930 * that we pay no attention to the JOB_IGNERR flag here. 930 * that we pay no attention to the JOB_IGNERR flag here.
931 * This is because when we're called because of a noexecute flag 931 * This is because when we're called because of a noexecute flag
932 * or something, jstat.w_status is 0 and when called from 932 * or something, jstat.w_status is 0 and when called from
933 * Job_CatchChildren, the status is zeroed if it s/b ignored. 933 * Job_CatchChildren, the status is zeroed if it s/b ignored.
934 * 934 *
935 * Input: 935 * Input:
936 * job job to finish 936 * job job to finish
937 * status sub-why job went away 937 * status sub-why job went away
938 * 938 *
939 * Side Effects: 939 * Side Effects:
940 * Final commands for the job are placed on postCommands. 940 * Final commands for the job are placed on postCommands.
941 * 941 *
942 * If we got an error and are aborting (aborting == ABORT_ERROR) and 942 * If we got an error and are aborting (aborting == ABORT_ERROR) and
943 * the job list is now empty, we are done for the day. 943 * the job list is now empty, we are done for the day.
944 * If we recognized an error (errors !=0), we set the aborting flag 944 * If we recognized an error (errors !=0), we set the aborting flag
945 * to ABORT_ERROR so no more jobs will be started. 945 * to ABORT_ERROR so no more jobs will be started.
946 *----------------------------------------------------------------------- 946 *-----------------------------------------------------------------------
947 */ 947 */
948static void 948static void
949JobFinish(Job *job, int status) 949JobFinish(Job *job, int status)
950{ 950{
951 Boolean done, return_job_token; 951 Boolean done, return_job_token;
952 952
953 DEBUG3(JOB, "JobFinish: %d [%s], status %d\n", 953 DEBUG3(JOB, "JobFinish: %d [%s], status %d\n",
954 job->pid, job->node->name, status); 954 job->pid, job->node->name, status);
955 955
956 if ((WIFEXITED(status) && 956 if ((WIFEXITED(status) &&
957 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) || 957 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) ||
958 WIFSIGNALED(status)) 958 WIFSIGNALED(status))
959 { 959 {
960 /* 960 /*
961 * If it exited non-zero and either we're doing things our 961 * If it exited non-zero and either we're doing things our
962 * way or we're not ignoring errors, the job is finished. 962 * way or we're not ignoring errors, the job is finished.
963 * Similarly, if the shell died because of a signal 963 * Similarly, if the shell died because of a signal
964 * the job is also finished. In these 964 * the job is also finished. In these
965 * cases, finish out the job's output before printing the exit 965 * cases, finish out the job's output before printing the exit
966 * status... 966 * status...
967 */ 967 */
968 JobClose(job); 968 JobClose(job);
969 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 969 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
970 (void)fclose(job->cmdFILE); 970 (void)fclose(job->cmdFILE);
971 job->cmdFILE = NULL; 971 job->cmdFILE = NULL;
972 } 972 }
973 done = TRUE; 973 done = TRUE;
974 } else if (WIFEXITED(status)) { 974 } else if (WIFEXITED(status)) {
975 /* 975 /*
976 * Deal with ignored errors in -B mode. We need to print a message 976 * Deal with ignored errors in -B mode. We need to print a message
977 * telling of the ignored error as well as setting status.w_status 977 * telling of the ignored error as well as setting status.w_status
978 * to 0 so the next command gets run. To do this, we set done to be 978 * to 0 so the next command gets run. To do this, we set done to be
979 * TRUE if in -B mode and the job exited non-zero. 979 * TRUE if in -B mode and the job exited non-zero.
980 */ 980 */
981 done = WEXITSTATUS(status) != 0; 981 done = WEXITSTATUS(status) != 0;
982 /* 982 /*
983 * Old comment said: "Note we don't 983 * Old comment said: "Note we don't
984 * want to close down any of the streams until we know we're at the 984 * want to close down any of the streams until we know we're at the
985 * end." 985 * end."
986 * But we do. Otherwise when are we going to print the rest of the 986 * But we do. Otherwise when are we going to print the rest of the
987 * stuff? 987 * stuff?
988 */ 988 */
989 JobClose(job); 989 JobClose(job);
990 } else { 990 } else {
991 /* 991 /*
992 * No need to close things down or anything. 992 * No need to close things down or anything.
993 */ 993 */
994 done = FALSE; 994 done = FALSE;
995 } 995 }
996 996
997 if (done) { 997 if (done) {
998 if (WIFEXITED(status)) { 998 if (WIFEXITED(status)) {
999 DEBUG2(JOB, "Process %d [%s] exited.\n", 999 DEBUG2(JOB, "Process %d [%s] exited.\n",
1000 job->pid, job->node->name); 1000 job->pid, job->node->name);
1001 if (WEXITSTATUS(status) != 0) { 1001 if (WEXITSTATUS(status) != 0) {
1002 if (job->node != lastNode) { 1002 if (job->node != lastNode) {
1003 MESSAGE(stdout, job->node); 1003 MESSAGE(stdout, job->node);
1004 lastNode = job->node; 1004 lastNode = job->node;
1005 } 1005 }
1006#ifdef USE_META 1006#ifdef USE_META
1007 if (useMeta) { 1007 if (useMeta) {
1008 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status)); 1008 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status));
1009 } 1009 }
1010#endif 1010#endif
1011 if (!dieQuietly(job->node, -1)) 1011 if (!dieQuietly(job->node, -1))
1012 (void)printf("*** [%s] Error code %d%s\n", 1012 (void)printf("*** [%s] Error code %d%s\n",
1013 job->node->name, 1013 job->node->name,
1014 WEXITSTATUS(status), 1014 WEXITSTATUS(status),
1015 (job->flags & JOB_IGNERR) ? " (ignored)" : ""); 1015 (job->flags & JOB_IGNERR) ? " (ignored)" : "");
1016 if (job->flags & JOB_IGNERR) { 1016 if (job->flags & JOB_IGNERR) {
1017 status = 0; 1017 status = 0;
1018 } else { 1018 } else {
1019 if (deleteOnError) { 1019 if (deleteOnError) {
1020 JobDeleteTarget(job->node); 1020 JobDeleteTarget(job->node);
1021 } 1021 }
1022 PrintOnError(job->node, NULL); 1022 PrintOnError(job->node, NULL);
1023 } 1023 }
1024 } else if (DEBUG(JOB)) { 1024 } else if (DEBUG(JOB)) {
1025 if (job->node != lastNode) { 1025 if (job->node != lastNode) {
1026 MESSAGE(stdout, job->node); 1026 MESSAGE(stdout, job->node);
1027 lastNode = job->node; 1027 lastNode = job->node;
1028 } 1028 }
1029 (void)printf("*** [%s] Completed successfully\n", 1029 (void)printf("*** [%s] Completed successfully\n",
1030 job->node->name); 1030 job->node->name);
1031 } 1031 }
1032 } else { 1032 } else {
1033 if (job->node != lastNode) { 1033 if (job->node != lastNode) {
1034 MESSAGE(stdout, job->node); 1034 MESSAGE(stdout, job->node);
1035 lastNode = job->node; 1035 lastNode = job->node;
1036 } 1036 }
1037 (void)printf("*** [%s] Signal %d\n", 1037 (void)printf("*** [%s] Signal %d\n",
1038 job->node->name, WTERMSIG(status)); 1038 job->node->name, WTERMSIG(status));
1039 if (deleteOnError) { 1039 if (deleteOnError) {
1040 JobDeleteTarget(job->node); 1040 JobDeleteTarget(job->node);
1041 } 1041 }
1042 } 1042 }
1043 (void)fflush(stdout); 1043 (void)fflush(stdout);
1044 } 1044 }
1045 1045
1046#ifdef USE_META 1046#ifdef USE_META
1047 if (useMeta) { 1047 if (useMeta) {
1048 int x; 1048 int x;
1049 1049
1050 if ((x = meta_job_finish(job)) != 0 && status == 0) { 1050 if ((x = meta_job_finish(job)) != 0 && status == 0) {
1051 status = x; 1051 status = x;
1052 } 1052 }
1053 } 1053 }
1054#endif 1054#endif
1055 1055
1056 return_job_token = FALSE; 1056 return_job_token = FALSE;
1057 1057
1058 Trace_Log(JOBEND, job); 1058 Trace_Log(JOBEND, job);
1059 if (!(job->flags & JOB_SPECIAL)) { 1059 if (!(job->flags & JOB_SPECIAL)) {
1060 if ((status != 0) || 1060 if ((status != 0) ||
1061 (aborting == ABORT_ERROR) || 1061 (aborting == ABORT_ERROR) ||
1062 (aborting == ABORT_INTERRUPT)) 1062 (aborting == ABORT_INTERRUPT))
1063 return_job_token = TRUE; 1063 return_job_token = TRUE;
1064 } 1064 }
1065 1065
1066 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) { 1066 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) {
1067 /* 1067 /*
1068 * As long as we aren't aborting and the job didn't return a non-zero 1068 * As long as we aren't aborting and the job didn't return a non-zero
1069 * status that we shouldn't ignore, we call Make_Update to update 1069 * status that we shouldn't ignore, we call Make_Update to update
1070 * the parents. 1070 * the parents.
1071 */ 1071 */
1072 JobSaveCommands(job); 1072 JobSaveCommands(job);
1073 job->node->made = MADE; 1073 job->node->made = MADE;
1074 if (!(job->flags & JOB_SPECIAL)) 1074 if (!(job->flags & JOB_SPECIAL))
1075 return_job_token = TRUE; 1075 return_job_token = TRUE;
1076 Make_Update(job->node); 1076 Make_Update(job->node);
1077 job->job_state = JOB_ST_FREE; 1077 job->job_state = JOB_ST_FREE;
1078 } else if (status != 0) { 1078 } else if (status != 0) {
1079 errors++; 1079 errors++;
1080 job->job_state = JOB_ST_FREE; 1080 job->job_state = JOB_ST_FREE;
1081 } 1081 }
1082 1082
1083 /* 1083 /*
1084 * Set aborting if any error. 1084 * Set aborting if any error.
1085 */ 1085 */
1086 if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) { 1086 if (errors && !opts.keepgoing && (aborting != ABORT_INTERRUPT)) {
1087 /* 1087 /*
1088 * If we found any errors in this batch of children and the -k flag 1088 * If we found any errors in this batch of children and the -k flag
1089 * wasn't given, we set the aborting flag so no more jobs get 1089 * wasn't given, we set the aborting flag so no more jobs get
1090 * started. 1090 * started.
1091 */ 1091 */
1092 aborting = ABORT_ERROR; 1092 aborting = ABORT_ERROR;
1093 } 1093 }
1094 1094
1095 if (return_job_token) 1095 if (return_job_token)
1096 Job_TokenReturn(); 1096 Job_TokenReturn();
1097 1097
1098 if (aborting == ABORT_ERROR && jobTokensRunning == 0) { 1098 if (aborting == ABORT_ERROR && jobTokensRunning == 0) {
1099 /* 1099 /*
1100 * If we are aborting and the job table is now empty, we finish. 1100 * If we are aborting and the job table is now empty, we finish.
1101 */ 1101 */
1102 Finish(errors); 1102 Finish(errors);
1103 } 1103 }
1104} 1104}
1105 1105
1106/* Touch the given target. Called by JobStart when the -t flag was given. 1106/* Touch the given target. Called by JobStart when the -t flag was given.
1107 * 1107 *
1108 * The modification date of the file is changed. 1108 * The modification date of the file is changed.
1109 * If the file did not exist, it is created. */ 1109 * If the file did not exist, it is created. */
1110void 1110void
1111Job_Touch(GNode *gn, Boolean silent) 1111Job_Touch(GNode *gn, Boolean silent)
1112{ 1112{
1113 int streamID; /* ID of stream opened to do the touch */ 1113 int streamID; /* ID of stream opened to do the touch */
1114 struct utimbuf times; /* Times for utime() call */ 1114 struct utimbuf times; /* Times for utime() call */
1115 1115
1116 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL| 1116 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|
1117 OP_SPECIAL|OP_PHONY)) { 1117 OP_SPECIAL|OP_PHONY)) {
1118 /* 1118 /*
1119 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 1119 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
1120 * and, as such, shouldn't really be created. 1120 * and, as such, shouldn't really be created.
1121 */ 1121 */
1122 return; 1122 return;
1123 } 1123 }
1124 1124
1125 if (!silent || NoExecute(gn)) { 1125 if (!silent || NoExecute(gn)) {
1126 (void)fprintf(stdout, "touch %s\n", gn->name); 1126 (void)fprintf(stdout, "touch %s\n", gn->name);
1127 (void)fflush(stdout); 1127 (void)fflush(stdout);
1128 } 1128 }
1129 1129
1130 if (NoExecute(gn)) { 1130 if (NoExecute(gn)) {
1131 return; 1131 return;
1132 } 1132 }
1133 1133
1134 if (gn->type & OP_ARCHV) { 1134 if (gn->type & OP_ARCHV) {
1135 Arch_Touch(gn); 1135 Arch_Touch(gn);
1136 } else if (gn->type & OP_LIB) { 1136 } else if (gn->type & OP_LIB) {
1137 Arch_TouchLib(gn); 1137 Arch_TouchLib(gn);
1138 } else { 1138 } else {
1139 const char *file = GNode_Path(gn); 1139 const char *file = GNode_Path(gn);
1140 1140
1141 times.actime = times.modtime = now; 1141 times.actime = times.modtime = now;
1142 if (utime(file, &times) < 0){ 1142 if (utime(file, &times) < 0){
1143 streamID = open(file, O_RDWR | O_CREAT, 0666); 1143 streamID = open(file, O_RDWR | O_CREAT, 0666);
1144 1144
1145 if (streamID >= 0) { 1145 if (streamID >= 0) {
@@ -1335,1516 +1335,1516 @@ JobExec(Job *job, char **argv) @@ -1335,1516 +1335,1516 @@ JobExec(Job *job, char **argv)
1335 /* 1335 /*
1336 * Set up the child's output to be routed through the pipe 1336 * Set up the child's output to be routed through the pipe
1337 * we've created for it. 1337 * we've created for it.
1338 */ 1338 */
1339 if (dup2(job->outPipe, 1) == -1) 1339 if (dup2(job->outPipe, 1) == -1)
1340 execDie("dup2", "job->outPipe"); 1340 execDie("dup2", "job->outPipe");
1341 1341
1342 /* 1342 /*
1343 * The output channels are marked close on exec. This bit was 1343 * The output channels are marked close on exec. This bit was
1344 * duplicated by the dup2(on some systems), so we have to clear 1344 * duplicated by the dup2(on some systems), so we have to clear
1345 * it before routing the shell's error output to the same place as 1345 * it before routing the shell's error output to the same place as
1346 * its standard output. 1346 * its standard output.
1347 */ 1347 */
1348 if (fcntl(1, F_SETFD, 0) == -1) 1348 if (fcntl(1, F_SETFD, 0) == -1)
1349 execDie("clear close-on-exec", "stdout"); 1349 execDie("clear close-on-exec", "stdout");
1350 if (dup2(1, 2) == -1) 1350 if (dup2(1, 2) == -1)
1351 execDie("dup2", "1, 2"); 1351 execDie("dup2", "1, 2");
1352 1352
1353 /* 1353 /*
1354 * We want to switch the child into a different process family so 1354 * We want to switch the child into a different process family so
1355 * we can kill it and all its descendants in one fell swoop, 1355 * we can kill it and all its descendants in one fell swoop,
1356 * by killing its process family, but not commit suicide. 1356 * by killing its process family, but not commit suicide.
1357 */ 1357 */
1358#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID) 1358#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID)
1359#if defined(SYSV) 1359#if defined(SYSV)
1360 /* XXX: dsl - I'm sure this should be setpgrp()... */ 1360 /* XXX: dsl - I'm sure this should be setpgrp()... */
1361 (void)setsid(); 1361 (void)setsid();
1362#else 1362#else
1363 (void)setpgid(0, getpid()); 1363 (void)setpgid(0, getpid());
1364#endif 1364#endif
1365#endif 1365#endif
1366 1366
1367 Var_ExportVars(); 1367 Var_ExportVars();
1368 1368
1369 (void)execv(shellPath, argv); 1369 (void)execv(shellPath, argv);
1370 execDie("exec", shellPath); 1370 execDie("exec", shellPath);
1371 } 1371 }
1372 1372
1373 /* Parent, continuing after the child exec */ 1373 /* Parent, continuing after the child exec */
1374 job->pid = cpid; 1374 job->pid = cpid;
1375 1375
1376 Trace_Log(JOBSTART, job); 1376 Trace_Log(JOBSTART, job);
1377 1377
1378#ifdef USE_META 1378#ifdef USE_META
1379 if (useMeta) { 1379 if (useMeta) {
1380 meta_job_parent(job, cpid); 1380 meta_job_parent(job, cpid);
1381 } 1381 }
1382#endif 1382#endif
1383 1383
1384 /* 1384 /*
1385 * Set the current position in the buffer to the beginning 1385 * Set the current position in the buffer to the beginning
1386 * and mark another stream to watch in the outputs mask 1386 * and mark another stream to watch in the outputs mask
1387 */ 1387 */
1388 job->curPos = 0; 1388 job->curPos = 0;
1389 1389
1390 watchfd(job); 1390 watchfd(job);
1391 1391
1392 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1392 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1393 (void)fclose(job->cmdFILE); 1393 (void)fclose(job->cmdFILE);
1394 job->cmdFILE = NULL; 1394 job->cmdFILE = NULL;
1395 } 1395 }
1396 1396
1397 /* 1397 /*
1398 * Now the job is actually running, add it to the table. 1398 * Now the job is actually running, add it to the table.
1399 */ 1399 */
1400 if (DEBUG(JOB)) { 1400 if (DEBUG(JOB)) {
1401 debug_printf("JobExec(%s): pid %d added to jobs table\n", 1401 debug_printf("JobExec(%s): pid %d added to jobs table\n",
1402 job->node->name, job->pid); 1402 job->node->name, job->pid);
1403 job_table_dump("job started"); 1403 job_table_dump("job started");
1404 } 1404 }
1405 JobSigUnlock(&mask); 1405 JobSigUnlock(&mask);
1406} 1406}
1407 1407
1408/* Create the argv needed to execute the shell for a given job. */ 1408/* Create the argv needed to execute the shell for a given job. */
1409static void 1409static void
1410JobMakeArgv(Job *job, char **argv) 1410JobMakeArgv(Job *job, char **argv)
1411{ 1411{
1412 int argc; 1412 int argc;
1413 static char args[10]; /* For merged arguments */ 1413 static char args[10]; /* For merged arguments */
1414 1414
1415 argv[0] = UNCONST(shellName); 1415 argv[0] = UNCONST(shellName);
1416 argc = 1; 1416 argc = 1;
1417 1417
1418 if ((commandShell->exit && commandShell->exit[0] != '-') || 1418 if ((commandShell->exit && commandShell->exit[0] != '-') ||
1419 (commandShell->echo && commandShell->echo[0] != '-')) 1419 (commandShell->echo && commandShell->echo[0] != '-'))
1420 { 1420 {
1421 /* 1421 /*
1422 * At least one of the flags doesn't have a minus before it, so 1422 * At least one of the flags doesn't have a minus before it, so
1423 * merge them together. Have to do this because the *(&(@*#*&#$# 1423 * merge them together. Have to do this because the *(&(@*#*&#$#
1424 * Bourne shell thinks its second argument is a file to source. 1424 * Bourne shell thinks its second argument is a file to source.
1425 * Grrrr. Note the ten-character limitation on the combined arguments. 1425 * Grrrr. Note the ten-character limitation on the combined arguments.
1426 */ 1426 */
1427 (void)snprintf(args, sizeof(args), "-%s%s", 1427 (void)snprintf(args, sizeof(args), "-%s%s",
1428 ((job->flags & JOB_IGNERR) ? "" : 1428 ((job->flags & JOB_IGNERR) ? "" :
1429 (commandShell->exit ? commandShell->exit : "")), 1429 (commandShell->exit ? commandShell->exit : "")),
1430 ((job->flags & JOB_SILENT) ? "" : 1430 ((job->flags & JOB_SILENT) ? "" :
1431 (commandShell->echo ? commandShell->echo : ""))); 1431 (commandShell->echo ? commandShell->echo : "")));
1432 1432
1433 if (args[1]) { 1433 if (args[1]) {
1434 argv[argc] = args; 1434 argv[argc] = args;
1435 argc++; 1435 argc++;
1436 } 1436 }
1437 } else { 1437 } else {
1438 if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1438 if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
1439 argv[argc] = UNCONST(commandShell->exit); 1439 argv[argc] = UNCONST(commandShell->exit);
1440 argc++; 1440 argc++;
1441 } 1441 }
1442 if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1442 if (!(job->flags & JOB_SILENT) && commandShell->echo) {
1443 argv[argc] = UNCONST(commandShell->echo); 1443 argv[argc] = UNCONST(commandShell->echo);
1444 argc++; 1444 argc++;
1445 } 1445 }
1446 } 1446 }
1447 argv[argc] = NULL; 1447 argv[argc] = NULL;
1448} 1448}
1449 1449
1450/*- 1450/*-
1451 *----------------------------------------------------------------------- 1451 *-----------------------------------------------------------------------
1452 * JobStart -- 1452 * JobStart --
1453 * Start a target-creation process going for the target described 1453 * Start a target-creation process going for the target described
1454 * by the graph node gn. 1454 * by the graph node gn.
1455 * 1455 *
1456 * Input: 1456 * Input:
1457 * gn target to create 1457 * gn target to create
1458 * flags flags for the job to override normal ones. 1458 * flags flags for the job to override normal ones.
1459 * e.g. JOB_SPECIAL or JOB_IGNDOTS 1459 * e.g. JOB_SPECIAL or JOB_IGNDOTS
1460 * previous The previous Job structure for this node, if any. 1460 * previous The previous Job structure for this node, if any.
1461 * 1461 *
1462 * Results: 1462 * Results:
1463 * JOB_ERROR if there was an error in the commands, JOB_FINISHED 1463 * JOB_ERROR if there was an error in the commands, JOB_FINISHED
1464 * if there isn't actually anything left to do for the job and 1464 * if there isn't actually anything left to do for the job and
1465 * JOB_RUNNING if the job has been started. 1465 * JOB_RUNNING if the job has been started.
1466 * 1466 *
1467 * Side Effects: 1467 * Side Effects:
1468 * A new Job node is created and added to the list of running 1468 * A new Job node is created and added to the list of running
1469 * jobs. PMake is forked and a child shell created. 1469 * jobs. PMake is forked and a child shell created.
1470 * 1470 *
1471 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set 1471 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set
1472 * JOB_IGNDOTS is never set (dsl) 1472 * JOB_IGNDOTS is never set (dsl)
1473 * Also the return value is ignored by everyone. 1473 * Also the return value is ignored by everyone.
1474 *----------------------------------------------------------------------- 1474 *-----------------------------------------------------------------------
1475 */ 1475 */
1476static JobStartResult 1476static JobStartResult
1477JobStart(GNode *gn, int flags) 1477JobStart(GNode *gn, int flags)
1478{ 1478{
1479 Job *job; /* new job descriptor */ 1479 Job *job; /* new job descriptor */
1480 char *argv[10]; /* Argument vector to shell */ 1480 char *argv[10]; /* Argument vector to shell */
1481 Boolean cmdsOK; /* true if the nodes commands were all right */ 1481 Boolean cmdsOK; /* true if the nodes commands were all right */
1482 Boolean noExec; /* Set true if we decide not to run the job */ 1482 Boolean noExec; /* Set true if we decide not to run the job */
1483 int tfd; /* File descriptor to the temp file */ 1483 int tfd; /* File descriptor to the temp file */
1484 1484
1485 for (job = job_table; job < job_table_end; job++) { 1485 for (job = job_table; job < job_table_end; job++) {
1486 if (job->job_state == JOB_ST_FREE) 1486 if (job->job_state == JOB_ST_FREE)
1487 break; 1487 break;
1488 } 1488 }
1489 if (job >= job_table_end) 1489 if (job >= job_table_end)
1490 Punt("JobStart no job slots vacant"); 1490 Punt("JobStart no job slots vacant");
1491 1491
1492 memset(job, 0, sizeof *job); 1492 memset(job, 0, sizeof *job);
1493 job->job_state = JOB_ST_SETUP; 1493 job->job_state = JOB_ST_SETUP;
1494 if (gn->type & OP_SPECIAL) 1494 if (gn->type & OP_SPECIAL)
1495 flags |= JOB_SPECIAL; 1495 flags |= JOB_SPECIAL;
1496 1496
1497 job->node = gn; 1497 job->node = gn;
1498 job->tailCmds = NULL; 1498 job->tailCmds = NULL;
1499 1499
1500 /* 1500 /*
1501 * Set the initial value of the flags for this job based on the global 1501 * Set the initial value of the flags for this job based on the global
1502 * ones and the node's attributes... Any flags supplied by the caller 1502 * ones and the node's attributes... Any flags supplied by the caller
1503 * are also added to the field. 1503 * are also added to the field.
1504 */ 1504 */
1505 job->flags = 0; 1505 job->flags = 0;
1506 if (Targ_Ignore(gn)) { 1506 if (Targ_Ignore(gn)) {
1507 job->flags |= JOB_IGNERR; 1507 job->flags |= JOB_IGNERR;
1508 } 1508 }
1509 if (Targ_Silent(gn)) { 1509 if (Targ_Silent(gn)) {
1510 job->flags |= JOB_SILENT; 1510 job->flags |= JOB_SILENT;
1511 } 1511 }
1512 job->flags |= flags; 1512 job->flags |= flags;
1513 1513
1514 /* 1514 /*
1515 * Check the commands now so any attributes from .DEFAULT have a chance 1515 * Check the commands now so any attributes from .DEFAULT have a chance
1516 * to migrate to the node 1516 * to migrate to the node
1517 */ 1517 */
1518 cmdsOK = Job_CheckCommands(gn, Error); 1518 cmdsOK = Job_CheckCommands(gn, Error);
1519 1519
1520 job->inPollfd = NULL; 1520 job->inPollfd = NULL;
1521 /* 1521 /*
1522 * If the -n flag wasn't given, we open up OUR (not the child's) 1522 * If the -n flag wasn't given, we open up OUR (not the child's)
1523 * temporary file to stuff commands in it. The thing is rd/wr so we don't 1523 * temporary file to stuff commands in it. The thing is rd/wr so we don't
1524 * need to reopen it to feed it to the shell. If the -n flag *was* given, 1524 * need to reopen it to feed it to the shell. If the -n flag *was* given,
1525 * we just set the file to be stdout. Cute, huh? 1525 * we just set the file to be stdout. Cute, huh?
1526 */ 1526 */
1527 if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) || 1527 if (((gn->type & OP_MAKE) && !opts.noRecursiveExecute) ||
1528 (!opts.noExecute && !opts.touchFlag)) { 1528 (!opts.noExecute && !opts.touchFlag)) {
1529 /* 1529 /*
1530 * tfile is the name of a file into which all shell commands are 1530 * tfile is the name of a file into which all shell commands are
1531 * put. It is removed before the child shell is executed, unless 1531 * put. It is removed before the child shell is executed, unless
1532 * DEBUG(SCRIPT) is set. 1532 * DEBUG(SCRIPT) is set.
1533 */ 1533 */
1534 char *tfile; 1534 char *tfile;
1535 sigset_t mask; 1535 sigset_t mask;
1536 /* 1536 /*
1537 * We're serious here, but if the commands were bogus, we're 1537 * We're serious here, but if the commands were bogus, we're
1538 * also dead... 1538 * also dead...
1539 */ 1539 */
1540 if (!cmdsOK) { 1540 if (!cmdsOK) {
1541 PrintOnError(gn, NULL); /* provide some clue */ 1541 PrintOnError(gn, NULL); /* provide some clue */
1542 DieHorribly(); 1542 DieHorribly();
1543 } 1543 }
1544 1544
1545 JobSigLock(&mask); 1545 JobSigLock(&mask);
1546 tfd = mkTempFile(TMPPAT, &tfile); 1546 tfd = mkTempFile(TMPPAT, &tfile);
1547 if (!DEBUG(SCRIPT)) 1547 if (!DEBUG(SCRIPT))
1548 (void)eunlink(tfile); 1548 (void)eunlink(tfile);
1549 JobSigUnlock(&mask); 1549 JobSigUnlock(&mask);
1550 1550
1551 job->cmdFILE = fdopen(tfd, "w+"); 1551 job->cmdFILE = fdopen(tfd, "w+");
1552 if (job->cmdFILE == NULL) { 1552 if (job->cmdFILE == NULL) {
1553 Punt("Could not fdopen %s", tfile); 1553 Punt("Could not fdopen %s", tfile);
1554 } 1554 }
1555 (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC); 1555 (void)fcntl(fileno(job->cmdFILE), F_SETFD, FD_CLOEXEC);
1556 /* 1556 /*
1557 * Send the commands to the command file, flush all its buffers then 1557 * Send the commands to the command file, flush all its buffers then
1558 * rewind and remove the thing. 1558 * rewind and remove the thing.
1559 */ 1559 */
1560 noExec = FALSE; 1560 noExec = FALSE;
1561 1561
1562#ifdef USE_META 1562#ifdef USE_META
1563 if (useMeta) { 1563 if (useMeta) {
1564 meta_job_start(job, gn); 1564 meta_job_start(job, gn);
1565 if (Targ_Silent(gn)) { /* might have changed */ 1565 if (Targ_Silent(gn)) { /* might have changed */
1566 job->flags |= JOB_SILENT; 1566 job->flags |= JOB_SILENT;
1567 } 1567 }
1568 } 1568 }
1569#endif 1569#endif
1570 /* 1570 /*
1571 * We can do all the commands at once. hooray for sanity 1571 * We can do all the commands at once. hooray for sanity
1572 */ 1572 */
1573 numCommands = 0; 1573 numCommands = 0;
1574 JobPrintCommands(job); 1574 JobPrintCommands(job);
1575 1575
1576 /* 1576 /*
1577 * If we didn't print out any commands to the shell script, 1577 * If we didn't print out any commands to the shell script,
1578 * there's not much point in executing the shell, is there? 1578 * there's not much point in executing the shell, is there?
1579 */ 1579 */
1580 if (numCommands == 0) { 1580 if (numCommands == 0) {
1581 noExec = TRUE; 1581 noExec = TRUE;
1582 } 1582 }
1583 1583
1584 free(tfile); 1584 free(tfile);
1585 } else if (NoExecute(gn)) { 1585 } else if (NoExecute(gn)) {
1586 /* 1586 /*
1587 * Not executing anything -- just print all the commands to stdout 1587 * Not executing anything -- just print all the commands to stdout
1588 * in one fell swoop. This will still set up job->tailCmds correctly. 1588 * in one fell swoop. This will still set up job->tailCmds correctly.
1589 */ 1589 */
1590 if (lastNode != gn) { 1590 if (lastNode != gn) {
1591 MESSAGE(stdout, gn); 1591 MESSAGE(stdout, gn);
1592 lastNode = gn; 1592 lastNode = gn;
1593 } 1593 }
1594 job->cmdFILE = stdout; 1594 job->cmdFILE = stdout;
1595 /* 1595 /*
1596 * Only print the commands if they're ok, but don't die if they're 1596 * Only print the commands if they're ok, but don't die if they're
1597 * not -- just let the user know they're bad and keep going. It 1597 * not -- just let the user know they're bad and keep going. It
1598 * doesn't do any harm in this case and may do some good. 1598 * doesn't do any harm in this case and may do some good.
1599 */ 1599 */
1600 if (cmdsOK) 1600 if (cmdsOK)
1601 JobPrintCommands(job); 1601 JobPrintCommands(job);
1602 /* 1602 /*
1603 * Don't execute the shell, thank you. 1603 * Don't execute the shell, thank you.
1604 */ 1604 */
1605 noExec = TRUE; 1605 noExec = TRUE;
1606 } else { 1606 } else {
1607 /* 1607 /*
1608 * Just touch the target and note that no shell should be executed. 1608 * Just touch the target and note that no shell should be executed.
1609 * Set cmdFILE to stdout to make life easier. Check the commands, too, 1609 * Set cmdFILE to stdout to make life easier. Check the commands, too,
1610 * but don't die if they're no good -- it does no harm to keep working 1610 * but don't die if they're no good -- it does no harm to keep working
1611 * up the graph. 1611 * up the graph.
1612 */ 1612 */
1613 job->cmdFILE = stdout; 1613 job->cmdFILE = stdout;
1614 Job_Touch(gn, job->flags&JOB_SILENT); 1614 Job_Touch(gn, job->flags&JOB_SILENT);
1615 noExec = TRUE; 1615 noExec = TRUE;
1616 } 1616 }
1617 /* Just in case it isn't already... */ 1617 /* Just in case it isn't already... */
1618 (void)fflush(job->cmdFILE); 1618 (void)fflush(job->cmdFILE);
1619 1619
1620 /* 1620 /*
1621 * If we're not supposed to execute a shell, don't. 1621 * If we're not supposed to execute a shell, don't.
1622 */ 1622 */
1623 if (noExec) { 1623 if (noExec) {
1624 if (!(job->flags & JOB_SPECIAL)) 1624 if (!(job->flags & JOB_SPECIAL))
1625 Job_TokenReturn(); 1625 Job_TokenReturn();
1626 /* 1626 /*
1627 * Unlink and close the command file if we opened one 1627 * Unlink and close the command file if we opened one
1628 */ 1628 */
1629 if (job->cmdFILE != stdout) { 1629 if (job->cmdFILE != stdout) {
1630 if (job->cmdFILE != NULL) { 1630 if (job->cmdFILE != NULL) {
1631 (void)fclose(job->cmdFILE); 1631 (void)fclose(job->cmdFILE);
1632 job->cmdFILE = NULL; 1632 job->cmdFILE = NULL;
1633 } 1633 }
1634 } 1634 }
1635 1635
1636 /* 1636 /*
1637 * We only want to work our way up the graph if we aren't here because 1637 * We only want to work our way up the graph if we aren't here because
1638 * the commands for the job were no good. 1638 * the commands for the job were no good.
1639 */ 1639 */
1640 if (cmdsOK && aborting == 0) { 1640 if (cmdsOK && aborting == 0) {
1641 JobSaveCommands(job); 1641 JobSaveCommands(job);
1642 job->node->made = MADE; 1642 job->node->made = MADE;
1643 Make_Update(job->node); 1643 Make_Update(job->node);
1644 } 1644 }
1645 job->job_state = JOB_ST_FREE; 1645 job->job_state = JOB_ST_FREE;
1646 return cmdsOK ? JOB_FINISHED : JOB_ERROR; 1646 return cmdsOK ? JOB_FINISHED : JOB_ERROR;
1647 } 1647 }
1648 1648
1649 /* 1649 /*
1650 * Set up the control arguments to the shell. This is based on the flags 1650 * Set up the control arguments to the shell. This is based on the flags
1651 * set earlier for this job. 1651 * set earlier for this job.
1652 */ 1652 */
1653 JobMakeArgv(job, argv); 1653 JobMakeArgv(job, argv);
1654 1654
1655 /* Create the pipe by which we'll get the shell's output. */ 1655 /* Create the pipe by which we'll get the shell's output. */
1656 JobCreatePipe(job, 3); 1656 JobCreatePipe(job, 3);
1657 1657
1658 JobExec(job, argv); 1658 JobExec(job, argv);
1659 return JOB_RUNNING; 1659 return JOB_RUNNING;
1660} 1660}
1661 1661
1662static char * 1662static char *
1663JobOutput(Job *job, char *cp, char *endp) 1663JobOutput(Job *job, char *cp, char *endp)
1664{ 1664{
1665 char *ecp; 1665 char *ecp;
1666 1666
1667 if (commandShell->noPrint && commandShell->noPrint[0] != '\0') { 1667 if (commandShell->noPrint && commandShell->noPrint[0] != '\0') {
1668 while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) { 1668 while ((ecp = strstr(cp, commandShell->noPrint)) != NULL) {
1669 if (cp != ecp) { 1669 if (cp != ecp) {
1670 *ecp = '\0'; 1670 *ecp = '\0';
1671 /* 1671 /*
1672 * The only way there wouldn't be a newline after 1672 * The only way there wouldn't be a newline after
1673 * this line is if it were the last in the buffer. 1673 * this line is if it were the last in the buffer.
1674 * however, since the non-printable comes after it, 1674 * however, since the non-printable comes after it,
1675 * there must be a newline, so we don't print one. 1675 * there must be a newline, so we don't print one.
1676 */ 1676 */
1677 (void)fprintf(stdout, "%s", cp); 1677 (void)fprintf(stdout, "%s", cp);
1678 (void)fflush(stdout); 1678 (void)fflush(stdout);
1679 } 1679 }
1680 cp = ecp + commandShell->noPrintLen; 1680 cp = ecp + commandShell->noPrintLen;
1681 if (cp != endp) { 1681 if (cp != endp) {
1682 /* 1682 /*
1683 * Still more to print, look again after skipping 1683 * Still more to print, look again after skipping
1684 * the whitespace following the non-printable 1684 * the whitespace following the non-printable
1685 * command.... 1685 * command....
1686 */ 1686 */
1687 cp++; 1687 cp++;
1688 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 1688 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
1689 cp++; 1689 cp++;
1690 } 1690 }
1691 } else { 1691 } else {
1692 return cp; 1692 return cp;
1693 } 1693 }
1694 } 1694 }
1695 } 1695 }
1696 return cp; 1696 return cp;
1697} 1697}
1698 1698
1699/*- 1699/*-
1700 *----------------------------------------------------------------------- 1700 *-----------------------------------------------------------------------
1701 * JobDoOutput -- 1701 * JobDoOutput --
1702 * This function is called at different times depending on 1702 * This function is called at different times depending on
1703 * whether the user has specified that output is to be collected 1703 * whether the user has specified that output is to be collected
1704 * via pipes or temporary files. In the former case, we are called 1704 * via pipes or temporary files. In the former case, we are called
1705 * whenever there is something to read on the pipe. We collect more 1705 * whenever there is something to read on the pipe. We collect more
1706 * output from the given job and store it in the job's outBuf. If 1706 * output from the given job and store it in the job's outBuf. If
1707 * this makes up a line, we print it tagged by the job's identifier, 1707 * this makes up a line, we print it tagged by the job's identifier,
1708 * as necessary. 1708 * as necessary.
1709 * If output has been collected in a temporary file, we open the 1709 * If output has been collected in a temporary file, we open the
1710 * file and read it line by line, transferring it to our own 1710 * file and read it line by line, transferring it to our own
1711 * output channel until the file is empty. At which point we 1711 * output channel until the file is empty. At which point we
1712 * remove the temporary file. 1712 * remove the temporary file.
1713 * In both cases, however, we keep our figurative eye out for the 1713 * In both cases, however, we keep our figurative eye out for the
1714 * 'noPrint' line for the shell from which the output came. If 1714 * 'noPrint' line for the shell from which the output came. If
1715 * we recognize a line, we don't print it. If the command is not 1715 * we recognize a line, we don't print it. If the command is not
1716 * alone on the line (the character after it is not \0 or \n), we 1716 * alone on the line (the character after it is not \0 or \n), we
1717 * do print whatever follows it. 1717 * do print whatever follows it.
1718 * 1718 *
1719 * Input: 1719 * Input:
1720 * job the job whose output needs printing 1720 * job the job whose output needs printing
1721 * finish TRUE if this is the last time we'll be called 1721 * finish TRUE if this is the last time we'll be called
1722 * for this job 1722 * for this job
1723 * 1723 *
1724 * Results: 1724 * Results:
1725 * None 1725 * None
1726 * 1726 *
1727 * Side Effects: 1727 * Side Effects:
1728 * curPos may be shifted as may the contents of outBuf. 1728 * curPos may be shifted as may the contents of outBuf.
1729 *----------------------------------------------------------------------- 1729 *-----------------------------------------------------------------------
1730 */ 1730 */
1731static void 1731static void
1732JobDoOutput(Job *job, Boolean finish) 1732JobDoOutput(Job *job, Boolean finish)
1733{ 1733{
1734 Boolean gotNL = FALSE; /* true if got a newline */ 1734 Boolean gotNL = FALSE; /* true if got a newline */
1735 Boolean fbuf; /* true if our buffer filled up */ 1735 Boolean fbuf; /* true if our buffer filled up */
1736 size_t nr; /* number of bytes read */ 1736 size_t nr; /* number of bytes read */
1737 size_t i; /* auxiliary index into outBuf */ 1737 size_t i; /* auxiliary index into outBuf */
1738 size_t max; /* limit for i (end of current data) */ 1738 size_t max; /* limit for i (end of current data) */
1739 ssize_t nRead; /* (Temporary) number of bytes read */ 1739 ssize_t nRead; /* (Temporary) number of bytes read */
1740 1740
1741 /* 1741 /*
1742 * Read as many bytes as will fit in the buffer. 1742 * Read as many bytes as will fit in the buffer.
1743 */ 1743 */
1744end_loop: 1744end_loop:
1745 gotNL = FALSE; 1745 gotNL = FALSE;
1746 fbuf = FALSE; 1746 fbuf = FALSE;
1747 1747
1748 nRead = read(job->inPipe, &job->outBuf[job->curPos], 1748 nRead = read(job->inPipe, &job->outBuf[job->curPos],
1749 JOB_BUFSIZE - job->curPos); 1749 JOB_BUFSIZE - job->curPos);
1750 if (nRead < 0) { 1750 if (nRead < 0) {
1751 if (errno == EAGAIN) 1751 if (errno == EAGAIN)
1752 return; 1752 return;
1753 if (DEBUG(JOB)) { 1753 if (DEBUG(JOB)) {
1754 perror("JobDoOutput(piperead)"); 1754 perror("JobDoOutput(piperead)");
1755 } 1755 }
1756 nr = 0; 1756 nr = 0;
1757 } else { 1757 } else {
1758 nr = (size_t)nRead; 1758 nr = (size_t)nRead;
1759 } 1759 }
1760 1760
1761 /* 1761 /*
1762 * If we hit the end-of-file (the job is dead), we must flush its 1762 * If we hit the end-of-file (the job is dead), we must flush its
1763 * remaining output, so pretend we read a newline if there's any 1763 * remaining output, so pretend we read a newline if there's any
1764 * output remaining in the buffer. 1764 * output remaining in the buffer.
1765 * Also clear the 'finish' flag so we stop looping. 1765 * Also clear the 'finish' flag so we stop looping.
1766 */ 1766 */
1767 if ((nr == 0) && (job->curPos != 0)) { 1767 if ((nr == 0) && (job->curPos != 0)) {
1768 job->outBuf[job->curPos] = '\n'; 1768 job->outBuf[job->curPos] = '\n';
1769 nr = 1; 1769 nr = 1;
1770 finish = FALSE; 1770 finish = FALSE;
1771 } else if (nr == 0) { 1771 } else if (nr == 0) {
1772 finish = FALSE; 1772 finish = FALSE;
1773 } 1773 }
1774 1774
1775 /* 1775 /*
1776 * Look for the last newline in the bytes we just got. If there is 1776 * Look for the last newline in the bytes we just got. If there is
1777 * one, break out of the loop with 'i' as its index and gotNL set 1777 * one, break out of the loop with 'i' as its index and gotNL set
1778 * TRUE. 1778 * TRUE.
1779 */ 1779 */
1780 max = job->curPos + nr; 1780 max = job->curPos + nr;
1781 for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) { 1781 for (i = job->curPos + nr - 1; i >= job->curPos && i != (size_t)-1; i--) {
1782 if (job->outBuf[i] == '\n') { 1782 if (job->outBuf[i] == '\n') {
1783 gotNL = TRUE; 1783 gotNL = TRUE;
1784 break; 1784 break;
1785 } else if (job->outBuf[i] == '\0') { 1785 } else if (job->outBuf[i] == '\0') {
1786 /* 1786 /*
1787 * Why? 1787 * Why?
1788 */ 1788 */
1789 job->outBuf[i] = ' '; 1789 job->outBuf[i] = ' ';
1790 } 1790 }
1791 } 1791 }
1792 1792
1793 if (!gotNL) { 1793 if (!gotNL) {
1794 job->curPos += nr; 1794 job->curPos += nr;
1795 if (job->curPos == JOB_BUFSIZE) { 1795 if (job->curPos == JOB_BUFSIZE) {
1796 /* 1796 /*
1797 * If we've run out of buffer space, we have no choice 1797 * If we've run out of buffer space, we have no choice
1798 * but to print the stuff. sigh. 1798 * but to print the stuff. sigh.
1799 */ 1799 */
1800 fbuf = TRUE; 1800 fbuf = TRUE;
1801 i = job->curPos; 1801 i = job->curPos;
1802 } 1802 }
1803 } 1803 }
1804 if (gotNL || fbuf) { 1804 if (gotNL || fbuf) {
1805 /* 1805 /*
1806 * Need to send the output to the screen. Null terminate it 1806 * Need to send the output to the screen. Null terminate it
1807 * first, overwriting the newline character if there was one. 1807 * first, overwriting the newline character if there was one.
1808 * So long as the line isn't one we should filter (according 1808 * So long as the line isn't one we should filter (according
1809 * to the shell description), we print the line, preceded 1809 * to the shell description), we print the line, preceded
1810 * by a target banner if this target isn't the same as the 1810 * by a target banner if this target isn't the same as the
1811 * one for which we last printed something. 1811 * one for which we last printed something.
1812 * The rest of the data in the buffer are then shifted down 1812 * The rest of the data in the buffer are then shifted down
1813 * to the start of the buffer and curPos is set accordingly. 1813 * to the start of the buffer and curPos is set accordingly.
1814 */ 1814 */
1815 job->outBuf[i] = '\0'; 1815 job->outBuf[i] = '\0';
1816 if (i >= job->curPos) { 1816 if (i >= job->curPos) {
1817 char *cp; 1817 char *cp;
1818 1818
1819 cp = JobOutput(job, job->outBuf, &job->outBuf[i]); 1819 cp = JobOutput(job, job->outBuf, &job->outBuf[i]);
1820 1820
1821 /* 1821 /*
1822 * There's still more in that thar buffer. This time, though, 1822 * There's still more in that thar buffer. This time, though,
1823 * we know there's no newline at the end, so we add one of 1823 * we know there's no newline at the end, so we add one of
1824 * our own free will. 1824 * our own free will.
1825 */ 1825 */
1826 if (*cp != '\0') { 1826 if (*cp != '\0') {
1827 if (!opts.beSilent && job->node != lastNode) { 1827 if (!opts.beSilent && job->node != lastNode) {
1828 MESSAGE(stdout, job->node); 1828 MESSAGE(stdout, job->node);
1829 lastNode = job->node; 1829 lastNode = job->node;
1830 } 1830 }
1831#ifdef USE_META 1831#ifdef USE_META
1832 if (useMeta) { 1832 if (useMeta) {
1833 meta_job_output(job, cp, gotNL ? "\n" : ""); 1833 meta_job_output(job, cp, gotNL ? "\n" : "");
1834 } 1834 }
1835#endif 1835#endif
1836 (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : ""); 1836 (void)fprintf(stdout, "%s%s", cp, gotNL ? "\n" : "");
1837 (void)fflush(stdout); 1837 (void)fflush(stdout);
1838 } 1838 }
1839 } 1839 }
1840 /* 1840 /*
1841 * max is the last offset still in the buffer. Move any remaining 1841 * max is the last offset still in the buffer. Move any remaining
1842 * characters to the start of the buffer and update the end marker 1842 * characters to the start of the buffer and update the end marker
1843 * curPos. 1843 * curPos.
1844 */ 1844 */
1845 if (i < max) { 1845 if (i < max) {
1846 (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1)); 1846 (void)memmove(job->outBuf, &job->outBuf[i + 1], max - (i + 1));
1847 job->curPos = max - (i + 1); 1847 job->curPos = max - (i + 1);
1848 } else { 1848 } else {
1849 assert(i == max); 1849 assert(i == max);
1850 job->curPos = 0; 1850 job->curPos = 0;
1851 } 1851 }
1852 } 1852 }
1853 if (finish) { 1853 if (finish) {
1854 /* 1854 /*
1855 * If the finish flag is true, we must loop until we hit 1855 * If the finish flag is true, we must loop until we hit
1856 * end-of-file on the pipe. This is guaranteed to happen 1856 * end-of-file on the pipe. This is guaranteed to happen
1857 * eventually since the other end of the pipe is now closed 1857 * eventually since the other end of the pipe is now closed
1858 * (we closed it explicitly and the child has exited). When 1858 * (we closed it explicitly and the child has exited). When
1859 * we do get an EOF, finish will be set FALSE and we'll fall 1859 * we do get an EOF, finish will be set FALSE and we'll fall
1860 * through and out. 1860 * through and out.
1861 */ 1861 */
1862 goto end_loop; 1862 goto end_loop;
1863 } 1863 }
1864} 1864}
1865 1865
1866static void 1866static void
1867JobRun(GNode *targ) 1867JobRun(GNode *targ)
1868{ 1868{
1869#if 0 1869#if 0
1870 /* 1870 /*
1871 * Unfortunately it is too complicated to run .BEGIN, .END, and 1871 * Unfortunately it is too complicated to run .BEGIN, .END, and
1872 * .INTERRUPT job in the parallel job module. As of 2020-09-25, 1872 * .INTERRUPT job in the parallel job module. As of 2020-09-25,
1873 * unit-tests/deptgt-end-jobs.mk hangs in an endless loop. 1873 * unit-tests/deptgt-end-jobs.mk hangs in an endless loop.
1874 * 1874 *
1875 * Running these jobs in compat mode also guarantees that these 1875 * Running these jobs in compat mode also guarantees that these
1876 * jobs do not overlap with other unrelated jobs. 1876 * jobs do not overlap with other unrelated jobs.
1877 */ 1877 */
1878 List *lst = Lst_New(); 1878 List *lst = Lst_New();
1879 Lst_Append(lst, targ); 1879 Lst_Append(lst, targ);
1880 (void)Make_Run(lst); 1880 (void)Make_Run(lst);
1881 Lst_Destroy(lst, NULL); 1881 Lst_Destroy(lst, NULL);
1882 JobStart(targ, JOB_SPECIAL); 1882 JobStart(targ, JOB_SPECIAL);
1883 while (jobTokensRunning) { 1883 while (jobTokensRunning) {
1884 Job_CatchOutput(); 1884 Job_CatchOutput();
1885 } 1885 }
1886#else 1886#else
1887 Compat_Make(targ, targ); 1887 Compat_Make(targ, targ);
1888 if (targ->made == ERROR) { 1888 if (targ->made == ERROR) {
1889 PrintOnError(targ, "\n\nStop."); 1889 PrintOnError(targ, "\n\nStop.");
1890 exit(1); 1890 exit(1);
1891 } 1891 }
1892#endif 1892#endif
1893} 1893}
1894 1894
1895/* Handle the exit of a child. Called from Make_Make. 1895/* Handle the exit of a child. Called from Make_Make.
1896 * 1896 *
1897 * The job descriptor is removed from the list of children. 1897 * The job descriptor is removed from the list of children.
1898 * 1898 *
1899 * Notes: 1899 * Notes:
1900 * We do waits, blocking or not, according to the wisdom of our 1900 * We do waits, blocking or not, according to the wisdom of our
1901 * caller, until there are no more children to report. For each 1901 * caller, until there are no more children to report. For each
1902 * job, call JobFinish to finish things off. 1902 * job, call JobFinish to finish things off.
1903 */ 1903 */
1904void 1904void
1905Job_CatchChildren(void) 1905Job_CatchChildren(void)
1906{ 1906{
1907 int pid; /* pid of dead child */ 1907 int pid; /* pid of dead child */
1908 int status; /* Exit/termination status */ 1908 int status; /* Exit/termination status */
1909 1909
1910 /* 1910 /*
1911 * Don't even bother if we know there's no one around. 1911 * Don't even bother if we know there's no one around.
1912 */ 1912 */
1913 if (jobTokensRunning == 0) 1913 if (jobTokensRunning == 0)
1914 return; 1914 return;
1915 1915
1916 while ((pid = waitpid((pid_t) -1, &status, WNOHANG | WUNTRACED)) > 0) { 1916 while ((pid = waitpid((pid_t) -1, &status, WNOHANG | WUNTRACED)) > 0) {
1917 DEBUG2(JOB, "Process %d exited/stopped status %x.\n", pid, status); 1917 DEBUG2(JOB, "Process %d exited/stopped status %x.\n", pid, status);
1918 JobReapChild(pid, status, TRUE); 1918 JobReapChild(pid, status, TRUE);
1919 } 1919 }
1920} 1920}
1921 1921
1922/* 1922/*
1923 * It is possible that wait[pid]() was called from elsewhere, 1923 * It is possible that wait[pid]() was called from elsewhere,
1924 * this lets us reap jobs regardless. 1924 * this lets us reap jobs regardless.
1925 */ 1925 */
1926void 1926void
1927JobReapChild(pid_t pid, int status, Boolean isJobs) 1927JobReapChild(pid_t pid, int status, Boolean isJobs)
1928{ 1928{
1929 Job *job; /* job descriptor for dead child */ 1929 Job *job; /* job descriptor for dead child */
1930 1930
1931 /* 1931 /*
1932 * Don't even bother if we know there's no one around. 1932 * Don't even bother if we know there's no one around.
1933 */ 1933 */
1934 if (jobTokensRunning == 0) 1934 if (jobTokensRunning == 0)
1935 return; 1935 return;
1936 1936
1937 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs); 1937 job = JobFindPid(pid, JOB_ST_RUNNING, isJobs);
1938 if (job == NULL) { 1938 if (job == NULL) {
1939 if (isJobs) { 1939 if (isJobs) {
1940 if (!lurking_children) 1940 if (!lurking_children)
1941 Error("Child (%d) status %x not in table?", pid, status); 1941 Error("Child (%d) status %x not in table?", pid, status);
1942 } 1942 }
1943 return; /* not ours */ 1943 return; /* not ours */
1944 } 1944 }
1945 if (WIFSTOPPED(status)) { 1945 if (WIFSTOPPED(status)) {
1946 DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name); 1946 DEBUG2(JOB, "Process %d (%s) stopped.\n", job->pid, job->node->name);
1947 if (!make_suspended) { 1947 if (!make_suspended) {
1948 switch (WSTOPSIG(status)) { 1948 switch (WSTOPSIG(status)) {
1949 case SIGTSTP: 1949 case SIGTSTP:
1950 (void)printf("*** [%s] Suspended\n", job->node->name); 1950 (void)printf("*** [%s] Suspended\n", job->node->name);
1951 break; 1951 break;
1952 case SIGSTOP: 1952 case SIGSTOP:
1953 (void)printf("*** [%s] Stopped\n", job->node->name); 1953 (void)printf("*** [%s] Stopped\n", job->node->name);
1954 break; 1954 break;
1955 default: 1955 default:
1956 (void)printf("*** [%s] Stopped -- signal %d\n", 1956 (void)printf("*** [%s] Stopped -- signal %d\n",
1957 job->node->name, WSTOPSIG(status)); 1957 job->node->name, WSTOPSIG(status));
1958 } 1958 }
1959 job->job_suspended = 1; 1959 job->job_suspended = 1;
1960 } 1960 }
1961 (void)fflush(stdout); 1961 (void)fflush(stdout);
1962 return; 1962 return;
1963 } 1963 }
1964 1964
1965 job->job_state = JOB_ST_FINISHED; 1965 job->job_state = JOB_ST_FINISHED;
1966 job->exit_status = status; 1966 job->exit_status = status;
1967 1967
1968 JobFinish(job, status); 1968 JobFinish(job, status);
1969} 1969}
1970 1970
1971/* Catch the output from our children, if we're using pipes do so. Otherwise 1971/* Catch the output from our children, if we're using pipes do so. Otherwise
1972 * just block time until we get a signal(most likely a SIGCHLD) since there's 1972 * just block time until we get a signal(most likely a SIGCHLD) since there's
1973 * no point in just spinning when there's nothing to do and the reaping of a 1973 * no point in just spinning when there's nothing to do and the reaping of a
1974 * child can wait for a while. */ 1974 * child can wait for a while. */
1975void 1975void
1976Job_CatchOutput(void) 1976Job_CatchOutput(void)
1977{ 1977{
1978 int nready; 1978 int nready;
1979 Job *job; 1979 Job *job;
1980 unsigned int i; 1980 unsigned int i;
1981 1981
1982 (void)fflush(stdout); 1982 (void)fflush(stdout);
1983 1983
1984 /* The first fd in the list is the job token pipe */ 1984 /* The first fd in the list is the job token pipe */
1985 do { 1985 do {
1986 nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC); 1986 nready = poll(fds + 1 - wantToken, nfds - 1 + wantToken, POLL_MSEC);
1987 } while (nready < 0 && errno == EINTR); 1987 } while (nready < 0 && errno == EINTR);
1988 1988
1989 if (nready < 0) 1989 if (nready < 0)
1990 Punt("poll: %s", strerror(errno)); 1990 Punt("poll: %s", strerror(errno));
1991 1991
1992 if (nready > 0 && readyfd(&childExitJob)) { 1992 if (nready > 0 && readyfd(&childExitJob)) {
1993 char token = 0; 1993 char token = 0;
1994 ssize_t count; 1994 ssize_t count;
1995 count = read(childExitJob.inPipe, &token, 1); 1995 count = read(childExitJob.inPipe, &token, 1);
1996 switch (count) { 1996 switch (count) {
1997 case 0: 1997 case 0:
1998 Punt("unexpected eof on token pipe"); 1998 Punt("unexpected eof on token pipe");
1999 case -1: 1999 case -1:
2000 Punt("token pipe read: %s", strerror(errno)); 2000 Punt("token pipe read: %s", strerror(errno));
2001 case 1: 2001 case 1:
2002 if (token == DO_JOB_RESUME[0]) 2002 if (token == DO_JOB_RESUME[0])
2003 /* Complete relay requested from our SIGCONT handler */ 2003 /* Complete relay requested from our SIGCONT handler */
2004 JobRestartJobs(); 2004 JobRestartJobs();
2005 break; 2005 break;
2006 default: 2006 default:
2007 abort(); 2007 abort();
2008 } 2008 }
2009 --nready; 2009 --nready;
2010 } 2010 }
2011 2011
2012 Job_CatchChildren(); 2012 Job_CatchChildren();
2013 if (nready == 0) 2013 if (nready == 0)
2014 return; 2014 return;
2015 2015
2016 for (i = npseudojobs * nfds_per_job(); i < nfds; i++) { 2016 for (i = npseudojobs * nfds_per_job(); i < nfds; i++) {
2017 if (!fds[i].revents) 2017 if (!fds[i].revents)
2018 continue; 2018 continue;
2019 job = jobfds[i]; 2019 job = jobfds[i];
2020 if (job->job_state == JOB_ST_RUNNING) 2020 if (job->job_state == JOB_ST_RUNNING)
2021 JobDoOutput(job, FALSE); 2021 JobDoOutput(job, FALSE);
2022#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2022#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2023 /* 2023 /*
2024 * With meta mode, we may have activity on the job's filemon 2024 * With meta mode, we may have activity on the job's filemon
2025 * descriptor too, which at the moment is any pollfd other than 2025 * descriptor too, which at the moment is any pollfd other than
2026 * job->inPollfd. 2026 * job->inPollfd.
2027 */ 2027 */
2028 if (useMeta && job->inPollfd != &fds[i]) { 2028 if (useMeta && job->inPollfd != &fds[i]) {
2029 if (meta_job_event(job) <= 0) { 2029 if (meta_job_event(job) <= 0) {
2030 fds[i].events = 0; /* never mind */ 2030 fds[i].events = 0; /* never mind */
2031 } 2031 }
2032 } 2032 }
2033#endif 2033#endif
2034 if (--nready == 0) 2034 if (--nready == 0)
2035 return; 2035 return;
2036 } 2036 }
2037} 2037}
2038 2038
2039/* Start the creation of a target. Basically a front-end for JobStart used by 2039/* Start the creation of a target. Basically a front-end for JobStart used by
2040 * the Make module. */ 2040 * the Make module. */
2041void 2041void
2042Job_Make(GNode *gn) 2042Job_Make(GNode *gn)
2043{ 2043{
2044 (void)JobStart(gn, 0); 2044 (void)JobStart(gn, 0);
2045} 2045}
2046 2046
2047void 2047void
2048Shell_Init(void) 2048Shell_Init(void)
2049{ 2049{
2050 if (shellPath == NULL) { 2050 if (shellPath == NULL) {
2051 /* 2051 /*
2052 * We are using the default shell, which may be an absolute 2052 * We are using the default shell, which may be an absolute
2053 * path if DEFSHELL_CUSTOM is defined. 2053 * path if DEFSHELL_CUSTOM is defined.
2054 */ 2054 */
2055 shellName = commandShell->name; 2055 shellName = commandShell->name;
2056#ifdef DEFSHELL_CUSTOM 2056#ifdef DEFSHELL_CUSTOM
2057 if (*shellName == '/') { 2057 if (*shellName == '/') {
2058 shellPath = shellName; 2058 shellPath = shellName;
2059 shellName = strrchr(shellPath, '/'); 2059 shellName = strrchr(shellPath, '/');
2060 shellName++; 2060 shellName++;
2061 } else 2061 } else
2062#endif 2062#endif
2063 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName); 2063 shellPath = str_concat3(_PATH_DEFSHELLDIR, "/", shellName);
2064 } 2064 }
2065 Var_Set_with_flags(".SHELL", shellPath, VAR_CMD, VAR_SET_READONLY); 2065 Var_Set_with_flags(".SHELL", shellPath, VAR_CMD, VAR_SET_READONLY);
2066 if (commandShell->exit == NULL) { 2066 if (commandShell->exit == NULL) {
2067 commandShell->exit = ""; 2067 commandShell->exit = "";
2068 } 2068 }
2069 if (commandShell->echo == NULL) { 2069 if (commandShell->echo == NULL) {
2070 commandShell->echo = ""; 2070 commandShell->echo = "";
2071 } 2071 }
2072 if (commandShell->hasErrCtl && commandShell->exit[0] != '\0') { 2072 if (commandShell->hasErrCtl && commandShell->exit[0] != '\0') {
2073 if (shellErrFlag && 2073 if (shellErrFlag &&
2074 strcmp(commandShell->exit, &shellErrFlag[1]) != 0) { 2074 strcmp(commandShell->exit, &shellErrFlag[1]) != 0) {
2075 free(shellErrFlag); 2075 free(shellErrFlag);
2076 shellErrFlag = NULL; 2076 shellErrFlag = NULL;
2077 } 2077 }
2078 if (!shellErrFlag) { 2078 if (!shellErrFlag) {
2079 size_t n = strlen(commandShell->exit) + 2; 2079 size_t n = strlen(commandShell->exit) + 2;
2080 2080
2081 shellErrFlag = bmake_malloc(n); 2081 shellErrFlag = bmake_malloc(n);
2082 if (shellErrFlag) { 2082 if (shellErrFlag) {
2083 snprintf(shellErrFlag, n, "-%s", commandShell->exit); 2083 snprintf(shellErrFlag, n, "-%s", commandShell->exit);
2084 } 2084 }
2085 } 2085 }
2086 } else if (shellErrFlag) { 2086 } else if (shellErrFlag) {
2087 free(shellErrFlag); 2087 free(shellErrFlag);
2088 shellErrFlag = NULL; 2088 shellErrFlag = NULL;
2089 } 2089 }
2090} 2090}
2091 2091
2092/* Return the string literal that is used in the current command shell 2092/* Return the string literal that is used in the current command shell
2093 * to produce a newline character. */ 2093 * to produce a newline character. */
2094const char * 2094const char *
2095Shell_GetNewline(void) 2095Shell_GetNewline(void)
2096{ 2096{
2097 return commandShell->newline; 2097 return commandShell->newline;
2098} 2098}
2099 2099
2100void 2100void
2101Job_SetPrefix(void) 2101Job_SetPrefix(void)
2102{ 2102{
2103 if (targPrefix) { 2103 if (targPrefix) {
2104 free(targPrefix); 2104 free(targPrefix);
2105 } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) { 2105 } else if (!Var_Exists(MAKE_JOB_PREFIX, VAR_GLOBAL)) {
2106 Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL); 2106 Var_Set(MAKE_JOB_PREFIX, "---", VAR_GLOBAL);
2107 } 2107 }
2108 2108
2109 (void)Var_Subst("${" MAKE_JOB_PREFIX "}", 2109 (void)Var_Subst("${" MAKE_JOB_PREFIX "}",
2110 VAR_GLOBAL, VARE_WANTRES, &targPrefix); 2110 VAR_GLOBAL, VARE_WANTRES, &targPrefix);
2111 /* TODO: handle errors */ 2111 /* TODO: handle errors */
2112} 2112}
2113 2113
2114/* Initialize the process module. */ 2114/* Initialize the process module. */
2115void 2115void
2116Job_Init(void) 2116Job_Init(void)
2117{ 2117{
2118 Job_SetPrefix(); 2118 Job_SetPrefix();
2119 /* Allocate space for all the job info */ 2119 /* Allocate space for all the job info */
2120 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table); 2120 job_table = bmake_malloc((size_t)opts.maxJobs * sizeof *job_table);
2121 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table); 2121 memset(job_table, 0, (size_t)opts.maxJobs * sizeof *job_table);
2122 job_table_end = job_table + opts.maxJobs; 2122 job_table_end = job_table + opts.maxJobs;
2123 wantToken = 0; 2123 wantToken = 0;
2124 2124
2125 aborting = 0; 2125 aborting = 0;
2126 errors = 0; 2126 errors = 0;
2127 2127
2128 lastNode = NULL; 2128 lastNode = NULL;
2129 2129
2130 /* 2130 /*
2131 * There is a non-zero chance that we already have children. 2131 * There is a non-zero chance that we already have children.
2132 * eg after 'make -f- <<EOF' 2132 * eg after 'make -f- <<EOF'
2133 * Since their termination causes a 'Child (pid) not in table' message, 2133 * Since their termination causes a 'Child (pid) not in table' message,
2134 * Collect the status of any that are already dead, and suppress the 2134 * Collect the status of any that are already dead, and suppress the
2135 * error message if there are any undead ones. 2135 * error message if there are any undead ones.
2136 */ 2136 */
2137 for (;;) { 2137 for (;;) {
2138 int rval, status; 2138 int rval, status;
2139 rval = waitpid((pid_t) -1, &status, WNOHANG); 2139 rval = waitpid((pid_t) -1, &status, WNOHANG);
2140 if (rval > 0) 2140 if (rval > 0)
2141 continue; 2141 continue;
2142 if (rval == 0) 2142 if (rval == 0)
2143 lurking_children = 1; 2143 lurking_children = 1;
2144 break; 2144 break;
2145 } 2145 }
2146 2146
2147 Shell_Init(); 2147 Shell_Init();
2148 2148
2149 JobCreatePipe(&childExitJob, 3); 2149 JobCreatePipe(&childExitJob, 3);
2150 2150
2151 /* Preallocate enough for the maximum number of jobs. */ 2151 /* Preallocate enough for the maximum number of jobs. */
2152 fds = bmake_malloc(sizeof(*fds) * 2152 fds = bmake_malloc(sizeof(*fds) *
2153 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); 2153 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
2154 jobfds = bmake_malloc(sizeof(*jobfds) * 2154 jobfds = bmake_malloc(sizeof(*jobfds) *
2155 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job()); 2155 (npseudojobs + (size_t)opts.maxJobs) * nfds_per_job());
2156 2156
2157 /* These are permanent entries and take slots 0 and 1 */ 2157 /* These are permanent entries and take slots 0 and 1 */
2158 watchfd(&tokenWaitJob); 2158 watchfd(&tokenWaitJob);
2159 watchfd(&childExitJob); 2159 watchfd(&childExitJob);
2160 2160
2161 sigemptyset(&caught_signals); 2161 sigemptyset(&caught_signals);
2162 /* 2162 /*
2163 * Install a SIGCHLD handler. 2163 * Install a SIGCHLD handler.
2164 */ 2164 */
2165 (void)bmake_signal(SIGCHLD, JobChildSig); 2165 (void)bmake_signal(SIGCHLD, JobChildSig);
2166 sigaddset(&caught_signals, SIGCHLD); 2166 sigaddset(&caught_signals, SIGCHLD);
2167 2167
2168#define ADDSIG(s,h) \ 2168#define ADDSIG(s,h) \
2169 if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \ 2169 if (bmake_signal(s, SIG_IGN) != SIG_IGN) { \
2170 sigaddset(&caught_signals, s); \ 2170 sigaddset(&caught_signals, s); \
2171 (void)bmake_signal(s, h); \ 2171 (void)bmake_signal(s, h); \
2172 } 2172 }
2173 2173
2174 /* 2174 /*
2175 * Catch the four signals that POSIX specifies if they aren't ignored. 2175 * Catch the four signals that POSIX specifies if they aren't ignored.
2176 * JobPassSig will take care of calling JobInterrupt if appropriate. 2176 * JobPassSig will take care of calling JobInterrupt if appropriate.
2177 */ 2177 */
2178 ADDSIG(SIGINT, JobPassSig_int) 2178 ADDSIG(SIGINT, JobPassSig_int)
2179 ADDSIG(SIGHUP, JobPassSig_term) 2179 ADDSIG(SIGHUP, JobPassSig_term)
2180 ADDSIG(SIGTERM, JobPassSig_term) 2180 ADDSIG(SIGTERM, JobPassSig_term)
2181 ADDSIG(SIGQUIT, JobPassSig_term) 2181 ADDSIG(SIGQUIT, JobPassSig_term)
2182 2182
2183 /* 2183 /*
2184 * There are additional signals that need to be caught and passed if 2184 * There are additional signals that need to be caught and passed if
2185 * either the export system wants to be told directly of signals or if 2185 * either the export system wants to be told directly of signals or if
2186 * we're giving each job its own process group (since then it won't get 2186 * we're giving each job its own process group (since then it won't get
2187 * signals from the terminal driver as we own the terminal) 2187 * signals from the terminal driver as we own the terminal)
2188 */ 2188 */
2189 ADDSIG(SIGTSTP, JobPassSig_suspend) 2189 ADDSIG(SIGTSTP, JobPassSig_suspend)
2190 ADDSIG(SIGTTOU, JobPassSig_suspend) 2190 ADDSIG(SIGTTOU, JobPassSig_suspend)
2191 ADDSIG(SIGTTIN, JobPassSig_suspend) 2191 ADDSIG(SIGTTIN, JobPassSig_suspend)
2192 ADDSIG(SIGWINCH, JobCondPassSig) 2192 ADDSIG(SIGWINCH, JobCondPassSig)
2193 ADDSIG(SIGCONT, JobContinueSig) 2193 ADDSIG(SIGCONT, JobContinueSig)
2194#undef ADDSIG 2194#undef ADDSIG
2195 2195
2196 (void)Job_RunTarget(".BEGIN", NULL); 2196 (void)Job_RunTarget(".BEGIN", NULL);
2197 /* Create the .END node now, even though no code in the unit tests 2197 /* Create the .END node now, even though no code in the unit tests
2198 * depends on it. See also Targ_GetEndNode in Compat_Run. */ 2198 * depends on it. See also Targ_GetEndNode in Compat_Run. */
2199 (void)Targ_GetEndNode(); 2199 (void)Targ_GetEndNode();
2200} 2200}
2201 2201
2202static void JobSigReset(void) 2202static void JobSigReset(void)
2203{ 2203{
2204#define DELSIG(s) \ 2204#define DELSIG(s) \
2205 if (sigismember(&caught_signals, s)) { \ 2205 if (sigismember(&caught_signals, s)) { \
2206 (void)bmake_signal(s, SIG_DFL); \ 2206 (void)bmake_signal(s, SIG_DFL); \
2207 } 2207 }
2208 2208
2209 DELSIG(SIGINT) 2209 DELSIG(SIGINT)
2210 DELSIG(SIGHUP) 2210 DELSIG(SIGHUP)
2211 DELSIG(SIGQUIT) 2211 DELSIG(SIGQUIT)
2212 DELSIG(SIGTERM) 2212 DELSIG(SIGTERM)
2213 DELSIG(SIGTSTP) 2213 DELSIG(SIGTSTP)
2214 DELSIG(SIGTTOU) 2214 DELSIG(SIGTTOU)
2215 DELSIG(SIGTTIN) 2215 DELSIG(SIGTTIN)
2216 DELSIG(SIGWINCH) 2216 DELSIG(SIGWINCH)
2217 DELSIG(SIGCONT) 2217 DELSIG(SIGCONT)
2218#undef DELSIG 2218#undef DELSIG
2219 (void)bmake_signal(SIGCHLD, SIG_DFL); 2219 (void)bmake_signal(SIGCHLD, SIG_DFL);
2220} 2220}
2221 2221
2222/* Find a shell in 'shells' given its name, or return NULL. */ 2222/* Find a shell in 'shells' given its name, or return NULL. */
2223static Shell * 2223static Shell *
2224JobMatchShell(const char *name) 2224JobMatchShell(const char *name)
2225{ 2225{
2226 Shell *sh = shells; 2226 Shell *sh = shells;
2227 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0]; 2227 const Shell *shellsEnd = sh + sizeof shells / sizeof shells[0];
2228 2228
2229 for (sh = shells; sh < shellsEnd; sh++) { 2229 for (sh = shells; sh < shellsEnd; sh++) {
2230 if (strcmp(name, sh->name) == 0) 2230 if (strcmp(name, sh->name) == 0)
2231 return sh; 2231 return sh;
2232 } 2232 }
2233 return NULL; 2233 return NULL;
2234} 2234}
2235 2235
2236/*- 2236/*-
2237 *----------------------------------------------------------------------- 2237 *-----------------------------------------------------------------------
2238 * Job_ParseShell -- 2238 * Job_ParseShell --
2239 * Parse a shell specification and set up commandShell, shellPath 2239 * Parse a shell specification and set up commandShell, shellPath
2240 * and shellName appropriately. 2240 * and shellName appropriately.
2241 * 2241 *
2242 * Input: 2242 * Input:
2243 * line The shell spec 2243 * line The shell spec
2244 * 2244 *
2245 * Results: 2245 * Results:
2246 * FALSE if the specification was incorrect. 2246 * FALSE if the specification was incorrect.
2247 * 2247 *
2248 * Side Effects: 2248 * Side Effects:
2249 * commandShell points to a Shell structure (either predefined or 2249 * commandShell points to a Shell structure (either predefined or
2250 * created from the shell spec), shellPath is the full path of the 2250 * created from the shell spec), shellPath is the full path of the
2251 * shell described by commandShell, while shellName is just the 2251 * shell described by commandShell, while shellName is just the
2252 * final component of shellPath. 2252 * final component of shellPath.
2253 * 2253 *
2254 * Notes: 2254 * Notes:
2255 * A shell specification consists of a .SHELL target, with dependency 2255 * A shell specification consists of a .SHELL target, with dependency
2256 * operator, followed by a series of blank-separated words. Double 2256 * operator, followed by a series of blank-separated words. Double
2257 * quotes can be used to use blanks in words. A backslash escapes 2257 * quotes can be used to use blanks in words. A backslash escapes
2258 * anything (most notably a double-quote and a space) and 2258 * anything (most notably a double-quote and a space) and
2259 * provides the functionality it does in C. Each word consists of 2259 * provides the functionality it does in C. Each word consists of
2260 * keyword and value separated by an equal sign. There should be no 2260 * keyword and value separated by an equal sign. There should be no
2261 * unnecessary spaces in the word. The keywords are as follows: 2261 * unnecessary spaces in the word. The keywords are as follows:
2262 * name Name of shell. 2262 * name Name of shell.
2263 * path Location of shell. 2263 * path Location of shell.
2264 * quiet Command to turn off echoing. 2264 * quiet Command to turn off echoing.
2265 * echo Command to turn echoing on 2265 * echo Command to turn echoing on
2266 * filter Result of turning off echoing that shouldn't be 2266 * filter Result of turning off echoing that shouldn't be
2267 * printed. 2267 * printed.
2268 * echoFlag Flag to turn echoing on at the start 2268 * echoFlag Flag to turn echoing on at the start
2269 * errFlag Flag to turn error checking on at the start 2269 * errFlag Flag to turn error checking on at the start
2270 * hasErrCtl True if shell has error checking control 2270 * hasErrCtl True if shell has error checking control
2271 * newline String literal to represent a newline char 2271 * newline String literal to represent a newline char
2272 * check Command to turn on error checking if hasErrCtl 2272 * check Command to turn on error checking if hasErrCtl
2273 * is TRUE or template of command to echo a command 2273 * is TRUE or template of command to echo a command
2274 * for which error checking is off if hasErrCtl is 2274 * for which error checking is off if hasErrCtl is
2275 * FALSE. 2275 * FALSE.
2276 * ignore Command to turn off error checking if hasErrCtl 2276 * ignore Command to turn off error checking if hasErrCtl
2277 * is TRUE or template of command to execute a 2277 * is TRUE or template of command to execute a
2278 * command so as to ignore any errors it returns if 2278 * command so as to ignore any errors it returns if
2279 * hasErrCtl is FALSE. 2279 * hasErrCtl is FALSE.
2280 * 2280 *
2281 *----------------------------------------------------------------------- 2281 *-----------------------------------------------------------------------
2282 */ 2282 */
2283Boolean 2283Boolean
2284Job_ParseShell(char *line) 2284Job_ParseShell(char *line)
2285{ 2285{
2286 Words wordsList; 2286 Words wordsList;
2287 char **words; 2287 char **words;
2288 char **argv; 2288 char **argv;
2289 size_t argc; 2289 size_t argc;
2290 char *path; 2290 char *path;
2291 Shell newShell; 2291 Shell newShell;
2292 Boolean fullSpec = FALSE; 2292 Boolean fullSpec = FALSE;
2293 Shell *sh; 2293 Shell *sh;
2294 2294
2295 pp_skip_whitespace(&line); 2295 pp_skip_whitespace(&line);
2296 2296
2297 free(shellArgv); 2297 free(shellArgv);
2298 2298
2299 memset(&newShell, 0, sizeof(newShell)); 2299 memset(&newShell, 0, sizeof(newShell));
2300 2300
2301 /* 2301 /*
2302 * Parse the specification by keyword 2302 * Parse the specification by keyword
2303 */ 2303 */
2304 wordsList = Str_Words(line, TRUE); 2304 wordsList = Str_Words(line, TRUE);
2305 words = wordsList.words; 2305 words = wordsList.words;
2306 argc = wordsList.len; 2306 argc = wordsList.len;
2307 path = wordsList.freeIt; 2307 path = wordsList.freeIt;
2308 if (words == NULL) { 2308 if (words == NULL) {
2309 Error("Unterminated quoted string [%s]", line); 2309 Error("Unterminated quoted string [%s]", line);
2310 return FALSE; 2310 return FALSE;
2311 } 2311 }
2312 shellArgv = path; 2312 shellArgv = path;
2313 2313
2314 for (path = NULL, argv = words; argc != 0; argc--, argv++) { 2314 for (path = NULL, argv = words; argc != 0; argc--, argv++) {
2315 char *arg = *argv; 2315 char *arg = *argv;
2316 if (strncmp(arg, "path=", 5) == 0) { 2316 if (strncmp(arg, "path=", 5) == 0) {
2317 path = arg + 5; 2317 path = arg + 5;
2318 } else if (strncmp(arg, "name=", 5) == 0) { 2318 } else if (strncmp(arg, "name=", 5) == 0) {
2319 newShell.name = arg + 5; 2319 newShell.name = arg + 5;
2320 } else { 2320 } else {
2321 if (strncmp(arg, "quiet=", 6) == 0) { 2321 if (strncmp(arg, "quiet=", 6) == 0) {
2322 newShell.echoOff = arg + 6; 2322 newShell.echoOff = arg + 6;
2323 } else if (strncmp(arg, "echo=", 5) == 0) { 2323 } else if (strncmp(arg, "echo=", 5) == 0) {
2324 newShell.echoOn = arg + 5; 2324 newShell.echoOn = arg + 5;
2325 } else if (strncmp(arg, "filter=", 7) == 0) { 2325 } else if (strncmp(arg, "filter=", 7) == 0) {
2326 newShell.noPrint = arg + 7; 2326 newShell.noPrint = arg + 7;
2327 newShell.noPrintLen = strlen(newShell.noPrint); 2327 newShell.noPrintLen = strlen(newShell.noPrint);
2328 } else if (strncmp(arg, "echoFlag=", 9) == 0) { 2328 } else if (strncmp(arg, "echoFlag=", 9) == 0) {
2329 newShell.echo = arg + 9; 2329 newShell.echo = arg + 9;
2330 } else if (strncmp(arg, "errFlag=", 8) == 0) { 2330 } else if (strncmp(arg, "errFlag=", 8) == 0) {
2331 newShell.exit = arg + 8; 2331 newShell.exit = arg + 8;
2332 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) { 2332 } else if (strncmp(arg, "hasErrCtl=", 10) == 0) {
2333 char c = arg[10]; 2333 char c = arg[10];
2334 newShell.hasErrCtl = !((c != 'Y') && (c != 'y') && 2334 newShell.hasErrCtl = c == 'Y' || c == 'y' ||
2335 (c != 'T') && (c != 't')); 2335 c == 'T' || c == 't';
2336 } else if (strncmp(arg, "newline=", 8) == 0) { 2336 } else if (strncmp(arg, "newline=", 8) == 0) {
2337 newShell.newline = arg + 8; 2337 newShell.newline = arg + 8;
2338 } else if (strncmp(arg, "check=", 6) == 0) { 2338 } else if (strncmp(arg, "check=", 6) == 0) {
2339 newShell.errOnOrEcho = arg + 6; 2339 newShell.errOnOrEcho = arg + 6;
2340 } else if (strncmp(arg, "ignore=", 7) == 0) { 2340 } else if (strncmp(arg, "ignore=", 7) == 0) {
2341 newShell.errOffOrExecIgnore = arg + 7; 2341 newShell.errOffOrExecIgnore = arg + 7;
2342 } else if (strncmp(arg, "errout=", 7) == 0) { 2342 } else if (strncmp(arg, "errout=", 7) == 0) {
2343 newShell.errExit = arg + 7; 2343 newShell.errExit = arg + 7;
2344 } else if (strncmp(arg, "comment=", 8) == 0) { 2344 } else if (strncmp(arg, "comment=", 8) == 0) {
2345 newShell.commentChar = arg[8]; 2345 newShell.commentChar = arg[8];
2346 } else { 2346 } else {
2347 Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", arg); 2347 Parse_Error(PARSE_FATAL, "Unknown keyword \"%s\"", arg);
2348 free(words); 2348 free(words);
2349 return FALSE; 2349 return FALSE;
2350 } 2350 }
2351 fullSpec = TRUE; 2351 fullSpec = TRUE;
2352 } 2352 }
2353 } 2353 }
2354 2354
2355 if (path == NULL) { 2355 if (path == NULL) {
2356 /* 2356 /*
2357 * If no path was given, the user wants one of the pre-defined shells, 2357 * If no path was given, the user wants one of the pre-defined shells,
2358 * yes? So we find the one s/he wants with the help of JobMatchShell 2358 * yes? So we find the one s/he wants with the help of JobMatchShell
2359 * and set things up the right way. shellPath will be set up by 2359 * and set things up the right way. shellPath will be set up by
2360 * Shell_Init. 2360 * Shell_Init.
2361 */ 2361 */
2362 if (newShell.name == NULL) { 2362 if (newShell.name == NULL) {
2363 Parse_Error(PARSE_FATAL, "Neither path nor name specified"); 2363 Parse_Error(PARSE_FATAL, "Neither path nor name specified");
2364 free(words); 2364 free(words);
2365 return FALSE; 2365 return FALSE;
2366 } else { 2366 } else {
2367 if ((sh = JobMatchShell(newShell.name)) == NULL) { 2367 if ((sh = JobMatchShell(newShell.name)) == NULL) {
2368 Parse_Error(PARSE_WARNING, "%s: No matching shell", 2368 Parse_Error(PARSE_WARNING, "%s: No matching shell",
2369 newShell.name); 2369 newShell.name);
2370 free(words); 2370 free(words);
2371 return FALSE; 2371 return FALSE;
2372 } 2372 }
2373 commandShell = sh; 2373 commandShell = sh;
2374 shellName = newShell.name; 2374 shellName = newShell.name;
2375 if (shellPath) { 2375 if (shellPath) {
2376 /* Shell_Init has already been called! Do it again. */ 2376 /* Shell_Init has already been called! Do it again. */
2377 free(UNCONST(shellPath)); 2377 free(UNCONST(shellPath));
2378 shellPath = NULL; 2378 shellPath = NULL;
2379 Shell_Init(); 2379 Shell_Init();
2380 } 2380 }
2381 } 2381 }
2382 } else { 2382 } else {
2383 /* 2383 /*
2384 * The user provided a path. If s/he gave nothing else (fullSpec is 2384 * The user provided a path. If s/he gave nothing else (fullSpec is
2385 * FALSE), try and find a matching shell in the ones we know of. 2385 * FALSE), try and find a matching shell in the ones we know of.
2386 * Else we just take the specification at its word and copy it 2386 * Else we just take the specification at its word and copy it
2387 * to a new location. In either case, we need to record the 2387 * to a new location. In either case, we need to record the
2388 * path the user gave for the shell. 2388 * path the user gave for the shell.
2389 */ 2389 */
2390 shellPath = path; 2390 shellPath = path;
2391 path = strrchr(path, '/'); 2391 path = strrchr(path, '/');
2392 if (path == NULL) { 2392 if (path == NULL) {
2393 path = UNCONST(shellPath); 2393 path = UNCONST(shellPath);
2394 } else { 2394 } else {
2395 path++; 2395 path++;
2396 } 2396 }
2397 if (newShell.name != NULL) { 2397 if (newShell.name != NULL) {
2398 shellName = newShell.name; 2398 shellName = newShell.name;
2399 } else { 2399 } else {
2400 shellName = path; 2400 shellName = path;
2401 } 2401 }
2402 if (!fullSpec) { 2402 if (!fullSpec) {
2403 if ((sh = JobMatchShell(shellName)) == NULL) { 2403 if ((sh = JobMatchShell(shellName)) == NULL) {
2404 Parse_Error(PARSE_WARNING, "%s: No matching shell", 2404 Parse_Error(PARSE_WARNING, "%s: No matching shell",
2405 shellName); 2405 shellName);
2406 free(words); 2406 free(words);
2407 return FALSE; 2407 return FALSE;
2408 } 2408 }
2409 commandShell = sh; 2409 commandShell = sh;
2410 } else { 2410 } else {
2411 commandShell = bmake_malloc(sizeof(Shell)); 2411 commandShell = bmake_malloc(sizeof(Shell));
2412 *commandShell = newShell; 2412 *commandShell = newShell;
2413 } 2413 }
2414 /* this will take care of shellErrFlag */ 2414 /* this will take care of shellErrFlag */
2415 Shell_Init(); 2415 Shell_Init();
2416 } 2416 }
2417 2417
2418 if (commandShell->echoOn && commandShell->echoOff) { 2418 if (commandShell->echoOn && commandShell->echoOff) {
2419 commandShell->hasEchoCtl = TRUE; 2419 commandShell->hasEchoCtl = TRUE;
2420 } 2420 }
2421 2421
2422 if (!commandShell->hasErrCtl) { 2422 if (!commandShell->hasErrCtl) {
2423 if (commandShell->errOnOrEcho == NULL) { 2423 if (commandShell->errOnOrEcho == NULL) {
2424 commandShell->errOnOrEcho = ""; 2424 commandShell->errOnOrEcho = "";
2425 } 2425 }
2426 if (commandShell->errOffOrExecIgnore == NULL) { 2426 if (commandShell->errOffOrExecIgnore == NULL) {
2427 commandShell->errOffOrExecIgnore = "%s\n"; 2427 commandShell->errOffOrExecIgnore = "%s\n";
2428 } 2428 }
2429 } 2429 }
2430 2430
2431 /* 2431 /*
2432 * Do not free up the words themselves, since they might be in use by the 2432 * Do not free up the words themselves, since they might be in use by the
2433 * shell specification. 2433 * shell specification.
2434 */ 2434 */
2435 free(words); 2435 free(words);
2436 return TRUE; 2436 return TRUE;
2437} 2437}
2438 2438
2439/* Handle the receipt of an interrupt. 2439/* Handle the receipt of an interrupt.
2440 * 2440 *
2441 * All children are killed. Another job will be started if the .INTERRUPT 2441 * All children are killed. Another job will be started if the .INTERRUPT
2442 * target is defined. 2442 * target is defined.
2443 * 2443 *
2444 * Input: 2444 * Input:
2445 * runINTERRUPT Non-zero if commands for the .INTERRUPT target 2445 * runINTERRUPT Non-zero if commands for the .INTERRUPT target
2446 * should be executed 2446 * should be executed
2447 * signo signal received 2447 * signo signal received
2448 */ 2448 */
2449static void 2449static void
2450JobInterrupt(int runINTERRUPT, int signo) 2450JobInterrupt(int runINTERRUPT, int signo)
2451{ 2451{
2452 Job *job; /* job descriptor in that element */ 2452 Job *job; /* job descriptor in that element */
2453 GNode *interrupt; /* the node describing the .INTERRUPT target */ 2453 GNode *interrupt; /* the node describing the .INTERRUPT target */
2454 sigset_t mask; 2454 sigset_t mask;
2455 GNode *gn; 2455 GNode *gn;
2456 2456
2457 aborting = ABORT_INTERRUPT; 2457 aborting = ABORT_INTERRUPT;
2458 2458
2459 JobSigLock(&mask); 2459 JobSigLock(&mask);
2460 2460
2461 for (job = job_table; job < job_table_end; job++) { 2461 for (job = job_table; job < job_table_end; job++) {
2462 if (job->job_state != JOB_ST_RUNNING) 2462 if (job->job_state != JOB_ST_RUNNING)
2463 continue; 2463 continue;
2464 2464
2465 gn = job->node; 2465 gn = job->node;
2466 2466
2467 JobDeleteTarget(gn); 2467 JobDeleteTarget(gn);
2468 if (job->pid) { 2468 if (job->pid) {
2469 DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n", 2469 DEBUG2(JOB, "JobInterrupt passing signal %d to child %d.\n",
2470 signo, job->pid); 2470 signo, job->pid);
2471 KILLPG(job->pid, signo); 2471 KILLPG(job->pid, signo);
2472 } 2472 }
2473 } 2473 }
2474 2474
2475 JobSigUnlock(&mask); 2475 JobSigUnlock(&mask);
2476 2476
2477 if (runINTERRUPT && !opts.touchFlag) { 2477 if (runINTERRUPT && !opts.touchFlag) {
2478 interrupt = Targ_FindNode(".INTERRUPT"); 2478 interrupt = Targ_FindNode(".INTERRUPT");
2479 if (interrupt != NULL) { 2479 if (interrupt != NULL) {
2480 opts.ignoreErrors = FALSE; 2480 opts.ignoreErrors = FALSE;
2481 JobRun(interrupt); 2481 JobRun(interrupt);
2482 } 2482 }
2483 } 2483 }
2484 Trace_Log(MAKEINTR, 0); 2484 Trace_Log(MAKEINTR, 0);
2485 exit(signo); 2485 exit(signo);
2486} 2486}
2487 2487
2488/* Do the final processing, i.e. run the commands attached to the .END target. 2488/* Do the final processing, i.e. run the commands attached to the .END target.
2489 * 2489 *
2490 * Return the number of errors reported. */ 2490 * Return the number of errors reported. */
2491int 2491int
2492Job_Finish(void) 2492Job_Finish(void)
2493{ 2493{
2494 GNode *endNode = Targ_GetEndNode(); 2494 GNode *endNode = Targ_GetEndNode();
2495 if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) { 2495 if (!Lst_IsEmpty(endNode->commands) || !Lst_IsEmpty(endNode->children)) {
2496 if (errors) { 2496 if (errors) {
2497 Error("Errors reported so .END ignored"); 2497 Error("Errors reported so .END ignored");
2498 } else { 2498 } else {
2499 JobRun(endNode); 2499 JobRun(endNode);
2500 } 2500 }
2501 } 2501 }
2502 return errors; 2502 return errors;
2503} 2503}
2504 2504
2505/* Clean up any memory used by the jobs module. */ 2505/* Clean up any memory used by the jobs module. */
2506void 2506void
2507Job_End(void) 2507Job_End(void)
2508{ 2508{
2509#ifdef CLEANUP 2509#ifdef CLEANUP
2510 free(shellArgv); 2510 free(shellArgv);
2511#endif 2511#endif
2512} 2512}
2513 2513
2514/* Waits for all running jobs to finish and returns. 2514/* Waits for all running jobs to finish and returns.
2515 * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. */ 2515 * Sets 'aborting' to ABORT_WAIT to prevent other jobs from starting. */
2516void 2516void
2517Job_Wait(void) 2517Job_Wait(void)
2518{ 2518{
2519 aborting = ABORT_WAIT; 2519 aborting = ABORT_WAIT;
2520 while (jobTokensRunning != 0) { 2520 while (jobTokensRunning != 0) {
2521 Job_CatchOutput(); 2521 Job_CatchOutput();
2522 } 2522 }
2523 aborting = 0; 2523 aborting = 0;
2524} 2524}
2525 2525
2526/* Abort all currently running jobs without handling output or anything. 2526/* Abort all currently running jobs without handling output or anything.
2527 * This function is to be called only in the event of a major error. 2527 * This function is to be called only in the event of a major error.
2528 * Most definitely NOT to be called from JobInterrupt. 2528 * Most definitely NOT to be called from JobInterrupt.
2529 * 2529 *
2530 * All children are killed, not just the firstborn. */ 2530 * All children are killed, not just the firstborn. */
2531void 2531void
2532Job_AbortAll(void) 2532Job_AbortAll(void)
2533{ 2533{
2534 Job *job; /* the job descriptor in that element */ 2534 Job *job; /* the job descriptor in that element */
2535 int foo; 2535 int foo;
2536 2536
2537 aborting = ABORT_ERROR; 2537 aborting = ABORT_ERROR;
2538 2538
2539 if (jobTokensRunning) { 2539 if (jobTokensRunning) {
2540 for (job = job_table; job < job_table_end; job++) { 2540 for (job = job_table; job < job_table_end; job++) {
2541 if (job->job_state != JOB_ST_RUNNING) 2541 if (job->job_state != JOB_ST_RUNNING)
2542 continue; 2542 continue;
2543 /* 2543 /*
2544 * kill the child process with increasingly drastic signals to make 2544 * kill the child process with increasingly drastic signals to make
2545 * darn sure it's dead. 2545 * darn sure it's dead.
2546 */ 2546 */
2547 KILLPG(job->pid, SIGINT); 2547 KILLPG(job->pid, SIGINT);
2548 KILLPG(job->pid, SIGKILL); 2548 KILLPG(job->pid, SIGKILL);
2549 } 2549 }
2550 } 2550 }
2551 2551
2552 /* 2552 /*
2553 * Catch as many children as want to report in at first, then give up 2553 * Catch as many children as want to report in at first, then give up
2554 */ 2554 */
2555 while (waitpid((pid_t) -1, &foo, WNOHANG) > 0) 2555 while (waitpid((pid_t) -1, &foo, WNOHANG) > 0)
2556 continue; 2556 continue;
2557} 2557}
2558 2558
2559/* Tries to restart stopped jobs if there are slots available. 2559/* Tries to restart stopped jobs if there are slots available.
2560 * Called in process context in response to a SIGCONT. */ 2560 * Called in process context in response to a SIGCONT. */
2561static void 2561static void
2562JobRestartJobs(void) 2562JobRestartJobs(void)
2563{ 2563{
2564 Job *job; 2564 Job *job;
2565 2565
2566 for (job = job_table; job < job_table_end; job++) { 2566 for (job = job_table; job < job_table_end; job++) {
2567 if (job->job_state == JOB_ST_RUNNING && 2567 if (job->job_state == JOB_ST_RUNNING &&
2568 (make_suspended || job->job_suspended)) { 2568 (make_suspended || job->job_suspended)) {
2569 DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid); 2569 DEBUG1(JOB, "Restarting stopped job pid %d.\n", job->pid);
2570 if (job->job_suspended) { 2570 if (job->job_suspended) {
2571 (void)printf("*** [%s] Continued\n", job->node->name); 2571 (void)printf("*** [%s] Continued\n", job->node->name);
2572 (void)fflush(stdout); 2572 (void)fflush(stdout);
2573 } 2573 }
2574 job->job_suspended = 0; 2574 job->job_suspended = 0;
2575 if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) { 2575 if (KILLPG(job->pid, SIGCONT) != 0 && DEBUG(JOB)) {
2576 debug_printf("Failed to send SIGCONT to %d\n", job->pid); 2576 debug_printf("Failed to send SIGCONT to %d\n", job->pid);
2577 } 2577 }
2578 } 2578 }
2579 if (job->job_state == JOB_ST_FINISHED) 2579 if (job->job_state == JOB_ST_FINISHED)
2580 /* Job exit deferred after calling waitpid() in a signal handler */ 2580 /* Job exit deferred after calling waitpid() in a signal handler */
2581 JobFinish(job, job->exit_status); 2581 JobFinish(job, job->exit_status);
2582 } 2582 }
2583 make_suspended = 0; 2583 make_suspended = 0;
2584} 2584}
2585 2585
2586static void 2586static void
2587watchfd(Job *job) 2587watchfd(Job *job)
2588{ 2588{
2589 if (job->inPollfd != NULL) 2589 if (job->inPollfd != NULL)
2590 Punt("Watching watched job"); 2590 Punt("Watching watched job");
2591 2591
2592 fds[nfds].fd = job->inPipe; 2592 fds[nfds].fd = job->inPipe;
2593 fds[nfds].events = POLLIN; 2593 fds[nfds].events = POLLIN;
2594 jobfds[nfds] = job; 2594 jobfds[nfds] = job;
2595 job->inPollfd = &fds[nfds]; 2595 job->inPollfd = &fds[nfds];
2596 nfds++; 2596 nfds++;
2597#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2597#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2598 if (useMeta) { 2598 if (useMeta) {
2599 fds[nfds].fd = meta_job_fd(job); 2599 fds[nfds].fd = meta_job_fd(job);
2600 fds[nfds].events = fds[nfds].fd == -1 ? 0 : POLLIN; 2600 fds[nfds].events = fds[nfds].fd == -1 ? 0 : POLLIN;
2601 jobfds[nfds] = job; 2601 jobfds[nfds] = job;
2602 nfds++; 2602 nfds++;
2603 } 2603 }
2604#endif 2604#endif
2605} 2605}
2606 2606
2607static void 2607static void
2608clearfd(Job *job) 2608clearfd(Job *job)
2609{ 2609{
2610 size_t i; 2610 size_t i;
2611 if (job->inPollfd == NULL) 2611 if (job->inPollfd == NULL)
2612 Punt("Unwatching unwatched job"); 2612 Punt("Unwatching unwatched job");
2613 i = (size_t)(job->inPollfd - fds); 2613 i = (size_t)(job->inPollfd - fds);
2614 nfds--; 2614 nfds--;
2615#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2615#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2616 if (useMeta) { 2616 if (useMeta) {
2617 /* 2617 /*
2618 * Sanity check: there should be two fds per job, so the job's 2618 * Sanity check: there should be two fds per job, so the job's
2619 * pollfd number should be even. 2619 * pollfd number should be even.
2620 */ 2620 */
2621 assert(nfds_per_job() == 2); 2621 assert(nfds_per_job() == 2);
2622 if (i % 2) 2622 if (i % 2)
2623 Punt("odd-numbered fd with meta"); 2623 Punt("odd-numbered fd with meta");
2624 nfds--; 2624 nfds--;
2625 } 2625 }
2626#endif 2626#endif
2627 /* 2627 /*
2628 * Move last job in table into hole made by dead job. 2628 * Move last job in table into hole made by dead job.
2629 */ 2629 */
2630 if (nfds != i) { 2630 if (nfds != i) {
2631 fds[i] = fds[nfds]; 2631 fds[i] = fds[nfds];
2632 jobfds[i] = jobfds[nfds]; 2632 jobfds[i] = jobfds[nfds];
2633 jobfds[i]->inPollfd = &fds[i]; 2633 jobfds[i]->inPollfd = &fds[i];
2634#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 2634#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
2635 if (useMeta) { 2635 if (useMeta) {
2636 fds[i + 1] = fds[nfds + 1]; 2636 fds[i + 1] = fds[nfds + 1];
2637 jobfds[i + 1] = jobfds[nfds + 1]; 2637 jobfds[i + 1] = jobfds[nfds + 1];
2638 } 2638 }
2639#endif 2639#endif
2640 } 2640 }
2641 job->inPollfd = NULL; 2641 job->inPollfd = NULL;
2642} 2642}
2643 2643
2644static int 2644static int
2645readyfd(Job *job) 2645readyfd(Job *job)
2646{ 2646{
2647 if (job->inPollfd == NULL) 2647 if (job->inPollfd == NULL)
2648 Punt("Polling unwatched job"); 2648 Punt("Polling unwatched job");
2649 return (job->inPollfd->revents & POLLIN) != 0; 2649 return (job->inPollfd->revents & POLLIN) != 0;
2650} 2650}
2651 2651
2652/* Put a token (back) into the job pipe. 2652/* Put a token (back) into the job pipe.
2653 * This allows a make process to start a build job. */ 2653 * This allows a make process to start a build job. */
2654static void 2654static void
2655JobTokenAdd(void) 2655JobTokenAdd(void)
2656{ 2656{
2657 char tok = JOB_TOKENS[aborting], tok1; 2657 char tok = JOB_TOKENS[aborting], tok1;
2658 2658
2659 /* If we are depositing an error token flush everything else */ 2659 /* If we are depositing an error token flush everything else */
2660 while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1) 2660 while (tok != '+' && read(tokenWaitJob.inPipe, &tok1, 1) == 1)
2661 continue; 2661 continue;
2662 2662
2663 DEBUG3(JOB, "(%d) aborting %d, deposit token %c\n", 2663 DEBUG3(JOB, "(%d) aborting %d, deposit token %c\n",
2664 getpid(), aborting, JOB_TOKENS[aborting]); 2664 getpid(), aborting, JOB_TOKENS[aborting]);
2665 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) 2665 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
2666 continue; 2666 continue;
2667} 2667}
2668 2668
2669/* Prep the job token pipe in the root make process. */ 2669/* Prep the job token pipe in the root make process. */
2670void 2670void
2671Job_ServerStart(int max_tokens, int jp_0, int jp_1) 2671Job_ServerStart(int max_tokens, int jp_0, int jp_1)
2672{ 2672{
2673 int i; 2673 int i;
2674 char jobarg[64]; 2674 char jobarg[64];
2675 2675
2676 if (jp_0 >= 0 && jp_1 >= 0) { 2676 if (jp_0 >= 0 && jp_1 >= 0) {
2677 /* Pipe passed in from parent */ 2677 /* Pipe passed in from parent */
2678 tokenWaitJob.inPipe = jp_0; 2678 tokenWaitJob.inPipe = jp_0;
2679 tokenWaitJob.outPipe = jp_1; 2679 tokenWaitJob.outPipe = jp_1;
2680 (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC); 2680 (void)fcntl(jp_0, F_SETFD, FD_CLOEXEC);
2681 (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC); 2681 (void)fcntl(jp_1, F_SETFD, FD_CLOEXEC);
2682 return; 2682 return;
2683 } 2683 }
2684 2684
2685 JobCreatePipe(&tokenWaitJob, 15); 2685 JobCreatePipe(&tokenWaitJob, 15);
2686 2686
2687 snprintf(jobarg, sizeof(jobarg), "%d,%d", 2687 snprintf(jobarg, sizeof(jobarg), "%d,%d",
2688 tokenWaitJob.inPipe, tokenWaitJob.outPipe); 2688 tokenWaitJob.inPipe, tokenWaitJob.outPipe);
2689 2689
2690 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); 2690 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
2691 Var_Append(MAKEFLAGS, jobarg, VAR_GLOBAL); 2691 Var_Append(MAKEFLAGS, jobarg, VAR_GLOBAL);
2692 2692
2693 /* 2693 /*
2694 * Preload the job pipe with one token per job, save the one 2694 * Preload the job pipe with one token per job, save the one
2695 * "extra" token for the primary job. 2695 * "extra" token for the primary job.
2696 * 2696 *
2697 * XXX should clip maxJobs against PIPE_BUF -- if max_tokens is 2697 * XXX should clip maxJobs against PIPE_BUF -- if max_tokens is
2698 * larger than the write buffer size of the pipe, we will 2698 * larger than the write buffer size of the pipe, we will
2699 * deadlock here. 2699 * deadlock here.
2700 */ 2700 */
2701 for (i = 1; i < max_tokens; i++) 2701 for (i = 1; i < max_tokens; i++)
2702 JobTokenAdd(); 2702 JobTokenAdd();
2703} 2703}
2704 2704
2705/* Return a withdrawn token to the pool. */ 2705/* Return a withdrawn token to the pool. */
2706void 2706void
2707Job_TokenReturn(void) 2707Job_TokenReturn(void)
2708{ 2708{
2709 jobTokensRunning--; 2709 jobTokensRunning--;
2710 if (jobTokensRunning < 0) 2710 if (jobTokensRunning < 0)
2711 Punt("token botch"); 2711 Punt("token botch");
2712 if (jobTokensRunning || JOB_TOKENS[aborting] != '+') 2712 if (jobTokensRunning || JOB_TOKENS[aborting] != '+')
2713 JobTokenAdd(); 2713 JobTokenAdd();
2714} 2714}
2715 2715
2716/* Attempt to withdraw a token from the pool. 2716/* Attempt to withdraw a token from the pool.
2717 * 2717 *
2718 * If pool is empty, set wantToken so that we wake up when a token is 2718 * If pool is empty, set wantToken so that we wake up when a token is
2719 * released. 2719 * released.
2720 * 2720 *
2721 * Returns TRUE if a token was withdrawn, and FALSE if the pool is currently 2721 * Returns TRUE if a token was withdrawn, and FALSE if the pool is currently
2722 * empty. */ 2722 * empty. */
2723Boolean 2723Boolean
2724Job_TokenWithdraw(void) 2724Job_TokenWithdraw(void)
2725{ 2725{
2726 char tok, tok1; 2726 char tok, tok1;
2727 ssize_t count; 2727 ssize_t count;
2728 2728
2729 wantToken = 0; 2729 wantToken = 0;
2730 DEBUG3(JOB, "Job_TokenWithdraw(%d): aborting %d, running %d\n", 2730 DEBUG3(JOB, "Job_TokenWithdraw(%d): aborting %d, running %d\n",
2731 getpid(), aborting, jobTokensRunning); 2731 getpid(), aborting, jobTokensRunning);
2732 2732
2733 if (aborting || (jobTokensRunning >= opts.maxJobs)) 2733 if (aborting || (jobTokensRunning >= opts.maxJobs))
2734 return FALSE; 2734 return FALSE;
2735 2735
2736 count = read(tokenWaitJob.inPipe, &tok, 1); 2736 count = read(tokenWaitJob.inPipe, &tok, 1);
2737 if (count == 0) 2737 if (count == 0)
2738 Fatal("eof on job pipe!"); 2738 Fatal("eof on job pipe!");
2739 if (count < 0 && jobTokensRunning != 0) { 2739 if (count < 0 && jobTokensRunning != 0) {
2740 if (errno != EAGAIN) { 2740 if (errno != EAGAIN) {
2741 Fatal("job pipe read: %s", strerror(errno)); 2741 Fatal("job pipe read: %s", strerror(errno));
2742 } 2742 }
2743 DEBUG1(JOB, "(%d) blocked for token\n", getpid()); 2743 DEBUG1(JOB, "(%d) blocked for token\n", getpid());
2744 return FALSE; 2744 return FALSE;
2745 } 2745 }
2746 2746
2747 if (count == 1 && tok != '+') { 2747 if (count == 1 && tok != '+') {
2748 /* make being abvorted - remove any other job tokens */ 2748 /* make being abvorted - remove any other job tokens */
2749 DEBUG2(JOB, "(%d) aborted by token %c\n", getpid(), tok); 2749 DEBUG2(JOB, "(%d) aborted by token %c\n", getpid(), tok);
2750 while (read(tokenWaitJob.inPipe, &tok1, 1) == 1) 2750 while (read(tokenWaitJob.inPipe, &tok1, 1) == 1)
2751 continue; 2751 continue;
2752 /* And put the stopper back */ 2752 /* And put the stopper back */
2753 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) 2753 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
2754 continue; 2754 continue;
2755 if (dieQuietly(NULL, 1)) 2755 if (dieQuietly(NULL, 1))
2756 exit(2); 2756 exit(2);
2757 Fatal("A failure has been detected in another branch of the parallel make"); 2757 Fatal("A failure has been detected in another branch of the parallel make");
2758 } 2758 }
2759 2759
2760 if (count == 1 && jobTokensRunning == 0) 2760 if (count == 1 && jobTokensRunning == 0)
2761 /* We didn't want the token really */ 2761 /* We didn't want the token really */
2762 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN) 2762 while (write(tokenWaitJob.outPipe, &tok, 1) == -1 && errno == EAGAIN)
2763 continue; 2763 continue;
2764 2764
2765 jobTokensRunning++; 2765 jobTokensRunning++;
2766 DEBUG1(JOB, "(%d) withdrew token\n", getpid()); 2766 DEBUG1(JOB, "(%d) withdrew token\n", getpid());
2767 return TRUE; 2767 return TRUE;
2768} 2768}
2769 2769
2770/* Run the named target if found. If a filename is specified, then set that 2770/* Run the named target if found. If a filename is specified, then set that
2771 * to the sources. 2771 * to the sources.
2772 * 2772 *
2773 * Exits if the target fails. */ 2773 * Exits if the target fails. */
2774Boolean 2774Boolean
2775Job_RunTarget(const char *target, const char *fname) { 2775Job_RunTarget(const char *target, const char *fname) {
2776 GNode *gn = Targ_FindNode(target); 2776 GNode *gn = Targ_FindNode(target);
2777 if (gn == NULL) 2777 if (gn == NULL)
2778 return FALSE; 2778 return FALSE;
2779 2779
2780 if (fname) 2780 if (fname)
2781 Var_Set(ALLSRC, fname, gn); 2781 Var_Set(ALLSRC, fname, gn);
2782 2782
2783 JobRun(gn); 2783 JobRun(gn);
2784 if (gn->made == ERROR) { 2784 if (gn->made == ERROR) {
2785 PrintOnError(gn, "\n\nStop."); 2785 PrintOnError(gn, "\n\nStop.");
2786 exit(1); 2786 exit(1);
2787 } 2787 }
2788 return TRUE; 2788 return TRUE;
2789} 2789}
2790 2790
2791#ifdef USE_SELECT 2791#ifdef USE_SELECT
2792int 2792int
2793emul_poll(struct pollfd *fd, int nfd, int timeout) 2793emul_poll(struct pollfd *fd, int nfd, int timeout)
2794{ 2794{
2795 fd_set rfds, wfds; 2795 fd_set rfds, wfds;
2796 int i, maxfd, nselect, npoll; 2796 int i, maxfd, nselect, npoll;
2797 struct timeval tv, *tvp; 2797 struct timeval tv, *tvp;
2798 long usecs; 2798 long usecs;
2799 2799
2800 FD_ZERO(&rfds); 2800 FD_ZERO(&rfds);
2801 FD_ZERO(&wfds); 2801 FD_ZERO(&wfds);
2802 2802
2803 maxfd = -1; 2803 maxfd = -1;
2804 for (i = 0; i < nfd; i++) { 2804 for (i = 0; i < nfd; i++) {
2805 fd[i].revents = 0; 2805 fd[i].revents = 0;
2806 2806
2807 if (fd[i].events & POLLIN) 2807 if (fd[i].events & POLLIN)
2808 FD_SET(fd[i].fd, &rfds); 2808 FD_SET(fd[i].fd, &rfds);
2809 2809
2810 if (fd[i].events & POLLOUT) 2810 if (fd[i].events & POLLOUT)
2811 FD_SET(fd[i].fd, &wfds); 2811 FD_SET(fd[i].fd, &wfds);
2812 2812
2813 if (fd[i].fd > maxfd) 2813 if (fd[i].fd > maxfd)
2814 maxfd = fd[i].fd; 2814 maxfd = fd[i].fd;
2815 } 2815 }
2816 2816
2817 if (maxfd >= FD_SETSIZE) { 2817 if (maxfd >= FD_SETSIZE) {
2818 Punt("Ran out of fd_set slots; " 2818 Punt("Ran out of fd_set slots; "
2819 "recompile with a larger FD_SETSIZE."); 2819 "recompile with a larger FD_SETSIZE.");
2820 } 2820 }
2821 2821
2822 if (timeout < 0) { 2822 if (timeout < 0) {
2823 tvp = NULL; 2823 tvp = NULL;
2824 } else { 2824 } else {
2825 usecs = timeout * 1000; 2825 usecs = timeout * 1000;
2826 tv.tv_sec = usecs / 1000000; 2826 tv.tv_sec = usecs / 1000000;
2827 tv.tv_usec = usecs % 1000000; 2827 tv.tv_usec = usecs % 1000000;
2828 tvp = &tv; 2828 tvp = &tv;
2829 } 2829 }
2830 2830
2831 nselect = select(maxfd + 1, &rfds, &wfds, 0, tvp); 2831 nselect = select(maxfd + 1, &rfds, &wfds, 0, tvp);
2832 2832
2833 if (nselect <= 0) 2833 if (nselect <= 0)
2834 return nselect; 2834 return nselect;
2835 2835
2836 npoll = 0; 2836 npoll = 0;
2837 for (i = 0; i < nfd; i++) { 2837 for (i = 0; i < nfd; i++) {
2838 if (FD_ISSET(fd[i].fd, &rfds)) 2838 if (FD_ISSET(fd[i].fd, &rfds))
2839 fd[i].revents |= POLLIN; 2839 fd[i].revents |= POLLIN;
2840 2840
2841 if (FD_ISSET(fd[i].fd, &wfds)) 2841 if (FD_ISSET(fd[i].fd, &wfds))
2842 fd[i].revents |= POLLOUT; 2842 fd[i].revents |= POLLOUT;
2843 2843
2844 if (fd[i].revents) 2844 if (fd[i].revents)
2845 npoll++; 2845 npoll++;
2846 } 2846 }
2847 2847
2848 return npoll; 2848 return npoll;
2849} 2849}
2850#endif /* USE_SELECT */ 2850#endif /* USE_SELECT */