Sun Dec 23 23:29:28 2018 UTC ()
On Minix3 the call to read returns EAGAIN (-1) and causes the build to break.
Skip punting on Minix3 as workaround for now, change via sjg@


(sevan)
diff -r1.17 -r1.18 pkgsrc/devel/bmake/files/job.c

cvs diff -r1.17 -r1.18 pkgsrc/devel/bmake/files/job.c (switch to unified diff)

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