Fri Aug 28 20:23:20 2020 UTC ()
make(1): remove unused variable not_parallel

The variable malloc_options seems unused as well, but the manual page
for jemalloc(3) mentions it.


(rillig)
diff -r1.220 -r1.221 src/usr.bin/make/job.c

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

--- src/usr.bin/make/job.c 2020/08/28 04:48:57 1.220
+++ src/usr.bin/make/job.c 2020/08/28 20:23:20 1.221
@@ -1,1908 +1,1907 @@ @@ -1,1908 +1,1907 @@
1/* $NetBSD: job.c,v 1.220 2020/08/28 04:48:57 rillig Exp $ */ 1/* $NetBSD: job.c,v 1.221 2020/08/28 20:23:20 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#ifndef MAKE_NATIVE 72#ifndef MAKE_NATIVE
73static char rcsid[] = "$NetBSD: job.c,v 1.220 2020/08/28 04:48:57 rillig Exp $"; 73static char rcsid[] = "$NetBSD: job.c,v 1.221 2020/08/28 20:23:20 rillig Exp $";
74#else 74#else
75#include <sys/cdefs.h> 75#include <sys/cdefs.h>
76#ifndef lint 76#ifndef lint
77#if 0 77#if 0
78static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94"; 78static char sccsid[] = "@(#)job.c 8.2 (Berkeley) 3/19/94";
79#else 79#else
80__RCSID("$NetBSD: job.c,v 1.220 2020/08/28 04:48:57 rillig Exp $"); 80__RCSID("$NetBSD: job.c,v 1.221 2020/08/28 20:23:20 rillig Exp $");
81#endif 81#endif
82#endif /* not lint */ 82#endif /* not lint */
83#endif 83#endif
84 84
85/*- 85/*-
86 * job.c -- 86 * job.c --
87 * handle the creation etc. of our child processes. 87 * handle the creation etc. of our child processes.
88 * 88 *
89 * Interface: 89 * Interface:
90 * Job_Make Start the creation of the given target. 90 * Job_Make Start the creation of the given target.
91 * 91 *
92 * Job_CatchChildren Check for and handle the termination of any 92 * Job_CatchChildren Check for and handle the termination of any
93 * children. This must be called reasonably 93 * children. This must be called reasonably
94 * frequently to keep the whole make going at 94 * frequently to keep the whole make going at
95 * a decent clip, since job table entries aren't 95 * a decent clip, since job table entries aren't
96 * removed until their process is caught this way. 96 * removed until their process is caught this way.
97 * 97 *
98 * Job_CatchOutput Print any output our children have produced. 98 * Job_CatchOutput Print any output our children have produced.
99 * Should also be called fairly frequently to 99 * Should also be called fairly frequently to
100 * keep the user informed of what's going on. 100 * keep the user informed of what's going on.
101 * If no output is waiting, it will block for 101 * If no output is waiting, it will block for
102 * a time given by the SEL_* constants, below, 102 * a time given by the SEL_* constants, below,
103 * or until output is ready. 103 * or until output is ready.
104 * 104 *
105 * Job_Init Called to initialize this module. in addition, 105 * Job_Init Called to initialize this module. in addition,
106 * any commands attached to the .BEGIN target 106 * any commands attached to the .BEGIN target
107 * are executed before this function returns. 107 * are executed before this function returns.
108 * Hence, the makefile must have been parsed 108 * Hence, the makefile must have been parsed
109 * before this function is called. 109 * before this function is called.
110 * 110 *
111 * Job_End Cleanup any memory used. 111 * Job_End Cleanup any memory used.
112 * 112 *
113 * Job_ParseShell Given the line following a .SHELL target, parse 113 * Job_ParseShell Given the line following a .SHELL target, parse
114 * the line as a shell specification. Returns 114 * the line as a shell specification. Returns
115 * FAILURE if the spec was incorrect. 115 * FAILURE if the spec was incorrect.
116 * 116 *
117 * Job_Finish Perform any final processing which needs doing. 117 * Job_Finish Perform any final processing which needs doing.
118 * This includes the execution of any commands 118 * This includes the execution of any commands
119 * which have been/were attached to the .END 119 * which have been/were attached to the .END
120 * target. It should only be called when the 120 * target. It should only be called when the
121 * job table is empty. 121 * job table is empty.
122 * 122 *
123 * Job_AbortAll Abort all currently running jobs. It doesn't 123 * Job_AbortAll Abort all currently running jobs. It doesn't
124 * handle output or do anything for the jobs, 124 * handle output or do anything for the jobs,
125 * just kills them. It should only be called in 125 * just kills them. It should only be called in
126 * an emergency, as it were. 126 * an emergency, as it were.
127 * 127 *
128 * Job_CheckCommands Verify that the commands for a target are 128 * Job_CheckCommands Verify that the commands for a target are
129 * ok. Provide them if necessary and possible. 129 * ok. Provide them if necessary and possible.
130 * 130 *
131 * Job_Touch Update a target without really updating it. 131 * Job_Touch Update a target without really updating it.
132 * 132 *
133 * Job_Wait Wait for all currently-running jobs to finish. 133 * Job_Wait Wait for all currently-running jobs to finish.
134 */ 134 */
135 135
136#include <sys/types.h> 136#include <sys/types.h>
137#include <sys/stat.h> 137#include <sys/stat.h>
138#include <sys/file.h> 138#include <sys/file.h>
139#include <sys/time.h> 139#include <sys/time.h>
140#include <sys/wait.h> 140#include <sys/wait.h>
141 141
142#include <errno.h> 142#include <errno.h>
143#ifndef USE_SELECT 143#ifndef USE_SELECT
144#include <poll.h> 144#include <poll.h>
145#endif 145#endif
146#include <signal.h> 146#include <signal.h>
147#include <utime.h> 147#include <utime.h>
148 148
149#include "make.h" 149#include "make.h"
150#include "dir.h" 150#include "dir.h"
151#include "job.h" 151#include "job.h"
152#include "pathnames.h" 152#include "pathnames.h"
153#include "trace.h" 153#include "trace.h"
154# define STATIC static 154# define STATIC static
155 155
156/* 156/*
157 * error handling variables 157 * error handling variables
158 */ 158 */
159static int errors = 0; /* number of errors reported */ 159static int errors = 0; /* number of errors reported */
160static int aborting = 0; /* why is the make aborting? */ 160static int aborting = 0; /* why is the make aborting? */
161#define ABORT_ERROR 1 /* Because of an error */ 161#define ABORT_ERROR 1 /* Because of an error */
162#define ABORT_INTERRUPT 2 /* Because it was interrupted */ 162#define ABORT_INTERRUPT 2 /* Because it was interrupted */
163#define ABORT_WAIT 3 /* Waiting for jobs to finish */ 163#define ABORT_WAIT 3 /* Waiting for jobs to finish */
164#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */ 164#define JOB_TOKENS "+EI+" /* Token to requeue for each abort state */
165 165
166/* 166/*
167 * this tracks the number of tokens currently "out" to build jobs. 167 * this tracks the number of tokens currently "out" to build jobs.
168 */ 168 */
169int jobTokensRunning = 0; 169int jobTokensRunning = 0;
170int not_parallel = 0; /* set if .NOT_PARALLEL */ 
171 170
172/* 171/*
173 * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file 172 * XXX: Avoid SunOS bug... FILENO() is fp->_file, and file
174 * is a char! So when we go above 127 we turn negative! 173 * is a char! So when we go above 127 we turn negative!
175 */ 174 */
176#define FILENO(a) ((unsigned) fileno(a)) 175#define FILENO(a) ((unsigned) fileno(a))
177 176
178/* 177/*
179 * post-make command processing. The node postCommands is really just the 178 * post-make command processing. The node postCommands is really just the
180 * .END target but we keep it around to avoid having to search for it 179 * .END target but we keep it around to avoid having to search for it
181 * all the time. 180 * all the time.
182 */ 181 */
183static GNode *postCommands = NULL; 182static GNode *postCommands = NULL;
184 /* node containing commands to execute when 183 /* node containing commands to execute when
185 * everything else is done */ 184 * everything else is done */
186static int numCommands; /* The number of commands actually printed 185static int numCommands; /* The number of commands actually printed
187 * for a target. Should this number be 186 * for a target. Should this number be
188 * 0, no shell will be executed. */ 187 * 0, no shell will be executed. */
189 188
190/* 189/*
191 * Return values from JobStart. 190 * Return values from JobStart.
192 */ 191 */
193#define JOB_RUNNING 0 /* Job is running */ 192#define JOB_RUNNING 0 /* Job is running */
194#define JOB_ERROR 1 /* Error in starting the job */ 193#define JOB_ERROR 1 /* Error in starting the job */
195#define JOB_FINISHED 2 /* The job is already finished */ 194#define JOB_FINISHED 2 /* The job is already finished */
196 195
197/* 196/*
198 * Descriptions for various shells. 197 * Descriptions for various shells.
199 * 198 *
200 * The build environment may set DEFSHELL_INDEX to one of 199 * The build environment may set DEFSHELL_INDEX to one of
201 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to 200 * DEFSHELL_INDEX_SH, DEFSHELL_INDEX_KSH, or DEFSHELL_INDEX_CSH, to
202 * select one of the prefedined shells as the default shell. 201 * select one of the prefedined shells as the default shell.
203 * 202 *
204 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the 203 * Alternatively, the build environment may set DEFSHELL_CUSTOM to the
205 * name or the full path of a sh-compatible shell, which will be used as 204 * name or the full path of a sh-compatible shell, which will be used as
206 * the default shell. 205 * the default shell.
207 * 206 *
208 * ".SHELL" lines in Makefiles can choose the default shell from the 207 * ".SHELL" lines in Makefiles can choose the default shell from the
209 # set defined here, or add additional shells. 208 # set defined here, or add additional shells.
210 */ 209 */
211 210
212#ifdef DEFSHELL_CUSTOM 211#ifdef DEFSHELL_CUSTOM
213#define DEFSHELL_INDEX_CUSTOM 0 212#define DEFSHELL_INDEX_CUSTOM 0
214#define DEFSHELL_INDEX_SH 1 213#define DEFSHELL_INDEX_SH 1
215#define DEFSHELL_INDEX_KSH 2 214#define DEFSHELL_INDEX_KSH 2
216#define DEFSHELL_INDEX_CSH 3 215#define DEFSHELL_INDEX_CSH 3
217#else /* !DEFSHELL_CUSTOM */ 216#else /* !DEFSHELL_CUSTOM */
218#define DEFSHELL_INDEX_SH 0 217#define DEFSHELL_INDEX_SH 0
219#define DEFSHELL_INDEX_KSH 1 218#define DEFSHELL_INDEX_KSH 1
220#define DEFSHELL_INDEX_CSH 2 219#define DEFSHELL_INDEX_CSH 2
221#endif /* !DEFSHELL_CUSTOM */ 220#endif /* !DEFSHELL_CUSTOM */
222 221
223#ifndef DEFSHELL_INDEX 222#ifndef DEFSHELL_INDEX
224#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */ 223#define DEFSHELL_INDEX 0 /* DEFSHELL_INDEX_CUSTOM or DEFSHELL_INDEX_SH */
225#endif /* !DEFSHELL_INDEX */ 224#endif /* !DEFSHELL_INDEX */
226 225
227static Shell shells[] = { 226static Shell shells[] = {
228#ifdef DEFSHELL_CUSTOM 227#ifdef DEFSHELL_CUSTOM
229 /* 228 /*
230 * An sh-compatible shell with a non-standard name. 229 * An sh-compatible shell with a non-standard name.
231 * 230 *
232 * Keep this in sync with the "sh" description below, but avoid 231 * Keep this in sync with the "sh" description below, but avoid
233 * non-portable features that might not be supplied by all 232 * non-portable features that might not be supplied by all
234 * sh-compatible shells. 233 * sh-compatible shells.
235 */ 234 */
236{ 235{
237 DEFSHELL_CUSTOM, 236 DEFSHELL_CUSTOM,
238 FALSE, "", "", "", 0, 237 FALSE, "", "", "", 0,
239 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', 238 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#',
240 "", 239 "",
241 "", 240 "",
242}, 241},
243#endif /* DEFSHELL_CUSTOM */ 242#endif /* DEFSHELL_CUSTOM */
244 /* 243 /*
245 * SH description. Echo control is also possible and, under 244 * SH description. Echo control is also possible and, under
246 * sun UNIX anyway, one can even control error checking. 245 * sun UNIX anyway, one can even control error checking.
247 */ 246 */
248{ 247{
249 "sh", 248 "sh",
250 FALSE, "", "", "", 0, 249 FALSE, "", "", "", 0,
251 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', 250 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#',
252#if defined(MAKE_NATIVE) && defined(__NetBSD__) 251#if defined(MAKE_NATIVE) && defined(__NetBSD__)
253 "q", 252 "q",
254#else 253#else
255 "", 254 "",
256#endif 255#endif
257 "", 256 "",
258}, 257},
259 /* 258 /*
260 * KSH description. 259 * KSH description.
261 */ 260 */
262{ 261{
263 "ksh", 262 "ksh",
264 TRUE, "set +v", "set -v", "set +v", 6, 263 TRUE, "set +v", "set -v", "set +v", 6,
265 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#', 264 FALSE, "echo \"%s\"\n", "%s\n", "{ %s \n} || exit $?\n", "'\n'", '#',
266 "v", 265 "v",
267 "", 266 "",
268}, 267},
269 /* 268 /*
270 * CSH description. The csh can do echo control by playing 269 * CSH description. The csh can do echo control by playing
271 * with the setting of the 'echo' shell variable. Sadly, 270 * with the setting of the 'echo' shell variable. Sadly,
272 * however, it is unable to do error control nicely. 271 * however, it is unable to do error control nicely.
273 */ 272 */
274{ 273{
275 "csh", 274 "csh",
276 TRUE, "unset verbose", "set verbose", "unset verbose", 10, 275 TRUE, "unset verbose", "set verbose", "unset verbose", 10,
277 FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"\n", "", "'\\\n'", '#', 276 FALSE, "echo \"%s\"\n", "csh -c \"%s || exit 0\"\n", "", "'\\\n'", '#',
278 "v", "e", 277 "v", "e",
279}, 278},
280 /* 279 /*
281 * UNKNOWN. 280 * UNKNOWN.
282 */ 281 */
283{ 282{
284 NULL, 283 NULL,
285 FALSE, NULL, NULL, NULL, 0, 284 FALSE, NULL, NULL, NULL, 0,
286 FALSE, NULL, NULL, NULL, NULL, 0, 285 FALSE, NULL, NULL, NULL, NULL, 0,
287 NULL, NULL, 286 NULL, NULL,
288} 287}
289}; 288};
290static Shell *commandShell = &shells[DEFSHELL_INDEX]; /* this is the shell to 289static Shell *commandShell = &shells[DEFSHELL_INDEX]; /* this is the shell to
291 * which we pass all 290 * which we pass all
292 * commands in the Makefile. 291 * commands in the Makefile.
293 * It is set by the 292 * It is set by the
294 * Job_ParseShell function */ 293 * Job_ParseShell function */
295const char *shellPath = NULL, /* full pathname of 294const char *shellPath = NULL, /* full pathname of
296 * executable image */ 295 * executable image */
297 *shellName = NULL; /* last component of shell */ 296 *shellName = NULL; /* last component of shell */
298char *shellErrFlag = NULL; 297char *shellErrFlag = NULL;
299static char *shellArgv = NULL; /* Custom shell args */ 298static char *shellArgv = NULL; /* Custom shell args */
300 299
301 300
302STATIC Job *job_table; /* The structures that describe them */ 301STATIC Job *job_table; /* The structures that describe them */
303STATIC Job *job_table_end; /* job_table + maxJobs */ 302STATIC Job *job_table_end; /* job_table + maxJobs */
304static int wantToken; /* we want a token */ 303static int wantToken; /* we want a token */
305static int lurking_children = 0; 304static int lurking_children = 0;
306static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */ 305static int make_suspended = 0; /* non-zero if we've seen a SIGTSTP (etc) */
307 306
308/* 307/*
309 * Set of descriptors of pipes connected to 308 * Set of descriptors of pipes connected to
310 * the output channels of children 309 * the output channels of children
311 */ 310 */
312static struct pollfd *fds = NULL; 311static struct pollfd *fds = NULL;
313static Job **jobfds = NULL; 312static Job **jobfds = NULL;
314static int nfds = 0; 313static int nfds = 0;
315static void watchfd(Job *); 314static void watchfd(Job *);
316static void clearfd(Job *); 315static void clearfd(Job *);
317static int readyfd(Job *); 316static int readyfd(Job *);
318 317
319STATIC GNode *lastNode; /* The node for which output was most recently 318STATIC GNode *lastNode; /* The node for which output was most recently
320 * produced. */ 319 * produced. */
321static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */ 320static char *targPrefix = NULL; /* What we print at the start of TARG_FMT */
322static Job tokenWaitJob; /* token wait pseudo-job */ 321static Job tokenWaitJob; /* token wait pseudo-job */
323 322
324static Job childExitJob; /* child exit pseudo-job */ 323static Job childExitJob; /* child exit pseudo-job */
325#define CHILD_EXIT "." 324#define CHILD_EXIT "."
326#define DO_JOB_RESUME "R" 325#define DO_JOB_RESUME "R"
327 326
328static const int npseudojobs = 2; /* number of pseudo-jobs */ 327static const int npseudojobs = 2; /* number of pseudo-jobs */
329 328
330#define TARG_FMT "%s %s ---\n" /* Default format */ 329#define TARG_FMT "%s %s ---\n" /* Default format */
331#define MESSAGE(fp, gn) \ 330#define MESSAGE(fp, gn) \
332 if (maxJobs != 1 && targPrefix && *targPrefix) \ 331 if (maxJobs != 1 && targPrefix && *targPrefix) \
333 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name) 332 (void)fprintf(fp, TARG_FMT, targPrefix, gn->name)
334 333
335static sigset_t caught_signals; /* Set of signals we handle */ 334static sigset_t caught_signals; /* Set of signals we handle */
336 335
337static void JobChildSig(int); 336static void JobChildSig(int);
338static void JobContinueSig(int); 337static void JobContinueSig(int);
339static Job *JobFindPid(int, int, Boolean); 338static Job *JobFindPid(int, int, Boolean);
340static int JobPrintCommand(void *, void *); 339static int JobPrintCommand(void *, void *);
341static int JobSaveCommand(void *, void *); 340static int JobSaveCommand(void *, void *);
342static void JobClose(Job *); 341static void JobClose(Job *);
343static void JobExec(Job *, char **); 342static void JobExec(Job *, char **);
344static void JobMakeArgv(Job *, char **); 343static void JobMakeArgv(Job *, char **);
345static int JobStart(GNode *, int); 344static int JobStart(GNode *, int);
346static char *JobOutput(Job *, char *, char *, int); 345static char *JobOutput(Job *, char *, char *, int);
347static void JobDoOutput(Job *, Boolean); 346static void JobDoOutput(Job *, Boolean);
348static Shell *JobMatchShell(const char *); 347static Shell *JobMatchShell(const char *);
349static void JobInterrupt(int, int) MAKE_ATTR_DEAD; 348static void JobInterrupt(int, int) MAKE_ATTR_DEAD;
350static void JobRestartJobs(void); 349static void JobRestartJobs(void);
351static void JobTokenAdd(void); 350static void JobTokenAdd(void);
352static void JobSigLock(sigset_t *); 351static void JobSigLock(sigset_t *);
353static void JobSigUnlock(sigset_t *); 352static void JobSigUnlock(sigset_t *);
354static void JobSigReset(void); 353static void JobSigReset(void);
355 354
356const char *malloc_options="A"; 355const char *malloc_options MAKE_ATTR_UNUSED = "A"; /* see jemalloc(3) */
357 356
358static unsigned 357static unsigned
359nfds_per_job(void) 358nfds_per_job(void)
360{ 359{
361#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV) 360#if defined(USE_FILEMON) && !defined(USE_FILEMON_DEV)
362 if (useMeta) 361 if (useMeta)
363 return 2; 362 return 2;
364#endif 363#endif
365 return 1; 364 return 1;
366} 365}
367 366
368static void 367static void
369job_table_dump(const char *where) 368job_table_dump(const char *where)
370{ 369{
371 Job *job; 370 Job *job;
372 371
373 fprintf(debug_file, "job table @ %s\n", where); 372 fprintf(debug_file, "job table @ %s\n", where);
374 for (job = job_table; job < job_table_end; job++) { 373 for (job = job_table; job < job_table_end; job++) {
375 fprintf(debug_file, "job %d, status %d, flags %d, pid %d\n", 374 fprintf(debug_file, "job %d, status %d, flags %d, pid %d\n",
376 (int)(job - job_table), job->job_state, job->flags, job->pid); 375 (int)(job - job_table), job->job_state, job->flags, job->pid);
377 } 376 }
378} 377}
379 378
380/* 379/*
381 * Delete the target of a failed, interrupted, or otherwise 380 * Delete the target of a failed, interrupted, or otherwise
382 * unsuccessful job unless inhibited by .PRECIOUS. 381 * unsuccessful job unless inhibited by .PRECIOUS.
383 */ 382 */
384static void 383static void
385JobDeleteTarget(GNode *gn) 384JobDeleteTarget(GNode *gn)
386{ 385{
387 if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) { 386 if ((gn->type & (OP_JOIN|OP_PHONY)) == 0 && !Targ_Precious(gn)) {
388 char *file = (gn->path == NULL ? gn->name : gn->path); 387 char *file = (gn->path == NULL ? gn->name : gn->path);
389 if (!noExecute && eunlink(file) != -1) { 388 if (!noExecute && eunlink(file) != -1) {
390 Error("*** %s removed", file); 389 Error("*** %s removed", file);
391 } 390 }
392 } 391 }
393} 392}
394 393
395/* 394/*
396 * JobSigLock/JobSigUnlock 395 * JobSigLock/JobSigUnlock
397 * 396 *
398 * Signal lock routines to get exclusive access. Currently used to 397 * Signal lock routines to get exclusive access. Currently used to
399 * protect `jobs' and `stoppedJobs' list manipulations. 398 * protect `jobs' and `stoppedJobs' list manipulations.
400 */ 399 */
401static void JobSigLock(sigset_t *omaskp) 400static void JobSigLock(sigset_t *omaskp)
402{ 401{
403 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) { 402 if (sigprocmask(SIG_BLOCK, &caught_signals, omaskp) != 0) {
404 Punt("JobSigLock: sigprocmask: %s", strerror(errno)); 403 Punt("JobSigLock: sigprocmask: %s", strerror(errno));
405 sigemptyset(omaskp); 404 sigemptyset(omaskp);
406 } 405 }
407} 406}
408 407
409static void JobSigUnlock(sigset_t *omaskp) 408static void JobSigUnlock(sigset_t *omaskp)
410{ 409{
411 (void)sigprocmask(SIG_SETMASK, omaskp, NULL); 410 (void)sigprocmask(SIG_SETMASK, omaskp, NULL);
412} 411}
413 412
414static void 413static void
415JobCreatePipe(Job *job, int minfd) 414JobCreatePipe(Job *job, int minfd)
416{ 415{
417 int i, fd, flags; 416 int i, fd, flags;
418 417
419 if (pipe(job->jobPipe) == -1) 418 if (pipe(job->jobPipe) == -1)
420 Punt("Cannot create pipe: %s", strerror(errno)); 419 Punt("Cannot create pipe: %s", strerror(errno));
421 420
422 for (i = 0; i < 2; i++) { 421 for (i = 0; i < 2; i++) {
423 /* Avoid using low numbered fds */ 422 /* Avoid using low numbered fds */
424 fd = fcntl(job->jobPipe[i], F_DUPFD, minfd); 423 fd = fcntl(job->jobPipe[i], F_DUPFD, minfd);
425 if (fd != -1) { 424 if (fd != -1) {
426 close(job->jobPipe[i]); 425 close(job->jobPipe[i]);
427 job->jobPipe[i] = fd; 426 job->jobPipe[i] = fd;
428 } 427 }
429 } 428 }
430 429
431 /* Set close-on-exec flag for both */ 430 /* Set close-on-exec flag for both */
432 if (fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC) == -1) 431 if (fcntl(job->jobPipe[0], F_SETFD, FD_CLOEXEC) == -1)
433 Punt("Cannot set close-on-exec: %s", strerror(errno)); 432 Punt("Cannot set close-on-exec: %s", strerror(errno));
434 if (fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC) == -1) 433 if (fcntl(job->jobPipe[1], F_SETFD, FD_CLOEXEC) == -1)
435 Punt("Cannot set close-on-exec: %s", strerror(errno)); 434 Punt("Cannot set close-on-exec: %s", strerror(errno));
436 435
437 /* 436 /*
438 * We mark the input side of the pipe non-blocking; we poll(2) the 437 * We mark the input side of the pipe non-blocking; we poll(2) the
439 * pipe when we're waiting for a job token, but we might lose the 438 * pipe when we're waiting for a job token, but we might lose the
440 * race for the token when a new one becomes available, so the read 439 * race for the token when a new one becomes available, so the read
441 * from the pipe should not block. 440 * from the pipe should not block.
442 */ 441 */
443 flags = fcntl(job->jobPipe[0], F_GETFL, 0); 442 flags = fcntl(job->jobPipe[0], F_GETFL, 0);
444 if (flags == -1) 443 if (flags == -1)
445 Punt("Cannot get flags: %s", strerror(errno)); 444 Punt("Cannot get flags: %s", strerror(errno));
446 flags |= O_NONBLOCK; 445 flags |= O_NONBLOCK;
447 if (fcntl(job->jobPipe[0], F_SETFL, flags) == -1) 446 if (fcntl(job->jobPipe[0], F_SETFL, flags) == -1)
448 Punt("Cannot set flags: %s", strerror(errno)); 447 Punt("Cannot set flags: %s", strerror(errno));
449} 448}
450 449
451/*- 450/*-
452 *----------------------------------------------------------------------- 451 *-----------------------------------------------------------------------
453 * JobCondPassSig -- 452 * JobCondPassSig --
454 * Pass a signal to a job 453 * Pass a signal to a job
455 * 454 *
456 * Input: 455 * Input:
457 * signop Signal to send it 456 * signop Signal to send it
458 * 457 *
459 * Side Effects: 458 * Side Effects:
460 * None, except the job may bite it. 459 * None, except the job may bite it.
461 * 460 *
462 *----------------------------------------------------------------------- 461 *-----------------------------------------------------------------------
463 */ 462 */
464static void 463static void
465JobCondPassSig(int signo) 464JobCondPassSig(int signo)
466{ 465{
467 Job *job; 466 Job *job;
468 467
469 if (DEBUG(JOB)) { 468 if (DEBUG(JOB)) {
470 (void)fprintf(debug_file, "JobCondPassSig(%d) called.\n", signo); 469 (void)fprintf(debug_file, "JobCondPassSig(%d) called.\n", signo);
471 } 470 }
472 471
473 for (job = job_table; job < job_table_end; job++) { 472 for (job = job_table; job < job_table_end; job++) {
474 if (job->job_state != JOB_ST_RUNNING) 473 if (job->job_state != JOB_ST_RUNNING)
475 continue; 474 continue;
476 if (DEBUG(JOB)) { 475 if (DEBUG(JOB)) {
477 (void)fprintf(debug_file, 476 (void)fprintf(debug_file,
478 "JobCondPassSig passing signal %d to child %d.\n", 477 "JobCondPassSig passing signal %d to child %d.\n",
479 signo, job->pid); 478 signo, job->pid);
480 } 479 }
481 KILLPG(job->pid, signo); 480 KILLPG(job->pid, signo);
482 } 481 }
483} 482}
484 483
485/*- 484/*-
486 *----------------------------------------------------------------------- 485 *-----------------------------------------------------------------------
487 * JobChldSig -- 486 * JobChldSig --
488 * SIGCHLD handler. 487 * SIGCHLD handler.
489 * 488 *
490 * Input: 489 * Input:
491 * signo The signal number we've received 490 * signo The signal number we've received
492 * 491 *
493 * Results: 492 * Results:
494 * None. 493 * None.
495 * 494 *
496 * Side Effects: 495 * Side Effects:
497 * Sends a token on the child exit pipe to wake us up from 496 * Sends a token on the child exit pipe to wake us up from
498 * select()/poll(). 497 * select()/poll().
499 * 498 *
500 *----------------------------------------------------------------------- 499 *-----------------------------------------------------------------------
501 */ 500 */
502static void 501static void
503JobChildSig(int signo MAKE_ATTR_UNUSED) 502JobChildSig(int signo MAKE_ATTR_UNUSED)
504{ 503{
505 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN) 504 while (write(childExitJob.outPipe, CHILD_EXIT, 1) == -1 && errno == EAGAIN)
506 continue; 505 continue;
507} 506}
508 507
509 508
510/*- 509/*-
511 *----------------------------------------------------------------------- 510 *-----------------------------------------------------------------------
512 * JobContinueSig -- 511 * JobContinueSig --
513 * Resume all stopped jobs. 512 * Resume all stopped jobs.
514 * 513 *
515 * Input: 514 * Input:
516 * signo The signal number we've received 515 * signo The signal number we've received
517 * 516 *
518 * Results: 517 * Results:
519 * None. 518 * None.
520 * 519 *
521 * Side Effects: 520 * Side Effects:
522 * Jobs start running again. 521 * Jobs start running again.
523 * 522 *
524 *----------------------------------------------------------------------- 523 *-----------------------------------------------------------------------
525 */ 524 */
526static void 525static void
527JobContinueSig(int signo MAKE_ATTR_UNUSED) 526JobContinueSig(int signo MAKE_ATTR_UNUSED)
528{ 527{
529 /* 528 /*
530 * Defer sending to SIGCONT to our stopped children until we return 529 * Defer sending to SIGCONT to our stopped children until we return
531 * from the signal handler. 530 * from the signal handler.
532 */ 531 */
533 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 && 532 while (write(childExitJob.outPipe, DO_JOB_RESUME, 1) == -1 &&
534 errno == EAGAIN) 533 errno == EAGAIN)
535 continue; 534 continue;
536} 535}
537 536
538/*- 537/*-
539 *----------------------------------------------------------------------- 538 *-----------------------------------------------------------------------
540 * JobPassSig -- 539 * JobPassSig --
541 * Pass a signal on to all jobs, then resend to ourselves. 540 * Pass a signal on to all jobs, then resend to ourselves.
542 * 541 *
543 * Input: 542 * Input:
544 * signo The signal number we've received 543 * signo The signal number we've received
545 * 544 *
546 * Results: 545 * Results:
547 * None. 546 * None.
548 * 547 *
549 * Side Effects: 548 * Side Effects:
550 * We die by the same signal. 549 * We die by the same signal.
551 * 550 *
552 *----------------------------------------------------------------------- 551 *-----------------------------------------------------------------------
553 */ 552 */
554MAKE_ATTR_DEAD static void 553MAKE_ATTR_DEAD static void
555JobPassSig_int(int signo) 554JobPassSig_int(int signo)
556{ 555{
557 /* Run .INTERRUPT target then exit */ 556 /* Run .INTERRUPT target then exit */
558 JobInterrupt(TRUE, signo); 557 JobInterrupt(TRUE, signo);
559} 558}
560 559
561MAKE_ATTR_DEAD static void 560MAKE_ATTR_DEAD static void
562JobPassSig_term(int signo) 561JobPassSig_term(int signo)
563{ 562{
564 /* Dont run .INTERRUPT target then exit */ 563 /* Dont run .INTERRUPT target then exit */
565 JobInterrupt(FALSE, signo); 564 JobInterrupt(FALSE, signo);
566} 565}
567 566
568static void 567static void
569JobPassSig_suspend(int signo) 568JobPassSig_suspend(int signo)
570{ 569{
571 sigset_t nmask, omask; 570 sigset_t nmask, omask;
572 struct sigaction act; 571 struct sigaction act;
573 572
574 /* Suppress job started/continued messages */ 573 /* Suppress job started/continued messages */
575 make_suspended = 1; 574 make_suspended = 1;
576 575
577 /* Pass the signal onto every job */ 576 /* Pass the signal onto every job */
578 JobCondPassSig(signo); 577 JobCondPassSig(signo);
579 578
580 /* 579 /*
581 * Send ourselves the signal now we've given the message to everyone else. 580 * Send ourselves the signal now we've given the message to everyone else.
582 * Note we block everything else possible while we're getting the signal. 581 * Note we block everything else possible while we're getting the signal.
583 * This ensures that all our jobs get continued when we wake up before 582 * This ensures that all our jobs get continued when we wake up before
584 * we take any other signal. 583 * we take any other signal.
585 */ 584 */
586 sigfillset(&nmask); 585 sigfillset(&nmask);
587 sigdelset(&nmask, signo); 586 sigdelset(&nmask, signo);
588 (void)sigprocmask(SIG_SETMASK, &nmask, &omask); 587 (void)sigprocmask(SIG_SETMASK, &nmask, &omask);
589 588
590 act.sa_handler = SIG_DFL; 589 act.sa_handler = SIG_DFL;
591 sigemptyset(&act.sa_mask); 590 sigemptyset(&act.sa_mask);
592 act.sa_flags = 0; 591 act.sa_flags = 0;
593 (void)sigaction(signo, &act, NULL); 592 (void)sigaction(signo, &act, NULL);
594 593
595 if (DEBUG(JOB)) { 594 if (DEBUG(JOB)) {
596 (void)fprintf(debug_file, 595 (void)fprintf(debug_file,
597 "JobPassSig passing signal %d to self.\n", signo); 596 "JobPassSig passing signal %d to self.\n", signo);
598 } 597 }
599 598
600 (void)kill(getpid(), signo); 599 (void)kill(getpid(), signo);
601 600
602 /* 601 /*
603 * We've been continued. 602 * We've been continued.
604 * 603 *
605 * A whole host of signals continue to happen! 604 * A whole host of signals continue to happen!
606 * SIGCHLD for any processes that actually suspended themselves. 605 * SIGCHLD for any processes that actually suspended themselves.
607 * SIGCHLD for any processes that exited while we were alseep. 606 * SIGCHLD for any processes that exited while we were alseep.
608 * The SIGCONT that actually caused us to wakeup. 607 * The SIGCONT that actually caused us to wakeup.
609 * 608 *
610 * Since we defer passing the SIGCONT on to our children until 609 * Since we defer passing the SIGCONT on to our children until
611 * the main processing loop, we can be sure that all the SIGCHLD 610 * the main processing loop, we can be sure that all the SIGCHLD
612 * events will have happened by then - and that the waitpid() will 611 * events will have happened by then - and that the waitpid() will
613 * collect the child 'suspended' events. 612 * collect the child 'suspended' events.
614 * For correct sequencing we just need to ensure we process the 613 * For correct sequencing we just need to ensure we process the
615 * waitpid() before passign on the SIGCONT. 614 * waitpid() before passign on the SIGCONT.
616 * 615 *
617 * In any case nothing else is needed here. 616 * In any case nothing else is needed here.
618 */ 617 */
619 618
620 /* Restore handler and signal mask */ 619 /* Restore handler and signal mask */
621 act.sa_handler = JobPassSig_suspend; 620 act.sa_handler = JobPassSig_suspend;
622 (void)sigaction(signo, &act, NULL); 621 (void)sigaction(signo, &act, NULL);
623 (void)sigprocmask(SIG_SETMASK, &omask, NULL); 622 (void)sigprocmask(SIG_SETMASK, &omask, NULL);
624} 623}
625 624
626/*- 625/*-
627 *----------------------------------------------------------------------- 626 *-----------------------------------------------------------------------
628 * JobFindPid -- 627 * JobFindPid --
629 * Compare the pid of the job with the given pid and return 0 if they 628 * Compare the pid of the job with the given pid and return 0 if they
630 * are equal. This function is called from Job_CatchChildren 629 * are equal. This function is called from Job_CatchChildren
631 * to find the job descriptor of the finished job. 630 * to find the job descriptor of the finished job.
632 * 631 *
633 * Input: 632 * Input:
634 * job job to examine 633 * job job to examine
635 * pid process id desired 634 * pid process id desired
636 * 635 *
637 * Results: 636 * Results:
638 * Job with matching pid 637 * Job with matching pid
639 * 638 *
640 * Side Effects: 639 * Side Effects:
641 * None 640 * None
642 *----------------------------------------------------------------------- 641 *-----------------------------------------------------------------------
643 */ 642 */
644static Job * 643static Job *
645JobFindPid(int pid, int status, Boolean isJobs) 644JobFindPid(int pid, int status, Boolean isJobs)
646{ 645{
647 Job *job; 646 Job *job;
648 647
649 for (job = job_table; job < job_table_end; job++) { 648 for (job = job_table; job < job_table_end; job++) {
650 if ((job->job_state == status) && job->pid == pid) 649 if ((job->job_state == status) && job->pid == pid)
651 return job; 650 return job;
652 } 651 }
653 if (DEBUG(JOB) && isJobs) 652 if (DEBUG(JOB) && isJobs)
654 job_table_dump("no pid"); 653 job_table_dump("no pid");
655 return NULL; 654 return NULL;
656} 655}
657 656
658/*- 657/*-
659 *----------------------------------------------------------------------- 658 *-----------------------------------------------------------------------
660 * JobPrintCommand -- 659 * JobPrintCommand --
661 * Put out another command for the given job. If the command starts 660 * Put out another command for the given job. If the command starts
662 * with an @ or a - we process it specially. In the former case, 661 * with an @ or a - we process it specially. In the former case,
663 * so long as the -s and -n flags weren't given to make, we stick 662 * so long as the -s and -n flags weren't given to make, we stick
664 * a shell-specific echoOff command in the script. In the latter, 663 * a shell-specific echoOff command in the script. In the latter,
665 * we ignore errors for the entire job, unless the shell has error 664 * we ignore errors for the entire job, unless the shell has error
666 * control. 665 * control.
667 * If the command is just "..." we take all future commands for this 666 * If the command is just "..." we take all future commands for this
668 * job to be commands to be executed once the entire graph has been 667 * job to be commands to be executed once the entire graph has been
669 * made and return non-zero to signal that the end of the commands 668 * made and return non-zero to signal that the end of the commands
670 * was reached. These commands are later attached to the postCommands 669 * was reached. These commands are later attached to the postCommands
671 * node and executed by Job_End when all things are done. 670 * node and executed by Job_End when all things are done.
672 * This function is called from JobStart via Lst_ForEach. 671 * This function is called from JobStart via Lst_ForEach.
673 * 672 *
674 * Input: 673 * Input:
675 * cmdp command string to print 674 * cmdp command string to print
676 * jobp job for which to print it 675 * jobp job for which to print it
677 * 676 *
678 * Results: 677 * Results:
679 * Always 0, unless the command was "..." 678 * Always 0, unless the command was "..."
680 * 679 *
681 * Side Effects: 680 * Side Effects:
682 * If the command begins with a '-' and the shell has no error control, 681 * If the command begins with a '-' and the shell has no error control,
683 * the JOB_IGNERR flag is set in the job descriptor. 682 * the JOB_IGNERR flag is set in the job descriptor.
684 * If the command is "..." and we're not ignoring such things, 683 * If the command is "..." and we're not ignoring such things,
685 * tailCmds is set to the successor node of the cmd. 684 * tailCmds is set to the successor node of the cmd.
686 * numCommands is incremented if the command is actually printed. 685 * numCommands is incremented if the command is actually printed.
687 *----------------------------------------------------------------------- 686 *-----------------------------------------------------------------------
688 */ 687 */
689static int 688static int
690JobPrintCommand(void *cmdp, void *jobp) 689JobPrintCommand(void *cmdp, void *jobp)
691{ 690{
692 Boolean noSpecials; /* true if we shouldn't worry about 691 Boolean noSpecials; /* true if we shouldn't worry about
693 * inserting special commands into 692 * inserting special commands into
694 * the input stream. */ 693 * the input stream. */
695 Boolean shutUp = FALSE; /* true if we put a no echo command 694 Boolean shutUp = FALSE; /* true if we put a no echo command
696 * into the command file */ 695 * into the command file */
697 Boolean errOff = FALSE; /* true if we turned error checking 696 Boolean errOff = FALSE; /* true if we turned error checking
698 * off before printing the command 697 * off before printing the command
699 * and need to turn it back on */ 698 * and need to turn it back on */
700 const char *cmdTemplate; /* Template to use when printing the 699 const char *cmdTemplate; /* Template to use when printing the
701 * command */ 700 * command */
702 char *cmdStart; /* Start of expanded command */ 701 char *cmdStart; /* Start of expanded command */
703 char *escCmd = NULL; /* Command with quotes/backticks escaped */ 702 char *escCmd = NULL; /* Command with quotes/backticks escaped */
704 char *cmd = (char *)cmdp; 703 char *cmd = (char *)cmdp;
705 Job *job = (Job *)jobp; 704 Job *job = (Job *)jobp;
706 int i, j; 705 int i, j;
707 706
708 noSpecials = NoExecute(job->node); 707 noSpecials = NoExecute(job->node);
709 708
710 if (strcmp(cmd, "...") == 0) { 709 if (strcmp(cmd, "...") == 0) {
711 job->node->type |= OP_SAVE_CMDS; 710 job->node->type |= OP_SAVE_CMDS;
712 if ((job->flags & JOB_IGNDOTS) == 0) { 711 if ((job->flags & JOB_IGNDOTS) == 0) {
713 LstNode dotsNode = Lst_Member(job->node->commands, cmd); 712 LstNode dotsNode = Lst_Member(job->node->commands, cmd);
714 job->tailCmds = dotsNode != NULL ? Lst_Succ(dotsNode) : NULL; 713 job->tailCmds = dotsNode != NULL ? Lst_Succ(dotsNode) : NULL;
715 return 1; 714 return 1;
716 } 715 }
717 return 0; 716 return 0;
718 } 717 }
719 718
720#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \ 719#define DBPRINTF(fmt, arg) if (DEBUG(JOB)) { \
721 (void)fprintf(debug_file, fmt, arg); \ 720 (void)fprintf(debug_file, fmt, arg); \
722 } \ 721 } \
723 (void)fprintf(job->cmdFILE, fmt, arg); \ 722 (void)fprintf(job->cmdFILE, fmt, arg); \
724 (void)fflush(job->cmdFILE); 723 (void)fflush(job->cmdFILE);
725 724
726 numCommands += 1; 725 numCommands += 1;
727 726
728 cmdStart = cmd = Var_Subst(cmd, job->node, VARE_WANTRES); 727 cmdStart = cmd = Var_Subst(cmd, job->node, VARE_WANTRES);
729 728
730 cmdTemplate = "%s\n"; 729 cmdTemplate = "%s\n";
731 730
732 /* 731 /*
733 * Check for leading @' and -'s to control echoing and error checking. 732 * Check for leading @' and -'s to control echoing and error checking.
734 */ 733 */
735 while (*cmd == '@' || *cmd == '-' || (*cmd == '+')) { 734 while (*cmd == '@' || *cmd == '-' || (*cmd == '+')) {
736 switch (*cmd) { 735 switch (*cmd) {
737 case '@': 736 case '@':
738 shutUp = DEBUG(LOUD) ? FALSE : TRUE; 737 shutUp = DEBUG(LOUD) ? FALSE : TRUE;
739 break; 738 break;
740 case '-': 739 case '-':
741 errOff = TRUE; 740 errOff = TRUE;
742 break; 741 break;
743 case '+': 742 case '+':
744 if (noSpecials) { 743 if (noSpecials) {
745 /* 744 /*
746 * We're not actually executing anything... 745 * We're not actually executing anything...
747 * but this one needs to be - use compat mode just for it. 746 * but this one needs to be - use compat mode just for it.
748 */ 747 */
749 CompatRunCommand(cmdp, job->node); 748 CompatRunCommand(cmdp, job->node);
750 free(cmdStart); 749 free(cmdStart);
751 return 0; 750 return 0;
752 } 751 }
753 break; 752 break;
754 } 753 }
755 cmd++; 754 cmd++;
756 } 755 }
757 756
758 while (isspace((unsigned char) *cmd)) 757 while (isspace((unsigned char) *cmd))
759 cmd++; 758 cmd++;
760 759
761 /* 760 /*
762 * If the shell doesn't have error control the alternate echo'ing will 761 * If the shell doesn't have error control the alternate echo'ing will
763 * be done (to avoid showing additional error checking code) 762 * be done (to avoid showing additional error checking code)
764 * and this will need the characters '$ ` \ "' escaped 763 * and this will need the characters '$ ` \ "' escaped
765 */ 764 */
766 765
767 if (!commandShell->hasErrCtl) { 766 if (!commandShell->hasErrCtl) {
768 /* Worst that could happen is every char needs escaping. */ 767 /* Worst that could happen is every char needs escaping. */
769 escCmd = bmake_malloc((strlen(cmd) * 2) + 1); 768 escCmd = bmake_malloc((strlen(cmd) * 2) + 1);
770 for (i = 0, j= 0; cmd[i] != '\0'; i++, j++) { 769 for (i = 0, j= 0; cmd[i] != '\0'; i++, j++) {
771 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' || 770 if (cmd[i] == '$' || cmd[i] == '`' || cmd[i] == '\\' ||
772 cmd[i] == '"') 771 cmd[i] == '"')
773 escCmd[j++] = '\\'; 772 escCmd[j++] = '\\';
774 escCmd[j] = cmd[i]; 773 escCmd[j] = cmd[i];
775 } 774 }
776 escCmd[j] = 0; 775 escCmd[j] = 0;
777 } 776 }
778 777
779 if (shutUp) { 778 if (shutUp) {
780 if (!(job->flags & JOB_SILENT) && !noSpecials && 779 if (!(job->flags & JOB_SILENT) && !noSpecials &&
781 commandShell->hasEchoCtl) { 780 commandShell->hasEchoCtl) {
782 DBPRINTF("%s\n", commandShell->echoOff); 781 DBPRINTF("%s\n", commandShell->echoOff);
783 } else { 782 } else {
784 if (commandShell->hasErrCtl) 783 if (commandShell->hasErrCtl)
785 shutUp = FALSE; 784 shutUp = FALSE;
786 } 785 }
787 } 786 }
788 787
789 if (errOff) { 788 if (errOff) {
790 if (!noSpecials) { 789 if (!noSpecials) {
791 if (commandShell->hasErrCtl) { 790 if (commandShell->hasErrCtl) {
792 /* 791 /*
793 * we don't want the error-control commands showing 792 * we don't want the error-control commands showing
794 * up either, so we turn off echoing while executing 793 * up either, so we turn off echoing while executing
795 * them. We could put another field in the shell 794 * them. We could put another field in the shell
796 * structure to tell JobDoOutput to look for this 795 * structure to tell JobDoOutput to look for this
797 * string too, but why make it any more complex than 796 * string too, but why make it any more complex than
798 * it already is? 797 * it already is?
799 */ 798 */
800 if (!(job->flags & JOB_SILENT) && !shutUp && 799 if (!(job->flags & JOB_SILENT) && !shutUp &&
801 commandShell->hasEchoCtl) { 800 commandShell->hasEchoCtl) {
802 DBPRINTF("%s\n", commandShell->echoOff); 801 DBPRINTF("%s\n", commandShell->echoOff);
803 DBPRINTF("%s\n", commandShell->ignErr); 802 DBPRINTF("%s\n", commandShell->ignErr);
804 DBPRINTF("%s\n", commandShell->echoOn); 803 DBPRINTF("%s\n", commandShell->echoOn);
805 } else { 804 } else {
806 DBPRINTF("%s\n", commandShell->ignErr); 805 DBPRINTF("%s\n", commandShell->ignErr);
807 } 806 }
808 } else if (commandShell->ignErr && 807 } else if (commandShell->ignErr &&
809 (*commandShell->ignErr != '\0')) 808 (*commandShell->ignErr != '\0'))
810 { 809 {
811 /* 810 /*
812 * The shell has no error control, so we need to be 811 * The shell has no error control, so we need to be
813 * weird to get it to ignore any errors from the command. 812 * weird to get it to ignore any errors from the command.
814 * If echoing is turned on, we turn it off and use the 813 * If echoing is turned on, we turn it off and use the
815 * errCheck template to echo the command. Leave echoing 814 * errCheck template to echo the command. Leave echoing
816 * off so the user doesn't see the weirdness we go through 815 * off so the user doesn't see the weirdness we go through
817 * to ignore errors. Set cmdTemplate to use the weirdness 816 * to ignore errors. Set cmdTemplate to use the weirdness
818 * instead of the simple "%s\n" template. 817 * instead of the simple "%s\n" template.
819 */ 818 */
820 job->flags |= JOB_IGNERR; 819 job->flags |= JOB_IGNERR;
821 if (!(job->flags & JOB_SILENT) && !shutUp) { 820 if (!(job->flags & JOB_SILENT) && !shutUp) {
822 if (commandShell->hasEchoCtl) { 821 if (commandShell->hasEchoCtl) {
823 DBPRINTF("%s\n", commandShell->echoOff); 822 DBPRINTF("%s\n", commandShell->echoOff);
824 } 823 }
825 DBPRINTF(commandShell->errCheck, escCmd); 824 DBPRINTF(commandShell->errCheck, escCmd);
826 shutUp = TRUE; 825 shutUp = TRUE;
827 } else { 826 } else {
828 if (!shutUp) { 827 if (!shutUp) {
829 DBPRINTF(commandShell->errCheck, escCmd); 828 DBPRINTF(commandShell->errCheck, escCmd);
830 } 829 }
831 } 830 }
832 cmdTemplate = commandShell->ignErr; 831 cmdTemplate = commandShell->ignErr;
833 /* 832 /*
834 * The error ignoration (hee hee) is already taken care 833 * The error ignoration (hee hee) is already taken care
835 * of by the ignErr template, so pretend error checking 834 * of by the ignErr template, so pretend error checking
836 * is still on. 835 * is still on.
837 */ 836 */
838 errOff = FALSE; 837 errOff = FALSE;
839 } else { 838 } else {
840 errOff = FALSE; 839 errOff = FALSE;
841 } 840 }
842 } else { 841 } else {
843 errOff = FALSE; 842 errOff = FALSE;
844 } 843 }
845 } else { 844 } else {
846 845
847 /* 846 /*
848 * If errors are being checked and the shell doesn't have error control 847 * If errors are being checked and the shell doesn't have error control
849 * but does supply an errOut template, then setup commands to run 848 * but does supply an errOut template, then setup commands to run
850 * through it. 849 * through it.
851 */ 850 */
852 851
853 if (!commandShell->hasErrCtl && commandShell->errOut && 852 if (!commandShell->hasErrCtl && commandShell->errOut &&
854 (*commandShell->errOut != '\0')) { 853 (*commandShell->errOut != '\0')) {
855 if (!(job->flags & JOB_SILENT) && !shutUp) { 854 if (!(job->flags & JOB_SILENT) && !shutUp) {
856 if (commandShell->hasEchoCtl) { 855 if (commandShell->hasEchoCtl) {
857 DBPRINTF("%s\n", commandShell->echoOff); 856 DBPRINTF("%s\n", commandShell->echoOff);
858 } 857 }
859 DBPRINTF(commandShell->errCheck, escCmd); 858 DBPRINTF(commandShell->errCheck, escCmd);
860 shutUp = TRUE; 859 shutUp = TRUE;
861 } 860 }
862 /* If it's a comment line or blank, treat as an ignored error */ 861 /* If it's a comment line or blank, treat as an ignored error */
863 if ((escCmd[0] == commandShell->commentChar) || 862 if ((escCmd[0] == commandShell->commentChar) ||
864 (escCmd[0] == 0)) 863 (escCmd[0] == 0))
865 cmdTemplate = commandShell->ignErr; 864 cmdTemplate = commandShell->ignErr;
866 else 865 else
867 cmdTemplate = commandShell->errOut; 866 cmdTemplate = commandShell->errOut;
868 errOff = FALSE; 867 errOff = FALSE;
869 } 868 }
870 } 869 }
871 870
872 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 && 871 if (DEBUG(SHELL) && strcmp(shellName, "sh") == 0 &&
873 (job->flags & JOB_TRACED) == 0) { 872 (job->flags & JOB_TRACED) == 0) {
874 DBPRINTF("set -%s\n", "x"); 873 DBPRINTF("set -%s\n", "x");
875 job->flags |= JOB_TRACED; 874 job->flags |= JOB_TRACED;
876 } 875 }
877 876
878 DBPRINTF(cmdTemplate, cmd); 877 DBPRINTF(cmdTemplate, cmd);
879 free(cmdStart); 878 free(cmdStart);
880 free(escCmd); 879 free(escCmd);
881 if (errOff) { 880 if (errOff) {
882 /* 881 /*
883 * If echoing is already off, there's no point in issuing the 882 * If echoing is already off, there's no point in issuing the
884 * echoOff command. Otherwise we issue it and pretend it was on 883 * echoOff command. Otherwise we issue it and pretend it was on
885 * for the whole command... 884 * for the whole command...
886 */ 885 */
887 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){ 886 if (!shutUp && !(job->flags & JOB_SILENT) && commandShell->hasEchoCtl){
888 DBPRINTF("%s\n", commandShell->echoOff); 887 DBPRINTF("%s\n", commandShell->echoOff);
889 shutUp = TRUE; 888 shutUp = TRUE;
890 } 889 }
891 DBPRINTF("%s\n", commandShell->errCheck); 890 DBPRINTF("%s\n", commandShell->errCheck);
892 } 891 }
893 if (shutUp && commandShell->hasEchoCtl) { 892 if (shutUp && commandShell->hasEchoCtl) {
894 DBPRINTF("%s\n", commandShell->echoOn); 893 DBPRINTF("%s\n", commandShell->echoOn);
895 } 894 }
896 return 0; 895 return 0;
897} 896}
898 897
899/*- 898/*-
900 *----------------------------------------------------------------------- 899 *-----------------------------------------------------------------------
901 * JobSaveCommand -- 900 * JobSaveCommand --
902 * Save a command to be executed when everything else is done. 901 * Save a command to be executed when everything else is done.
903 * Callback function for JobFinish... 902 * Callback function for JobFinish...
904 * 903 *
905 * Results: 904 * Results:
906 * Always returns 0 905 * Always returns 0
907 * 906 *
908 * Side Effects: 907 * Side Effects:
909 * The command is tacked onto the end of postCommands's commands list. 908 * The command is tacked onto the end of postCommands' commands list.
910 * 909 *
911 *----------------------------------------------------------------------- 910 *-----------------------------------------------------------------------
912 */ 911 */
913static int 912static int
914JobSaveCommand(void *cmd, void *gn) 913JobSaveCommand(void *cmd, void *gn)
915{ 914{
916 cmd = Var_Subst((char *)cmd, (GNode *)gn, VARE_WANTRES); 915 cmd = Var_Subst((char *)cmd, (GNode *)gn, VARE_WANTRES);
917 Lst_Append(postCommands->commands, cmd); 916 Lst_Append(postCommands->commands, cmd);
918 return 0; 917 return 0;
919} 918}
920 919
921 920
922/*- 921/*-
923 *----------------------------------------------------------------------- 922 *-----------------------------------------------------------------------
924 * JobClose -- 923 * JobClose --
925 * Called to close both input and output pipes when a job is finished. 924 * Called to close both input and output pipes when a job is finished.
926 * 925 *
927 * Results: 926 * Results:
928 * Nada 927 * Nada
929 * 928 *
930 * Side Effects: 929 * Side Effects:
931 * The file descriptors associated with the job are closed. 930 * The file descriptors associated with the job are closed.
932 * 931 *
933 *----------------------------------------------------------------------- 932 *-----------------------------------------------------------------------
934 */ 933 */
935static void 934static void
936JobClose(Job *job) 935JobClose(Job *job)
937{ 936{
938 clearfd(job); 937 clearfd(job);
939 (void)close(job->outPipe); 938 (void)close(job->outPipe);
940 job->outPipe = -1; 939 job->outPipe = -1;
941 940
942 JobDoOutput(job, TRUE); 941 JobDoOutput(job, TRUE);
943 (void)close(job->inPipe); 942 (void)close(job->inPipe);
944 job->inPipe = -1; 943 job->inPipe = -1;
945} 944}
946 945
947/*- 946/*-
948 *----------------------------------------------------------------------- 947 *-----------------------------------------------------------------------
949 * JobFinish -- 948 * JobFinish --
950 * Do final processing for the given job including updating 949 * Do final processing for the given job including updating
951 * parents and starting new jobs as available/necessary. Note 950 * parents and starting new jobs as available/necessary. Note
952 * that we pay no attention to the JOB_IGNERR flag here. 951 * that we pay no attention to the JOB_IGNERR flag here.
953 * This is because when we're called because of a noexecute flag 952 * This is because when we're called because of a noexecute flag
954 * or something, jstat.w_status is 0 and when called from 953 * or something, jstat.w_status is 0 and when called from
955 * Job_CatchChildren, the status is zeroed if it s/b ignored. 954 * Job_CatchChildren, the status is zeroed if it s/b ignored.
956 * 955 *
957 * Input: 956 * Input:
958 * job job to finish 957 * job job to finish
959 * status sub-why job went away 958 * status sub-why job went away
960 * 959 *
961 * Results: 960 * Results:
962 * None 961 * None
963 * 962 *
964 * Side Effects: 963 * Side Effects:
965 * Final commands for the job are placed on postCommands. 964 * Final commands for the job are placed on postCommands.
966 * 965 *
967 * If we got an error and are aborting (aborting == ABORT_ERROR) and 966 * If we got an error and are aborting (aborting == ABORT_ERROR) and
968 * the job list is now empty, we are done for the day. 967 * the job list is now empty, we are done for the day.
969 * If we recognized an error (errors !=0), we set the aborting flag 968 * If we recognized an error (errors !=0), we set the aborting flag
970 * to ABORT_ERROR so no more jobs will be started. 969 * to ABORT_ERROR so no more jobs will be started.
971 *----------------------------------------------------------------------- 970 *-----------------------------------------------------------------------
972 */ 971 */
973/*ARGSUSED*/ 972/*ARGSUSED*/
974static void 973static void
975JobFinish(Job *job, int status) 974JobFinish(Job *job, int status)
976{ 975{
977 Boolean done, return_job_token; 976 Boolean done, return_job_token;
978 977
979 if (DEBUG(JOB)) { 978 if (DEBUG(JOB)) {
980 fprintf(debug_file, "Jobfinish: %d [%s], status %d\n", 979 fprintf(debug_file, "Jobfinish: %d [%s], status %d\n",
981 job->pid, job->node->name, status); 980 job->pid, job->node->name, status);
982 } 981 }
983 982
984 if ((WIFEXITED(status) && 983 if ((WIFEXITED(status) &&
985 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) || 984 (((WEXITSTATUS(status) != 0) && !(job->flags & JOB_IGNERR)))) ||
986 WIFSIGNALED(status)) 985 WIFSIGNALED(status))
987 { 986 {
988 /* 987 /*
989 * If it exited non-zero and either we're doing things our 988 * If it exited non-zero and either we're doing things our
990 * way or we're not ignoring errors, the job is finished. 989 * way or we're not ignoring errors, the job is finished.
991 * Similarly, if the shell died because of a signal 990 * Similarly, if the shell died because of a signal
992 * the job is also finished. In these 991 * the job is also finished. In these
993 * cases, finish out the job's output before printing the exit 992 * cases, finish out the job's output before printing the exit
994 * status... 993 * status...
995 */ 994 */
996 JobClose(job); 995 JobClose(job);
997 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 996 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
998 (void)fclose(job->cmdFILE); 997 (void)fclose(job->cmdFILE);
999 job->cmdFILE = NULL; 998 job->cmdFILE = NULL;
1000 } 999 }
1001 done = TRUE; 1000 done = TRUE;
1002 } else if (WIFEXITED(status)) { 1001 } else if (WIFEXITED(status)) {
1003 /* 1002 /*
1004 * Deal with ignored errors in -B mode. We need to print a message 1003 * Deal with ignored errors in -B mode. We need to print a message
1005 * telling of the ignored error as well as setting status.w_status 1004 * telling of the ignored error as well as setting status.w_status
1006 * to 0 so the next command gets run. To do this, we set done to be 1005 * to 0 so the next command gets run. To do this, we set done to be
1007 * TRUE if in -B mode and the job exited non-zero. 1006 * TRUE if in -B mode and the job exited non-zero.
1008 */ 1007 */
1009 done = WEXITSTATUS(status) != 0; 1008 done = WEXITSTATUS(status) != 0;
1010 /* 1009 /*
1011 * Old comment said: "Note we don't 1010 * Old comment said: "Note we don't
1012 * want to close down any of the streams until we know we're at the 1011 * want to close down any of the streams until we know we're at the
1013 * end." 1012 * end."
1014 * But we do. Otherwise when are we going to print the rest of the 1013 * But we do. Otherwise when are we going to print the rest of the
1015 * stuff? 1014 * stuff?
1016 */ 1015 */
1017 JobClose(job); 1016 JobClose(job);
1018 } else { 1017 } else {
1019 /* 1018 /*
1020 * No need to close things down or anything. 1019 * No need to close things down or anything.
1021 */ 1020 */
1022 done = FALSE; 1021 done = FALSE;
1023 } 1022 }
1024 1023
1025 if (done) { 1024 if (done) {
1026 if (WIFEXITED(status)) { 1025 if (WIFEXITED(status)) {
1027 if (DEBUG(JOB)) { 1026 if (DEBUG(JOB)) {
1028 (void)fprintf(debug_file, "Process %d [%s] exited.\n", 1027 (void)fprintf(debug_file, "Process %d [%s] exited.\n",
1029 job->pid, job->node->name); 1028 job->pid, job->node->name);
1030 } 1029 }
1031 if (WEXITSTATUS(status) != 0) { 1030 if (WEXITSTATUS(status) != 0) {
1032 if (job->node != lastNode) { 1031 if (job->node != lastNode) {
1033 MESSAGE(stdout, job->node); 1032 MESSAGE(stdout, job->node);
1034 lastNode = job->node; 1033 lastNode = job->node;
1035 } 1034 }
1036#ifdef USE_META 1035#ifdef USE_META
1037 if (useMeta) { 1036 if (useMeta) {
1038 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status)); 1037 meta_job_error(job, job->node, job->flags, WEXITSTATUS(status));
1039 } 1038 }
1040#endif 1039#endif
1041 if (!dieQuietly(job->node, -1)) 1040 if (!dieQuietly(job->node, -1))
1042 (void)printf("*** [%s] Error code %d%s\n", 1041 (void)printf("*** [%s] Error code %d%s\n",
1043 job->node->name, 1042 job->node->name,
1044 WEXITSTATUS(status), 1043 WEXITSTATUS(status),
1045 (job->flags & JOB_IGNERR) ? " (ignored)" : ""); 1044 (job->flags & JOB_IGNERR) ? " (ignored)" : "");
1046 if (job->flags & JOB_IGNERR) { 1045 if (job->flags & JOB_IGNERR) {
1047 status = 0; 1046 status = 0;
1048 } else { 1047 } else {
1049 if (deleteOnError) { 1048 if (deleteOnError) {
1050 JobDeleteTarget(job->node); 1049 JobDeleteTarget(job->node);
1051 } 1050 }
1052 PrintOnError(job->node, NULL); 1051 PrintOnError(job->node, NULL);
1053 } 1052 }
1054 } else if (DEBUG(JOB)) { 1053 } else if (DEBUG(JOB)) {
1055 if (job->node != lastNode) { 1054 if (job->node != lastNode) {
1056 MESSAGE(stdout, job->node); 1055 MESSAGE(stdout, job->node);
1057 lastNode = job->node; 1056 lastNode = job->node;
1058 } 1057 }
1059 (void)printf("*** [%s] Completed successfully\n", 1058 (void)printf("*** [%s] Completed successfully\n",
1060 job->node->name); 1059 job->node->name);
1061 } 1060 }
1062 } else { 1061 } else {
1063 if (job->node != lastNode) { 1062 if (job->node != lastNode) {
1064 MESSAGE(stdout, job->node); 1063 MESSAGE(stdout, job->node);
1065 lastNode = job->node; 1064 lastNode = job->node;
1066 } 1065 }
1067 (void)printf("*** [%s] Signal %d\n", 1066 (void)printf("*** [%s] Signal %d\n",
1068 job->node->name, WTERMSIG(status)); 1067 job->node->name, WTERMSIG(status));
1069 if (deleteOnError) { 1068 if (deleteOnError) {
1070 JobDeleteTarget(job->node); 1069 JobDeleteTarget(job->node);
1071 } 1070 }
1072 } 1071 }
1073 (void)fflush(stdout); 1072 (void)fflush(stdout);
1074 } 1073 }
1075 1074
1076#ifdef USE_META 1075#ifdef USE_META
1077 if (useMeta) { 1076 if (useMeta) {
1078 int x; 1077 int x;
1079 1078
1080 if ((x = meta_job_finish(job)) != 0 && status == 0) { 1079 if ((x = meta_job_finish(job)) != 0 && status == 0) {
1081 status = x; 1080 status = x;
1082 } 1081 }
1083 } 1082 }
1084#endif 1083#endif
1085 1084
1086 return_job_token = FALSE; 1085 return_job_token = FALSE;
1087 1086
1088 Trace_Log(JOBEND, job); 1087 Trace_Log(JOBEND, job);
1089 if (!(job->flags & JOB_SPECIAL)) { 1088 if (!(job->flags & JOB_SPECIAL)) {
1090 if ((status != 0) || 1089 if ((status != 0) ||
1091 (aborting == ABORT_ERROR) || 1090 (aborting == ABORT_ERROR) ||
1092 (aborting == ABORT_INTERRUPT)) 1091 (aborting == ABORT_INTERRUPT))
1093 return_job_token = TRUE; 1092 return_job_token = TRUE;
1094 } 1093 }
1095 1094
1096 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) { 1095 if ((aborting != ABORT_ERROR) && (aborting != ABORT_INTERRUPT) && (status == 0)) {
1097 /* 1096 /*
1098 * As long as we aren't aborting and the job didn't return a non-zero 1097 * As long as we aren't aborting and the job didn't return a non-zero
1099 * status that we shouldn't ignore, we call Make_Update to update 1098 * status that we shouldn't ignore, we call Make_Update to update
1100 * the parents. In addition, any saved commands for the node are placed 1099 * the parents. In addition, any saved commands for the node are placed
1101 * on the .END target. 1100 * on the .END target.
1102 */ 1101 */
1103 if (job->tailCmds != NULL) { 1102 if (job->tailCmds != NULL) {
1104 Lst_ForEachFrom(job->node->commands, job->tailCmds, 1103 Lst_ForEachFrom(job->node->commands, job->tailCmds,
1105 JobSaveCommand, 1104 JobSaveCommand,
1106 job->node); 1105 job->node);
1107 } 1106 }
1108 job->node->made = MADE; 1107 job->node->made = MADE;
1109 if (!(job->flags & JOB_SPECIAL)) 1108 if (!(job->flags & JOB_SPECIAL))
1110 return_job_token = TRUE; 1109 return_job_token = TRUE;
1111 Make_Update(job->node); 1110 Make_Update(job->node);
1112 job->job_state = JOB_ST_FREE; 1111 job->job_state = JOB_ST_FREE;
1113 } else if (status != 0) { 1112 } else if (status != 0) {
1114 errors += 1; 1113 errors += 1;
1115 job->job_state = JOB_ST_FREE; 1114 job->job_state = JOB_ST_FREE;
1116 } 1115 }
1117 1116
1118 /* 1117 /*
1119 * Set aborting if any error. 1118 * Set aborting if any error.
1120 */ 1119 */
1121 if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) { 1120 if (errors && !keepgoing && (aborting != ABORT_INTERRUPT)) {
1122 /* 1121 /*
1123 * If we found any errors in this batch of children and the -k flag 1122 * If we found any errors in this batch of children and the -k flag
1124 * wasn't given, we set the aborting flag so no more jobs get 1123 * wasn't given, we set the aborting flag so no more jobs get
1125 * started. 1124 * started.
1126 */ 1125 */
1127 aborting = ABORT_ERROR; 1126 aborting = ABORT_ERROR;
1128 } 1127 }
1129 1128
1130 if (return_job_token) 1129 if (return_job_token)
1131 Job_TokenReturn(); 1130 Job_TokenReturn();
1132 1131
1133 if (aborting == ABORT_ERROR && jobTokensRunning == 0) { 1132 if (aborting == ABORT_ERROR && jobTokensRunning == 0) {
1134 /* 1133 /*
1135 * If we are aborting and the job table is now empty, we finish. 1134 * If we are aborting and the job table is now empty, we finish.
1136 */ 1135 */
1137 Finish(errors); 1136 Finish(errors);
1138 } 1137 }
1139} 1138}
1140 1139
1141/*- 1140/*-
1142 *----------------------------------------------------------------------- 1141 *-----------------------------------------------------------------------
1143 * Job_Touch -- 1142 * Job_Touch --
1144 * Touch the given target. Called by JobStart when the -t flag was 1143 * Touch the given target. Called by JobStart when the -t flag was
1145 * given 1144 * given
1146 * 1145 *
1147 * Input: 1146 * Input:
1148 * gn the node of the file to touch 1147 * gn the node of the file to touch
1149 * silent TRUE if should not print message 1148 * silent TRUE if should not print message
1150 * 1149 *
1151 * Results: 1150 * Results:
1152 * None 1151 * None
1153 * 1152 *
1154 * Side Effects: 1153 * Side Effects:
1155 * The data modification of the file is changed. In addition, if the 1154 * The data modification of the file is changed. In addition, if the
1156 * file did not exist, it is created. 1155 * file did not exist, it is created.
1157 *----------------------------------------------------------------------- 1156 *-----------------------------------------------------------------------
1158 */ 1157 */
1159void 1158void
1160Job_Touch(GNode *gn, Boolean silent) 1159Job_Touch(GNode *gn, Boolean silent)
1161{ 1160{
1162 int streamID; /* ID of stream opened to do the touch */ 1161 int streamID; /* ID of stream opened to do the touch */
1163 struct utimbuf times; /* Times for utime() call */ 1162 struct utimbuf times; /* Times for utime() call */
1164 1163
1165 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL| 1164 if (gn->type & (OP_JOIN|OP_USE|OP_USEBEFORE|OP_EXEC|OP_OPTIONAL|
1166 OP_SPECIAL|OP_PHONY)) { 1165 OP_SPECIAL|OP_PHONY)) {
1167 /* 1166 /*
1168 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets 1167 * .JOIN, .USE, .ZEROTIME and .OPTIONAL targets are "virtual" targets
1169 * and, as such, shouldn't really be created. 1168 * and, as such, shouldn't really be created.
1170 */ 1169 */
1171 return; 1170 return;
1172 } 1171 }
1173 1172
1174 if (!silent || NoExecute(gn)) { 1173 if (!silent || NoExecute(gn)) {
1175 (void)fprintf(stdout, "touch %s\n", gn->name); 1174 (void)fprintf(stdout, "touch %s\n", gn->name);
1176 (void)fflush(stdout); 1175 (void)fflush(stdout);
1177 } 1176 }
1178 1177
1179 if (NoExecute(gn)) { 1178 if (NoExecute(gn)) {
1180 return; 1179 return;
1181 } 1180 }
1182 1181
1183 if (gn->type & OP_ARCHV) { 1182 if (gn->type & OP_ARCHV) {
1184 Arch_Touch(gn); 1183 Arch_Touch(gn);
1185 } else if (gn->type & OP_LIB) { 1184 } else if (gn->type & OP_LIB) {
1186 Arch_TouchLib(gn); 1185 Arch_TouchLib(gn);
1187 } else { 1186 } else {
1188 char *file = gn->path ? gn->path : gn->name; 1187 char *file = gn->path ? gn->path : gn->name;
1189 1188
1190 times.actime = times.modtime = now; 1189 times.actime = times.modtime = now;
1191 if (utime(file, &times) < 0){ 1190 if (utime(file, &times) < 0){
1192 streamID = open(file, O_RDWR | O_CREAT, 0666); 1191 streamID = open(file, O_RDWR | O_CREAT, 0666);
1193 1192
1194 if (streamID >= 0) { 1193 if (streamID >= 0) {
1195 char c; 1194 char c;
1196 1195
1197 /* 1196 /*
1198 * Read and write a byte to the file to change the 1197 * Read and write a byte to the file to change the
1199 * modification time, then close the file. 1198 * modification time, then close the file.
1200 */ 1199 */
1201 if (read(streamID, &c, 1) == 1) { 1200 if (read(streamID, &c, 1) == 1) {
1202 (void)lseek(streamID, (off_t)0, SEEK_SET); 1201 (void)lseek(streamID, (off_t)0, SEEK_SET);
1203 while (write(streamID, &c, 1) == -1 && errno == EAGAIN) 1202 while (write(streamID, &c, 1) == -1 && errno == EAGAIN)
1204 continue; 1203 continue;
1205 } 1204 }
1206 1205
1207 (void)close(streamID); 1206 (void)close(streamID);
1208 } else { 1207 } else {
1209 (void)fprintf(stdout, "*** couldn't touch %s: %s", 1208 (void)fprintf(stdout, "*** couldn't touch %s: %s",
1210 file, strerror(errno)); 1209 file, strerror(errno));
1211 (void)fflush(stdout); 1210 (void)fflush(stdout);
1212 } 1211 }
1213 } 1212 }
1214 } 1213 }
1215} 1214}
1216 1215
1217/*- 1216/*-
1218 *----------------------------------------------------------------------- 1217 *-----------------------------------------------------------------------
1219 * Job_CheckCommands -- 1218 * Job_CheckCommands --
1220 * Make sure the given node has all the commands it needs. 1219 * Make sure the given node has all the commands it needs.
1221 * 1220 *
1222 * Input: 1221 * Input:
1223 * gn The target whose commands need verifying 1222 * gn The target whose commands need verifying
1224 * abortProc Function to abort with message 1223 * abortProc Function to abort with message
1225 * 1224 *
1226 * Results: 1225 * Results:
1227 * TRUE if the commands list is/was ok. 1226 * TRUE if the commands list is/was ok.
1228 * 1227 *
1229 * Side Effects: 1228 * Side Effects:
1230 * The node will have commands from the .DEFAULT rule added to it 1229 * The node will have commands from the .DEFAULT rule added to it
1231 * if it needs them. 1230 * if it needs them.
1232 *----------------------------------------------------------------------- 1231 *-----------------------------------------------------------------------
1233 */ 1232 */
1234Boolean 1233Boolean
1235Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...)) 1234Job_CheckCommands(GNode *gn, void (*abortProc)(const char *, ...))
1236{ 1235{
1237 if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) && 1236 if (OP_NOP(gn->type) && Lst_IsEmpty(gn->commands) &&
1238 ((gn->type & OP_LIB) == 0 || Lst_IsEmpty(gn->children))) { 1237 ((gn->type & OP_LIB) == 0 || Lst_IsEmpty(gn->children))) {
1239 /* 1238 /*
1240 * No commands. Look for .DEFAULT rule from which we might infer 1239 * No commands. Look for .DEFAULT rule from which we might infer
1241 * commands 1240 * commands
1242 */ 1241 */
1243 if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) && 1242 if ((DEFAULT != NULL) && !Lst_IsEmpty(DEFAULT->commands) &&
1244 (gn->type & OP_SPECIAL) == 0) { 1243 (gn->type & OP_SPECIAL) == 0) {
1245 char *p1; 1244 char *p1;
1246 /* 1245 /*
1247 * Make only looks for a .DEFAULT if the node was never the 1246 * Make only looks for a .DEFAULT if the node was never the
1248 * target of an operator, so that's what we do too. If 1247 * target of an operator, so that's what we do too. If
1249 * a .DEFAULT was given, we substitute its commands for gn's 1248 * a .DEFAULT was given, we substitute its commands for gn's
1250 * commands and set the IMPSRC variable to be the target's name 1249 * commands and set the IMPSRC variable to be the target's name
1251 * The DEFAULT node acts like a transformation rule, in that 1250 * The DEFAULT node acts like a transformation rule, in that
1252 * gn also inherits any attributes or sources attached to 1251 * gn also inherits any attributes or sources attached to
1253 * .DEFAULT itself. 1252 * .DEFAULT itself.
1254 */ 1253 */
1255 Make_HandleUse(DEFAULT, gn); 1254 Make_HandleUse(DEFAULT, gn);
1256 Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn); 1255 Var_Set(IMPSRC, Var_Value(TARGET, gn, &p1), gn);
1257 bmake_free(p1); 1256 bmake_free(p1);
1258 } else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) { 1257 } else if (Dir_MTime(gn, 0) == 0 && (gn->type & OP_SPECIAL) == 0) {
1259 /* 1258 /*
1260 * The node wasn't the target of an operator we have no .DEFAULT 1259 * The node wasn't the target of an operator we have no .DEFAULT
1261 * rule to go on and the target doesn't already exist. There's 1260 * rule to go on and the target doesn't already exist. There's
1262 * nothing more we can do for this branch. If the -k flag wasn't 1261 * nothing more we can do for this branch. If the -k flag wasn't
1263 * given, we stop in our tracks, otherwise we just don't update 1262 * given, we stop in our tracks, otherwise we just don't update
1264 * this node's parents so they never get examined. 1263 * this node's parents so they never get examined.
1265 */ 1264 */
1266 static const char msg[] = ": don't know how to make"; 1265 static const char msg[] = ": don't know how to make";
1267 1266
1268 if (gn->flags & FROM_DEPEND) { 1267 if (gn->flags & FROM_DEPEND) {
1269 if (!Job_RunTarget(".STALE", gn->fname)) 1268 if (!Job_RunTarget(".STALE", gn->fname))
1270 fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n", 1269 fprintf(stdout, "%s: %s, %d: ignoring stale %s for %s\n",
1271 progname, gn->fname, gn->lineno, makeDependfile, 1270 progname, gn->fname, gn->lineno, makeDependfile,
1272 gn->name); 1271 gn->name);
1273 return TRUE; 1272 return TRUE;
1274 } 1273 }
1275 1274
1276 if (gn->type & OP_OPTIONAL) { 1275 if (gn->type & OP_OPTIONAL) {
1277 (void)fprintf(stdout, "%s%s %s (ignored)\n", progname, 1276 (void)fprintf(stdout, "%s%s %s (ignored)\n", progname,
1278 msg, gn->name); 1277 msg, gn->name);
1279 (void)fflush(stdout); 1278 (void)fflush(stdout);
1280 } else if (keepgoing) { 1279 } else if (keepgoing) {
1281 (void)fprintf(stdout, "%s%s %s (continuing)\n", progname, 1280 (void)fprintf(stdout, "%s%s %s (continuing)\n", progname,
1282 msg, gn->name); 1281 msg, gn->name);
1283 (void)fflush(stdout); 1282 (void)fflush(stdout);
1284 return FALSE; 1283 return FALSE;
1285 } else { 1284 } else {
1286 (*abortProc)("%s%s %s. Stop", progname, msg, gn->name); 1285 (*abortProc)("%s%s %s. Stop", progname, msg, gn->name);
1287 return FALSE; 1286 return FALSE;
1288 } 1287 }
1289 } 1288 }
1290 } 1289 }
1291 return TRUE; 1290 return TRUE;
1292} 1291}
1293 1292
1294/*- 1293/*-
1295 *----------------------------------------------------------------------- 1294 *-----------------------------------------------------------------------
1296 * JobExec -- 1295 * JobExec --
1297 * Execute the shell for the given job. Called from JobStart 1296 * Execute the shell for the given job. Called from JobStart
1298 * 1297 *
1299 * Input: 1298 * Input:
1300 * job Job to execute 1299 * job Job to execute
1301 * 1300 *
1302 * Results: 1301 * Results:
1303 * None. 1302 * None.
1304 * 1303 *
1305 * Side Effects: 1304 * Side Effects:
1306 * A shell is executed, outputs is altered and the Job structure added 1305 * A shell is executed, outputs is altered and the Job structure added
1307 * to the job table. 1306 * to the job table.
1308 * 1307 *
1309 *----------------------------------------------------------------------- 1308 *-----------------------------------------------------------------------
1310 */ 1309 */
1311static void 1310static void
1312JobExec(Job *job, char **argv) 1311JobExec(Job *job, char **argv)
1313{ 1312{
1314 int cpid; /* ID of new child */ 1313 int cpid; /* ID of new child */
1315 sigset_t mask; 1314 sigset_t mask;
1316 1315
1317 job->flags &= ~JOB_TRACED; 1316 job->flags &= ~JOB_TRACED;
1318 1317
1319 if (DEBUG(JOB)) { 1318 if (DEBUG(JOB)) {
1320 int i; 1319 int i;
1321 1320
1322 (void)fprintf(debug_file, "Running %s %sly\n", job->node->name, "local"); 1321 (void)fprintf(debug_file, "Running %s %sly\n", job->node->name, "local");
1323 (void)fprintf(debug_file, "\tCommand: "); 1322 (void)fprintf(debug_file, "\tCommand: ");
1324 for (i = 0; argv[i] != NULL; i++) { 1323 for (i = 0; argv[i] != NULL; i++) {
1325 (void)fprintf(debug_file, "%s ", argv[i]); 1324 (void)fprintf(debug_file, "%s ", argv[i]);
1326 } 1325 }
1327 (void)fprintf(debug_file, "\n"); 1326 (void)fprintf(debug_file, "\n");
1328 } 1327 }
1329 1328
1330 /* 1329 /*
1331 * Some jobs produce no output and it's disconcerting to have 1330 * Some jobs produce no output and it's disconcerting to have
1332 * no feedback of their running (since they produce no output, the 1331 * no feedback of their running (since they produce no output, the
1333 * banner with their name in it never appears). This is an attempt to 1332 * banner with their name in it never appears). This is an attempt to
1334 * provide that feedback, even if nothing follows it. 1333 * provide that feedback, even if nothing follows it.
1335 */ 1334 */
1336 if ((lastNode != job->node) && !(job->flags & JOB_SILENT)) { 1335 if ((lastNode != job->node) && !(job->flags & JOB_SILENT)) {
1337 MESSAGE(stdout, job->node); 1336 MESSAGE(stdout, job->node);
1338 lastNode = job->node; 1337 lastNode = job->node;
1339 } 1338 }
1340 1339
1341 /* No interruptions until this job is on the `jobs' list */ 1340 /* No interruptions until this job is on the `jobs' list */
1342 JobSigLock(&mask); 1341 JobSigLock(&mask);
1343 1342
1344 /* Pre-emptively mark job running, pid still zero though */ 1343 /* Pre-emptively mark job running, pid still zero though */
1345 job->job_state = JOB_ST_RUNNING; 1344 job->job_state = JOB_ST_RUNNING;
1346 1345
1347 cpid = vFork(); 1346 cpid = vFork();
1348 if (cpid == -1) 1347 if (cpid == -1)
1349 Punt("Cannot vfork: %s", strerror(errno)); 1348 Punt("Cannot vfork: %s", strerror(errno));
1350 1349
1351 if (cpid == 0) { 1350 if (cpid == 0) {
1352 /* Child */ 1351 /* Child */
1353 sigset_t tmask; 1352 sigset_t tmask;
1354 1353
1355#ifdef USE_META 1354#ifdef USE_META
1356 if (useMeta) { 1355 if (useMeta) {
1357 meta_job_child(job); 1356 meta_job_child(job);
1358 } 1357 }
1359#endif 1358#endif
1360 /* 1359 /*
1361 * Reset all signal handlers; this is necessary because we also 1360 * Reset all signal handlers; this is necessary because we also
1362 * need to unblock signals before we exec(2). 1361 * need to unblock signals before we exec(2).
1363 */ 1362 */
1364 JobSigReset(); 1363 JobSigReset();
1365 1364
1366 /* Now unblock signals */ 1365 /* Now unblock signals */
1367 sigemptyset(&tmask); 1366 sigemptyset(&tmask);
1368 JobSigUnlock(&tmask); 1367 JobSigUnlock(&tmask);
1369 1368
1370 /* 1369 /*
1371 * Must duplicate the input stream down to the child's input and 1370 * Must duplicate the input stream down to the child's input and
1372 * reset it to the beginning (again). Since the stream was marked 1371 * reset it to the beginning (again). Since the stream was marked
1373 * close-on-exec, we must clear that bit in the new input. 1372 * close-on-exec, we must clear that bit in the new input.
1374 */ 1373 */
1375 if (dup2(FILENO(job->cmdFILE), 0) == -1) { 1374 if (dup2(FILENO(job->cmdFILE), 0) == -1) {
1376 execError("dup2", "job->cmdFILE"); 1375 execError("dup2", "job->cmdFILE");
1377 _exit(1); 1376 _exit(1);
1378 } 1377 }
1379 if (fcntl(0, F_SETFD, 0) == -1) { 1378 if (fcntl(0, F_SETFD, 0) == -1) {
1380 execError("fcntl clear close-on-exec", "stdin"); 1379 execError("fcntl clear close-on-exec", "stdin");
1381 _exit(1); 1380 _exit(1);
1382 } 1381 }
1383 if (lseek(0, (off_t)0, SEEK_SET) == -1) { 1382 if (lseek(0, (off_t)0, SEEK_SET) == -1) {
1384 execError("lseek to 0", "stdin"); 1383 execError("lseek to 0", "stdin");
1385 _exit(1); 1384 _exit(1);
1386 } 1385 }
1387 1386
1388 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) { 1387 if (job->node->type & (OP_MAKE | OP_SUBMAKE)) {
1389 /* 1388 /*
1390 * Pass job token pipe to submakes. 1389 * Pass job token pipe to submakes.
1391 */ 1390 */
1392 if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) { 1391 if (fcntl(tokenWaitJob.inPipe, F_SETFD, 0) == -1) {
1393 execError("clear close-on-exec", "tokenWaitJob.inPipe"); 1392 execError("clear close-on-exec", "tokenWaitJob.inPipe");
1394 _exit(1); 1393 _exit(1);
1395 } 1394 }
1396 if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) { 1395 if (fcntl(tokenWaitJob.outPipe, F_SETFD, 0) == -1) {
1397 execError("clear close-on-exec", "tokenWaitJob.outPipe"); 1396 execError("clear close-on-exec", "tokenWaitJob.outPipe");
1398 _exit(1); 1397 _exit(1);
1399 } 1398 }
1400 } 1399 }
1401 1400
1402 /* 1401 /*
1403 * Set up the child's output to be routed through the pipe 1402 * Set up the child's output to be routed through the pipe
1404 * we've created for it. 1403 * we've created for it.
1405 */ 1404 */
1406 if (dup2(job->outPipe, 1) == -1) { 1405 if (dup2(job->outPipe, 1) == -1) {
1407 execError("dup2", "job->outPipe"); 1406 execError("dup2", "job->outPipe");
1408 _exit(1); 1407 _exit(1);
1409 } 1408 }
1410 /* 1409 /*
1411 * The output channels are marked close on exec. This bit was 1410 * The output channels are marked close on exec. This bit was
1412 * duplicated by the dup2(on some systems), so we have to clear 1411 * duplicated by the dup2(on some systems), so we have to clear
1413 * it before routing the shell's error output to the same place as 1412 * it before routing the shell's error output to the same place as
1414 * its standard output. 1413 * its standard output.
1415 */ 1414 */
1416 if (fcntl(1, F_SETFD, 0) == -1) { 1415 if (fcntl(1, F_SETFD, 0) == -1) {
1417 execError("clear close-on-exec", "stdout"); 1416 execError("clear close-on-exec", "stdout");
1418 _exit(1); 1417 _exit(1);
1419 } 1418 }
1420 if (dup2(1, 2) == -1) { 1419 if (dup2(1, 2) == -1) {
1421 execError("dup2", "1, 2"); 1420 execError("dup2", "1, 2");
1422 _exit(1); 1421 _exit(1);
1423 } 1422 }
1424 1423
1425 /* 1424 /*
1426 * We want to switch the child into a different process family so 1425 * We want to switch the child into a different process family so
1427 * we can kill it and all its descendants in one fell swoop, 1426 * we can kill it and all its descendants in one fell swoop,
1428 * by killing its process family, but not commit suicide. 1427 * by killing its process family, but not commit suicide.
1429 */ 1428 */
1430#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID) 1429#if defined(MAKE_NATIVE) || defined(HAVE_SETPGID)
1431#if defined(SYSV) 1430#if defined(SYSV)
1432 /* XXX: dsl - I'm sure this should be setpgrp()... */ 1431 /* XXX: dsl - I'm sure this should be setpgrp()... */
1433 (void)setsid(); 1432 (void)setsid();
1434#else 1433#else
1435 (void)setpgid(0, getpid()); 1434 (void)setpgid(0, getpid());
1436#endif 1435#endif
1437#endif 1436#endif
1438 1437
1439 Var_ExportVars(); 1438 Var_ExportVars();
1440 1439
1441 (void)execv(shellPath, argv); 1440 (void)execv(shellPath, argv);
1442 execError("exec", shellPath); 1441 execError("exec", shellPath);
1443 _exit(1); 1442 _exit(1);
1444 } 1443 }
1445 1444
1446 /* Parent, continuing after the child exec */ 1445 /* Parent, continuing after the child exec */
1447 job->pid = cpid; 1446 job->pid = cpid;
1448 1447
1449 Trace_Log(JOBSTART, job); 1448 Trace_Log(JOBSTART, job);
1450 1449
1451#ifdef USE_META 1450#ifdef USE_META
1452 if (useMeta) { 1451 if (useMeta) {
1453 meta_job_parent(job, cpid); 1452 meta_job_parent(job, cpid);
1454 } 1453 }
1455#endif 1454#endif
1456 1455
1457 /* 1456 /*
1458 * Set the current position in the buffer to the beginning 1457 * Set the current position in the buffer to the beginning
1459 * and mark another stream to watch in the outputs mask 1458 * and mark another stream to watch in the outputs mask
1460 */ 1459 */
1461 job->curPos = 0; 1460 job->curPos = 0;
1462 1461
1463 watchfd(job); 1462 watchfd(job);
1464 1463
1465 if (job->cmdFILE != NULL && job->cmdFILE != stdout) { 1464 if (job->cmdFILE != NULL && job->cmdFILE != stdout) {
1466 (void)fclose(job->cmdFILE); 1465 (void)fclose(job->cmdFILE);
1467 job->cmdFILE = NULL; 1466 job->cmdFILE = NULL;
1468 } 1467 }
1469 1468
1470 /* 1469 /*
1471 * Now the job is actually running, add it to the table. 1470 * Now the job is actually running, add it to the table.
1472 */ 1471 */
1473 if (DEBUG(JOB)) { 1472 if (DEBUG(JOB)) {
1474 fprintf(debug_file, "JobExec(%s): pid %d added to jobs table\n", 1473 fprintf(debug_file, "JobExec(%s): pid %d added to jobs table\n",
1475 job->node->name, job->pid); 1474 job->node->name, job->pid);
1476 job_table_dump("job started"); 1475 job_table_dump("job started");
1477 } 1476 }
1478 JobSigUnlock(&mask); 1477 JobSigUnlock(&mask);
1479} 1478}
1480 1479
1481/*- 1480/*-
1482 *----------------------------------------------------------------------- 1481 *-----------------------------------------------------------------------
1483 * JobMakeArgv -- 1482 * JobMakeArgv --
1484 * Create the argv needed to execute the shell for a given job. 1483 * Create the argv needed to execute the shell for a given job.
1485 * 1484 *
1486 * 1485 *
1487 * Results: 1486 * Results:
1488 * 1487 *
1489 * Side Effects: 1488 * Side Effects:
1490 * 1489 *
1491 *----------------------------------------------------------------------- 1490 *-----------------------------------------------------------------------
1492 */ 1491 */
1493static void 1492static void
1494JobMakeArgv(Job *job, char **argv) 1493JobMakeArgv(Job *job, char **argv)
1495{ 1494{
1496 int argc; 1495 int argc;
1497 static char args[10]; /* For merged arguments */ 1496 static char args[10]; /* For merged arguments */
1498 1497
1499 argv[0] = UNCONST(shellName); 1498 argv[0] = UNCONST(shellName);
1500 argc = 1; 1499 argc = 1;
1501 1500
1502 if ((commandShell->exit && (*commandShell->exit != '-')) || 1501 if ((commandShell->exit && (*commandShell->exit != '-')) ||
1503 (commandShell->echo && (*commandShell->echo != '-'))) 1502 (commandShell->echo && (*commandShell->echo != '-')))
1504 { 1503 {
1505 /* 1504 /*
1506 * At least one of the flags doesn't have a minus before it, so 1505 * At least one of the flags doesn't have a minus before it, so
1507 * merge them together. Have to do this because the *(&(@*#*&#$# 1506 * merge them together. Have to do this because the *(&(@*#*&#$#
1508 * Bourne shell thinks its second argument is a file to source. 1507 * Bourne shell thinks its second argument is a file to source.
1509 * Grrrr. Note the ten-character limitation on the combined arguments. 1508 * Grrrr. Note the ten-character limitation on the combined arguments.
1510 */ 1509 */
1511 (void)snprintf(args, sizeof(args), "-%s%s", 1510 (void)snprintf(args, sizeof(args), "-%s%s",
1512 ((job->flags & JOB_IGNERR) ? "" : 1511 ((job->flags & JOB_IGNERR) ? "" :
1513 (commandShell->exit ? commandShell->exit : "")), 1512 (commandShell->exit ? commandShell->exit : "")),
1514 ((job->flags & JOB_SILENT) ? "" : 1513 ((job->flags & JOB_SILENT) ? "" :
1515 (commandShell->echo ? commandShell->echo : ""))); 1514 (commandShell->echo ? commandShell->echo : "")));
1516 1515
1517 if (args[1]) { 1516 if (args[1]) {
1518 argv[argc] = args; 1517 argv[argc] = args;
1519 argc++; 1518 argc++;
1520 } 1519 }
1521 } else { 1520 } else {
1522 if (!(job->flags & JOB_IGNERR) && commandShell->exit) { 1521 if (!(job->flags & JOB_IGNERR) && commandShell->exit) {
1523 argv[argc] = UNCONST(commandShell->exit); 1522 argv[argc] = UNCONST(commandShell->exit);
1524 argc++; 1523 argc++;
1525 } 1524 }
1526 if (!(job->flags & JOB_SILENT) && commandShell->echo) { 1525 if (!(job->flags & JOB_SILENT) && commandShell->echo) {
1527 argv[argc] = UNCONST(commandShell->echo); 1526 argv[argc] = UNCONST(commandShell->echo);
1528 argc++; 1527 argc++;
1529 } 1528 }
1530 } 1529 }
1531 argv[argc] = NULL; 1530 argv[argc] = NULL;
1532} 1531}
1533 1532
1534/*- 1533/*-
1535 *----------------------------------------------------------------------- 1534 *-----------------------------------------------------------------------
1536 * JobStart -- 1535 * JobStart --
1537 * Start a target-creation process going for the target described 1536 * Start a target-creation process going for the target described
1538 * by the graph node gn. 1537 * by the graph node gn.
1539 * 1538 *
1540 * Input: 1539 * Input:
1541 * gn target to create 1540 * gn target to create
1542 * flags flags for the job to override normal ones. 1541 * flags flags for the job to override normal ones.
1543 * e.g. JOB_SPECIAL or JOB_IGNDOTS 1542 * e.g. JOB_SPECIAL or JOB_IGNDOTS
1544 * previous The previous Job structure for this node, if any. 1543 * previous The previous Job structure for this node, if any.
1545 * 1544 *
1546 * Results: 1545 * Results:
1547 * JOB_ERROR if there was an error in the commands, JOB_FINISHED 1546 * JOB_ERROR if there was an error in the commands, JOB_FINISHED
1548 * if there isn't actually anything left to do for the job and 1547 * if there isn't actually anything left to do for the job and
1549 * JOB_RUNNING if the job has been started. 1548 * JOB_RUNNING if the job has been started.
1550 * 1549 *
1551 * Side Effects: 1550 * Side Effects:
1552 * A new Job node is created and added to the list of running 1551 * A new Job node is created and added to the list of running
1553 * jobs. PMake is forked and a child shell created. 1552 * jobs. PMake is forked and a child shell created.
1554 * 1553 *
1555 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set 1554 * NB: I'm fairly sure that this code is never called with JOB_SPECIAL set
1556 * JOB_IGNDOTS is never set (dsl) 1555 * JOB_IGNDOTS is never set (dsl)
1557 * Also the return value is ignored by everyone. 1556 * Also the return value is ignored by everyone.
1558 *----------------------------------------------------------------------- 1557 *-----------------------------------------------------------------------
1559 */ 1558 */
1560static int 1559static int
1561JobStart(GNode *gn, int flags) 1560JobStart(GNode *gn, int flags)
1562{ 1561{
1563 Job *job; /* new job descriptor */ 1562 Job *job; /* new job descriptor */
1564 char *argv[10]; /* Argument vector to shell */ 1563 char *argv[10]; /* Argument vector to shell */
1565 Boolean cmdsOK; /* true if the nodes commands were all right */ 1564 Boolean cmdsOK; /* true if the nodes commands were all right */
1566 Boolean noExec; /* Set true if we decide not to run the job */ 1565 Boolean noExec; /* Set true if we decide not to run the job */
1567 int tfd; /* File descriptor to the temp file */ 1566 int tfd; /* File descriptor to the temp file */
1568 1567
1569 for (job = job_table; job < job_table_end; job++) { 1568 for (job = job_table; job < job_table_end; job++) {
1570 if (job->job_state == JOB_ST_FREE) 1569 if (job->job_state == JOB_ST_FREE)
1571 break; 1570 break;
1572 } 1571 }
1573 if (job >= job_table_end) 1572 if (job >= job_table_end)
1574 Punt("JobStart no job slots vacant"); 1573 Punt("JobStart no job slots vacant");
1575 1574
1576 memset(job, 0, sizeof *job); 1575 memset(job, 0, sizeof *job);
1577 job->job_state = JOB_ST_SETUP; 1576 job->job_state = JOB_ST_SETUP;
1578 if (gn->type & OP_SPECIAL) 1577 if (gn->type & OP_SPECIAL)
1579 flags |= JOB_SPECIAL; 1578 flags |= JOB_SPECIAL;
1580 1579
1581 job->node = gn; 1580 job->node = gn;
1582 job->tailCmds = NULL; 1581 job->tailCmds = NULL;
1583 1582
1584 /* 1583 /*
1585 * Set the initial value of the flags for this job based on the global 1584 * Set the initial value of the flags for this job based on the global
1586 * ones and the node's attributes... Any flags supplied by the caller 1585 * ones and the node's attributes... Any flags supplied by the caller
1587 * are also added to the field. 1586 * are also added to the field.
1588 */ 1587 */
1589 job->flags = 0; 1588 job->flags = 0;
1590 if (Targ_Ignore(gn)) { 1589 if (Targ_Ignore(gn)) {
1591 job->flags |= JOB_IGNERR; 1590 job->flags |= JOB_IGNERR;
1592 } 1591 }
1593 if (Targ_Silent(gn)) { 1592 if (Targ_Silent(gn)) {
1594 job->flags |= JOB_SILENT; 1593 job->flags |= JOB_SILENT;
1595 } 1594 }
1596 job->flags |= flags; 1595 job->flags |= flags;
1597 1596
1598 /* 1597 /*
1599 * Check the commands now so any attributes from .DEFAULT have a chance 1598 * Check the commands now so any attributes from .DEFAULT have a chance
1600 * to migrate to the node 1599 * to migrate to the node
1601 */ 1600 */
1602 cmdsOK = Job_CheckCommands(gn, Error); 1601 cmdsOK = Job_CheckCommands(gn, Error);
1603 1602
1604 job->inPollfd = NULL; 1603 job->inPollfd = NULL;
1605 /* 1604 /*
1606 * If the -n flag wasn't given, we open up OUR (not the child's) 1605 * If the -n flag wasn't given, we open up OUR (not the child's)
1607 * temporary file to stuff commands in it. The thing is rd/wr so we don't 1606 * temporary file to stuff commands in it. The thing is rd/wr so we don't
1608 * need to reopen it to feed it to the shell. If the -n flag *was* given, 1607 * need to reopen it to feed it to the shell. If the -n flag *was* given,
1609 * we just set the file to be stdout. Cute, huh? 1608 * we just set the file to be stdout. Cute, huh?
1610 */ 1609 */
1611 if (((gn->type & OP_MAKE) && !(noRecursiveExecute)) || 1610 if (((gn->type & OP_MAKE) && !(noRecursiveExecute)) ||
1612 (!noExecute && !touchFlag)) { 1611 (!noExecute && !touchFlag)) {
1613 /* 1612 /*
1614 * tfile is the name of a file into which all shell commands are 1613 * tfile is the name of a file into which all shell commands are
1615 * put. It is removed before the child shell is executed, unless 1614 * put. It is removed before the child shell is executed, unless
1616 * DEBUG(SCRIPT) is set. 1615 * DEBUG(SCRIPT) is set.
1617 */ 1616 */
1618 char *tfile; 1617 char *tfile;
1619 sigset_t mask; 1618 sigset_t mask;
1620 /* 1619 /*
1621 * We're serious here, but if the commands were bogus, we're 1620 * We're serious here, but if the commands were bogus, we're
1622 * also dead... 1621 * also dead...
1623 */ 1622 */
1624 if (!cmdsOK) { 1623 if (!cmdsOK) {
1625 PrintOnError(gn, NULL); /* provide some clue */ 1624 PrintOnError(gn, NULL); /* provide some clue */
1626 DieHorribly(); 1625 DieHorribly();
1627 } 1626 }
1628 1627
1629 JobSigLock(&mask); 1628 JobSigLock(&mask);
1630 tfd = mkTempFile(TMPPAT, &tfile); 1629 tfd = mkTempFile(TMPPAT, &tfile);
1631 if (!DEBUG(SCRIPT)) 1630 if (!DEBUG(SCRIPT))
1632 (void)eunlink(tfile); 1631 (void)eunlink(tfile);
1633 JobSigUnlock(&mask); 1632 JobSigUnlock(&mask);
1634 1633
1635 job->cmdFILE = fdopen(tfd, "w+"); 1634 job->cmdFILE = fdopen(tfd, "w+");
1636 if (job->cmdFILE == NULL) { 1635 if (job->cmdFILE == NULL) {
1637 Punt("Could not fdopen %s", tfile); 1636 Punt("Could not fdopen %s", tfile);
1638 } 1637 }
1639 (void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC); 1638 (void)fcntl(FILENO(job->cmdFILE), F_SETFD, FD_CLOEXEC);
1640 /* 1639 /*
1641 * Send the commands to the command file, flush all its buffers then 1640 * Send the commands to the command file, flush all its buffers then
1642 * rewind and remove the thing. 1641 * rewind and remove the thing.
1643 */ 1642 */
1644 noExec = FALSE; 1643 noExec = FALSE;
1645 1644
1646#ifdef USE_META 1645#ifdef USE_META
1647 if (useMeta) { 1646 if (useMeta) {
1648 meta_job_start(job, gn); 1647 meta_job_start(job, gn);
1649 if (Targ_Silent(gn)) { /* might have changed */ 1648 if (Targ_Silent(gn)) { /* might have changed */
1650 job->flags |= JOB_SILENT; 1649 job->flags |= JOB_SILENT;
1651 } 1650 }
1652 } 1651 }
1653#endif 1652#endif
1654 /* 1653 /*
1655 * We can do all the commands at once. hooray for sanity 1654 * We can do all the commands at once. hooray for sanity
1656 */ 1655 */
1657 numCommands = 0; 1656 numCommands = 0;
1658 Lst_ForEach(gn->commands, JobPrintCommand, job); 1657 Lst_ForEach(gn->commands, JobPrintCommand, job);
1659 1658
1660 /* 1659 /*
1661 * If we didn't print out any commands to the shell script, 1660 * If we didn't print out any commands to the shell script,
1662 * there's not much point in executing the shell, is there? 1661 * there's not much point in executing the shell, is there?
1663 */ 1662 */
1664 if (numCommands == 0) { 1663 if (numCommands == 0) {
1665 noExec = TRUE; 1664 noExec = TRUE;
1666 } 1665 }
1667 1666
1668 free(tfile); 1667 free(tfile);
1669 } else if (NoExecute(gn)) { 1668 } else if (NoExecute(gn)) {
1670 /* 1669 /*
1671 * Not executing anything -- just print all the commands to stdout 1670 * Not executing anything -- just print all the commands to stdout
1672 * in one fell swoop. This will still set up job->tailCmds correctly. 1671 * in one fell swoop. This will still set up job->tailCmds correctly.
1673 */ 1672 */
1674 if (lastNode != gn) { 1673 if (lastNode != gn) {
1675 MESSAGE(stdout, gn); 1674 MESSAGE(stdout, gn);
1676 lastNode = gn; 1675 lastNode = gn;
1677 } 1676 }
1678 job->cmdFILE = stdout; 1677 job->cmdFILE = stdout;
1679 /* 1678 /*
1680 * Only print the commands if they're ok, but don't die if they're 1679 * Only print the commands if they're ok, but don't die if they're
1681 * not -- just let the user know they're bad and keep going. It 1680 * not -- just let the user know they're bad and keep going. It
1682 * doesn't do any harm in this case and may do some good. 1681 * doesn't do any harm in this case and may do some good.
1683 */ 1682 */
1684 if (cmdsOK) { 1683 if (cmdsOK) {
1685 Lst_ForEach(gn->commands, JobPrintCommand, job); 1684 Lst_ForEach(gn->commands, JobPrintCommand, job);
1686 } 1685 }
1687 /* 1686 /*
1688 * Don't execute the shell, thank you. 1687 * Don't execute the shell, thank you.
1689 */ 1688 */
1690 noExec = TRUE; 1689 noExec = TRUE;
1691 } else { 1690 } else {
1692 /* 1691 /*
1693 * Just touch the target and note that no shell should be executed. 1692 * Just touch the target and note that no shell should be executed.
1694 * Set cmdFILE to stdout to make life easier. Check the commands, too, 1693 * Set cmdFILE to stdout to make life easier. Check the commands, too,
1695 * but don't die if they're no good -- it does no harm to keep working 1694 * but don't die if they're no good -- it does no harm to keep working
1696 * up the graph. 1695 * up the graph.
1697 */ 1696 */
1698 job->cmdFILE = stdout; 1697 job->cmdFILE = stdout;
1699 Job_Touch(gn, job->flags&JOB_SILENT); 1698 Job_Touch(gn, job->flags&JOB_SILENT);
1700 noExec = TRUE; 1699 noExec = TRUE;
1701 } 1700 }
1702 /* Just in case it isn't already... */ 1701 /* Just in case it isn't already... */
1703 (void)fflush(job->cmdFILE); 1702 (void)fflush(job->cmdFILE);
1704 1703
1705 /* 1704 /*
1706 * If we're not supposed to execute a shell, don't. 1705 * If we're not supposed to execute a shell, don't.
1707 */ 1706 */
1708 if (noExec) { 1707 if (noExec) {
1709 if (!(job->flags & JOB_SPECIAL)) 1708 if (!(job->flags & JOB_SPECIAL))
1710 Job_TokenReturn(); 1709 Job_TokenReturn();
1711 /* 1710 /*
1712 * Unlink and close the command file if we opened one 1711 * Unlink and close the command file if we opened one
1713 */ 1712 */
1714 if (job->cmdFILE != stdout) { 1713 if (job->cmdFILE != stdout) {
1715 if (job->cmdFILE != NULL) { 1714 if (job->cmdFILE != NULL) {
1716 (void)fclose(job->cmdFILE); 1715 (void)fclose(job->cmdFILE);
1717 job->cmdFILE = NULL; 1716 job->cmdFILE = NULL;
1718 } 1717 }
1719 } 1718 }
1720 1719
1721 /* 1720 /*
1722 * We only want to work our way up the graph if we aren't here because 1721 * We only want to work our way up the graph if we aren't here because
1723 * the commands for the job were no good. 1722 * the commands for the job were no good.
1724 */ 1723 */
1725 if (cmdsOK && aborting == 0) { 1724 if (cmdsOK && aborting == 0) {
1726 if (job->tailCmds != NULL) { 1725 if (job->tailCmds != NULL) {
1727 Lst_ForEachFrom(job->node->commands, job->tailCmds, 1726 Lst_ForEachFrom(job->node->commands, job->tailCmds,
1728 JobSaveCommand, 1727 JobSaveCommand,
1729 job->node); 1728 job->node);
1730 } 1729 }
1731 job->node->made = MADE; 1730 job->node->made = MADE;
1732 Make_Update(job->node); 1731 Make_Update(job->node);
1733 } 1732 }
1734 job->job_state = JOB_ST_FREE; 1733 job->job_state = JOB_ST_FREE;
1735 return cmdsOK ? JOB_FINISHED : JOB_ERROR; 1734 return cmdsOK ? JOB_FINISHED : JOB_ERROR;
1736 } 1735 }
1737 1736
1738 /* 1737 /*
1739 * Set up the control arguments to the shell. This is based on the flags 1738 * Set up the control arguments to the shell. This is based on the flags
1740 * set earlier for this job. 1739 * set earlier for this job.
1741 */ 1740 */
1742 JobMakeArgv(job, argv); 1741 JobMakeArgv(job, argv);
1743 1742
1744 /* Create the pipe by which we'll get the shell's output. */ 1743 /* Create the pipe by which we'll get the shell's output. */
1745 JobCreatePipe(job, 3); 1744 JobCreatePipe(job, 3);
1746 1745
1747 JobExec(job, argv); 1746 JobExec(job, argv);
1748 return JOB_RUNNING; 1747 return JOB_RUNNING;
1749} 1748}
1750 1749
1751static char * 1750static char *
1752JobOutput(Job *job, char *cp, char *endp, int msg) 1751JobOutput(Job *job, char *cp, char *endp, int msg)
1753{ 1752{
1754 char *ecp; 1753 char *ecp;
1755 1754
1756 if (commandShell->noPrint) { 1755 if (commandShell->noPrint) {
1757 ecp = Str_FindSubstring(cp, commandShell->noPrint); 1756 ecp = Str_FindSubstring(cp, commandShell->noPrint);
1758 while (ecp != NULL) { 1757 while (ecp != NULL) {
1759 if (cp != ecp) { 1758 if (cp != ecp) {
1760 *ecp = '\0'; 1759 *ecp = '\0';
1761 if (!beSilent && msg && job->node != lastNode) { 1760 if (!beSilent && msg && job->node != lastNode) {
1762 MESSAGE(stdout, job->node); 1761 MESSAGE(stdout, job->node);
1763 lastNode = job->node; 1762 lastNode = job->node;
1764 } 1763 }
1765 /* 1764 /*
1766 * The only way there wouldn't be a newline after 1765 * The only way there wouldn't be a newline after
1767 * this line is if it were the last in the buffer. 1766 * this line is if it were the last in the buffer.
1768 * however, since the non-printable comes after it, 1767 * however, since the non-printable comes after it,
1769 * there must be a newline, so we don't print one. 1768 * there must be a newline, so we don't print one.
1770 */ 1769 */
1771 (void)fprintf(stdout, "%s", cp); 1770 (void)fprintf(stdout, "%s", cp);
1772 (void)fflush(stdout); 1771 (void)fflush(stdout);
1773 } 1772 }
1774 cp = ecp + commandShell->noPLen; 1773 cp = ecp + commandShell->noPLen;
1775 if (cp != endp) { 1774 if (cp != endp) {
1776 /* 1775 /*
1777 * Still more to print, look again after skipping 1776 * Still more to print, look again after skipping
1778 * the whitespace following the non-printable 1777 * the whitespace following the non-printable
1779 * command.... 1778 * command....
1780 */ 1779 */
1781 cp++; 1780 cp++;
1782 while (*cp == ' ' || *cp == '\t' || *cp == '\n') { 1781 while (*cp == ' ' || *cp == '\t' || *cp == '\n') {
1783 cp++; 1782 cp++;
1784 } 1783 }
1785 ecp = Str_FindSubstring(cp, commandShell->noPrint); 1784 ecp = Str_FindSubstring(cp, commandShell->noPrint);
1786 } else { 1785 } else {
1787 return cp; 1786 return cp;
1788 } 1787 }
1789 } 1788 }
1790 } 1789 }
1791 return cp; 1790 return cp;
1792} 1791}
1793 1792
1794/*- 1793/*-
1795 *----------------------------------------------------------------------- 1794 *-----------------------------------------------------------------------
1796 * JobDoOutput -- 1795 * JobDoOutput --
1797 * This function is called at different times depending on 1796 * This function is called at different times depending on
1798 * whether the user has specified that output is to be collected 1797 * whether the user has specified that output is to be collected
1799 * via pipes or temporary files. In the former case, we are called 1798 * via pipes or temporary files. In the former case, we are called
1800 * whenever there is something to read on the pipe. We collect more 1799 * whenever there is something to read on the pipe. We collect more
1801 * output from the given job and store it in the job's outBuf. If 1800 * output from the given job and store it in the job's outBuf. If
1802 * this makes up a line, we print it tagged by the job's identifier, 1801 * this makes up a line, we print it tagged by the job's identifier,
1803 * as necessary. 1802 * as necessary.
1804 * If output has been collected in a temporary file, we open the 1803 * If output has been collected in a temporary file, we open the
1805 * file and read it line by line, transfering it to our own 1804 * file and read it line by line, transfering it to our own
1806 * output channel until the file is empty. At which point we 1805 * output channel until the file is empty. At which point we
1807 * remove the temporary file. 1806 * remove the temporary file.
1808 * In both cases, however, we keep our figurative eye out for the 1807 * In both cases, however, we keep our figurative eye out for the
1809 * 'noPrint' line for the shell from which the output came. If 1808 * 'noPrint' line for the shell from which the output came. If
1810 * we recognize a line, we don't print it. If the command is not 1809 * we recognize a line, we don't print it. If the command is not
1811 * alone on the line (the character after it is not \0 or \n), we 1810 * alone on the line (the character after it is not \0 or \n), we
1812 * do print whatever follows it. 1811 * do print whatever follows it.
1813 * 1812 *
1814 * Input: 1813 * Input:
1815 * job the job whose output needs printing 1814 * job the job whose output needs printing
1816 * finish TRUE if this is the last time we'll be called 1815 * finish TRUE if this is the last time we'll be called
1817 * for this job 1816 * for this job
1818 * 1817 *
1819 * Results: 1818 * Results:
1820 * None 1819 * None
1821 * 1820 *
1822 * Side Effects: 1821 * Side Effects:
1823 * curPos may be shifted as may the contents of outBuf. 1822 * curPos may be shifted as may the contents of outBuf.
1824 *----------------------------------------------------------------------- 1823 *-----------------------------------------------------------------------
1825 */ 1824 */
1826STATIC void 1825STATIC void
1827JobDoOutput(Job *job, Boolean finish) 1826JobDoOutput(Job *job, Boolean finish)
1828{ 1827{
1829 Boolean gotNL = FALSE; /* true if got a newline */ 1828 Boolean gotNL = FALSE; /* true if got a newline */
1830 Boolean fbuf; /* true if our buffer filled up */ 1829 Boolean fbuf; /* true if our buffer filled up */
1831 int nr; /* number of bytes read */ 1830 int nr; /* number of bytes read */
1832 int i; /* auxiliary index into outBuf */ 1831 int i; /* auxiliary index into outBuf */
1833 int max; /* limit for i (end of current data) */ 1832 int max; /* limit for i (end of current data) */
1834 int nRead; /* (Temporary) number of bytes read */ 1833 int nRead; /* (Temporary) number of bytes read */
1835 1834
1836 /* 1835 /*
1837 * Read as many bytes as will fit in the buffer. 1836 * Read as many bytes as will fit in the buffer.
1838 */ 1837 */
1839end_loop: 1838end_loop:
1840 gotNL = FALSE; 1839 gotNL = FALSE;
1841 fbuf = FALSE; 1840 fbuf = FALSE;
1842 1841
1843 nRead = read(job->inPipe, &job->outBuf[job->curPos], 1842 nRead = read(job->inPipe, &job->outBuf[job->curPos],
1844 JOB_BUFSIZE - job->curPos); 1843 JOB_BUFSIZE - job->curPos);
1845 if (nRead < 0) { 1844 if (nRead < 0) {
1846 if (errno == EAGAIN) 1845 if (errno == EAGAIN)
1847 return; 1846 return;
1848 if (DEBUG(JOB)) { 1847 if (DEBUG(JOB)) {
1849 perror("JobDoOutput(piperead)"); 1848 perror("JobDoOutput(piperead)");
1850 } 1849 }
1851 nr = 0; 1850 nr = 0;
1852 } else { 1851 } else {
1853 nr = nRead; 1852 nr = nRead;
1854 } 1853 }
1855 1854
1856 /* 1855 /*
1857 * If we hit the end-of-file (the job is dead), we must flush its 1856 * If we hit the end-of-file (the job is dead), we must flush its
1858 * remaining output, so pretend we read a newline if there's any 1857 * remaining output, so pretend we read a newline if there's any
1859 * output remaining in the buffer. 1858 * output remaining in the buffer.
1860 * Also clear the 'finish' flag so we stop looping. 1859 * Also clear the 'finish' flag so we stop looping.
1861 */ 1860 */
1862 if ((nr == 0) && (job->curPos != 0)) { 1861 if ((nr == 0) && (job->curPos != 0)) {
1863 job->outBuf[job->curPos] = '\n'; 1862 job->outBuf[job->curPos] = '\n';
1864 nr = 1; 1863 nr = 1;
1865 finish = FALSE; 1864 finish = FALSE;
1866 } else if (nr == 0) { 1865 } else if (nr == 0) {
1867 finish = FALSE; 1866 finish = FALSE;
1868 } 1867 }
1869 1868
1870 /* 1869 /*
1871 * Look for the last newline in the bytes we just got. If there is 1870 * Look for the last newline in the bytes we just got. If there is
1872 * one, break out of the loop with 'i' as its index and gotNL set 1871 * one, break out of the loop with 'i' as its index and gotNL set
1873 * TRUE. 1872 * TRUE.
1874 */ 1873 */
1875 max = job->curPos + nr; 1874 max = job->curPos + nr;
1876 for (i = job->curPos + nr - 1; i >= job->curPos; i--) { 1875 for (i = job->curPos + nr - 1; i >= job->curPos; i--) {
1877 if (job->outBuf[i] == '\n') { 1876 if (job->outBuf[i] == '\n') {
1878 gotNL = TRUE; 1877 gotNL = TRUE;
1879 break; 1878 break;
1880 } else if (job->outBuf[i] == '\0') { 1879 } else if (job->outBuf[i] == '\0') {
1881 /* 1880 /*
1882 * Why? 1881 * Why?
1883 */ 1882 */
1884 job->outBuf[i] = ' '; 1883 job->outBuf[i] = ' ';
1885 } 1884 }
1886 } 1885 }
1887 1886
1888 if (!gotNL) { 1887 if (!gotNL) {
1889 job->curPos += nr; 1888 job->curPos += nr;
1890 if (job->curPos == JOB_BUFSIZE) { 1889 if (job->curPos == JOB_BUFSIZE) {
1891 /* 1890 /*
1892 * If we've run out of buffer space, we have no choice 1891 * If we've run out of buffer space, we have no choice
1893 * but to print the stuff. sigh. 1892 * but to print the stuff. sigh.
1894 */ 1893 */
1895 fbuf = TRUE; 1894 fbuf = TRUE;
1896 i = job->curPos; 1895 i = job->curPos;
1897 } 1896 }
1898 } 1897 }
1899 if (gotNL || fbuf) { 1898 if (gotNL || fbuf) {
1900 /* 1899 /*
1901 * Need to send the output to the screen. Null terminate it 1900 * Need to send the output to the screen. Null terminate it
1902 * first, overwriting the newline character if there was one. 1901 * first, overwriting the newline character if there was one.
1903 * So long as the line isn't one we should filter (according 1902 * So long as the line isn't one we should filter (according
1904 * to the shell description), we print the line, preceded 1903 * to the shell description), we print the line, preceded
1905 * by a target banner if this target isn't the same as the 1904 * by a target banner if this target isn't the same as the
1906 * one for which we last printed something. 1905 * one for which we last printed something.
1907 * The rest of the data in the buffer are then shifted down 1906 * The rest of the data in the buffer are then shifted down
1908 * to the start of the buffer and curPos is set accordingly. 1907 * to the start of the buffer and curPos is set accordingly.