Sat Jan 26 15:53:00 2013 UTC ()
Check read and write errors to avoid warnings from linux.
XXX: Should we print an error and exit instead?


(christos)
diff -r1.164 -r1.165 src/usr.bin/make/job.c
diff -r1.204 -r1.205 src/usr.bin/make/main.c

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

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

cvs diff -r1.204 -r1.205 src/usr.bin/make/main.c (switch to unified diff)

--- src/usr.bin/make/main.c 2013/01/25 02:01:10 1.204
+++ src/usr.bin/make/main.c 2013/01/26 15:53:00 1.205
@@ -1,1897 +1,1898 @@ @@ -1,1897 +1,1898 @@
1/* $NetBSD: main.c,v 1.204 2013/01/25 02:01:10 sjg Exp $ */ 1/* $NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990, 1993 4 * Copyright (c) 1988, 1989, 1990, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. 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) 1989 by Berkeley Softworks 36 * Copyright (c) 1989 by Berkeley Softworks
37 * All rights reserved. 37 * All rights reserved.
38 * 38 *
39 * This code is derived from software contributed to Berkeley by 39 * This code is derived from software contributed to Berkeley by
40 * Adam de Boor. 40 * Adam de Boor.
41 * 41 *
42 * Redistribution and use in source and binary forms, with or without 42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions 43 * modification, are permitted provided that the following conditions
44 * are met: 44 * are met:
45 * 1. Redistributions of source code must retain the above copyright 45 * 1. Redistributions of source code must retain the above copyright
46 * notice, this list of conditions and the following disclaimer. 46 * notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright 47 * 2. Redistributions in binary form must reproduce the above copyright
48 * notice, this list of conditions and the following disclaimer in the 48 * notice, this list of conditions and the following disclaimer in the
49 * documentation and/or other materials provided with the distribution. 49 * documentation and/or other materials provided with the distribution.
50 * 3. All advertising materials mentioning features or use of this software 50 * 3. All advertising materials mentioning features or use of this software
51 * must display the following acknowledgement: 51 * must display the following acknowledgement:
52 * This product includes software developed by the University of 52 * This product includes software developed by the University of
53 * California, Berkeley and its contributors. 53 * California, Berkeley and its contributors.
54 * 4. Neither the name of the University nor the names of its contributors 54 * 4. Neither the name of the University nor the names of its contributors
55 * may be used to endorse or promote products derived from this software 55 * may be used to endorse or promote products derived from this software
56 * without specific prior written permission. 56 * without specific prior written permission.
57 * 57 *
58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
68 * SUCH DAMAGE. 68 * SUCH DAMAGE.
69 */ 69 */
70 70
71#ifndef MAKE_NATIVE 71#ifndef MAKE_NATIVE
72static char rcsid[] = "$NetBSD: main.c,v 1.204 2013/01/25 02:01:10 sjg Exp $"; 72static char rcsid[] = "$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $";
73#else 73#else
74#include <sys/cdefs.h> 74#include <sys/cdefs.h>
75#ifndef lint 75#ifndef lint
76__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\ 76__COPYRIGHT("@(#) Copyright (c) 1988, 1989, 1990, 1993\
77 The Regents of the University of California. All rights reserved."); 77 The Regents of the University of California. All rights reserved.");
78#endif /* not lint */ 78#endif /* not lint */
79 79
80#ifndef lint 80#ifndef lint
81#if 0 81#if 0
82static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94"; 82static char sccsid[] = "@(#)main.c 8.3 (Berkeley) 3/19/94";
83#else 83#else
84__RCSID("$NetBSD: main.c,v 1.204 2013/01/25 02:01:10 sjg Exp $"); 84__RCSID("$NetBSD: main.c,v 1.205 2013/01/26 15:53:00 christos Exp $");
85#endif 85#endif
86#endif /* not lint */ 86#endif /* not lint */
87#endif 87#endif
88 88
89/*- 89/*-
90 * main.c -- 90 * main.c --
91 * The main file for this entire program. Exit routines etc 91 * The main file for this entire program. Exit routines etc
92 * reside here. 92 * reside here.
93 * 93 *
94 * Utility functions defined in this file: 94 * Utility functions defined in this file:
95 * Main_ParseArgLine Takes a line of arguments, breaks them and 95 * Main_ParseArgLine Takes a line of arguments, breaks them and
96 * treats them as if they were given when first 96 * treats them as if they were given when first
97 * invoked. Used by the parse module to implement 97 * invoked. Used by the parse module to implement
98 * the .MFLAGS target. 98 * the .MFLAGS target.
99 * 99 *
100 * Error Print a tagged error message. The global 100 * Error Print a tagged error message. The global
101 * MAKE variable must have been defined. This 101 * MAKE variable must have been defined. This
102 * takes a format string and two optional 102 * takes a format string and two optional
103 * arguments for it. 103 * arguments for it.
104 * 104 *
105 * Fatal Print an error message and exit. Also takes 105 * Fatal Print an error message and exit. Also takes
106 * a format string and two arguments. 106 * a format string and two arguments.
107 * 107 *
108 * Punt Aborts all jobs and exits with a message. Also 108 * Punt Aborts all jobs and exits with a message. Also
109 * takes a format string and two arguments. 109 * takes a format string and two arguments.
110 * 110 *
111 * Finish Finish things up by printing the number of 111 * Finish Finish things up by printing the number of
112 * errors which occurred, as passed to it, and 112 * errors which occurred, as passed to it, and
113 * exiting. 113 * exiting.
114 */ 114 */
115 115
116#include <sys/types.h> 116#include <sys/types.h>
117#include <sys/time.h> 117#include <sys/time.h>
118#include <sys/param.h> 118#include <sys/param.h>
119#include <sys/resource.h> 119#include <sys/resource.h>
120#include <sys/signal.h> 120#include <sys/signal.h>
121#include <sys/stat.h> 121#include <sys/stat.h>
122#ifdef MAKE_NATIVE 122#ifdef MAKE_NATIVE
123#include <sys/utsname.h> 123#include <sys/utsname.h>
124#endif 124#endif
125#include <sys/wait.h> 125#include <sys/wait.h>
126 126
127#include <errno.h> 127#include <errno.h>
128#include <fcntl.h> 128#include <fcntl.h>
129#include <stdarg.h> 129#include <stdarg.h>
130#include <stdio.h> 130#include <stdio.h>
131#include <stdlib.h> 131#include <stdlib.h>
132#include <time.h> 132#include <time.h>
133 133
134#include "make.h" 134#include "make.h"
135#include "hash.h" 135#include "hash.h"
136#include "dir.h" 136#include "dir.h"
137#include "job.h" 137#include "job.h"
138#include "pathnames.h" 138#include "pathnames.h"
139#include "trace.h" 139#include "trace.h"
140 140
141#ifdef USE_IOVEC 141#ifdef USE_IOVEC
142#include <sys/uio.h> 142#include <sys/uio.h>
143#endif 143#endif
144 144
145#ifndef DEFMAXLOCAL 145#ifndef DEFMAXLOCAL
146#define DEFMAXLOCAL DEFMAXJOBS 146#define DEFMAXLOCAL DEFMAXJOBS
147#endif /* DEFMAXLOCAL */ 147#endif /* DEFMAXLOCAL */
148 148
149Lst create; /* Targets to be made */ 149Lst create; /* Targets to be made */
150time_t now; /* Time at start of make */ 150time_t now; /* Time at start of make */
151GNode *DEFAULT; /* .DEFAULT node */ 151GNode *DEFAULT; /* .DEFAULT node */
152Boolean allPrecious; /* .PRECIOUS given on line by itself */ 152Boolean allPrecious; /* .PRECIOUS given on line by itself */
153 153
154static Boolean noBuiltins; /* -r flag */ 154static Boolean noBuiltins; /* -r flag */
155static Lst makefiles; /* ordered list of makefiles to read */ 155static Lst makefiles; /* ordered list of makefiles to read */
156static Boolean printVars; /* print value of one or more vars */ 156static Boolean printVars; /* print value of one or more vars */
157static Lst variables; /* list of variables to print */ 157static Lst variables; /* list of variables to print */
158int maxJobs; /* -j argument */ 158int maxJobs; /* -j argument */
159static int maxJobTokens; /* -j argument */ 159static int maxJobTokens; /* -j argument */
160Boolean compatMake; /* -B argument */ 160Boolean compatMake; /* -B argument */
161int debug; /* -d argument */ 161int debug; /* -d argument */
162Boolean debugVflag; /* -dV */ 162Boolean debugVflag; /* -dV */
163Boolean noExecute; /* -n flag */ 163Boolean noExecute; /* -n flag */
164Boolean noRecursiveExecute; /* -N flag */ 164Boolean noRecursiveExecute; /* -N flag */
165Boolean keepgoing; /* -k flag */ 165Boolean keepgoing; /* -k flag */
166Boolean queryFlag; /* -q flag */ 166Boolean queryFlag; /* -q flag */
167Boolean touchFlag; /* -t flag */ 167Boolean touchFlag; /* -t flag */
168Boolean ignoreErrors; /* -i flag */ 168Boolean ignoreErrors; /* -i flag */
169Boolean beSilent; /* -s flag */ 169Boolean beSilent; /* -s flag */
170Boolean oldVars; /* variable substitution style */ 170Boolean oldVars; /* variable substitution style */
171Boolean checkEnvFirst; /* -e flag */ 171Boolean checkEnvFirst; /* -e flag */
172Boolean parseWarnFatal; /* -W flag */ 172Boolean parseWarnFatal; /* -W flag */
173Boolean jobServer; /* -J flag */ 173Boolean jobServer; /* -J flag */
174static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */ 174static int jp_0 = -1, jp_1 = -1; /* ends of parent job pipe */
175Boolean varNoExportEnv; /* -X flag */ 175Boolean varNoExportEnv; /* -X flag */
176Boolean doing_depend; /* Set while reading .depend */ 176Boolean doing_depend; /* Set while reading .depend */
177static Boolean jobsRunning; /* TRUE if the jobs might be running */ 177static Boolean jobsRunning; /* TRUE if the jobs might be running */
178static const char * tracefile; 178static const char * tracefile;
179static void MainParseArgs(int, char **); 179static void MainParseArgs(int, char **);
180static int ReadMakefile(const void *, const void *); 180static int ReadMakefile(const void *, const void *);
181static void usage(void) MAKE_ATTR_DEAD; 181static void usage(void) MAKE_ATTR_DEAD;
182 182
183static Boolean ignorePWD; /* if we use -C, PWD is meaningless */ 183static Boolean ignorePWD; /* if we use -C, PWD is meaningless */
184static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */ 184static char objdir[MAXPATHLEN + 1]; /* where we chdir'ed to */
185char curdir[MAXPATHLEN + 1]; /* Startup directory */ 185char curdir[MAXPATHLEN + 1]; /* Startup directory */
186char *progname; /* the program name */ 186char *progname; /* the program name */
187char *makeDependfile; 187char *makeDependfile;
188pid_t myPid; 188pid_t myPid;
189 189
190Boolean forceJobs = FALSE; 190Boolean forceJobs = FALSE;
191 191
192extern Lst parseIncPath; 192extern Lst parseIncPath;
193 193
194static void 194static void
195parse_debug_options(const char *argvalue) 195parse_debug_options(const char *argvalue)
196{ 196{
197 const char *modules; 197 const char *modules;
198 const char *mode; 198 const char *mode;
199 char *fname; 199 char *fname;
200 int len; 200 int len;
201 201
202 for (modules = argvalue; *modules; ++modules) { 202 for (modules = argvalue; *modules; ++modules) {
203 switch (*modules) { 203 switch (*modules) {
204 case 'A': 204 case 'A':
205 debug = ~0; 205 debug = ~0;
206 break; 206 break;
207 case 'a': 207 case 'a':
208 debug |= DEBUG_ARCH; 208 debug |= DEBUG_ARCH;
209 break; 209 break;
210 case 'C': 210 case 'C':
211 debug |= DEBUG_CWD; 211 debug |= DEBUG_CWD;
212 break; 212 break;
213 case 'c': 213 case 'c':
214 debug |= DEBUG_COND; 214 debug |= DEBUG_COND;
215 break; 215 break;
216 case 'd': 216 case 'd':
217 debug |= DEBUG_DIR; 217 debug |= DEBUG_DIR;
218 break; 218 break;
219 case 'e': 219 case 'e':
220 debug |= DEBUG_ERROR; 220 debug |= DEBUG_ERROR;
221 break; 221 break;
222 case 'f': 222 case 'f':
223 debug |= DEBUG_FOR; 223 debug |= DEBUG_FOR;
224 break; 224 break;
225 case 'g': 225 case 'g':
226 if (modules[1] == '1') { 226 if (modules[1] == '1') {
227 debug |= DEBUG_GRAPH1; 227 debug |= DEBUG_GRAPH1;
228 ++modules; 228 ++modules;
229 } 229 }
230 else if (modules[1] == '2') { 230 else if (modules[1] == '2') {
231 debug |= DEBUG_GRAPH2; 231 debug |= DEBUG_GRAPH2;
232 ++modules; 232 ++modules;
233 } 233 }
234 else if (modules[1] == '3') { 234 else if (modules[1] == '3') {
235 debug |= DEBUG_GRAPH3; 235 debug |= DEBUG_GRAPH3;
236 ++modules; 236 ++modules;
237 } 237 }
238 break; 238 break;
239 case 'j': 239 case 'j':
240 debug |= DEBUG_JOB; 240 debug |= DEBUG_JOB;
241 break; 241 break;
242 case 'l': 242 case 'l':
243 debug |= DEBUG_LOUD; 243 debug |= DEBUG_LOUD;
244 break; 244 break;
245 case 'M': 245 case 'M':
246 debug |= DEBUG_META; 246 debug |= DEBUG_META;
247 break; 247 break;
248 case 'm': 248 case 'm':
249 debug |= DEBUG_MAKE; 249 debug |= DEBUG_MAKE;
250 break; 250 break;
251 case 'n': 251 case 'n':
252 debug |= DEBUG_SCRIPT; 252 debug |= DEBUG_SCRIPT;
253 break; 253 break;
254 case 'p': 254 case 'p':
255 debug |= DEBUG_PARSE; 255 debug |= DEBUG_PARSE;
256 break; 256 break;
257 case 's': 257 case 's':
258 debug |= DEBUG_SUFF; 258 debug |= DEBUG_SUFF;
259 break; 259 break;
260 case 't': 260 case 't':
261 debug |= DEBUG_TARG; 261 debug |= DEBUG_TARG;
262 break; 262 break;
263 case 'V': 263 case 'V':
264 debugVflag = TRUE; 264 debugVflag = TRUE;
265 break; 265 break;
266 case 'v': 266 case 'v':
267 debug |= DEBUG_VAR; 267 debug |= DEBUG_VAR;
268 break; 268 break;
269 case 'x': 269 case 'x':
270 debug |= DEBUG_SHELL; 270 debug |= DEBUG_SHELL;
271 break; 271 break;
272 case 'F': 272 case 'F':
273 if (debug_file != stdout && debug_file != stderr) 273 if (debug_file != stdout && debug_file != stderr)
274 fclose(debug_file); 274 fclose(debug_file);
275 if (*++modules == '+') { 275 if (*++modules == '+') {
276 modules++; 276 modules++;
277 mode = "a"; 277 mode = "a";
278 } else 278 } else
279 mode = "w"; 279 mode = "w";
280 if (strcmp(modules, "stdout") == 0) { 280 if (strcmp(modules, "stdout") == 0) {
281 debug_file = stdout; 281 debug_file = stdout;
282 goto debug_setbuf; 282 goto debug_setbuf;
283 } 283 }
284 if (strcmp(modules, "stderr") == 0) { 284 if (strcmp(modules, "stderr") == 0) {
285 debug_file = stderr; 285 debug_file = stderr;
286 goto debug_setbuf; 286 goto debug_setbuf;
287 } 287 }
288 len = strlen(modules); 288 len = strlen(modules);
289 fname = malloc(len + 20); 289 fname = malloc(len + 20);
290 memcpy(fname, modules, len + 1); 290 memcpy(fname, modules, len + 1);
291 /* Let the filename be modified by the pid */ 291 /* Let the filename be modified by the pid */
292 if (strcmp(fname + len - 3, ".%d") == 0) 292 if (strcmp(fname + len - 3, ".%d") == 0)
293 snprintf(fname + len - 2, 20, "%d", getpid()); 293 snprintf(fname + len - 2, 20, "%d", getpid());
294 debug_file = fopen(fname, mode); 294 debug_file = fopen(fname, mode);
295 if (!debug_file) { 295 if (!debug_file) {
296 fprintf(stderr, "Cannot open debug file %s\n", 296 fprintf(stderr, "Cannot open debug file %s\n",
297 fname); 297 fname);
298 usage(); 298 usage();
299 } 299 }
300 free(fname); 300 free(fname);
301 goto debug_setbuf; 301 goto debug_setbuf;
302 default: 302 default:
303 (void)fprintf(stderr, 303 (void)fprintf(stderr,
304 "%s: illegal argument to d option -- %c\n", 304 "%s: illegal argument to d option -- %c\n",
305 progname, *modules); 305 progname, *modules);
306 usage(); 306 usage();
307 } 307 }
308 } 308 }
309debug_setbuf: 309debug_setbuf:
310 /* 310 /*
311 * Make the debug_file unbuffered, and make 311 * Make the debug_file unbuffered, and make
312 * stdout line buffered (unless debugfile == stdout). 312 * stdout line buffered (unless debugfile == stdout).
313 */ 313 */
314 setvbuf(debug_file, NULL, _IONBF, 0); 314 setvbuf(debug_file, NULL, _IONBF, 0);
315 if (debug_file != stdout) { 315 if (debug_file != stdout) {
316 setvbuf(stdout, NULL, _IOLBF, 0); 316 setvbuf(stdout, NULL, _IOLBF, 0);
317 } 317 }
318} 318}
319 319
320/*- 320/*-
321 * MainParseArgs -- 321 * MainParseArgs --
322 * Parse a given argument vector. Called from main() and from 322 * Parse a given argument vector. Called from main() and from
323 * Main_ParseArgLine() when the .MAKEFLAGS target is used. 323 * Main_ParseArgLine() when the .MAKEFLAGS target is used.
324 * 324 *
325 * XXX: Deal with command line overriding .MAKEFLAGS in makefile 325 * XXX: Deal with command line overriding .MAKEFLAGS in makefile
326 * 326 *
327 * Results: 327 * Results:
328 * None 328 * None
329 * 329 *
330 * Side Effects: 330 * Side Effects:
331 * Various global and local flags will be set depending on the flags 331 * Various global and local flags will be set depending on the flags
332 * given 332 * given
333 */ 333 */
334static void 334static void
335MainParseArgs(int argc, char **argv) 335MainParseArgs(int argc, char **argv)
336{ 336{
337 char *p; 337 char *p;
338 int c = '?'; 338 int c = '?';
339 int arginc; 339 int arginc;
340 char *argvalue; 340 char *argvalue;
341 const char *getopt_def; 341 const char *getopt_def;
342 char *optscan; 342 char *optscan;
343 Boolean inOption, dashDash = FALSE; 343 Boolean inOption, dashDash = FALSE;
344 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ 344 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
345 345
346#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrst" 346#define OPTFLAGS "BC:D:I:J:NST:V:WXd:ef:ij:km:nqrst"
347/* Can't actually use getopt(3) because rescanning is not portable */ 347/* Can't actually use getopt(3) because rescanning is not portable */
348 348
349 getopt_def = OPTFLAGS; 349 getopt_def = OPTFLAGS;
350rearg:  350rearg:
351 inOption = FALSE; 351 inOption = FALSE;
352 optscan = NULL; 352 optscan = NULL;
353 while(argc > 1) { 353 while(argc > 1) {
354 char *getopt_spec; 354 char *getopt_spec;
355 if(!inOption) 355 if(!inOption)
356 optscan = argv[1]; 356 optscan = argv[1];
357 c = *optscan++; 357 c = *optscan++;
358 arginc = 0; 358 arginc = 0;
359 if(inOption) { 359 if(inOption) {
360 if(c == '\0') { 360 if(c == '\0') {
361 ++argv; 361 ++argv;
362 --argc; 362 --argc;
363 inOption = FALSE; 363 inOption = FALSE;
364 continue; 364 continue;
365 } 365 }
366 } else { 366 } else {
367 if (c != '-' || dashDash) 367 if (c != '-' || dashDash)
368 break; 368 break;
369 inOption = TRUE; 369 inOption = TRUE;
370 c = *optscan++; 370 c = *optscan++;
371 } 371 }
372 /* '-' found at some earlier point */ 372 /* '-' found at some earlier point */
373 getopt_spec = strchr(getopt_def, c); 373 getopt_spec = strchr(getopt_def, c);
374 if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') { 374 if(c != '\0' && getopt_spec != NULL && getopt_spec[1] == ':') {
375 /* -<something> found, and <something> should have an arg */ 375 /* -<something> found, and <something> should have an arg */
376 inOption = FALSE; 376 inOption = FALSE;
377 arginc = 1; 377 arginc = 1;
378 argvalue = optscan; 378 argvalue = optscan;
379 if(*argvalue == '\0') { 379 if(*argvalue == '\0') {
380 if (argc < 3) 380 if (argc < 3)
381 goto noarg; 381 goto noarg;
382 argvalue = argv[2]; 382 argvalue = argv[2];
383 arginc = 2; 383 arginc = 2;
384 } 384 }
385 } else { 385 } else {
386 argvalue = NULL;  386 argvalue = NULL;
387 } 387 }
388 switch(c) { 388 switch(c) {
389 case '\0': 389 case '\0':
390 arginc = 1; 390 arginc = 1;
391 inOption = FALSE; 391 inOption = FALSE;
392 break; 392 break;
393 case 'B': 393 case 'B':
394 compatMake = TRUE; 394 compatMake = TRUE;
395 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL); 395 Var_Append(MAKEFLAGS, "-B", VAR_GLOBAL);
396 Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0); 396 Var_Set(MAKE_MODE, "compat", VAR_GLOBAL, 0);
397 break; 397 break;
398 case 'C': 398 case 'C':
399 if (chdir(argvalue) == -1) { 399 if (chdir(argvalue) == -1) {
400 (void)fprintf(stderr, 400 (void)fprintf(stderr,
401 "%s: chdir %s: %s\n", 401 "%s: chdir %s: %s\n",
402 progname, argvalue, 402 progname, argvalue,
403 strerror(errno)); 403 strerror(errno));
404 exit(1); 404 exit(1);
405 } 405 }
406 if (getcwd(curdir, MAXPATHLEN) == NULL) { 406 if (getcwd(curdir, MAXPATHLEN) == NULL) {
407 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno)); 407 (void)fprintf(stderr, "%s: %s.\n", progname, strerror(errno));
408 exit(2); 408 exit(2);
409 } 409 }
410 ignorePWD = TRUE; 410 ignorePWD = TRUE;
411 break; 411 break;
412 case 'D': 412 case 'D':
413 if (argvalue == NULL || argvalue[0] == 0) goto noarg; 413 if (argvalue == NULL || argvalue[0] == 0) goto noarg;
414 Var_Set(argvalue, "1", VAR_GLOBAL, 0); 414 Var_Set(argvalue, "1", VAR_GLOBAL, 0);
415 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL); 415 Var_Append(MAKEFLAGS, "-D", VAR_GLOBAL);
416 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 416 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
417 break; 417 break;
418 case 'I': 418 case 'I':
419 if (argvalue == NULL) goto noarg; 419 if (argvalue == NULL) goto noarg;
420 Parse_AddIncludeDir(argvalue); 420 Parse_AddIncludeDir(argvalue);
421 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL); 421 Var_Append(MAKEFLAGS, "-I", VAR_GLOBAL);
422 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 422 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
423 break; 423 break;
424 case 'J': 424 case 'J':
425 if (argvalue == NULL) goto noarg; 425 if (argvalue == NULL) goto noarg;
426 if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) { 426 if (sscanf(argvalue, "%d,%d", &jp_0, &jp_1) != 2) {
427 (void)fprintf(stderr, 427 (void)fprintf(stderr,
428 "%s: internal error -- J option malformed (%s)\n", 428 "%s: internal error -- J option malformed (%s)\n",
429 progname, argvalue); 429 progname, argvalue);
430 usage(); 430 usage();
431 } 431 }
432 if ((fcntl(jp_0, F_GETFD, 0) < 0) || 432 if ((fcntl(jp_0, F_GETFD, 0) < 0) ||
433 (fcntl(jp_1, F_GETFD, 0) < 0)) { 433 (fcntl(jp_1, F_GETFD, 0) < 0)) {
434#if 0 434#if 0
435 (void)fprintf(stderr, 435 (void)fprintf(stderr,
436 "%s: ###### warning -- J descriptors were closed!\n", 436 "%s: ###### warning -- J descriptors were closed!\n",
437 progname); 437 progname);
438 exit(2); 438 exit(2);
439#endif 439#endif
440 jp_0 = -1; 440 jp_0 = -1;
441 jp_1 = -1; 441 jp_1 = -1;
442 compatMake = TRUE; 442 compatMake = TRUE;
443 } else { 443 } else {
444 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL); 444 Var_Append(MAKEFLAGS, "-J", VAR_GLOBAL);
445 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 445 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
446 jobServer = TRUE; 446 jobServer = TRUE;
447 } 447 }
448 break; 448 break;
449 case 'N': 449 case 'N':
450 noExecute = TRUE; 450 noExecute = TRUE;
451 noRecursiveExecute = TRUE; 451 noRecursiveExecute = TRUE;
452 Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL); 452 Var_Append(MAKEFLAGS, "-N", VAR_GLOBAL);
453 break; 453 break;
454 case 'S': 454 case 'S':
455 keepgoing = FALSE; 455 keepgoing = FALSE;
456 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL); 456 Var_Append(MAKEFLAGS, "-S", VAR_GLOBAL);
457 break; 457 break;
458 case 'T': 458 case 'T':
459 if (argvalue == NULL) goto noarg; 459 if (argvalue == NULL) goto noarg;
460 tracefile = bmake_strdup(argvalue); 460 tracefile = bmake_strdup(argvalue);
461 Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL); 461 Var_Append(MAKEFLAGS, "-T", VAR_GLOBAL);
462 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 462 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
463 break; 463 break;
464 case 'V': 464 case 'V':
465 if (argvalue == NULL) goto noarg; 465 if (argvalue == NULL) goto noarg;
466 printVars = TRUE; 466 printVars = TRUE;
467 (void)Lst_AtEnd(variables, argvalue); 467 (void)Lst_AtEnd(variables, argvalue);
468 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL); 468 Var_Append(MAKEFLAGS, "-V", VAR_GLOBAL);
469 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 469 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
470 break; 470 break;
471 case 'W': 471 case 'W':
472 parseWarnFatal = TRUE; 472 parseWarnFatal = TRUE;
473 break; 473 break;
474 case 'X': 474 case 'X':
475 varNoExportEnv = TRUE; 475 varNoExportEnv = TRUE;
476 Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL); 476 Var_Append(MAKEFLAGS, "-X", VAR_GLOBAL);
477 break; 477 break;
478 case 'd': 478 case 'd':
479 if (argvalue == NULL) goto noarg; 479 if (argvalue == NULL) goto noarg;
480 /* If '-d-opts' don't pass to children */ 480 /* If '-d-opts' don't pass to children */
481 if (argvalue[0] == '-') 481 if (argvalue[0] == '-')
482 argvalue++; 482 argvalue++;
483 else { 483 else {
484 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL); 484 Var_Append(MAKEFLAGS, "-d", VAR_GLOBAL);
485 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 485 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
486 } 486 }
487 parse_debug_options(argvalue); 487 parse_debug_options(argvalue);
488 break; 488 break;
489 case 'e': 489 case 'e':
490 checkEnvFirst = TRUE; 490 checkEnvFirst = TRUE;
491 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL); 491 Var_Append(MAKEFLAGS, "-e", VAR_GLOBAL);
492 break; 492 break;
493 case 'f': 493 case 'f':
494 if (argvalue == NULL) goto noarg; 494 if (argvalue == NULL) goto noarg;
495 (void)Lst_AtEnd(makefiles, argvalue); 495 (void)Lst_AtEnd(makefiles, argvalue);
496 break; 496 break;
497 case 'i': 497 case 'i':
498 ignoreErrors = TRUE; 498 ignoreErrors = TRUE;
499 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL); 499 Var_Append(MAKEFLAGS, "-i", VAR_GLOBAL);
500 break; 500 break;
501 case 'j': 501 case 'j':
502 if (argvalue == NULL) goto noarg; 502 if (argvalue == NULL) goto noarg;
503 forceJobs = TRUE; 503 forceJobs = TRUE;
504 maxJobs = strtol(argvalue, &p, 0); 504 maxJobs = strtol(argvalue, &p, 0);
505 if (*p != '\0' || maxJobs < 1) { 505 if (*p != '\0' || maxJobs < 1) {
506 (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n", 506 (void)fprintf(stderr, "%s: illegal argument to -j -- must be positive integer!\n",
507 progname); 507 progname);
508 exit(1); 508 exit(1);
509 } 509 }
510 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL); 510 Var_Append(MAKEFLAGS, "-j", VAR_GLOBAL);
511 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 511 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
512 Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0); 512 Var_Set(".MAKE.JOBS", argvalue, VAR_GLOBAL, 0);
513 maxJobTokens = maxJobs; 513 maxJobTokens = maxJobs;
514 break; 514 break;
515 case 'k': 515 case 'k':
516 keepgoing = TRUE; 516 keepgoing = TRUE;
517 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL); 517 Var_Append(MAKEFLAGS, "-k", VAR_GLOBAL);
518 break; 518 break;
519 case 'm': 519 case 'm':
520 if (argvalue == NULL) goto noarg; 520 if (argvalue == NULL) goto noarg;
521 /* look for magic parent directory search string */ 521 /* look for magic parent directory search string */
522 if (strncmp(".../", argvalue, 4) == 0) { 522 if (strncmp(".../", argvalue, 4) == 0) {
523 if (!Dir_FindHereOrAbove(curdir, argvalue+4, 523 if (!Dir_FindHereOrAbove(curdir, argvalue+4,
524 found_path, sizeof(found_path))) 524 found_path, sizeof(found_path)))
525 break; /* nothing doing */ 525 break; /* nothing doing */
526 (void)Dir_AddDir(sysIncPath, found_path); 526 (void)Dir_AddDir(sysIncPath, found_path);
527 } else { 527 } else {
528 (void)Dir_AddDir(sysIncPath, argvalue); 528 (void)Dir_AddDir(sysIncPath, argvalue);
529 } 529 }
530 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL); 530 Var_Append(MAKEFLAGS, "-m", VAR_GLOBAL);
531 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL); 531 Var_Append(MAKEFLAGS, argvalue, VAR_GLOBAL);
532 break; 532 break;
533 case 'n': 533 case 'n':
534 noExecute = TRUE; 534 noExecute = TRUE;
535 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL); 535 Var_Append(MAKEFLAGS, "-n", VAR_GLOBAL);
536 break; 536 break;
537 case 'q': 537 case 'q':
538 queryFlag = TRUE; 538 queryFlag = TRUE;
539 /* Kind of nonsensical, wot? */ 539 /* Kind of nonsensical, wot? */
540 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL); 540 Var_Append(MAKEFLAGS, "-q", VAR_GLOBAL);
541 break; 541 break;
542 case 'r': 542 case 'r':
543 noBuiltins = TRUE; 543 noBuiltins = TRUE;
544 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL); 544 Var_Append(MAKEFLAGS, "-r", VAR_GLOBAL);
545 break; 545 break;
546 case 's': 546 case 's':
547 beSilent = TRUE; 547 beSilent = TRUE;
548 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL); 548 Var_Append(MAKEFLAGS, "-s", VAR_GLOBAL);
549 break; 549 break;
550 case 't': 550 case 't':
551 touchFlag = TRUE; 551 touchFlag = TRUE;
552 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL); 552 Var_Append(MAKEFLAGS, "-t", VAR_GLOBAL);
553 break; 553 break;
554 case '-': 554 case '-':
555 dashDash = TRUE; 555 dashDash = TRUE;
556 break; 556 break;
557 default: 557 default:
558 case '?': 558 case '?':
559 usage(); 559 usage();
560 } 560 }
561 argv += arginc; 561 argv += arginc;
562 argc -= arginc; 562 argc -= arginc;
563 } 563 }
564 564
565 oldVars = TRUE; 565 oldVars = TRUE;
566 566
567 /* 567 /*
568 * See if the rest of the arguments are variable assignments and 568 * See if the rest of the arguments are variable assignments and
569 * perform them if so. Else take them to be targets and stuff them 569 * perform them if so. Else take them to be targets and stuff them
570 * on the end of the "create" list. 570 * on the end of the "create" list.
571 */ 571 */
572 for (; argc > 1; ++argv, --argc) 572 for (; argc > 1; ++argv, --argc)
573 if (Parse_IsVar(argv[1])) { 573 if (Parse_IsVar(argv[1])) {
574 Parse_DoVar(argv[1], VAR_CMD); 574 Parse_DoVar(argv[1], VAR_CMD);
575 } else { 575 } else {
576 if (!*argv[1]) 576 if (!*argv[1])
577 Punt("illegal (null) argument."); 577 Punt("illegal (null) argument.");
578 if (*argv[1] == '-' && !dashDash) 578 if (*argv[1] == '-' && !dashDash)
579 goto rearg; 579 goto rearg;
580 (void)Lst_AtEnd(create, bmake_strdup(argv[1])); 580 (void)Lst_AtEnd(create, bmake_strdup(argv[1]));
581 } 581 }
582 582
583 return; 583 return;
584noarg: 584noarg:
585 (void)fprintf(stderr, "%s: option requires an argument -- %c\n", 585 (void)fprintf(stderr, "%s: option requires an argument -- %c\n",
586 progname, c); 586 progname, c);
587 usage(); 587 usage();
588} 588}
589 589
590/*- 590/*-
591 * Main_ParseArgLine -- 591 * Main_ParseArgLine --
592 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target 592 * Used by the parse module when a .MFLAGS or .MAKEFLAGS target
593 * is encountered and by main() when reading the .MAKEFLAGS envariable. 593 * is encountered and by main() when reading the .MAKEFLAGS envariable.
594 * Takes a line of arguments and breaks it into its 594 * Takes a line of arguments and breaks it into its
595 * component words and passes those words and the number of them to the 595 * component words and passes those words and the number of them to the
596 * MainParseArgs function. 596 * MainParseArgs function.
597 * The line should have all its leading whitespace removed. 597 * The line should have all its leading whitespace removed.
598 * 598 *
599 * Input: 599 * Input:
600 * line Line to fracture 600 * line Line to fracture
601 * 601 *
602 * Results: 602 * Results:
603 * None 603 * None
604 * 604 *
605 * Side Effects: 605 * Side Effects:
606 * Only those that come from the various arguments. 606 * Only those that come from the various arguments.
607 */ 607 */
608void 608void
609Main_ParseArgLine(const char *line) 609Main_ParseArgLine(const char *line)
610{ 610{
611 char **argv; /* Manufactured argument vector */ 611 char **argv; /* Manufactured argument vector */
612 int argc; /* Number of arguments in argv */ 612 int argc; /* Number of arguments in argv */
613 char *args; /* Space used by the args */ 613 char *args; /* Space used by the args */
614 char *buf, *p1; 614 char *buf, *p1;
615 char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1); 615 char *argv0 = Var_Value(".MAKE", VAR_GLOBAL, &p1);
616 size_t len; 616 size_t len;
617 617
618 if (line == NULL) 618 if (line == NULL)
619 return; 619 return;
620 for (; *line == ' '; ++line) 620 for (; *line == ' '; ++line)
621 continue; 621 continue;
622 if (!*line) 622 if (!*line)
623 return; 623 return;
624 624
625 buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2); 625 buf = bmake_malloc(len = strlen(line) + strlen(argv0) + 2);
626 (void)snprintf(buf, len, "%s %s", argv0, line); 626 (void)snprintf(buf, len, "%s %s", argv0, line);
627 if (p1) 627 if (p1)
628 free(p1); 628 free(p1);
629 629
630 argv = brk_string(buf, &argc, TRUE, &args); 630 argv = brk_string(buf, &argc, TRUE, &args);
631 if (argv == NULL) { 631 if (argv == NULL) {
632 Error("Unterminated quoted string [%s]", buf); 632 Error("Unterminated quoted string [%s]", buf);
633 free(buf); 633 free(buf);
634 return; 634 return;
635 } 635 }
636 free(buf); 636 free(buf);
637 MainParseArgs(argc, argv); 637 MainParseArgs(argc, argv);
638 638
639 free(args); 639 free(args);
640 free(argv); 640 free(argv);
641} 641}
642 642
643Boolean 643Boolean
644Main_SetObjdir(const char *path) 644Main_SetObjdir(const char *path)
645{ 645{
646 struct stat sb; 646 struct stat sb;
647 char *p = NULL; 647 char *p = NULL;
648 char buf[MAXPATHLEN + 1]; 648 char buf[MAXPATHLEN + 1];
649 Boolean rc = FALSE; 649 Boolean rc = FALSE;
650 650
651 /* expand variable substitutions */ 651 /* expand variable substitutions */
652 if (strchr(path, '$') != 0) { 652 if (strchr(path, '$') != 0) {
653 snprintf(buf, MAXPATHLEN, "%s", path); 653 snprintf(buf, MAXPATHLEN, "%s", path);
654 path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0); 654 path = p = Var_Subst(NULL, buf, VAR_GLOBAL, 0);
655 } 655 }
656 656
657 if (path[0] != '/') { 657 if (path[0] != '/') {
658 snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path); 658 snprintf(buf, MAXPATHLEN, "%s/%s", curdir, path);
659 path = buf; 659 path = buf;
660 } 660 }
661 661
662 /* look for the directory and try to chdir there */ 662 /* look for the directory and try to chdir there */
663 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) { 663 if (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
664 if (chdir(path)) { 664 if (chdir(path)) {
665 (void)fprintf(stderr, "make warning: %s: %s.\n", 665 (void)fprintf(stderr, "make warning: %s: %s.\n",
666 path, strerror(errno)); 666 path, strerror(errno));
667 } else { 667 } else {
668 strncpy(objdir, path, MAXPATHLEN); 668 strncpy(objdir, path, MAXPATHLEN);
669 Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0); 669 Var_Set(".OBJDIR", objdir, VAR_GLOBAL, 0);
670 setenv("PWD", objdir, 1); 670 setenv("PWD", objdir, 1);
671 Dir_InitDot(); 671 Dir_InitDot();
672 rc = TRUE; 672 rc = TRUE;
673 } 673 }
674 } 674 }
675 675
676 if (p) 676 if (p)
677 free(p); 677 free(p);
678 return rc; 678 return rc;
679} 679}
680 680
681/*- 681/*-
682 * ReadAllMakefiles -- 682 * ReadAllMakefiles --
683 * wrapper around ReadMakefile() to read all. 683 * wrapper around ReadMakefile() to read all.
684 * 684 *
685 * Results: 685 * Results:
686 * TRUE if ok, FALSE on error 686 * TRUE if ok, FALSE on error
687 */ 687 */
688static int 688static int
689ReadAllMakefiles(const void *p, const void *q) 689ReadAllMakefiles(const void *p, const void *q)
690{ 690{
691 return (ReadMakefile(p, q) == 0); 691 return (ReadMakefile(p, q) == 0);
692} 692}
693 693
694int 694int
695str2Lst_Append(Lst lp, char *str, const char *sep) 695str2Lst_Append(Lst lp, char *str, const char *sep)
696{ 696{
697 char *cp; 697 char *cp;
698 int n; 698 int n;
699 699
700 if (!sep) 700 if (!sep)
701 sep = " \t"; 701 sep = " \t";
702 702
703 for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) { 703 for (n = 0, cp = strtok(str, sep); cp; cp = strtok(NULL, sep)) {
704 (void)Lst_AtEnd(lp, cp); 704 (void)Lst_AtEnd(lp, cp);
705 n++; 705 n++;
706 } 706 }
707 return (n); 707 return (n);
708} 708}
709 709
710#ifdef SIGINFO 710#ifdef SIGINFO
711/*ARGSUSED*/ 711/*ARGSUSED*/
712static void 712static void
713siginfo(int signo MAKE_ATTR_UNUSED) 713siginfo(int signo MAKE_ATTR_UNUSED)
714{ 714{
715 char dir[MAXPATHLEN]; 715 char dir[MAXPATHLEN];
716 char str[2 * MAXPATHLEN]; 716 char str[2 * MAXPATHLEN];
717 int len; 717 int len;
718 if (getcwd(dir, sizeof(dir)) == NULL) 718 if (getcwd(dir, sizeof(dir)) == NULL)
719 return; 719 return;
720 len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir); 720 len = snprintf(str, sizeof(str), "%s: Working in: %s\n", progname, dir);
721 if (len > 0) 721 if (len > 0)
722 (void)write(STDERR_FILENO, str, (size_t)len); 722 (void)write(STDERR_FILENO, str, (size_t)len);
723} 723}
724#endif 724#endif
725 725
726/* 726/*
727 * Allow makefiles some control over the mode we run in. 727 * Allow makefiles some control over the mode we run in.
728 */ 728 */
729void 729void
730MakeMode(const char *mode) 730MakeMode(const char *mode)
731{ 731{
732 char *mp = NULL; 732 char *mp = NULL;
733 733
734 if (!mode) 734 if (!mode)
735 mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0); 735 mode = mp = Var_Subst(NULL, "${" MAKE_MODE ":tl}", VAR_GLOBAL, 0);
736 736
737 if (mode && *mode) { 737 if (mode && *mode) {
738 if (strstr(mode, "compat")) { 738 if (strstr(mode, "compat")) {
739 compatMake = TRUE; 739 compatMake = TRUE;
740 forceJobs = FALSE; 740 forceJobs = FALSE;
741 } 741 }
742#if USE_META 742#if USE_META
743 if (strstr(mode, "meta")) 743 if (strstr(mode, "meta"))
744 meta_init(mode); 744 meta_init(mode);
745#endif 745#endif
746 } 746 }
747 if (mp) 747 if (mp)
748 free(mp); 748 free(mp);
749} 749}
750 750
751/*- 751/*-
752 * main -- 752 * main --
753 * The main function, for obvious reasons. Initializes variables 753 * The main function, for obvious reasons. Initializes variables
754 * and a few modules, then parses the arguments give it in the 754 * and a few modules, then parses the arguments give it in the
755 * environment and on the command line. Reads the system makefile 755 * environment and on the command line. Reads the system makefile
756 * followed by either Makefile, makefile or the file given by the 756 * followed by either Makefile, makefile or the file given by the
757 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the 757 * -f argument. Sets the .MAKEFLAGS PMake variable based on all the
758 * flags it has received by then uses either the Make or the Compat 758 * flags it has received by then uses either the Make or the Compat
759 * module to create the initial list of targets. 759 * module to create the initial list of targets.
760 * 760 *
761 * Results: 761 * Results:
762 * If -q was given, exits -1 if anything was out-of-date. Else it exits 762 * If -q was given, exits -1 if anything was out-of-date. Else it exits
763 * 0. 763 * 0.
764 * 764 *
765 * Side Effects: 765 * Side Effects:
766 * The program exits when done. Targets are created. etc. etc. etc. 766 * The program exits when done. Targets are created. etc. etc. etc.
767 */ 767 */
768int 768int
769main(int argc, char **argv) 769main(int argc, char **argv)
770{ 770{
771 Lst targs; /* target nodes to create -- passed to Make_Init */ 771 Lst targs; /* target nodes to create -- passed to Make_Init */
772 Boolean outOfDate = FALSE; /* FALSE if all targets up to date */ 772 Boolean outOfDate = FALSE; /* FALSE if all targets up to date */
773 struct stat sb, sa; 773 struct stat sb, sa;
774 char *p1, *path, *pwd; 774 char *p1, *path, *pwd;
775 char mdpath[MAXPATHLEN]; 775 char mdpath[MAXPATHLEN];
776 const char *machine = getenv("MACHINE"); 776 const char *machine = getenv("MACHINE");
777 const char *machine_arch = getenv("MACHINE_ARCH"); 777 const char *machine_arch = getenv("MACHINE_ARCH");
778 char *syspath = getenv("MAKESYSPATH"); 778 char *syspath = getenv("MAKESYSPATH");
779 Lst sysMkPath; /* Path of sys.mk */ 779 Lst sysMkPath; /* Path of sys.mk */
780 char *cp = NULL, *start; 780 char *cp = NULL, *start;
781 /* avoid faults on read-only strings */ 781 /* avoid faults on read-only strings */
782 static char defsyspath[] = _PATH_DEFSYSPATH; 782 static char defsyspath[] = _PATH_DEFSYSPATH;
783 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */ 783 char found_path[MAXPATHLEN + 1]; /* for searching for sys.mk */
784 struct timeval rightnow; /* to initialize random seed */ 784 struct timeval rightnow; /* to initialize random seed */
785#ifdef MAKE_NATIVE 785#ifdef MAKE_NATIVE
786 struct utsname utsname; 786 struct utsname utsname;
787#endif 787#endif
788 788
789 /* default to writing debug to stderr */ 789 /* default to writing debug to stderr */
790 debug_file = stderr; 790 debug_file = stderr;
791 791
792#ifdef SIGINFO 792#ifdef SIGINFO
793 (void)bmake_signal(SIGINFO, siginfo); 793 (void)bmake_signal(SIGINFO, siginfo);
794#endif 794#endif
795 /* 795 /*
796 * Set the seed to produce a different random sequence 796 * Set the seed to produce a different random sequence
797 * on each program execution. 797 * on each program execution.
798 */ 798 */
799 gettimeofday(&rightnow, NULL); 799 gettimeofday(&rightnow, NULL);
800 srandom(rightnow.tv_sec + rightnow.tv_usec); 800 srandom(rightnow.tv_sec + rightnow.tv_usec);
801  801
802 if ((progname = strrchr(argv[0], '/')) != NULL) 802 if ((progname = strrchr(argv[0], '/')) != NULL)
803 progname++; 803 progname++;
804 else 804 else
805 progname = argv[0]; 805 progname = argv[0];
806#ifdef RLIMIT_NOFILE 806#ifdef RLIMIT_NOFILE
807 /* 807 /*
808 * get rid of resource limit on file descriptors 808 * get rid of resource limit on file descriptors
809 */ 809 */
810 { 810 {
811 struct rlimit rl; 811 struct rlimit rl;
812 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 && 812 if (getrlimit(RLIMIT_NOFILE, &rl) != -1 &&
813 rl.rlim_cur != rl.rlim_max) { 813 rl.rlim_cur != rl.rlim_max) {
814 rl.rlim_cur = rl.rlim_max; 814 rl.rlim_cur = rl.rlim_max;
815 (void)setrlimit(RLIMIT_NOFILE, &rl); 815 (void)setrlimit(RLIMIT_NOFILE, &rl);
816 } 816 }
817 } 817 }
818#endif 818#endif
819 819
820 /* 820 /*
821 * Get the name of this type of MACHINE from utsname 821 * Get the name of this type of MACHINE from utsname
822 * so we can share an executable for similar machines. 822 * so we can share an executable for similar machines.
823 * (i.e. m68k: amiga hp300, mac68k, sun3, ...) 823 * (i.e. m68k: amiga hp300, mac68k, sun3, ...)
824 * 824 *
825 * Note that both MACHINE and MACHINE_ARCH are decided at 825 * Note that both MACHINE and MACHINE_ARCH are decided at
826 * run-time. 826 * run-time.
827 */ 827 */
828 if (!machine) { 828 if (!machine) {
829#ifdef MAKE_NATIVE 829#ifdef MAKE_NATIVE
830 if (uname(&utsname) == -1) { 830 if (uname(&utsname) == -1) {
831 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname, 831 (void)fprintf(stderr, "%s: uname failed (%s).\n", progname,
832 strerror(errno)); 832 strerror(errno));
833 exit(2); 833 exit(2);
834 } 834 }
835 machine = utsname.machine; 835 machine = utsname.machine;
836#else 836#else
837#ifdef MAKE_MACHINE 837#ifdef MAKE_MACHINE
838 machine = MAKE_MACHINE; 838 machine = MAKE_MACHINE;
839#else 839#else
840 machine = "unknown"; 840 machine = "unknown";
841#endif 841#endif
842#endif 842#endif
843 } 843 }
844 844
845 if (!machine_arch) { 845 if (!machine_arch) {
846#ifndef MACHINE_ARCH 846#ifndef MACHINE_ARCH
847#ifdef MAKE_MACHINE_ARCH 847#ifdef MAKE_MACHINE_ARCH
848 machine_arch = MAKE_MACHINE_ARCH; 848 machine_arch = MAKE_MACHINE_ARCH;
849#else 849#else
850 machine_arch = "unknown"; 850 machine_arch = "unknown";
851#endif 851#endif
852#else 852#else
853 machine_arch = MACHINE_ARCH; 853 machine_arch = MACHINE_ARCH;
854#endif 854#endif
855 } 855 }
856 856
857 myPid = getpid(); /* remember this for vFork() */ 857 myPid = getpid(); /* remember this for vFork() */
858 858
859 /* 859 /*
860 * Just in case MAKEOBJDIR wants us to do something tricky. 860 * Just in case MAKEOBJDIR wants us to do something tricky.
861 */ 861 */
862 Var_Init(); /* Initialize the lists of variables for 862 Var_Init(); /* Initialize the lists of variables for
863 * parsing arguments */ 863 * parsing arguments */
864 Var_Set("MACHINE", machine, VAR_GLOBAL, 0); 864 Var_Set("MACHINE", machine, VAR_GLOBAL, 0);
865 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0); 865 Var_Set("MACHINE_ARCH", machine_arch, VAR_GLOBAL, 0);
866#ifdef MAKE_VERSION 866#ifdef MAKE_VERSION
867 Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0); 867 Var_Set("MAKE_VERSION", MAKE_VERSION, VAR_GLOBAL, 0);
868#endif 868#endif
869 Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */ 869 Var_Set(".newline", "\n", VAR_GLOBAL, 0); /* handy for :@ loops */
870 /* 870 /*
871 * This is the traditional preference for makefiles. 871 * This is the traditional preference for makefiles.
872 */ 872 */
873#ifndef MAKEFILE_PREFERENCE_LIST 873#ifndef MAKEFILE_PREFERENCE_LIST
874# define MAKEFILE_PREFERENCE_LIST "makefile Makefile" 874# define MAKEFILE_PREFERENCE_LIST "makefile Makefile"
875#endif 875#endif
876 Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST, 876 Var_Set(MAKEFILE_PREFERENCE, MAKEFILE_PREFERENCE_LIST,
877 VAR_GLOBAL, 0); 877 VAR_GLOBAL, 0);
878 Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0); 878 Var_Set(MAKE_DEPENDFILE, ".depend", VAR_GLOBAL, 0);
879 879
880 create = Lst_Init(FALSE); 880 create = Lst_Init(FALSE);
881 makefiles = Lst_Init(FALSE); 881 makefiles = Lst_Init(FALSE);
882 printVars = FALSE; 882 printVars = FALSE;
883 debugVflag = FALSE; 883 debugVflag = FALSE;
884 variables = Lst_Init(FALSE); 884 variables = Lst_Init(FALSE);
885 beSilent = FALSE; /* Print commands as executed */ 885 beSilent = FALSE; /* Print commands as executed */
886 ignoreErrors = FALSE; /* Pay attention to non-zero returns */ 886 ignoreErrors = FALSE; /* Pay attention to non-zero returns */
887 noExecute = FALSE; /* Execute all commands */ 887 noExecute = FALSE; /* Execute all commands */
888 noRecursiveExecute = FALSE; /* Execute all .MAKE targets */ 888 noRecursiveExecute = FALSE; /* Execute all .MAKE targets */
889 keepgoing = FALSE; /* Stop on error */ 889 keepgoing = FALSE; /* Stop on error */
890 allPrecious = FALSE; /* Remove targets when interrupted */ 890 allPrecious = FALSE; /* Remove targets when interrupted */
891 queryFlag = FALSE; /* This is not just a check-run */ 891 queryFlag = FALSE; /* This is not just a check-run */
892 noBuiltins = FALSE; /* Read the built-in rules */ 892 noBuiltins = FALSE; /* Read the built-in rules */
893 touchFlag = FALSE; /* Actually update targets */ 893 touchFlag = FALSE; /* Actually update targets */
894 debug = 0; /* No debug verbosity, please. */ 894 debug = 0; /* No debug verbosity, please. */
895 jobsRunning = FALSE; 895 jobsRunning = FALSE;
896 896
897 maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */ 897 maxJobs = DEFMAXLOCAL; /* Set default local max concurrency */
898 maxJobTokens = maxJobs; 898 maxJobTokens = maxJobs;
899 compatMake = FALSE; /* No compat mode */ 899 compatMake = FALSE; /* No compat mode */
900 ignorePWD = FALSE; 900 ignorePWD = FALSE;
901 901
902 /* 902 /*
903 * Initialize the parsing, directory and variable modules to prepare 903 * Initialize the parsing, directory and variable modules to prepare
904 * for the reading of inclusion paths and variable settings on the 904 * for the reading of inclusion paths and variable settings on the
905 * command line 905 * command line
906 */ 906 */
907 907
908 /* 908 /*
909 * Initialize various variables. 909 * Initialize various variables.
910 * MAKE also gets this name, for compatibility 910 * MAKE also gets this name, for compatibility
911 * .MAKEFLAGS gets set to the empty string just in case. 911 * .MAKEFLAGS gets set to the empty string just in case.
912 * MFLAGS also gets initialized empty, for compatibility. 912 * MFLAGS also gets initialized empty, for compatibility.
913 */ 913 */
914 Parse_Init(); 914 Parse_Init();
915 if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) { 915 if (argv[0][0] == '/' || strchr(argv[0], '/') == NULL) {
916 /* 916 /*
917 * Leave alone if it is an absolute path, or if it does 917 * Leave alone if it is an absolute path, or if it does
918 * not contain a '/' in which case we need to find it in 918 * not contain a '/' in which case we need to find it in
919 * the path, like execvp(3) and the shells do. 919 * the path, like execvp(3) and the shells do.
920 */ 920 */
921 p1 = argv[0]; 921 p1 = argv[0];
922 } else { 922 } else {
923 /* 923 /*
924 * A relative path, canonicalize it. 924 * A relative path, canonicalize it.
925 */ 925 */
926 p1 = realpath(argv[0], mdpath); 926 p1 = realpath(argv[0], mdpath);
927 if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) { 927 if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
928 p1 = argv[0]; /* realpath failed */ 928 p1 = argv[0]; /* realpath failed */
929 } 929 }
930 } 930 }
931 Var_Set("MAKE", p1, VAR_GLOBAL, 0); 931 Var_Set("MAKE", p1, VAR_GLOBAL, 0);
932 Var_Set(".MAKE", p1, VAR_GLOBAL, 0); 932 Var_Set(".MAKE", p1, VAR_GLOBAL, 0);
933 Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0); 933 Var_Set(MAKEFLAGS, "", VAR_GLOBAL, 0);
934 Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0); 934 Var_Set(MAKEOVERRIDES, "", VAR_GLOBAL, 0);
935 Var_Set("MFLAGS", "", VAR_GLOBAL, 0); 935 Var_Set("MFLAGS", "", VAR_GLOBAL, 0);
936 Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0); 936 Var_Set(".ALLTARGETS", "", VAR_GLOBAL, 0);
937 937
938 /* 938 /*
939 * Set some other useful macros 939 * Set some other useful macros
940 */ 940 */
941 { 941 {
942 char tmp[64]; 942 char tmp[64];
943 const char *ep; 943 const char *ep;
944 944
945 if (!(ep = getenv(MAKE_LEVEL))) { 945 if (!(ep = getenv(MAKE_LEVEL))) {
946 ep = "0"; 946 ep = "0";
947 } 947 }
948 Var_Set(MAKE_LEVEL, ep, VAR_GLOBAL, 0); 948 Var_Set(MAKE_LEVEL, ep, VAR_GLOBAL, 0);
949 snprintf(tmp, sizeof(tmp), "%u", myPid); 949 snprintf(tmp, sizeof(tmp), "%u", myPid);
950 Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0); 950 Var_Set(".MAKE.PID", tmp, VAR_GLOBAL, 0);
951 snprintf(tmp, sizeof(tmp), "%u", getppid()); 951 snprintf(tmp, sizeof(tmp), "%u", getppid());
952 Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0); 952 Var_Set(".MAKE.PPID", tmp, VAR_GLOBAL, 0);
953 } 953 }
954 Job_SetPrefix(); 954 Job_SetPrefix();
955 955
956 /* 956 /*
957 * First snag any flags out of the MAKE environment variable. 957 * First snag any flags out of the MAKE environment variable.
958 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's 958 * (Note this is *not* MAKEFLAGS since /bin/make uses that and it's
959 * in a different format). 959 * in a different format).
960 */ 960 */
961#ifdef POSIX 961#ifdef POSIX
962 Main_ParseArgLine(getenv("MAKEFLAGS")); 962 Main_ParseArgLine(getenv("MAKEFLAGS"));
963#else 963#else
964 Main_ParseArgLine(getenv("MAKE")); 964 Main_ParseArgLine(getenv("MAKE"));
965#endif 965#endif
966 966
967 /* 967 /*
968 * Find where we are (now). 968 * Find where we are (now).
969 * We take care of PWD for the automounter below... 969 * We take care of PWD for the automounter below...
970 */ 970 */
971 if (getcwd(curdir, MAXPATHLEN) == NULL) { 971 if (getcwd(curdir, MAXPATHLEN) == NULL) {
972 (void)fprintf(stderr, "%s: getcwd: %s.\n", 972 (void)fprintf(stderr, "%s: getcwd: %s.\n",
973 progname, strerror(errno)); 973 progname, strerror(errno));
974 exit(2); 974 exit(2);
975 } 975 }
976 976
977 MainParseArgs(argc, argv); 977 MainParseArgs(argc, argv);
978 978
979 /* 979 /*
980 * Verify that cwd is sane. 980 * Verify that cwd is sane.
981 */ 981 */
982 if (stat(curdir, &sa) == -1) { 982 if (stat(curdir, &sa) == -1) {
983 (void)fprintf(stderr, "%s: %s: %s.\n", 983 (void)fprintf(stderr, "%s: %s: %s.\n",
984 progname, curdir, strerror(errno)); 984 progname, curdir, strerror(errno));
985 exit(2); 985 exit(2);
986 } 986 }
987 987
988 /* 988 /*
989 * All this code is so that we know where we are when we start up 989 * All this code is so that we know where we are when we start up
990 * on a different machine with pmake. 990 * on a different machine with pmake.
991 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX 991 * Overriding getcwd() with $PWD totally breaks MAKEOBJDIRPREFIX
992 * since the value of curdir can vary depending on how we got 992 * since the value of curdir can vary depending on how we got
993 * here. Ie sitting at a shell prompt (shell that provides $PWD) 993 * here. Ie sitting at a shell prompt (shell that provides $PWD)
994 * or via subdir.mk in which case its likely a shell which does 994 * or via subdir.mk in which case its likely a shell which does
995 * not provide it. 995 * not provide it.
996 * So, to stop it breaking this case only, we ignore PWD if 996 * So, to stop it breaking this case only, we ignore PWD if
997 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform. 997 * MAKEOBJDIRPREFIX is set or MAKEOBJDIR contains a transform.
998 */ 998 */
999 if (!ignorePWD && 999 if (!ignorePWD &&
1000 (pwd = getenv("PWD")) != NULL && 1000 (pwd = getenv("PWD")) != NULL &&
1001 getenv("MAKEOBJDIRPREFIX") == NULL) { 1001 getenv("MAKEOBJDIRPREFIX") == NULL) {
1002 const char *makeobjdir = getenv("MAKEOBJDIR"); 1002 const char *makeobjdir = getenv("MAKEOBJDIR");
1003 1003
1004 if (makeobjdir == NULL || !strchr(makeobjdir, '$')) { 1004 if (makeobjdir == NULL || !strchr(makeobjdir, '$')) {
1005 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino && 1005 if (stat(pwd, &sb) == 0 && sa.st_ino == sb.st_ino &&
1006 sa.st_dev == sb.st_dev) 1006 sa.st_dev == sb.st_dev)
1007 (void)strncpy(curdir, pwd, MAXPATHLEN); 1007 (void)strncpy(curdir, pwd, MAXPATHLEN);
1008 } 1008 }
1009 } 1009 }
1010 Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0); 1010 Var_Set(".CURDIR", curdir, VAR_GLOBAL, 0);
1011 1011
1012 /* 1012 /*
1013 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that, 1013 * Find the .OBJDIR. If MAKEOBJDIRPREFIX, or failing that,
1014 * MAKEOBJDIR is set in the environment, try only that value 1014 * MAKEOBJDIR is set in the environment, try only that value
1015 * and fall back to .CURDIR if it does not exist. 1015 * and fall back to .CURDIR if it does not exist.
1016 * 1016 *
1017 * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and 1017 * Otherwise, try _PATH_OBJDIR.MACHINE, _PATH_OBJDIR, and
1018 * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none 1018 * finally _PATH_OBJDIRPREFIX`pwd`, in that order. If none
1019 * of these paths exist, just use .CURDIR. 1019 * of these paths exist, just use .CURDIR.
1020 */ 1020 */
1021 Dir_Init(curdir); 1021 Dir_Init(curdir);
1022 (void)Main_SetObjdir(curdir); 1022 (void)Main_SetObjdir(curdir);
1023 1023
1024 if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) { 1024 if ((path = getenv("MAKEOBJDIRPREFIX")) != NULL) {
1025 (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir); 1025 (void)snprintf(mdpath, MAXPATHLEN, "%s%s", path, curdir);
1026 (void)Main_SetObjdir(mdpath); 1026 (void)Main_SetObjdir(mdpath);
1027 } else if ((path = getenv("MAKEOBJDIR")) != NULL) { 1027 } else if ((path = getenv("MAKEOBJDIR")) != NULL) {
1028 (void)Main_SetObjdir(path); 1028 (void)Main_SetObjdir(path);
1029 } else { 1029 } else {
1030 (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine); 1030 (void)snprintf(mdpath, MAXPATHLEN, "%s.%s", _PATH_OBJDIR, machine);
1031 if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) { 1031 if (!Main_SetObjdir(mdpath) && !Main_SetObjdir(_PATH_OBJDIR)) {
1032 (void)snprintf(mdpath, MAXPATHLEN, "%s%s",  1032 (void)snprintf(mdpath, MAXPATHLEN, "%s%s",
1033 _PATH_OBJDIRPREFIX, curdir); 1033 _PATH_OBJDIRPREFIX, curdir);
1034 (void)Main_SetObjdir(mdpath); 1034 (void)Main_SetObjdir(mdpath);
1035 } 1035 }
1036 } 1036 }
1037 1037
1038 /* 1038 /*
1039 * Be compatible if user did not specify -j and did not explicitly 1039 * Be compatible if user did not specify -j and did not explicitly
1040 * turned compatibility on 1040 * turned compatibility on
1041 */ 1041 */
1042 if (!compatMake && !forceJobs) { 1042 if (!compatMake && !forceJobs) {
1043 compatMake = TRUE; 1043 compatMake = TRUE;
1044 } 1044 }
1045  1045
1046 /* 1046 /*
1047 * Initialize archive, target and suffix modules in preparation for 1047 * Initialize archive, target and suffix modules in preparation for
1048 * parsing the makefile(s) 1048 * parsing the makefile(s)
1049 */ 1049 */
1050 Arch_Init(); 1050 Arch_Init();
1051 Targ_Init(); 1051 Targ_Init();
1052 Suff_Init(); 1052 Suff_Init();
1053 Trace_Init(tracefile); 1053 Trace_Init(tracefile);
1054 1054
1055 DEFAULT = NULL; 1055 DEFAULT = NULL;
1056 (void)time(&now); 1056 (void)time(&now);
1057 1057
1058 Trace_Log(MAKESTART, NULL); 1058 Trace_Log(MAKESTART, NULL);
1059  1059
1060 /* 1060 /*
1061 * Set up the .TARGETS variable to contain the list of targets to be 1061 * Set up the .TARGETS variable to contain the list of targets to be
1062 * created. If none specified, make the variable empty -- the parser 1062 * created. If none specified, make the variable empty -- the parser
1063 * will fill the thing in with the default or .MAIN target. 1063 * will fill the thing in with the default or .MAIN target.
1064 */ 1064 */
1065 if (!Lst_IsEmpty(create)) { 1065 if (!Lst_IsEmpty(create)) {
1066 LstNode ln; 1066 LstNode ln;
1067 1067
1068 for (ln = Lst_First(create); ln != NULL; 1068 for (ln = Lst_First(create); ln != NULL;
1069 ln = Lst_Succ(ln)) { 1069 ln = Lst_Succ(ln)) {
1070 char *name = (char *)Lst_Datum(ln); 1070 char *name = (char *)Lst_Datum(ln);
1071 1071
1072 Var_Append(".TARGETS", name, VAR_GLOBAL); 1072 Var_Append(".TARGETS", name, VAR_GLOBAL);
1073 } 1073 }
1074 } else 1074 } else
1075 Var_Set(".TARGETS", "", VAR_GLOBAL, 0); 1075 Var_Set(".TARGETS", "", VAR_GLOBAL, 0);
1076 1076
1077 1077
1078 /* 1078 /*
1079 * If no user-supplied system path was given (through the -m option) 1079 * If no user-supplied system path was given (through the -m option)
1080 * add the directories from the DEFSYSPATH (more than one may be given 1080 * add the directories from the DEFSYSPATH (more than one may be given
1081 * as dir1:...:dirn) to the system include path. 1081 * as dir1:...:dirn) to the system include path.
1082 */ 1082 */
1083 if (syspath == NULL || *syspath == '\0') 1083 if (syspath == NULL || *syspath == '\0')
1084 syspath = defsyspath; 1084 syspath = defsyspath;
1085 else 1085 else
1086 syspath = bmake_strdup(syspath); 1086 syspath = bmake_strdup(syspath);
1087 1087
1088 for (start = syspath; *start != '\0'; start = cp) { 1088 for (start = syspath; *start != '\0'; start = cp) {
1089 for (cp = start; *cp != '\0' && *cp != ':'; cp++) 1089 for (cp = start; *cp != '\0' && *cp != ':'; cp++)
1090 continue; 1090 continue;
1091 if (*cp == ':') { 1091 if (*cp == ':') {
1092 *cp++ = '\0'; 1092 *cp++ = '\0';
1093 } 1093 }
1094 /* look for magic parent directory search string */ 1094 /* look for magic parent directory search string */
1095 if (strncmp(".../", start, 4) != 0) { 1095 if (strncmp(".../", start, 4) != 0) {
1096 (void)Dir_AddDir(defIncPath, start); 1096 (void)Dir_AddDir(defIncPath, start);
1097 } else { 1097 } else {
1098 if (Dir_FindHereOrAbove(curdir, start+4,  1098 if (Dir_FindHereOrAbove(curdir, start+4,
1099 found_path, sizeof(found_path))) { 1099 found_path, sizeof(found_path))) {
1100 (void)Dir_AddDir(defIncPath, found_path); 1100 (void)Dir_AddDir(defIncPath, found_path);
1101 } 1101 }
1102 } 1102 }
1103 } 1103 }
1104 if (syspath != defsyspath) 1104 if (syspath != defsyspath)
1105 free(syspath); 1105 free(syspath);
1106 1106
1107 /* 1107 /*
1108 * Read in the built-in rules first, followed by the specified 1108 * Read in the built-in rules first, followed by the specified
1109 * makefile, if it was (makefile != NULL), or the default 1109 * makefile, if it was (makefile != NULL), or the default
1110 * makefile and Makefile, in that order, if it wasn't. 1110 * makefile and Makefile, in that order, if it wasn't.
1111 */ 1111 */
1112 if (!noBuiltins) { 1112 if (!noBuiltins) {
1113 LstNode ln; 1113 LstNode ln;
1114 1114
1115 sysMkPath = Lst_Init(FALSE); 1115 sysMkPath = Lst_Init(FALSE);
1116 Dir_Expand(_PATH_DEFSYSMK, 1116 Dir_Expand(_PATH_DEFSYSMK,
1117 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath, 1117 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath,
1118 sysMkPath); 1118 sysMkPath);
1119 if (Lst_IsEmpty(sysMkPath)) 1119 if (Lst_IsEmpty(sysMkPath))
1120 Fatal("%s: no system rules (%s).", progname, 1120 Fatal("%s: no system rules (%s).", progname,
1121 _PATH_DEFSYSMK); 1121 _PATH_DEFSYSMK);
1122 ln = Lst_Find(sysMkPath, NULL, ReadMakefile); 1122 ln = Lst_Find(sysMkPath, NULL, ReadMakefile);
1123 if (ln == NULL) 1123 if (ln == NULL)
1124 Fatal("%s: cannot open %s.", progname, 1124 Fatal("%s: cannot open %s.", progname,
1125 (char *)Lst_Datum(ln)); 1125 (char *)Lst_Datum(ln));
1126 } 1126 }
1127 1127
1128 if (!Lst_IsEmpty(makefiles)) { 1128 if (!Lst_IsEmpty(makefiles)) {
1129 LstNode ln; 1129 LstNode ln;
1130 1130
1131 ln = Lst_Find(makefiles, NULL, ReadAllMakefiles); 1131 ln = Lst_Find(makefiles, NULL, ReadAllMakefiles);
1132 if (ln != NULL) 1132 if (ln != NULL)
1133 Fatal("%s: cannot open %s.", progname,  1133 Fatal("%s: cannot open %s.", progname,
1134 (char *)Lst_Datum(ln)); 1134 (char *)Lst_Datum(ln));
1135 } else { 1135 } else {
1136 p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}", 1136 p1 = Var_Subst(NULL, "${" MAKEFILE_PREFERENCE "}",
1137 VAR_CMD, 0); 1137 VAR_CMD, 0);
1138 if (p1) { 1138 if (p1) {
1139 (void)str2Lst_Append(makefiles, p1, NULL); 1139 (void)str2Lst_Append(makefiles, p1, NULL);
1140 (void)Lst_Find(makefiles, NULL, ReadMakefile); 1140 (void)Lst_Find(makefiles, NULL, ReadMakefile);
1141 free(p1); 1141 free(p1);
1142 } 1142 }
1143 } 1143 }
1144 1144
1145 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */ 1145 /* In particular suppress .depend for '-r -V .OBJDIR -f /dev/null' */
1146 if (!noBuiltins || !printVars) { 1146 if (!noBuiltins || !printVars) {
1147 makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}", 1147 makeDependfile = Var_Subst(NULL, "${.MAKE.DEPENDFILE:T}",
1148 VAR_CMD, 0); 1148 VAR_CMD, 0);
1149 doing_depend = TRUE; 1149 doing_depend = TRUE;
1150 (void)ReadMakefile(makeDependfile, NULL); 1150 (void)ReadMakefile(makeDependfile, NULL);
1151 doing_depend = FALSE; 1151 doing_depend = FALSE;
1152 } 1152 }
1153 1153
1154 MakeMode(NULL); 1154 MakeMode(NULL);
1155 1155
1156 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL); 1156 Var_Append("MFLAGS", Var_Value(MAKEFLAGS, VAR_GLOBAL, &p1), VAR_GLOBAL);
1157 if (p1) 1157 if (p1)
1158 free(p1); 1158 free(p1);
1159 1159
1160 if (!compatMake) 1160 if (!compatMake)
1161 Job_ServerStart(maxJobTokens, jp_0, jp_1); 1161 Job_ServerStart(maxJobTokens, jp_0, jp_1);
1162 if (DEBUG(JOB)) 1162 if (DEBUG(JOB))
1163 fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n", 1163 fprintf(debug_file, "job_pipe %d %d, maxjobs %d, tokens %d, compat %d\n",
1164 jp_0, jp_1, maxJobs, maxJobTokens, compatMake); 1164 jp_0, jp_1, maxJobs, maxJobTokens, compatMake);
1165 1165
1166 Main_ExportMAKEFLAGS(TRUE); /* initial export */ 1166 Main_ExportMAKEFLAGS(TRUE); /* initial export */
1167  1167
1168 1168
1169 /* 1169 /*
1170 * For compatibility, look at the directories in the VPATH variable 1170 * For compatibility, look at the directories in the VPATH variable
1171 * and add them to the search path, if the variable is defined. The 1171 * and add them to the search path, if the variable is defined. The
1172 * variable's value is in the same format as the PATH envariable, i.e. 1172 * variable's value is in the same format as the PATH envariable, i.e.
1173 * <directory>:<directory>:<directory>... 1173 * <directory>:<directory>:<directory>...
1174 */ 1174 */
1175 if (Var_Exists("VPATH", VAR_CMD)) { 1175 if (Var_Exists("VPATH", VAR_CMD)) {
1176 char *vpath, savec; 1176 char *vpath, savec;
1177 /* 1177 /*
1178 * GCC stores string constants in read-only memory, but 1178 * GCC stores string constants in read-only memory, but
1179 * Var_Subst will want to write this thing, so store it 1179 * Var_Subst will want to write this thing, so store it
1180 * in an array 1180 * in an array
1181 */ 1181 */
1182 static char VPATH[] = "${VPATH}"; 1182 static char VPATH[] = "${VPATH}";
1183 1183
1184 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE); 1184 vpath = Var_Subst(NULL, VPATH, VAR_CMD, FALSE);
1185 path = vpath; 1185 path = vpath;
1186 do { 1186 do {
1187 /* skip to end of directory */ 1187 /* skip to end of directory */
1188 for (cp = path; *cp != ':' && *cp != '\0'; cp++) 1188 for (cp = path; *cp != ':' && *cp != '\0'; cp++)
1189 continue; 1189 continue;
1190 /* Save terminator character so know when to stop */ 1190 /* Save terminator character so know when to stop */
1191 savec = *cp; 1191 savec = *cp;
1192 *cp = '\0'; 1192 *cp = '\0';
1193 /* Add directory to search path */ 1193 /* Add directory to search path */
1194 (void)Dir_AddDir(dirSearchPath, path); 1194 (void)Dir_AddDir(dirSearchPath, path);
1195 *cp = savec; 1195 *cp = savec;
1196 path = cp + 1; 1196 path = cp + 1;
1197 } while (savec == ':'); 1197 } while (savec == ':');
1198 free(vpath); 1198 free(vpath);
1199 } 1199 }
1200 1200
1201 /* 1201 /*
1202 * Now that all search paths have been read for suffixes et al, it's 1202 * Now that all search paths have been read for suffixes et al, it's
1203 * time to add the default search path to their lists... 1203 * time to add the default search path to their lists...
1204 */ 1204 */
1205 Suff_DoPaths(); 1205 Suff_DoPaths();
1206 1206
1207 /* 1207 /*
1208 * Propagate attributes through :: dependency lists. 1208 * Propagate attributes through :: dependency lists.
1209 */ 1209 */
1210 Targ_Propagate(); 1210 Targ_Propagate();
1211 1211
1212 /* print the initial graph, if the user requested it */ 1212 /* print the initial graph, if the user requested it */
1213 if (DEBUG(GRAPH1)) 1213 if (DEBUG(GRAPH1))
1214 Targ_PrintGraph(1); 1214 Targ_PrintGraph(1);
1215 1215
1216 /* print the values of any variables requested by the user */ 1216 /* print the values of any variables requested by the user */
1217 if (printVars) { 1217 if (printVars) {
1218 LstNode ln; 1218 LstNode ln;
1219 Boolean expandVars; 1219 Boolean expandVars;
1220 1220
1221 if (debugVflag) 1221 if (debugVflag)
1222 expandVars = FALSE; 1222 expandVars = FALSE;
1223 else 1223 else
1224 expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE); 1224 expandVars = getBoolean(".MAKE.EXPAND_VARIABLES", FALSE);
1225 for (ln = Lst_First(variables); ln != NULL; 1225 for (ln = Lst_First(variables); ln != NULL;
1226 ln = Lst_Succ(ln)) { 1226 ln = Lst_Succ(ln)) {
1227 char *var = (char *)Lst_Datum(ln); 1227 char *var = (char *)Lst_Datum(ln);
1228 char *value; 1228 char *value;
1229  1229
1230 if (strchr(var, '$')) { 1230 if (strchr(var, '$')) {
1231 value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0); 1231 value = p1 = Var_Subst(NULL, var, VAR_GLOBAL, 0);
1232 } else if (expandVars) { 1232 } else if (expandVars) {
1233 char tmp[128]; 1233 char tmp[128];
1234  1234
1235 if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp))) 1235 if (snprintf(tmp, sizeof(tmp), "${%s}", var) >= (int)(sizeof(tmp)))
1236 Fatal("%s: variable name too big: %s", 1236 Fatal("%s: variable name too big: %s",
1237 progname, var); 1237 progname, var);
1238 value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0); 1238 value = p1 = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1239 } else { 1239 } else {
1240 value = Var_Value(var, VAR_GLOBAL, &p1); 1240 value = Var_Value(var, VAR_GLOBAL, &p1);
1241 } 1241 }
1242 printf("%s\n", value ? value : ""); 1242 printf("%s\n", value ? value : "");
1243 if (p1) 1243 if (p1)
1244 free(p1); 1244 free(p1);
1245 } 1245 }
1246 } else { 1246 } else {
1247 /* 1247 /*
1248 * Have now read the entire graph and need to make a list of 1248 * Have now read the entire graph and need to make a list of
1249 * targets to create. If none was given on the command line, 1249 * targets to create. If none was given on the command line,
1250 * we consult the parsing module to find the main target(s) 1250 * we consult the parsing module to find the main target(s)
1251 * to create. 1251 * to create.
1252 */ 1252 */
1253 if (Lst_IsEmpty(create)) 1253 if (Lst_IsEmpty(create))
1254 targs = Parse_MainName(); 1254 targs = Parse_MainName();
1255 else 1255 else
1256 targs = Targ_FindList(create, TARG_CREATE); 1256 targs = Targ_FindList(create, TARG_CREATE);
1257 1257
1258 if (!compatMake) { 1258 if (!compatMake) {
1259 /* 1259 /*
1260 * Initialize job module before traversing the graph 1260 * Initialize job module before traversing the graph
1261 * now that any .BEGIN and .END targets have been read. 1261 * now that any .BEGIN and .END targets have been read.
1262 * This is done only if the -q flag wasn't given 1262 * This is done only if the -q flag wasn't given
1263 * (to prevent the .BEGIN from being executed should 1263 * (to prevent the .BEGIN from being executed should
1264 * it exist). 1264 * it exist).
1265 */ 1265 */
1266 if (!queryFlag) { 1266 if (!queryFlag) {
1267 Job_Init(); 1267 Job_Init();
1268 jobsRunning = TRUE; 1268 jobsRunning = TRUE;
1269 } 1269 }
1270 1270
1271 /* Traverse the graph, checking on all the targets */ 1271 /* Traverse the graph, checking on all the targets */
1272 outOfDate = Make_Run(targs); 1272 outOfDate = Make_Run(targs);
1273 } else { 1273 } else {
1274 /* 1274 /*
1275 * Compat_Init will take care of creating all the 1275 * Compat_Init will take care of creating all the
1276 * targets as well as initializing the module. 1276 * targets as well as initializing the module.
1277 */ 1277 */
1278 Compat_Run(targs); 1278 Compat_Run(targs);
1279 } 1279 }
1280 } 1280 }
1281 1281
1282#ifdef CLEANUP 1282#ifdef CLEANUP
1283 Lst_Destroy(targs, NULL); 1283 Lst_Destroy(targs, NULL);
1284 Lst_Destroy(variables, NULL); 1284 Lst_Destroy(variables, NULL);
1285 Lst_Destroy(makefiles, NULL); 1285 Lst_Destroy(makefiles, NULL);
1286 Lst_Destroy(create, (FreeProc *)free); 1286 Lst_Destroy(create, (FreeProc *)free);
1287#endif 1287#endif
1288 1288
1289 /* print the graph now it's been processed if the user requested it */ 1289 /* print the graph now it's been processed if the user requested it */
1290 if (DEBUG(GRAPH2)) 1290 if (DEBUG(GRAPH2))
1291 Targ_PrintGraph(2); 1291 Targ_PrintGraph(2);
1292 1292
1293 Trace_Log(MAKEEND, 0); 1293 Trace_Log(MAKEEND, 0);
1294 1294
1295 Suff_End(); 1295 Suff_End();
1296 Targ_End(); 1296 Targ_End();
1297 Arch_End(); 1297 Arch_End();
1298 Var_End(); 1298 Var_End();
1299 Parse_End(); 1299 Parse_End();
1300 Dir_End(); 1300 Dir_End();
1301 Job_End(); 1301 Job_End();
1302 Trace_End(); 1302 Trace_End();
1303 1303
1304 return outOfDate ? 1 : 0; 1304 return outOfDate ? 1 : 0;
1305} 1305}
1306 1306
1307/*- 1307/*-
1308 * ReadMakefile -- 1308 * ReadMakefile --
1309 * Open and parse the given makefile. 1309 * Open and parse the given makefile.
1310 * 1310 *
1311 * Results: 1311 * Results:
1312 * 0 if ok. -1 if couldn't open file. 1312 * 0 if ok. -1 if couldn't open file.
1313 * 1313 *
1314 * Side Effects: 1314 * Side Effects:
1315 * lots 1315 * lots
1316 */ 1316 */
1317static int 1317static int
1318ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED) 1318ReadMakefile(const void *p, const void *q MAKE_ATTR_UNUSED)
1319{ 1319{
1320 const char *fname = p; /* makefile to read */ 1320 const char *fname = p; /* makefile to read */
1321 int fd; 1321 int fd;
1322 size_t len = MAXPATHLEN; 1322 size_t len = MAXPATHLEN;
1323 char *name, *path = bmake_malloc(len); 1323 char *name, *path = bmake_malloc(len);
1324 1324
1325 if (!strcmp(fname, "-")) { 1325 if (!strcmp(fname, "-")) {
1326 Parse_File(NULL /*stdin*/, -1); 1326 Parse_File(NULL /*stdin*/, -1);
1327 Var_Set("MAKEFILE", "", VAR_GLOBAL, 0); 1327 Var_Set("MAKEFILE", "", VAR_GLOBAL, 0);
1328 } else { 1328 } else {
1329 /* if we've chdir'd, rebuild the path name */ 1329 /* if we've chdir'd, rebuild the path name */
1330 if (strcmp(curdir, objdir) && *fname != '/') { 1330 if (strcmp(curdir, objdir) && *fname != '/') {
1331 size_t plen = strlen(curdir) + strlen(fname) + 2; 1331 size_t plen = strlen(curdir) + strlen(fname) + 2;
1332 if (len < plen) 1332 if (len < plen)
1333 path = bmake_realloc(path, len = 2 * plen); 1333 path = bmake_realloc(path, len = 2 * plen);
1334  1334
1335 (void)snprintf(path, len, "%s/%s", curdir, fname); 1335 (void)snprintf(path, len, "%s/%s", curdir, fname);
1336 fd = open(path, O_RDONLY); 1336 fd = open(path, O_RDONLY);
1337 if (fd != -1) { 1337 if (fd != -1) {
1338 fname = path; 1338 fname = path;
1339 goto found; 1339 goto found;
1340 } 1340 }
1341  1341
1342 /* If curdir failed, try objdir (ala .depend) */ 1342 /* If curdir failed, try objdir (ala .depend) */
1343 plen = strlen(objdir) + strlen(fname) + 2; 1343 plen = strlen(objdir) + strlen(fname) + 2;
1344 if (len < plen) 1344 if (len < plen)
1345 path = bmake_realloc(path, len = 2 * plen); 1345 path = bmake_realloc(path, len = 2 * plen);
1346 (void)snprintf(path, len, "%s/%s", objdir, fname); 1346 (void)snprintf(path, len, "%s/%s", objdir, fname);
1347 fd = open(path, O_RDONLY); 1347 fd = open(path, O_RDONLY);
1348 if (fd != -1) { 1348 if (fd != -1) {
1349 fname = path; 1349 fname = path;
1350 goto found; 1350 goto found;
1351 } 1351 }
1352 } else { 1352 } else {
1353 fd = open(fname, O_RDONLY); 1353 fd = open(fname, O_RDONLY);
1354 if (fd != -1) 1354 if (fd != -1)
1355 goto found; 1355 goto found;
1356 } 1356 }
1357 /* look in -I and system include directories. */ 1357 /* look in -I and system include directories. */
1358 name = Dir_FindFile(fname, parseIncPath); 1358 name = Dir_FindFile(fname, parseIncPath);
1359 if (!name) 1359 if (!name)
1360 name = Dir_FindFile(fname, 1360 name = Dir_FindFile(fname,
1361 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath); 1361 Lst_IsEmpty(sysIncPath) ? defIncPath : sysIncPath);
1362 if (!name || (fd = open(name, O_RDONLY)) == -1) { 1362 if (!name || (fd = open(name, O_RDONLY)) == -1) {
1363 if (name) 1363 if (name)
1364 free(name); 1364 free(name);
1365 free(path); 1365 free(path);
1366 return(-1); 1366 return(-1);
1367 } 1367 }
1368 fname = name; 1368 fname = name;
1369 /* 1369 /*
1370 * set the MAKEFILE variable desired by System V fans -- the 1370 * set the MAKEFILE variable desired by System V fans -- the
1371 * placement of the setting here means it gets set to the last 1371 * placement of the setting here means it gets set to the last
1372 * makefile specified, as it is set by SysV make. 1372 * makefile specified, as it is set by SysV make.
1373 */ 1373 */
1374found: 1374found:
1375 if (!doing_depend) 1375 if (!doing_depend)
1376 Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0); 1376 Var_Set("MAKEFILE", fname, VAR_GLOBAL, 0);
1377 Parse_File(fname, fd); 1377 Parse_File(fname, fd);
1378 } 1378 }
1379 free(path); 1379 free(path);
1380 return(0); 1380 return(0);
1381} 1381}
1382 1382
1383 1383
1384 1384
1385/*- 1385/*-
1386 * Cmd_Exec -- 1386 * Cmd_Exec --
1387 * Execute the command in cmd, and return the output of that command 1387 * Execute the command in cmd, and return the output of that command
1388 * in a string. 1388 * in a string.
1389 * 1389 *
1390 * Results: 1390 * Results:
1391 * A string containing the output of the command, or the empty string 1391 * A string containing the output of the command, or the empty string
1392 * If errnum is not NULL, it contains the reason for the command failure 1392 * If errnum is not NULL, it contains the reason for the command failure
1393 * 1393 *
1394 * Side Effects: 1394 * Side Effects:
1395 * The string must be freed by the caller. 1395 * The string must be freed by the caller.
1396 */ 1396 */
1397char * 1397char *
1398Cmd_Exec(const char *cmd, const char **errnum) 1398Cmd_Exec(const char *cmd, const char **errnum)
1399{ 1399{
1400 const char *args[4]; /* Args for invoking the shell */ 1400 const char *args[4]; /* Args for invoking the shell */
1401 int fds[2]; /* Pipe streams */ 1401 int fds[2]; /* Pipe streams */
1402 int cpid; /* Child PID */ 1402 int cpid; /* Child PID */
1403 int pid; /* PID from wait() */ 1403 int pid; /* PID from wait() */
1404 char *res; /* result */ 1404 char *res; /* result */
1405 int status; /* command exit status */ 1405 int status; /* command exit status */
1406 Buffer buf; /* buffer to store the result */ 1406 Buffer buf; /* buffer to store the result */
1407 char *cp; 1407 char *cp;
1408 int cc; 1408 int cc;
1409 1409
1410 1410
1411 *errnum = NULL; 1411 *errnum = NULL;
1412 1412
1413 if (!shellName) 1413 if (!shellName)
1414 Shell_Init(); 1414 Shell_Init();
1415 /* 1415 /*
1416 * Set up arguments for shell 1416 * Set up arguments for shell
1417 */ 1417 */
1418 args[0] = shellName; 1418 args[0] = shellName;
1419 args[1] = "-c"; 1419 args[1] = "-c";
1420 args[2] = cmd; 1420 args[2] = cmd;
1421 args[3] = NULL; 1421 args[3] = NULL;
1422 1422
1423 /* 1423 /*
1424 * Open a pipe for fetching its output 1424 * Open a pipe for fetching its output
1425 */ 1425 */
1426 if (pipe(fds) == -1) { 1426 if (pipe(fds) == -1) {
1427 *errnum = "Couldn't create pipe for \"%s\""; 1427 *errnum = "Couldn't create pipe for \"%s\"";
1428 goto bad; 1428 goto bad;
1429 } 1429 }
1430 1430
1431 /* 1431 /*
1432 * Fork 1432 * Fork
1433 */ 1433 */
1434 switch (cpid = vFork()) { 1434 switch (cpid = vFork()) {
1435 case 0: 1435 case 0:
1436 /* 1436 /*
1437 * Close input side of pipe 1437 * Close input side of pipe
1438 */ 1438 */
1439 (void)close(fds[0]); 1439 (void)close(fds[0]);
1440 1440
1441 /* 1441 /*
1442 * Duplicate the output stream to the shell's output, then 1442 * Duplicate the output stream to the shell's output, then
1443 * shut the extra thing down. Note we don't fetch the error 1443 * shut the extra thing down. Note we don't fetch the error
1444 * stream...why not? Why? 1444 * stream...why not? Why?
1445 */ 1445 */
1446 (void)dup2(fds[1], 1); 1446 (void)dup2(fds[1], 1);
1447 (void)close(fds[1]); 1447 (void)close(fds[1]);
1448 1448
1449 Var_ExportVars(); 1449 Var_ExportVars();
1450 1450
1451 (void)execv(shellPath, UNCONST(args)); 1451 (void)execv(shellPath, UNCONST(args));
1452 _exit(1); 1452 _exit(1);
1453 /*NOTREACHED*/ 1453 /*NOTREACHED*/
1454 1454
1455 case -1: 1455 case -1:
1456 *errnum = "Couldn't exec \"%s\""; 1456 *errnum = "Couldn't exec \"%s\"";
1457 goto bad; 1457 goto bad;
1458 1458
1459 default: 1459 default:
1460 /* 1460 /*
1461 * No need for the writing half 1461 * No need for the writing half
1462 */ 1462 */
1463 (void)close(fds[1]); 1463 (void)close(fds[1]);
1464 1464
1465 Buf_Init(&buf, 0); 1465 Buf_Init(&buf, 0);
1466 1466
1467 do { 1467 do {
1468 char result[BUFSIZ]; 1468 char result[BUFSIZ];
1469 cc = read(fds[0], result, sizeof(result)); 1469 cc = read(fds[0], result, sizeof(result));
1470 if (cc > 0) 1470 if (cc > 0)
1471 Buf_AddBytes(&buf, cc, result); 1471 Buf_AddBytes(&buf, cc, result);
1472 } 1472 }
1473 while (cc > 0 || (cc == -1 && errno == EINTR)); 1473 while (cc > 0 || (cc == -1 && errno == EINTR));
1474 1474
1475 /* 1475 /*
1476 * Close the input side of the pipe. 1476 * Close the input side of the pipe.
1477 */ 1477 */
1478 (void)close(fds[0]); 1478 (void)close(fds[0]);
1479 1479
1480 /* 1480 /*
1481 * Wait for the process to exit. 1481 * Wait for the process to exit.
1482 */ 1482 */
1483 while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) { 1483 while(((pid = waitpid(cpid, &status, 0)) != cpid) && (pid >= 0)) {
1484 JobReapChild(pid, status, FALSE); 1484 JobReapChild(pid, status, FALSE);
1485 continue; 1485 continue;
1486 } 1486 }
1487 cc = Buf_Size(&buf); 1487 cc = Buf_Size(&buf);
1488 res = Buf_Destroy(&buf, FALSE); 1488 res = Buf_Destroy(&buf, FALSE);
1489 1489
1490 if (cc == 0) 1490 if (cc == 0)
1491 *errnum = "Couldn't read shell's output for \"%s\""; 1491 *errnum = "Couldn't read shell's output for \"%s\"";
1492 1492
1493 if (WIFSIGNALED(status)) 1493 if (WIFSIGNALED(status))
1494 *errnum = "\"%s\" exited on a signal"; 1494 *errnum = "\"%s\" exited on a signal";
1495 else if (WEXITSTATUS(status) != 0) 1495 else if (WEXITSTATUS(status) != 0)
1496 *errnum = "\"%s\" returned non-zero status"; 1496 *errnum = "\"%s\" returned non-zero status";
1497 1497
1498 /* 1498 /*
1499 * Null-terminate the result, convert newlines to spaces and 1499 * Null-terminate the result, convert newlines to spaces and
1500 * install it in the variable. 1500 * install it in the variable.
1501 */ 1501 */
1502 res[cc] = '\0'; 1502 res[cc] = '\0';
1503 cp = &res[cc]; 1503 cp = &res[cc];
1504 1504
1505 if (cc > 0 && *--cp == '\n') { 1505 if (cc > 0 && *--cp == '\n') {
1506 /* 1506 /*
1507 * A final newline is just stripped 1507 * A final newline is just stripped
1508 */ 1508 */
1509 *cp-- = '\0'; 1509 *cp-- = '\0';
1510 } 1510 }
1511 while (cp >= res) { 1511 while (cp >= res) {
1512 if (*cp == '\n') { 1512 if (*cp == '\n') {
1513 *cp = ' '; 1513 *cp = ' ';
1514 } 1514 }
1515 cp--; 1515 cp--;
1516 } 1516 }
1517 break; 1517 break;
1518 } 1518 }
1519 return res; 1519 return res;
1520bad: 1520bad:
1521 res = bmake_malloc(1); 1521 res = bmake_malloc(1);
1522 *res = '\0'; 1522 *res = '\0';
1523 return res; 1523 return res;
1524} 1524}
1525 1525
1526/*- 1526/*-
1527 * Error -- 1527 * Error --
1528 * Print an error message given its format. 1528 * Print an error message given its format.
1529 * 1529 *
1530 * Results: 1530 * Results:
1531 * None. 1531 * None.
1532 * 1532 *
1533 * Side Effects: 1533 * Side Effects:
1534 * The message is printed. 1534 * The message is printed.
1535 */ 1535 */
1536/* VARARGS */ 1536/* VARARGS */
1537void 1537void
1538Error(const char *fmt, ...) 1538Error(const char *fmt, ...)
1539{ 1539{
1540 va_list ap; 1540 va_list ap;
1541 FILE *err_file; 1541 FILE *err_file;
1542 1542
1543 err_file = debug_file; 1543 err_file = debug_file;
1544 if (err_file == stdout) 1544 if (err_file == stdout)
1545 err_file = stderr; 1545 err_file = stderr;
1546 (void)fflush(stdout); 1546 (void)fflush(stdout);
1547 for (;;) { 1547 for (;;) {
1548 va_start(ap, fmt); 1548 va_start(ap, fmt);
1549 fprintf(err_file, "%s: ", progname); 1549 fprintf(err_file, "%s: ", progname);
1550 (void)vfprintf(err_file, fmt, ap); 1550 (void)vfprintf(err_file, fmt, ap);
1551 va_end(ap); 1551 va_end(ap);
1552 (void)fprintf(err_file, "\n"); 1552 (void)fprintf(err_file, "\n");
1553 (void)fflush(err_file); 1553 (void)fflush(err_file);
1554 if (err_file == stderr) 1554 if (err_file == stderr)
1555 break; 1555 break;
1556 err_file = stderr; 1556 err_file = stderr;
1557 } 1557 }
1558} 1558}
1559 1559
1560/*- 1560/*-
1561 * Fatal -- 1561 * Fatal --
1562 * Produce a Fatal error message. If jobs are running, waits for them 1562 * Produce a Fatal error message. If jobs are running, waits for them
1563 * to finish. 1563 * to finish.
1564 * 1564 *
1565 * Results: 1565 * Results:
1566 * None 1566 * None
1567 * 1567 *
1568 * Side Effects: 1568 * Side Effects:
1569 * The program exits 1569 * The program exits
1570 */ 1570 */
1571/* VARARGS */ 1571/* VARARGS */
1572void 1572void
1573Fatal(const char *fmt, ...) 1573Fatal(const char *fmt, ...)
1574{ 1574{
1575 va_list ap; 1575 va_list ap;
1576 1576
1577 va_start(ap, fmt); 1577 va_start(ap, fmt);
1578 if (jobsRunning) 1578 if (jobsRunning)
1579 Job_Wait(); 1579 Job_Wait();
1580 1580
1581 (void)fflush(stdout); 1581 (void)fflush(stdout);
1582 (void)vfprintf(stderr, fmt, ap); 1582 (void)vfprintf(stderr, fmt, ap);
1583 va_end(ap); 1583 va_end(ap);
1584 (void)fprintf(stderr, "\n"); 1584 (void)fprintf(stderr, "\n");
1585 (void)fflush(stderr); 1585 (void)fflush(stderr);
1586 1586
1587 PrintOnError(NULL, NULL); 1587 PrintOnError(NULL, NULL);
1588 1588
1589 if (DEBUG(GRAPH2) || DEBUG(GRAPH3)) 1589 if (DEBUG(GRAPH2) || DEBUG(GRAPH3))
1590 Targ_PrintGraph(2); 1590 Targ_PrintGraph(2);
1591 Trace_Log(MAKEERROR, 0); 1591 Trace_Log(MAKEERROR, 0);
1592 exit(2); /* Not 1 so -q can distinguish error */ 1592 exit(2); /* Not 1 so -q can distinguish error */
1593} 1593}
1594 1594
1595/* 1595/*
1596 * Punt -- 1596 * Punt --
1597 * Major exception once jobs are being created. Kills all jobs, prints 1597 * Major exception once jobs are being created. Kills all jobs, prints
1598 * a message and exits. 1598 * a message and exits.
1599 * 1599 *
1600 * Results: 1600 * Results:
1601 * None 1601 * None
1602 * 1602 *
1603 * Side Effects: 1603 * Side Effects:
1604 * All children are killed indiscriminately and the program Lib_Exits 1604 * All children are killed indiscriminately and the program Lib_Exits
1605 */ 1605 */
1606/* VARARGS */ 1606/* VARARGS */
1607void 1607void
1608Punt(const char *fmt, ...) 1608Punt(const char *fmt, ...)
1609{ 1609{
1610 va_list ap; 1610 va_list ap;
1611 1611
1612 va_start(ap, fmt); 1612 va_start(ap, fmt);
1613 (void)fflush(stdout); 1613 (void)fflush(stdout);
1614 (void)fprintf(stderr, "%s: ", progname); 1614 (void)fprintf(stderr, "%s: ", progname);
1615 (void)vfprintf(stderr, fmt, ap); 1615 (void)vfprintf(stderr, fmt, ap);
1616 va_end(ap); 1616 va_end(ap);
1617 (void)fprintf(stderr, "\n"); 1617 (void)fprintf(stderr, "\n");
1618 (void)fflush(stderr); 1618 (void)fflush(stderr);
1619 1619
1620 PrintOnError(NULL, NULL); 1620 PrintOnError(NULL, NULL);
1621 1621
1622 DieHorribly(); 1622 DieHorribly();
1623} 1623}
1624 1624
1625/*- 1625/*-
1626 * DieHorribly -- 1626 * DieHorribly --
1627 * Exit without giving a message. 1627 * Exit without giving a message.
1628 * 1628 *
1629 * Results: 1629 * Results:
1630 * None 1630 * None
1631 * 1631 *
1632 * Side Effects: 1632 * Side Effects:
1633 * A big one... 1633 * A big one...
1634 */ 1634 */
1635void 1635void
1636DieHorribly(void) 1636DieHorribly(void)
1637{ 1637{
1638 if (jobsRunning) 1638 if (jobsRunning)
1639 Job_AbortAll(); 1639 Job_AbortAll();
1640 if (DEBUG(GRAPH2)) 1640 if (DEBUG(GRAPH2))
1641 Targ_PrintGraph(2); 1641 Targ_PrintGraph(2);
1642 Trace_Log(MAKEERROR, 0); 1642 Trace_Log(MAKEERROR, 0);
1643 exit(2); /* Not 1, so -q can distinguish error */ 1643 exit(2); /* Not 1, so -q can distinguish error */
1644} 1644}
1645 1645
1646/* 1646/*
1647 * Finish -- 1647 * Finish --
1648 * Called when aborting due to errors in child shell to signal 1648 * Called when aborting due to errors in child shell to signal
1649 * abnormal exit. 1649 * abnormal exit.
1650 * 1650 *
1651 * Results: 1651 * Results:
1652 * None 1652 * None
1653 * 1653 *
1654 * Side Effects: 1654 * Side Effects:
1655 * The program exits 1655 * The program exits
1656 */ 1656 */
1657void 1657void
1658Finish(int errors) 1658Finish(int errors)
1659 /* number of errors encountered in Make_Make */ 1659 /* number of errors encountered in Make_Make */
1660{ 1660{
1661 Fatal("%d error%s", errors, errors == 1 ? "" : "s"); 1661 Fatal("%d error%s", errors, errors == 1 ? "" : "s");
1662} 1662}
1663 1663
1664/* 1664/*
1665 * enunlink -- 1665 * enunlink --
1666 * Remove a file carefully, avoiding directories. 1666 * Remove a file carefully, avoiding directories.
1667 */ 1667 */
1668int 1668int
1669eunlink(const char *file) 1669eunlink(const char *file)
1670{ 1670{
1671 struct stat st; 1671 struct stat st;
1672 1672
1673 if (lstat(file, &st) == -1) 1673 if (lstat(file, &st) == -1)
1674 return -1; 1674 return -1;
1675 1675
1676 if (S_ISDIR(st.st_mode)) { 1676 if (S_ISDIR(st.st_mode)) {
1677 errno = EISDIR; 1677 errno = EISDIR;
1678 return -1; 1678 return -1;
1679 } 1679 }
1680 return unlink(file); 1680 return unlink(file);
1681} 1681}
1682 1682
1683/* 1683/*
1684 * execError -- 1684 * execError --
1685 * Print why exec failed, avoiding stdio. 1685 * Print why exec failed, avoiding stdio.
1686 */ 1686 */
1687void 1687void
1688execError(const char *af, const char *av) 1688execError(const char *af, const char *av)
1689{ 1689{
1690#ifdef USE_IOVEC 1690#ifdef USE_IOVEC
1691 int i = 0; 1691 int i = 0;
1692 struct iovec iov[8]; 1692 struct iovec iov[8];
1693#define IOADD(s) \ 1693#define IOADD(s) \
1694 (void)(iov[i].iov_base = UNCONST(s), \ 1694 (void)(iov[i].iov_base = UNCONST(s), \
1695 iov[i].iov_len = strlen(iov[i].iov_base), \ 1695 iov[i].iov_len = strlen(iov[i].iov_base), \
1696 i++) 1696 i++)
1697#else 1697#else
1698#define IOADD(void)write(2, s, strlen(s)) 1698#define IOADD(void)write(2, s, strlen(s))
1699#endif 1699#endif
1700 1700
1701 IOADD(progname); 1701 IOADD(progname);
1702 IOADD(": "); 1702 IOADD(": ");
1703 IOADD(af); 1703 IOADD(af);
1704 IOADD("("); 1704 IOADD("(");
1705 IOADD(av); 1705 IOADD(av);
1706 IOADD(") failed ("); 1706 IOADD(") failed (");
1707 IOADD(strerror(errno)); 1707 IOADD(strerror(errno));
1708 IOADD(")\n"); 1708 IOADD(")\n");
1709 1709
1710#ifdef USE_IOVEC 1710#ifdef USE_IOVEC
1711 (void)writev(2, iov, 8); 1711 while (writev(2, iov, 8) == -1 && errno == EAGAIN)
 1712 continue;
1712#endif 1713#endif
1713} 1714}
1714 1715
1715/* 1716/*
1716 * usage -- 1717 * usage --
1717 * exit with usage message 1718 * exit with usage message
1718 */ 1719 */
1719static void 1720static void
1720usage(void) 1721usage(void)
1721{ 1722{
1722 (void)fprintf(stderr, 1723 (void)fprintf(stderr,
1723"usage: %s [-BeikNnqrstWX] \n\ 1724"usage: %s [-BeikNnqrstWX] \n\
1724 [-C directory] [-D variable] [-d flags] [-f makefile]\n\ 1725 [-C directory] [-D variable] [-d flags] [-f makefile]\n\
1725 [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\ 1726 [-I directory] [-J private] [-j max_jobs] [-m directory] [-T file]\n\
1726 [-V variable] [variable=value] [target ...]\n", progname); 1727 [-V variable] [variable=value] [target ...]\n", progname);
1727 exit(2); 1728 exit(2);
1728} 1729}
1729 1730
1730 1731
1731int 1732int
1732PrintAddr(void *a, void *b) 1733PrintAddr(void *a, void *b)
1733{ 1734{
1734 printf("%lx ", (unsigned long) a); 1735 printf("%lx ", (unsigned long) a);
1735 return b ? 0 : 0; 1736 return b ? 0 : 0;
1736} 1737}
1737 1738
1738 1739
1739 1740
1740void 1741void
1741PrintOnError(GNode *gn, const char *s) 1742PrintOnError(GNode *gn, const char *s)
1742{ 1743{
1743 static GNode *en = NULL; 1744 static GNode *en = NULL;
1744 char tmp[64]; 1745 char tmp[64];
1745 char *cp; 1746 char *cp;
1746 1747
1747 if (s) 1748 if (s)
1748 printf("%s", s); 1749 printf("%s", s);
1749  1750
1750 printf("\n%s: stopped in %s\n", progname, curdir); 1751 printf("\n%s: stopped in %s\n", progname, curdir);
1751 1752
1752 if (en) 1753 if (en)
1753 return; /* we've been here! */ 1754 return; /* we've been here! */
1754 if (gn) { 1755 if (gn) {
1755 /* 1756 /*
1756 * We can print this even if there is no .ERROR target. 1757 * We can print this even if there is no .ERROR target.
1757 */ 1758 */
1758 Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0); 1759 Var_Set(".ERROR_TARGET", gn->name, VAR_GLOBAL, 0);
1759 } 1760 }
1760 strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}", 1761 strncpy(tmp, "${MAKE_PRINT_VAR_ON_ERROR:@v@$v='${$v}'\n@}",
1761 sizeof(tmp) - 1); 1762 sizeof(tmp) - 1);
1762 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0); 1763 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1763 if (cp) { 1764 if (cp) {
1764 if (*cp) 1765 if (*cp)
1765 printf("%s", cp); 1766 printf("%s", cp);
1766 free(cp); 1767 free(cp);
1767 } 1768 }
1768 /* 1769 /*
1769 * Finally, see if there is a .ERROR target, and run it if so. 1770 * Finally, see if there is a .ERROR target, and run it if so.
1770 */ 1771 */
1771 en = Targ_FindNode(".ERROR", TARG_NOCREATE); 1772 en = Targ_FindNode(".ERROR", TARG_NOCREATE);
1772 if (en) { 1773 if (en) {
1773 en->type |= OP_SPECIAL; 1774 en->type |= OP_SPECIAL;
1774 Compat_Make(en, en); 1775 Compat_Make(en, en);
1775 } 1776 }
1776} 1777}
1777 1778
1778void 1779void
1779Main_ExportMAKEFLAGS(Boolean first) 1780Main_ExportMAKEFLAGS(Boolean first)
1780{ 1781{
1781 static int once = 1; 1782 static int once = 1;
1782 char tmp[64]; 1783 char tmp[64];
1783 char *s; 1784 char *s;
1784 1785
1785 if (once != first) 1786 if (once != first)
1786 return; 1787 return;
1787 once = 0; 1788 once = 0;
1788  1789
1789 strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}", 1790 strncpy(tmp, "${.MAKEFLAGS} ${.MAKEOVERRIDES:O:u:@v@$v=${$v:Q}@}",
1790 sizeof(tmp)); 1791 sizeof(tmp));
1791 s = Var_Subst(NULL, tmp, VAR_CMD, 0); 1792 s = Var_Subst(NULL, tmp, VAR_CMD, 0);
1792 if (s && *s) { 1793 if (s && *s) {
1793#ifdef POSIX 1794#ifdef POSIX
1794 setenv("MAKEFLAGS", s, 1); 1795 setenv("MAKEFLAGS", s, 1);
1795#else 1796#else
1796 setenv("MAKE", s, 1); 1797 setenv("MAKE", s, 1);
1797#endif 1798#endif
1798 } 1799 }
1799} 1800}
1800 1801
1801char * 1802char *
1802getTmpdir(void) 1803getTmpdir(void)
1803{ 1804{
1804 static char *tmpdir = NULL; 1805 static char *tmpdir = NULL;
1805 1806
1806 if (!tmpdir) { 1807 if (!tmpdir) {
1807 struct stat st; 1808 struct stat st;
1808 1809
1809 /* 1810 /*
1810 * Honor $TMPDIR but only if it is valid. 1811 * Honor $TMPDIR but only if it is valid.
1811 * Ensure it ends with /. 1812 * Ensure it ends with /.
1812 */ 1813 */
1813 tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0); 1814 tmpdir = Var_Subst(NULL, "${TMPDIR:tA:U" _PATH_TMP "}/", VAR_GLOBAL, 0);
1814 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) { 1815 if (stat(tmpdir, &st) < 0 || !S_ISDIR(st.st_mode)) {
1815 free(tmpdir); 1816 free(tmpdir);
1816 tmpdir = bmake_strdup(_PATH_TMP); 1817 tmpdir = bmake_strdup(_PATH_TMP);
1817 } 1818 }
1818 } 1819 }
1819 return tmpdir; 1820 return tmpdir;
1820} 1821}
1821 1822
1822/* 1823/*
1823 * Create and open a temp file using "pattern". 1824 * Create and open a temp file using "pattern".
1824 * If "fnamep" is provided set it to a copy of the filename created. 1825 * If "fnamep" is provided set it to a copy of the filename created.
1825 * Otherwise unlink the file once open. 1826 * Otherwise unlink the file once open.
1826 */ 1827 */
1827int 1828int
1828mkTempFile(const char *pattern, char **fnamep) 1829mkTempFile(const char *pattern, char **fnamep)
1829{ 1830{
1830 static char *tmpdir = NULL; 1831 static char *tmpdir = NULL;
1831 char tfile[MAXPATHLEN]; 1832 char tfile[MAXPATHLEN];
1832 int fd; 1833 int fd;
1833  1834
1834 if (!pattern) 1835 if (!pattern)
1835 pattern = TMPPAT; 1836 pattern = TMPPAT;
1836 if (!tmpdir) 1837 if (!tmpdir)
1837 tmpdir = getTmpdir(); 1838 tmpdir = getTmpdir();
1838 if (pattern[0] == '/') { 1839 if (pattern[0] == '/') {
1839 snprintf(tfile, sizeof(tfile), "%s", pattern); 1840 snprintf(tfile, sizeof(tfile), "%s", pattern);
1840 } else { 1841 } else {
1841 snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern); 1842 snprintf(tfile, sizeof(tfile), "%s%s", tmpdir, pattern);
1842 } 1843 }
1843 if ((fd = mkstemp(tfile)) < 0) 1844 if ((fd = mkstemp(tfile)) < 0)
1844 Punt("Could not create temporary file %s: %s", tfile, strerror(errno)); 1845 Punt("Could not create temporary file %s: %s", tfile, strerror(errno));
1845 if (fnamep) { 1846 if (fnamep) {
1846 *fnamep = bmake_strdup(tfile); 1847 *fnamep = bmake_strdup(tfile);
1847 } else { 1848 } else {
1848 unlink(tfile); /* we just want the descriptor */ 1849 unlink(tfile); /* we just want the descriptor */
1849 } 1850 }
1850 return fd; 1851 return fd;
1851} 1852}
1852 1853
1853 1854
1854/* 1855/*
1855 * Return a Boolean based on setting of a knob. 1856 * Return a Boolean based on setting of a knob.
1856 * 1857 *
1857 * If the knob is not set, the supplied default is the return value. 1858 * If the knob is not set, the supplied default is the return value.
1858 * If set, anything that looks or smells like "No", "False", "Off", "0" etc, 1859 * If set, anything that looks or smells like "No", "False", "Off", "0" etc,
1859 * is FALSE, otherwise TRUE. 1860 * is FALSE, otherwise TRUE.
1860 */ 1861 */
1861Boolean 1862Boolean
1862getBoolean(const char *name, Boolean bf) 1863getBoolean(const char *name, Boolean bf)
1863{ 1864{
1864 char tmp[64]; 1865 char tmp[64];
1865 char *cp; 1866 char *cp;
1866 1867
1867 if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) { 1868 if (snprintf(tmp, sizeof(tmp), "${%s:tl}", name) < (int)(sizeof(tmp))) {
1868 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0); 1869 cp = Var_Subst(NULL, tmp, VAR_GLOBAL, 0);
1869 1870
1870 if (cp) { 1871 if (cp) {
1871 switch(*cp) { 1872 switch(*cp) {
1872 case '\0': /* not set - the default wins */ 1873 case '\0': /* not set - the default wins */
1873 break; 1874 break;
1874 case '0': 1875 case '0':
1875 case 'f': 1876 case 'f':
1876 case 'n': 1877 case 'n':
1877 bf = FALSE; 1878 bf = FALSE;
1878 break; 1879 break;
1879 case 'o': 1880 case 'o':
1880 switch (cp[1]) { 1881 switch (cp[1]) {
1881 case 'f': 1882 case 'f':
1882 bf = FALSE; 1883 bf = FALSE;
1883 break; 1884 break;
1884 default: 1885 default:
1885 bf = TRUE; 1886 bf = TRUE;
1886 break; 1887 break;
1887 } 1888 }
1888 break; 1889 break;
1889 default: 1890 default:
1890 bf = TRUE; 1891 bf = TRUE;
1891 break; 1892 break;
1892 } 1893 }
1893 free(cp); 1894 free(cp);
1894 } 1895 }
1895 } 1896 }
1896 return (bf); 1897 return (bf);
1897} 1898}