1*6eef5f0cSAntonio Huete Jimenez /* $NetBSD: compat.c,v 1.241 2022/08/17 20:10:29 rillig Exp $ */
201e196c8SJohn Marino
301e196c8SJohn Marino /*
401e196c8SJohn Marino * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
501e196c8SJohn Marino * All rights reserved.
601e196c8SJohn Marino *
701e196c8SJohn Marino * This code is derived from software contributed to Berkeley by
801e196c8SJohn Marino * Adam de Boor.
901e196c8SJohn Marino *
1001e196c8SJohn Marino * Redistribution and use in source and binary forms, with or without
1101e196c8SJohn Marino * modification, are permitted provided that the following conditions
1201e196c8SJohn Marino * are met:
1301e196c8SJohn Marino * 1. Redistributions of source code must retain the above copyright
1401e196c8SJohn Marino * notice, this list of conditions and the following disclaimer.
1501e196c8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
1601e196c8SJohn Marino * notice, this list of conditions and the following disclaimer in the
1701e196c8SJohn Marino * documentation and/or other materials provided with the distribution.
1801e196c8SJohn Marino * 3. Neither the name of the University nor the names of its contributors
1901e196c8SJohn Marino * may be used to endorse or promote products derived from this software
2001e196c8SJohn Marino * without specific prior written permission.
2101e196c8SJohn Marino *
2201e196c8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2301e196c8SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2401e196c8SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2501e196c8SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2601e196c8SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2701e196c8SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2801e196c8SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2901e196c8SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3001e196c8SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3101e196c8SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3201e196c8SJohn Marino * SUCH DAMAGE.
3301e196c8SJohn Marino */
3401e196c8SJohn Marino
3501e196c8SJohn Marino /*
3601e196c8SJohn Marino * Copyright (c) 1988, 1989 by Adam de Boor
3701e196c8SJohn Marino * Copyright (c) 1989 by Berkeley Softworks
3801e196c8SJohn Marino * All rights reserved.
3901e196c8SJohn Marino *
4001e196c8SJohn Marino * This code is derived from software contributed to Berkeley by
4101e196c8SJohn Marino * Adam de Boor.
4201e196c8SJohn Marino *
4301e196c8SJohn Marino * Redistribution and use in source and binary forms, with or without
4401e196c8SJohn Marino * modification, are permitted provided that the following conditions
4501e196c8SJohn Marino * are met:
4601e196c8SJohn Marino * 1. Redistributions of source code must retain the above copyright
4701e196c8SJohn Marino * notice, this list of conditions and the following disclaimer.
4801e196c8SJohn Marino * 2. Redistributions in binary form must reproduce the above copyright
4901e196c8SJohn Marino * notice, this list of conditions and the following disclaimer in the
5001e196c8SJohn Marino * documentation and/or other materials provided with the distribution.
5101e196c8SJohn Marino * 3. All advertising materials mentioning features or use of this software
5201e196c8SJohn Marino * must display the following acknowledgement:
5301e196c8SJohn Marino * This product includes software developed by the University of
5401e196c8SJohn Marino * California, Berkeley and its contributors.
5501e196c8SJohn Marino * 4. Neither the name of the University nor the names of its contributors
5601e196c8SJohn Marino * may be used to endorse or promote products derived from this software
5701e196c8SJohn Marino * without specific prior written permission.
5801e196c8SJohn Marino *
5901e196c8SJohn Marino * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
6001e196c8SJohn Marino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
6101e196c8SJohn Marino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
6201e196c8SJohn Marino * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
6301e196c8SJohn Marino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
6401e196c8SJohn Marino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
6501e196c8SJohn Marino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
6601e196c8SJohn Marino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
6701e196c8SJohn Marino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
6801e196c8SJohn Marino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
6901e196c8SJohn Marino * SUCH DAMAGE.
7001e196c8SJohn Marino */
7101e196c8SJohn Marino
72a34d5fb1SAntonio Huete Jimenez /*
73*6eef5f0cSAntonio Huete Jimenez * This file implements the full-compatibility mode of make, which makes the
74*6eef5f0cSAntonio Huete Jimenez * targets without parallelism and without a custom shell.
7501e196c8SJohn Marino *
7601e196c8SJohn Marino * Interface:
77*6eef5f0cSAntonio Huete Jimenez * Compat_MakeAll Initialize this module and make the given targets.
7801e196c8SJohn Marino */
7901e196c8SJohn Marino
8001e196c8SJohn Marino #ifdef HAVE_CONFIG_H
8101e196c8SJohn Marino # include "config.h"
8201e196c8SJohn Marino #endif
8301e196c8SJohn Marino #include <sys/types.h>
8401e196c8SJohn Marino #include <sys/stat.h>
8501e196c8SJohn Marino #include "wait.h"
8601e196c8SJohn Marino
8701e196c8SJohn Marino #include <errno.h>
8801e196c8SJohn Marino #include <signal.h>
8901e196c8SJohn Marino
9001e196c8SJohn Marino #include "make.h"
9101e196c8SJohn Marino #include "dir.h"
9201e196c8SJohn Marino #include "job.h"
93f445c897SJohn Marino #include "metachar.h"
9401e196c8SJohn Marino #include "pathnames.h"
9501e196c8SJohn Marino
96a34d5fb1SAntonio Huete Jimenez /* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
97*6eef5f0cSAntonio Huete Jimenez MAKE_RCSID("$NetBSD: compat.c,v 1.241 2022/08/17 20:10:29 rillig Exp $");
9801e196c8SJohn Marino
9901e196c8SJohn Marino static GNode *curTarg = NULL;
100ca58f742SDaniel Fojt static pid_t compatChild;
101ca58f742SDaniel Fojt static int compatSigno;
102ca58f742SDaniel Fojt
103ca58f742SDaniel Fojt /*
104a34d5fb1SAntonio Huete Jimenez * CompatDeleteTarget -- delete the file of a failed, interrupted, or
105a34d5fb1SAntonio Huete Jimenez * otherwise duffed target if not inhibited by .PRECIOUS.
106ca58f742SDaniel Fojt */
107ca58f742SDaniel Fojt static void
CompatDeleteTarget(GNode * gn)108ca58f742SDaniel Fojt CompatDeleteTarget(GNode *gn)
109ca58f742SDaniel Fojt {
110*6eef5f0cSAntonio Huete Jimenez if (gn != NULL && !GNode_IsPrecious(gn)) {
111a34d5fb1SAntonio Huete Jimenez const char *file = GNode_VarTarget(gn);
112ca58f742SDaniel Fojt
113*6eef5f0cSAntonio Huete Jimenez if (!opts.noExecute && unlink_file(file)) {
114ca58f742SDaniel Fojt Error("*** %s removed", file);
115ca58f742SDaniel Fojt }
116ca58f742SDaniel Fojt }
117ca58f742SDaniel Fojt }
11801e196c8SJohn Marino
119a34d5fb1SAntonio Huete Jimenez /*
120a34d5fb1SAntonio Huete Jimenez * Interrupt the creation of the current target and remove it if it ain't
121a34d5fb1SAntonio Huete Jimenez * precious. Then exit.
12201e196c8SJohn Marino *
123a34d5fb1SAntonio Huete Jimenez * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED.
12401e196c8SJohn Marino *
125ca58f742SDaniel Fojt * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've
126ca58f742SDaniel Fojt * left the logic alone for now. - dholland 20160826
12701e196c8SJohn Marino */
12801e196c8SJohn Marino static void
CompatInterrupt(int signo)12901e196c8SJohn Marino CompatInterrupt(int signo)
13001e196c8SJohn Marino {
131ca58f742SDaniel Fojt CompatDeleteTarget(curTarg);
132ca58f742SDaniel Fojt
133*6eef5f0cSAntonio Huete Jimenez if (curTarg != NULL && !GNode_IsPrecious(curTarg)) {
13401e196c8SJohn Marino /*
13501e196c8SJohn Marino * Run .INTERRUPT only if hit with interrupt signal
13601e196c8SJohn Marino */
13701e196c8SJohn Marino if (signo == SIGINT) {
138a34d5fb1SAntonio Huete Jimenez GNode *gn = Targ_FindNode(".INTERRUPT");
13901e196c8SJohn Marino if (gn != NULL) {
14001e196c8SJohn Marino Compat_Make(gn, gn);
14101e196c8SJohn Marino }
14201e196c8SJohn Marino }
14301e196c8SJohn Marino }
144a34d5fb1SAntonio Huete Jimenez
14501e196c8SJohn Marino if (signo == SIGQUIT)
14601e196c8SJohn Marino _exit(signo);
147a34d5fb1SAntonio Huete Jimenez
148ca58f742SDaniel Fojt /*
149a34d5fb1SAntonio Huete Jimenez * If there is a child running, pass the signal on.
150a34d5fb1SAntonio Huete Jimenez * We will exist after it has exited.
151ca58f742SDaniel Fojt */
152ca58f742SDaniel Fojt compatSigno = signo;
153ca58f742SDaniel Fojt if (compatChild > 0) {
154ca58f742SDaniel Fojt KILLPG(compatChild, signo);
155ca58f742SDaniel Fojt } else {
15601e196c8SJohn Marino bmake_signal(signo, SIG_DFL);
15701e196c8SJohn Marino kill(myPid, signo);
15801e196c8SJohn Marino }
159ca58f742SDaniel Fojt }
160a34d5fb1SAntonio Huete Jimenez
161a34d5fb1SAntonio Huete Jimenez static void
DebugFailedTarget(const char * cmd,const GNode * gn)162*6eef5f0cSAntonio Huete Jimenez DebugFailedTarget(const char *cmd, const GNode *gn)
16301e196c8SJohn Marino {
164a34d5fb1SAntonio Huete Jimenez const char *p = cmd;
165a34d5fb1SAntonio Huete Jimenez debug_printf("\n*** Failed target: %s\n*** Failed command: ",
166a34d5fb1SAntonio Huete Jimenez gn->name);
16701e196c8SJohn Marino
168*6eef5f0cSAntonio Huete Jimenez /*
169*6eef5f0cSAntonio Huete Jimenez * Replace runs of whitespace with a single space, to reduce the
170*6eef5f0cSAntonio Huete Jimenez * amount of whitespace for multi-line command lines.
171*6eef5f0cSAntonio Huete Jimenez */
172a34d5fb1SAntonio Huete Jimenez while (*p != '\0') {
173a34d5fb1SAntonio Huete Jimenez if (ch_isspace(*p)) {
174a34d5fb1SAntonio Huete Jimenez debug_printf(" ");
175a34d5fb1SAntonio Huete Jimenez cpp_skip_whitespace(&p);
176a34d5fb1SAntonio Huete Jimenez } else {
177a34d5fb1SAntonio Huete Jimenez debug_printf("%c", *p);
178a34d5fb1SAntonio Huete Jimenez p++;
17901e196c8SJohn Marino }
18001e196c8SJohn Marino }
181a34d5fb1SAntonio Huete Jimenez debug_printf("\n");
18201e196c8SJohn Marino }
18301e196c8SJohn Marino
184*6eef5f0cSAntonio Huete Jimenez static bool
UseShell(const char * cmd MAKE_ATTR_UNUSED)185a34d5fb1SAntonio Huete Jimenez UseShell(const char *cmd MAKE_ATTR_UNUSED)
186a34d5fb1SAntonio Huete Jimenez {
187*6eef5f0cSAntonio Huete Jimenez #if defined(FORCE_USE_SHELL) || !defined(MAKE_NATIVE)
18801e196c8SJohn Marino /*
18901e196c8SJohn Marino * In a non-native build, the host environment might be weird enough
19001e196c8SJohn Marino * that it's necessary to go through a shell to get the correct
19101e196c8SJohn Marino * behaviour. Or perhaps the shell has been replaced with something
19201e196c8SJohn Marino * that does extra logging, and that should not be bypassed.
19301e196c8SJohn Marino */
194*6eef5f0cSAntonio Huete Jimenez return true;
19501e196c8SJohn Marino #else
19601e196c8SJohn Marino /*
19701e196c8SJohn Marino * Search for meta characters in the command. If there are no meta
19801e196c8SJohn Marino * characters, there's no need to execute a shell to execute the
19901e196c8SJohn Marino * command.
200f445c897SJohn Marino *
201f445c897SJohn Marino * Additionally variable assignments and empty commands
202f445c897SJohn Marino * go to the shell. Therefore treat '=' and ':' like shell
203f445c897SJohn Marino * meta characters as documented in make(1).
20401e196c8SJohn Marino */
205f445c897SJohn Marino
206a34d5fb1SAntonio Huete Jimenez return needshell(cmd);
20701e196c8SJohn Marino #endif
208a34d5fb1SAntonio Huete Jimenez }
20901e196c8SJohn Marino
21001e196c8SJohn Marino /*
211a34d5fb1SAntonio Huete Jimenez * Execute the next command for a target. If the command returns an error,
212a34d5fb1SAntonio Huete Jimenez * the node's made field is set to ERROR and creation stops.
213a34d5fb1SAntonio Huete Jimenez *
214a34d5fb1SAntonio Huete Jimenez * Input:
215a34d5fb1SAntonio Huete Jimenez * cmdp Command to execute
216a34d5fb1SAntonio Huete Jimenez * gn Node from which the command came
217a34d5fb1SAntonio Huete Jimenez * ln List node that contains the command
218a34d5fb1SAntonio Huete Jimenez *
219a34d5fb1SAntonio Huete Jimenez * Results:
220*6eef5f0cSAntonio Huete Jimenez * true if the command succeeded.
22101e196c8SJohn Marino */
222*6eef5f0cSAntonio Huete Jimenez bool
Compat_RunCommand(const char * cmdp,GNode * gn,StringListNode * ln)223a34d5fb1SAntonio Huete Jimenez Compat_RunCommand(const char *cmdp, GNode *gn, StringListNode *ln)
224a34d5fb1SAntonio Huete Jimenez {
225a34d5fb1SAntonio Huete Jimenez char *cmdStart; /* Start of expanded command */
226a34d5fb1SAntonio Huete Jimenez char *bp;
227*6eef5f0cSAntonio Huete Jimenez bool silent; /* Don't print command */
228*6eef5f0cSAntonio Huete Jimenez bool doIt; /* Execute even if -n */
229*6eef5f0cSAntonio Huete Jimenez volatile bool errCheck; /* Check errors */
230a34d5fb1SAntonio Huete Jimenez WAIT_T reason; /* Reason for child's death */
231a34d5fb1SAntonio Huete Jimenez WAIT_T status; /* Description of child's death */
232a34d5fb1SAntonio Huete Jimenez pid_t cpid; /* Child actually found */
233a34d5fb1SAntonio Huete Jimenez pid_t retstat; /* Result of wait */
234a34d5fb1SAntonio Huete Jimenez const char **volatile av; /* Argument vector for thing to exec */
235a34d5fb1SAntonio Huete Jimenez char **volatile mav; /* Copy of the argument vector for freeing */
236*6eef5f0cSAntonio Huete Jimenez bool useShell; /* True if command should be executed using a
237*6eef5f0cSAntonio Huete Jimenez * shell */
238a34d5fb1SAntonio Huete Jimenez const char *volatile cmd = cmdp;
239a34d5fb1SAntonio Huete Jimenez
240*6eef5f0cSAntonio Huete Jimenez silent = (gn->type & OP_SILENT) != OP_NONE;
241a34d5fb1SAntonio Huete Jimenez errCheck = !(gn->type & OP_IGNORE);
242*6eef5f0cSAntonio Huete Jimenez doIt = false;
243a34d5fb1SAntonio Huete Jimenez
244a34d5fb1SAntonio Huete Jimenez (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
245a34d5fb1SAntonio Huete Jimenez /* TODO: handle errors */
246a34d5fb1SAntonio Huete Jimenez
247a34d5fb1SAntonio Huete Jimenez if (cmdStart[0] == '\0') {
248a34d5fb1SAntonio Huete Jimenez free(cmdStart);
249*6eef5f0cSAntonio Huete Jimenez return true;
250a34d5fb1SAntonio Huete Jimenez }
251a34d5fb1SAntonio Huete Jimenez cmd = cmdStart;
252a34d5fb1SAntonio Huete Jimenez LstNode_Set(ln, cmdStart);
253a34d5fb1SAntonio Huete Jimenez
254a34d5fb1SAntonio Huete Jimenez if (gn->type & OP_SAVE_CMDS) {
255a34d5fb1SAntonio Huete Jimenez GNode *endNode = Targ_GetEndNode();
256a34d5fb1SAntonio Huete Jimenez if (gn != endNode) {
257a34d5fb1SAntonio Huete Jimenez /*
258a34d5fb1SAntonio Huete Jimenez * Append the expanded command, to prevent the
259a34d5fb1SAntonio Huete Jimenez * local variables from being interpreted in the
260a34d5fb1SAntonio Huete Jimenez * scope of the .END node.
261a34d5fb1SAntonio Huete Jimenez *
262a34d5fb1SAntonio Huete Jimenez * A probably unintended side effect of this is that
263a34d5fb1SAntonio Huete Jimenez * the expanded command will be expanded again in the
264a34d5fb1SAntonio Huete Jimenez * .END node. Therefore, a literal '$' in these
265a34d5fb1SAntonio Huete Jimenez * commands must be written as '$$$$' instead of the
266a34d5fb1SAntonio Huete Jimenez * usual '$$'.
267a34d5fb1SAntonio Huete Jimenez */
268a34d5fb1SAntonio Huete Jimenez Lst_Append(&endNode->commands, cmdStart);
269*6eef5f0cSAntonio Huete Jimenez return true;
270a34d5fb1SAntonio Huete Jimenez }
271a34d5fb1SAntonio Huete Jimenez }
272a34d5fb1SAntonio Huete Jimenez if (strcmp(cmdStart, "...") == 0) {
273a34d5fb1SAntonio Huete Jimenez gn->type |= OP_SAVE_CMDS;
274*6eef5f0cSAntonio Huete Jimenez return true;
275a34d5fb1SAntonio Huete Jimenez }
276a34d5fb1SAntonio Huete Jimenez
277a34d5fb1SAntonio Huete Jimenez for (;;) {
278a34d5fb1SAntonio Huete Jimenez if (*cmd == '@')
279a34d5fb1SAntonio Huete Jimenez silent = !DEBUG(LOUD);
280a34d5fb1SAntonio Huete Jimenez else if (*cmd == '-')
281*6eef5f0cSAntonio Huete Jimenez errCheck = false;
282a34d5fb1SAntonio Huete Jimenez else if (*cmd == '+') {
283*6eef5f0cSAntonio Huete Jimenez doIt = true;
284a34d5fb1SAntonio Huete Jimenez if (shellName == NULL) /* we came here from jobs */
285a34d5fb1SAntonio Huete Jimenez Shell_Init();
286a34d5fb1SAntonio Huete Jimenez } else
287a34d5fb1SAntonio Huete Jimenez break;
288a34d5fb1SAntonio Huete Jimenez cmd++;
289a34d5fb1SAntonio Huete Jimenez }
290a34d5fb1SAntonio Huete Jimenez
291a34d5fb1SAntonio Huete Jimenez while (ch_isspace(*cmd))
292a34d5fb1SAntonio Huete Jimenez cmd++;
293a34d5fb1SAntonio Huete Jimenez
294a34d5fb1SAntonio Huete Jimenez /*
295a34d5fb1SAntonio Huete Jimenez * If we did not end up with a command, just skip it.
296a34d5fb1SAntonio Huete Jimenez */
297a34d5fb1SAntonio Huete Jimenez if (cmd[0] == '\0')
298*6eef5f0cSAntonio Huete Jimenez return true;
299a34d5fb1SAntonio Huete Jimenez
300a34d5fb1SAntonio Huete Jimenez useShell = UseShell(cmd);
301a34d5fb1SAntonio Huete Jimenez /*
302a34d5fb1SAntonio Huete Jimenez * Print the command before echoing if we're not supposed to be quiet
303a34d5fb1SAntonio Huete Jimenez * for this one. We also print the command if -n given.
304a34d5fb1SAntonio Huete Jimenez */
305a34d5fb1SAntonio Huete Jimenez if (!silent || !GNode_ShouldExecute(gn)) {
30601e196c8SJohn Marino printf("%s\n", cmd);
30701e196c8SJohn Marino fflush(stdout);
30801e196c8SJohn Marino }
30901e196c8SJohn Marino
31001e196c8SJohn Marino /*
31101e196c8SJohn Marino * If we're not supposed to execute any commands, this is as far as
31201e196c8SJohn Marino * we go...
31301e196c8SJohn Marino */
314a34d5fb1SAntonio Huete Jimenez if (!doIt && !GNode_ShouldExecute(gn))
315*6eef5f0cSAntonio Huete Jimenez return true;
31601e196c8SJohn Marino
317a34d5fb1SAntonio Huete Jimenez DEBUG1(JOB, "Execute: '%s'\n", cmd);
318a34d5fb1SAntonio Huete Jimenez
31901e196c8SJohn Marino if (useShell) {
32001e196c8SJohn Marino /*
32101e196c8SJohn Marino * We need to pass the command off to the shell, typically
32201e196c8SJohn Marino * because the command contains a "meta" character.
32301e196c8SJohn Marino */
3245f1e34d9SAlexandre Perrin static const char *shargv[5];
32501e196c8SJohn Marino
326a34d5fb1SAntonio Huete Jimenez /* The following work for any of the builtin shell specs. */
327a34d5fb1SAntonio Huete Jimenez int shargc = 0;
3285f1e34d9SAlexandre Perrin shargv[shargc++] = shellPath;
329a34d5fb1SAntonio Huete Jimenez if (errCheck && shellErrFlag != NULL)
3305f1e34d9SAlexandre Perrin shargv[shargc++] = shellErrFlag;
331a34d5fb1SAntonio Huete Jimenez shargv[shargc++] = DEBUG(SHELL) ? "-xc" : "-c";
3325f1e34d9SAlexandre Perrin shargv[shargc++] = cmd;
333a34d5fb1SAntonio Huete Jimenez shargv[shargc] = NULL;
33401e196c8SJohn Marino av = shargv;
33501e196c8SJohn Marino bp = NULL;
33601e196c8SJohn Marino mav = NULL;
33701e196c8SJohn Marino } else {
33801e196c8SJohn Marino /*
339a34d5fb1SAntonio Huete Jimenez * No meta-characters, so no need to exec a shell. Break the
340a34d5fb1SAntonio Huete Jimenez * command into words to form an argument vector we can
341a34d5fb1SAntonio Huete Jimenez * execute.
34201e196c8SJohn Marino */
343*6eef5f0cSAntonio Huete Jimenez Words words = Str_Words(cmd, false);
344a34d5fb1SAntonio Huete Jimenez mav = words.words;
345a34d5fb1SAntonio Huete Jimenez bp = words.freeIt;
34601e196c8SJohn Marino av = (void *)mav;
34701e196c8SJohn Marino }
34801e196c8SJohn Marino
34901e196c8SJohn Marino #ifdef USE_META
350*6eef5f0cSAntonio Huete Jimenez if (useMeta)
35101e196c8SJohn Marino meta_compat_start();
35201e196c8SJohn Marino #endif
35301e196c8SJohn Marino
354a34d5fb1SAntonio Huete Jimenez Var_ReexportVars();
355a34d5fb1SAntonio Huete Jimenez
356a34d5fb1SAntonio Huete Jimenez compatChild = cpid = vfork();
357*6eef5f0cSAntonio Huete Jimenez if (cpid < 0)
35801e196c8SJohn Marino Fatal("Could not fork");
359*6eef5f0cSAntonio Huete Jimenez
36001e196c8SJohn Marino if (cpid == 0) {
36101e196c8SJohn Marino #ifdef USE_META
362*6eef5f0cSAntonio Huete Jimenez if (useMeta)
36301e196c8SJohn Marino meta_compat_child();
36401e196c8SJohn Marino #endif
36501e196c8SJohn Marino (void)execvp(av[0], (char *const *)UNCONST(av));
366a34d5fb1SAntonio Huete Jimenez execDie("exec", av[0]);
36701e196c8SJohn Marino }
368f445c897SJohn Marino
36901e196c8SJohn Marino free(mav);
37001e196c8SJohn Marino free(bp);
371f445c897SJohn Marino
372a34d5fb1SAntonio Huete Jimenez /* XXX: Memory management looks suspicious here. */
373a34d5fb1SAntonio Huete Jimenez /* XXX: Setting a list item to NULL is unexpected. */
374a34d5fb1SAntonio Huete Jimenez LstNode_SetNull(ln);
37501e196c8SJohn Marino
37601e196c8SJohn Marino #ifdef USE_META
377*6eef5f0cSAntonio Huete Jimenez if (useMeta)
378ca58f742SDaniel Fojt meta_compat_parent(cpid);
37901e196c8SJohn Marino #endif
38001e196c8SJohn Marino
38101e196c8SJohn Marino /*
38201e196c8SJohn Marino * The child is off and running. Now all we can do is wait...
38301e196c8SJohn Marino */
38401e196c8SJohn Marino while ((retstat = wait(&reason)) != cpid) {
38501e196c8SJohn Marino if (retstat > 0)
386*6eef5f0cSAntonio Huete Jimenez JobReapChild(retstat, reason, false); /* not ours? */
38701e196c8SJohn Marino if (retstat == -1 && errno != EINTR) {
38801e196c8SJohn Marino break;
38901e196c8SJohn Marino }
39001e196c8SJohn Marino }
39101e196c8SJohn Marino
392a34d5fb1SAntonio Huete Jimenez if (retstat < 0)
393a34d5fb1SAntonio Huete Jimenez Fatal("error in wait: %d: %s", retstat, strerror(errno));
394a34d5fb1SAntonio Huete Jimenez
39501e196c8SJohn Marino if (WIFSTOPPED(reason)) {
39601e196c8SJohn Marino status = WSTOPSIG(reason); /* stopped */
39701e196c8SJohn Marino } else if (WIFEXITED(reason)) {
39801e196c8SJohn Marino status = WEXITSTATUS(reason); /* exited */
39901e196c8SJohn Marino #if defined(USE_META) && defined(USE_FILEMON_ONCE)
400*6eef5f0cSAntonio Huete Jimenez if (useMeta)
40101e196c8SJohn Marino meta_cmd_finish(NULL);
40201e196c8SJohn Marino #endif
40301e196c8SJohn Marino if (status != 0) {
404a34d5fb1SAntonio Huete Jimenez if (DEBUG(ERROR))
405a34d5fb1SAntonio Huete Jimenez DebugFailedTarget(cmd, gn);
40601e196c8SJohn Marino printf("*** Error code %d", status);
40701e196c8SJohn Marino }
40801e196c8SJohn Marino } else {
40901e196c8SJohn Marino status = WTERMSIG(reason); /* signaled */
41001e196c8SJohn Marino printf("*** Signal %d", status);
41101e196c8SJohn Marino }
41201e196c8SJohn Marino
41301e196c8SJohn Marino
414a34d5fb1SAntonio Huete Jimenez if (!WIFEXITED(reason) || status != 0) {
41501e196c8SJohn Marino if (errCheck) {
41601e196c8SJohn Marino #ifdef USE_META
417*6eef5f0cSAntonio Huete Jimenez if (useMeta)
418*6eef5f0cSAntonio Huete Jimenez meta_job_error(NULL, gn, false, status);
41901e196c8SJohn Marino #endif
42001e196c8SJohn Marino gn->made = ERROR;
421a34d5fb1SAntonio Huete Jimenez if (opts.keepgoing) {
42201e196c8SJohn Marino /*
423a34d5fb1SAntonio Huete Jimenez * Abort the current target,
424a34d5fb1SAntonio Huete Jimenez * but let others continue.
42501e196c8SJohn Marino */
42601e196c8SJohn Marino printf(" (continuing)\n");
427ca58f742SDaniel Fojt } else {
428ca58f742SDaniel Fojt printf("\n");
429ca58f742SDaniel Fojt }
430a34d5fb1SAntonio Huete Jimenez if (deleteOnError)
431ca58f742SDaniel Fojt CompatDeleteTarget(gn);
43201e196c8SJohn Marino } else {
43301e196c8SJohn Marino /*
43401e196c8SJohn Marino * Continue executing commands for this target.
43501e196c8SJohn Marino * If we return 0, this will happen...
43601e196c8SJohn Marino */
43701e196c8SJohn Marino printf(" (ignored)\n");
43801e196c8SJohn Marino status = 0;
43901e196c8SJohn Marino }
44001e196c8SJohn Marino }
441a34d5fb1SAntonio Huete Jimenez
44201e196c8SJohn Marino free(cmdStart);
443ca58f742SDaniel Fojt compatChild = 0;
444a34d5fb1SAntonio Huete Jimenez if (compatSigno != 0) {
445ca58f742SDaniel Fojt bmake_signal(compatSigno, SIG_DFL);
446ca58f742SDaniel Fojt kill(myPid, compatSigno);
447ca58f742SDaniel Fojt }
44801e196c8SJohn Marino
449*6eef5f0cSAntonio Huete Jimenez return status == 0;
45001e196c8SJohn Marino }
45101e196c8SJohn Marino
452a34d5fb1SAntonio Huete Jimenez static void
RunCommands(GNode * gn)453a34d5fb1SAntonio Huete Jimenez RunCommands(GNode *gn)
454a34d5fb1SAntonio Huete Jimenez {
455a34d5fb1SAntonio Huete Jimenez StringListNode *ln;
456a34d5fb1SAntonio Huete Jimenez
457a34d5fb1SAntonio Huete Jimenez for (ln = gn->commands.first; ln != NULL; ln = ln->next) {
458a34d5fb1SAntonio Huete Jimenez const char *cmd = ln->datum;
459*6eef5f0cSAntonio Huete Jimenez if (!Compat_RunCommand(cmd, gn, ln))
460a34d5fb1SAntonio Huete Jimenez break;
461a34d5fb1SAntonio Huete Jimenez }
462a34d5fb1SAntonio Huete Jimenez }
463a34d5fb1SAntonio Huete Jimenez
464a34d5fb1SAntonio Huete Jimenez static void
MakeInRandomOrder(GNode ** gnodes,GNode ** end,GNode * pgn)465*6eef5f0cSAntonio Huete Jimenez MakeInRandomOrder(GNode **gnodes, GNode **end, GNode *pgn)
466*6eef5f0cSAntonio Huete Jimenez {
467*6eef5f0cSAntonio Huete Jimenez GNode **it;
468*6eef5f0cSAntonio Huete Jimenez size_t r;
469*6eef5f0cSAntonio Huete Jimenez
470*6eef5f0cSAntonio Huete Jimenez for (r = (size_t)(end - gnodes); r >= 2; r--) {
471*6eef5f0cSAntonio Huete Jimenez /* Biased, but irrelevant in practice. */
472*6eef5f0cSAntonio Huete Jimenez size_t i = (size_t)random() % r;
473*6eef5f0cSAntonio Huete Jimenez GNode *t = gnodes[r - 1];
474*6eef5f0cSAntonio Huete Jimenez gnodes[r - 1] = gnodes[i];
475*6eef5f0cSAntonio Huete Jimenez gnodes[i] = t;
476*6eef5f0cSAntonio Huete Jimenez }
477*6eef5f0cSAntonio Huete Jimenez
478*6eef5f0cSAntonio Huete Jimenez for (it = gnodes; it != end; it++)
479*6eef5f0cSAntonio Huete Jimenez Compat_Make(*it, pgn);
480*6eef5f0cSAntonio Huete Jimenez }
481*6eef5f0cSAntonio Huete Jimenez
482*6eef5f0cSAntonio Huete Jimenez static void
MakeWaitGroupsInRandomOrder(GNodeList * gnodes,GNode * pgn)483*6eef5f0cSAntonio Huete Jimenez MakeWaitGroupsInRandomOrder(GNodeList *gnodes, GNode *pgn)
484*6eef5f0cSAntonio Huete Jimenez {
485*6eef5f0cSAntonio Huete Jimenez Vector vec;
486*6eef5f0cSAntonio Huete Jimenez GNodeListNode *ln;
487*6eef5f0cSAntonio Huete Jimenez GNode **nodes;
488*6eef5f0cSAntonio Huete Jimenez size_t i, n, start;
489*6eef5f0cSAntonio Huete Jimenez
490*6eef5f0cSAntonio Huete Jimenez Vector_Init(&vec, sizeof(GNode *));
491*6eef5f0cSAntonio Huete Jimenez for (ln = gnodes->first; ln != NULL; ln = ln->next)
492*6eef5f0cSAntonio Huete Jimenez *(GNode **)Vector_Push(&vec) = ln->datum;
493*6eef5f0cSAntonio Huete Jimenez nodes = vec.items;
494*6eef5f0cSAntonio Huete Jimenez n = vec.len;
495*6eef5f0cSAntonio Huete Jimenez
496*6eef5f0cSAntonio Huete Jimenez start = 0;
497*6eef5f0cSAntonio Huete Jimenez for (i = 0; i < n; i++) {
498*6eef5f0cSAntonio Huete Jimenez if (nodes[i]->type & OP_WAIT) {
499*6eef5f0cSAntonio Huete Jimenez MakeInRandomOrder(nodes + start, nodes + i, pgn);
500*6eef5f0cSAntonio Huete Jimenez Compat_Make(nodes[i], pgn);
501*6eef5f0cSAntonio Huete Jimenez start = i + 1;
502*6eef5f0cSAntonio Huete Jimenez }
503*6eef5f0cSAntonio Huete Jimenez }
504*6eef5f0cSAntonio Huete Jimenez MakeInRandomOrder(nodes + start, nodes + i, pgn);
505*6eef5f0cSAntonio Huete Jimenez
506*6eef5f0cSAntonio Huete Jimenez Vector_Done(&vec);
507*6eef5f0cSAntonio Huete Jimenez }
508*6eef5f0cSAntonio Huete Jimenez
509*6eef5f0cSAntonio Huete Jimenez static void
MakeNodes(GNodeList * gnodes,GNode * pgn)510a34d5fb1SAntonio Huete Jimenez MakeNodes(GNodeList *gnodes, GNode *pgn)
511a34d5fb1SAntonio Huete Jimenez {
512a34d5fb1SAntonio Huete Jimenez GNodeListNode *ln;
513a34d5fb1SAntonio Huete Jimenez
514*6eef5f0cSAntonio Huete Jimenez if (Lst_IsEmpty(gnodes))
515*6eef5f0cSAntonio Huete Jimenez return;
516*6eef5f0cSAntonio Huete Jimenez if (opts.randomizeTargets) {
517*6eef5f0cSAntonio Huete Jimenez MakeWaitGroupsInRandomOrder(gnodes, pgn);
518*6eef5f0cSAntonio Huete Jimenez return;
519*6eef5f0cSAntonio Huete Jimenez }
520*6eef5f0cSAntonio Huete Jimenez
521a34d5fb1SAntonio Huete Jimenez for (ln = gnodes->first; ln != NULL; ln = ln->next) {
522*6eef5f0cSAntonio Huete Jimenez GNode *cgn = ln->datum;
523*6eef5f0cSAntonio Huete Jimenez Compat_Make(cgn, pgn);
524a34d5fb1SAntonio Huete Jimenez }
525a34d5fb1SAntonio Huete Jimenez }
526a34d5fb1SAntonio Huete Jimenez
527*6eef5f0cSAntonio Huete Jimenez static bool
MakeUnmade(GNode * gn,GNode * pgn)528a34d5fb1SAntonio Huete Jimenez MakeUnmade(GNode *gn, GNode *pgn)
529a34d5fb1SAntonio Huete Jimenez {
530a34d5fb1SAntonio Huete Jimenez
531a34d5fb1SAntonio Huete Jimenez assert(gn->made == UNMADE);
532a34d5fb1SAntonio Huete Jimenez
53301e196c8SJohn Marino /*
53401e196c8SJohn Marino * First mark ourselves to be made, then apply whatever transformations
53501e196c8SJohn Marino * the suffix module thinks are necessary. Once that's done, we can
53601e196c8SJohn Marino * descend and make all our children. If any of them has an error
537*6eef5f0cSAntonio Huete Jimenez * but the -k flag was given, our 'make' field will be set to false
538a34d5fb1SAntonio Huete Jimenez * again. This is our signal to not attempt to do anything but abort
539a34d5fb1SAntonio Huete Jimenez * our parent as well.
54001e196c8SJohn Marino */
541*6eef5f0cSAntonio Huete Jimenez gn->flags.remake = true;
54201e196c8SJohn Marino gn->made = BEINGMADE;
543a34d5fb1SAntonio Huete Jimenez
544a34d5fb1SAntonio Huete Jimenez if (!(gn->type & OP_MADE))
54501e196c8SJohn Marino Suff_FindDeps(gn);
546a34d5fb1SAntonio Huete Jimenez
547a34d5fb1SAntonio Huete Jimenez MakeNodes(&gn->children, gn);
548a34d5fb1SAntonio Huete Jimenez
549*6eef5f0cSAntonio Huete Jimenez if (!gn->flags.remake) {
55001e196c8SJohn Marino gn->made = ABORTED;
551*6eef5f0cSAntonio Huete Jimenez pgn->flags.remake = false;
552*6eef5f0cSAntonio Huete Jimenez return false;
55301e196c8SJohn Marino }
55401e196c8SJohn Marino
555a34d5fb1SAntonio Huete Jimenez if (Lst_FindDatum(&gn->implicitParents, pgn) != NULL)
556a34d5fb1SAntonio Huete Jimenez Var_Set(pgn, IMPSRC, GNode_VarTarget(gn));
55701e196c8SJohn Marino
55801e196c8SJohn Marino /*
559a34d5fb1SAntonio Huete Jimenez * All the children were made ok. Now youngestChild->mtime contains the
56001e196c8SJohn Marino * modification time of the newest child, we need to find out if we
56101e196c8SJohn Marino * exist and when we were modified last. The criteria for datedness
562a34d5fb1SAntonio Huete Jimenez * are defined by GNode_IsOODate.
56301e196c8SJohn Marino */
564a34d5fb1SAntonio Huete Jimenez DEBUG1(MAKE, "Examining %s...", gn->name);
565a34d5fb1SAntonio Huete Jimenez if (!GNode_IsOODate(gn)) {
56601e196c8SJohn Marino gn->made = UPTODATE;
567a34d5fb1SAntonio Huete Jimenez DEBUG0(MAKE, "up-to-date.\n");
568*6eef5f0cSAntonio Huete Jimenez return false;
56901e196c8SJohn Marino }
57001e196c8SJohn Marino
57101e196c8SJohn Marino /*
57201e196c8SJohn Marino * If the user is just seeing if something is out-of-date, exit now
57301e196c8SJohn Marino * to tell him/her "yes".
57401e196c8SJohn Marino */
575a34d5fb1SAntonio Huete Jimenez DEBUG0(MAKE, "out-of-date.\n");
576*6eef5f0cSAntonio Huete Jimenez if (opts.query && gn != Targ_GetEndNode())
57701e196c8SJohn Marino exit(1);
57801e196c8SJohn Marino
57901e196c8SJohn Marino /*
580a34d5fb1SAntonio Huete Jimenez * We need to be re-made.
581a34d5fb1SAntonio Huete Jimenez * Ensure that $? (.OODATE) and $> (.ALLSRC) are both set.
58201e196c8SJohn Marino */
583*6eef5f0cSAntonio Huete Jimenez GNode_SetLocalVars(gn);
58401e196c8SJohn Marino
58501e196c8SJohn Marino /*
58601e196c8SJohn Marino * Alter our type to tell if errors should be ignored or things
587a34d5fb1SAntonio Huete Jimenez * should not be printed so Compat_RunCommand knows what to do.
58801e196c8SJohn Marino */
589a34d5fb1SAntonio Huete Jimenez if (opts.ignoreErrors)
59001e196c8SJohn Marino gn->type |= OP_IGNORE;
591*6eef5f0cSAntonio Huete Jimenez if (opts.silent)
59201e196c8SJohn Marino gn->type |= OP_SILENT;
59301e196c8SJohn Marino
59401e196c8SJohn Marino if (Job_CheckCommands(gn, Fatal)) {
59501e196c8SJohn Marino /*
596a34d5fb1SAntonio Huete Jimenez * Our commands are ok, but we still have to worry about
597a34d5fb1SAntonio Huete Jimenez * the -t flag.
59801e196c8SJohn Marino */
599*6eef5f0cSAntonio Huete Jimenez if (!opts.touch || (gn->type & OP_MAKE)) {
60001e196c8SJohn Marino curTarg = gn;
60101e196c8SJohn Marino #ifdef USE_META
602*6eef5f0cSAntonio Huete Jimenez if (useMeta && GNode_ShouldExecute(gn))
60301e196c8SJohn Marino meta_job_start(NULL, gn);
60401e196c8SJohn Marino #endif
605a34d5fb1SAntonio Huete Jimenez RunCommands(gn);
60601e196c8SJohn Marino curTarg = NULL;
60701e196c8SJohn Marino } else {
608*6eef5f0cSAntonio Huete Jimenez Job_Touch(gn, (gn->type & OP_SILENT) != OP_NONE);
60901e196c8SJohn Marino }
61001e196c8SJohn Marino } else {
61101e196c8SJohn Marino gn->made = ERROR;
61201e196c8SJohn Marino }
61301e196c8SJohn Marino #ifdef USE_META
614a34d5fb1SAntonio Huete Jimenez if (useMeta && GNode_ShouldExecute(gn)) {
615f445c897SJohn Marino if (meta_job_finish(NULL) != 0)
616f445c897SJohn Marino gn->made = ERROR;
61701e196c8SJohn Marino }
61801e196c8SJohn Marino #endif
61901e196c8SJohn Marino
62001e196c8SJohn Marino if (gn->made != ERROR) {
62101e196c8SJohn Marino /*
62201e196c8SJohn Marino * If the node was made successfully, mark it so, update
623a34d5fb1SAntonio Huete Jimenez * its modification time and timestamp all its parents.
62401e196c8SJohn Marino * This is to keep its state from affecting that of its parent.
62501e196c8SJohn Marino */
62601e196c8SJohn Marino gn->made = MADE;
627a34d5fb1SAntonio Huete Jimenez if (Make_Recheck(gn) == 0)
628*6eef5f0cSAntonio Huete Jimenez pgn->flags.force = true;
62901e196c8SJohn Marino if (!(gn->type & OP_EXEC)) {
630*6eef5f0cSAntonio Huete Jimenez pgn->flags.childMade = true;
631a34d5fb1SAntonio Huete Jimenez GNode_UpdateYoungestChild(pgn, gn);
63201e196c8SJohn Marino }
633a34d5fb1SAntonio Huete Jimenez } else if (opts.keepgoing) {
634*6eef5f0cSAntonio Huete Jimenez pgn->flags.remake = false;
63501e196c8SJohn Marino } else {
636*6eef5f0cSAntonio Huete Jimenez PrintOnError(gn, "\nStop.\n");
63701e196c8SJohn Marino exit(1);
63801e196c8SJohn Marino }
639*6eef5f0cSAntonio Huete Jimenez return true;
64001e196c8SJohn Marino }
641a34d5fb1SAntonio Huete Jimenez
642a34d5fb1SAntonio Huete Jimenez static void
MakeOther(GNode * gn,GNode * pgn)643a34d5fb1SAntonio Huete Jimenez MakeOther(GNode *gn, GNode *pgn)
644a34d5fb1SAntonio Huete Jimenez {
645a34d5fb1SAntonio Huete Jimenez
646a34d5fb1SAntonio Huete Jimenez if (Lst_FindDatum(&gn->implicitParents, pgn) != NULL) {
647a34d5fb1SAntonio Huete Jimenez const char *target = GNode_VarTarget(gn);
648a34d5fb1SAntonio Huete Jimenez Var_Set(pgn, IMPSRC, target != NULL ? target : "");
649a34d5fb1SAntonio Huete Jimenez }
650a34d5fb1SAntonio Huete Jimenez
65101e196c8SJohn Marino switch (gn->made) {
65201e196c8SJohn Marino case BEINGMADE:
65301e196c8SJohn Marino Error("Graph cycles through %s", gn->name);
65401e196c8SJohn Marino gn->made = ERROR;
655*6eef5f0cSAntonio Huete Jimenez pgn->flags.remake = false;
65601e196c8SJohn Marino break;
65701e196c8SJohn Marino case MADE:
658a34d5fb1SAntonio Huete Jimenez if (!(gn->type & OP_EXEC)) {
659*6eef5f0cSAntonio Huete Jimenez pgn->flags.childMade = true;
660a34d5fb1SAntonio Huete Jimenez GNode_UpdateYoungestChild(pgn, gn);
66101e196c8SJohn Marino }
66201e196c8SJohn Marino break;
66301e196c8SJohn Marino case UPTODATE:
664a34d5fb1SAntonio Huete Jimenez if (!(gn->type & OP_EXEC))
665a34d5fb1SAntonio Huete Jimenez GNode_UpdateYoungestChild(pgn, gn);
66601e196c8SJohn Marino break;
66701e196c8SJohn Marino default:
66801e196c8SJohn Marino break;
66901e196c8SJohn Marino }
67001e196c8SJohn Marino }
67101e196c8SJohn Marino
672a34d5fb1SAntonio Huete Jimenez /*
673a34d5fb1SAntonio Huete Jimenez * Make a target.
674a34d5fb1SAntonio Huete Jimenez *
675a34d5fb1SAntonio Huete Jimenez * If an error is detected and not being ignored, the process exits.
67601e196c8SJohn Marino *
67701e196c8SJohn Marino * Input:
678a34d5fb1SAntonio Huete Jimenez * gn The node to make
679a34d5fb1SAntonio Huete Jimenez * pgn Parent to abort if necessary
68001e196c8SJohn Marino *
681a34d5fb1SAntonio Huete Jimenez * Output:
682a34d5fb1SAntonio Huete Jimenez * gn->made
683a34d5fb1SAntonio Huete Jimenez * UPTODATE gn was already up-to-date.
684a34d5fb1SAntonio Huete Jimenez * MADE gn was recreated successfully.
685a34d5fb1SAntonio Huete Jimenez * ERROR An error occurred while gn was being created,
686a34d5fb1SAntonio Huete Jimenez * either due to missing commands or in -k mode.
687a34d5fb1SAntonio Huete Jimenez * ABORTED gn was not remade because one of its
688a34d5fb1SAntonio Huete Jimenez * dependencies could not be made due to errors.
68901e196c8SJohn Marino */
69001e196c8SJohn Marino void
Compat_Make(GNode * gn,GNode * pgn)691a34d5fb1SAntonio Huete Jimenez Compat_Make(GNode *gn, GNode *pgn)
69201e196c8SJohn Marino {
693a34d5fb1SAntonio Huete Jimenez if (shellName == NULL) /* we came here from jobs */
694f445c897SJohn Marino Shell_Init();
69501e196c8SJohn Marino
696a34d5fb1SAntonio Huete Jimenez if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) {
697a34d5fb1SAntonio Huete Jimenez if (!MakeUnmade(gn, pgn))
698a34d5fb1SAntonio Huete Jimenez goto cohorts;
699a34d5fb1SAntonio Huete Jimenez
700a34d5fb1SAntonio Huete Jimenez /* XXX: Replace with GNode_IsError(gn) */
701a34d5fb1SAntonio Huete Jimenez } else if (gn->made == ERROR) {
702a34d5fb1SAntonio Huete Jimenez /*
703a34d5fb1SAntonio Huete Jimenez * Already had an error when making this.
704a34d5fb1SAntonio Huete Jimenez * Tell the parent to abort.
705a34d5fb1SAntonio Huete Jimenez */
706*6eef5f0cSAntonio Huete Jimenez pgn->flags.remake = false;
707a34d5fb1SAntonio Huete Jimenez } else {
708a34d5fb1SAntonio Huete Jimenez MakeOther(gn, pgn);
70901e196c8SJohn Marino }
71001e196c8SJohn Marino
711a34d5fb1SAntonio Huete Jimenez cohorts:
712a34d5fb1SAntonio Huete Jimenez MakeNodes(&gn->cohorts, pgn);
713a34d5fb1SAntonio Huete Jimenez }
714a34d5fb1SAntonio Huete Jimenez
715a34d5fb1SAntonio Huete Jimenez static void
MakeBeginNode(void)716a34d5fb1SAntonio Huete Jimenez MakeBeginNode(void)
717a34d5fb1SAntonio Huete Jimenez {
718a34d5fb1SAntonio Huete Jimenez GNode *gn = Targ_FindNode(".BEGIN");
719a34d5fb1SAntonio Huete Jimenez if (gn == NULL)
720a34d5fb1SAntonio Huete Jimenez return;
721a34d5fb1SAntonio Huete Jimenez
72201e196c8SJohn Marino Compat_Make(gn, gn);
723a34d5fb1SAntonio Huete Jimenez if (GNode_IsError(gn)) {
724*6eef5f0cSAntonio Huete Jimenez PrintOnError(gn, "\nStop.\n");
72501e196c8SJohn Marino exit(1);
72601e196c8SJohn Marino }
72701e196c8SJohn Marino }
728a34d5fb1SAntonio Huete Jimenez
729a34d5fb1SAntonio Huete Jimenez static void
InitSignals(void)730a34d5fb1SAntonio Huete Jimenez InitSignals(void)
731a34d5fb1SAntonio Huete Jimenez {
732a34d5fb1SAntonio Huete Jimenez if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN)
733a34d5fb1SAntonio Huete Jimenez bmake_signal(SIGINT, CompatInterrupt);
734a34d5fb1SAntonio Huete Jimenez if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN)
735a34d5fb1SAntonio Huete Jimenez bmake_signal(SIGTERM, CompatInterrupt);
736a34d5fb1SAntonio Huete Jimenez if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN)
737a34d5fb1SAntonio Huete Jimenez bmake_signal(SIGHUP, CompatInterrupt);
738a34d5fb1SAntonio Huete Jimenez if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN)
739a34d5fb1SAntonio Huete Jimenez bmake_signal(SIGQUIT, CompatInterrupt);
74001e196c8SJohn Marino }
74101e196c8SJohn Marino
742a34d5fb1SAntonio Huete Jimenez void
Compat_MakeAll(GNodeList * targs)743*6eef5f0cSAntonio Huete Jimenez Compat_MakeAll(GNodeList *targs)
744a34d5fb1SAntonio Huete Jimenez {
745a34d5fb1SAntonio Huete Jimenez GNode *errorNode = NULL;
746a34d5fb1SAntonio Huete Jimenez
747a34d5fb1SAntonio Huete Jimenez if (shellName == NULL)
748a34d5fb1SAntonio Huete Jimenez Shell_Init();
749a34d5fb1SAntonio Huete Jimenez
750a34d5fb1SAntonio Huete Jimenez InitSignals();
751a34d5fb1SAntonio Huete Jimenez
752*6eef5f0cSAntonio Huete Jimenez /*
753*6eef5f0cSAntonio Huete Jimenez * Create the .END node now, to keep the (debug) output of the
754*6eef5f0cSAntonio Huete Jimenez * counter.mk test the same as before 2020-09-23. This
755*6eef5f0cSAntonio Huete Jimenez * implementation detail probably doesn't matter though.
756*6eef5f0cSAntonio Huete Jimenez */
757a34d5fb1SAntonio Huete Jimenez (void)Targ_GetEndNode();
758a34d5fb1SAntonio Huete Jimenez
759*6eef5f0cSAntonio Huete Jimenez if (!opts.query)
760a34d5fb1SAntonio Huete Jimenez MakeBeginNode();
761a34d5fb1SAntonio Huete Jimenez
762a34d5fb1SAntonio Huete Jimenez /*
76301e196c8SJohn Marino * Expand .USE nodes right now, because they can modify the structure
76401e196c8SJohn Marino * of the tree.
76501e196c8SJohn Marino */
76601e196c8SJohn Marino Make_ExpandUse(targs);
76701e196c8SJohn Marino
76801e196c8SJohn Marino while (!Lst_IsEmpty(targs)) {
769a34d5fb1SAntonio Huete Jimenez GNode *gn = Lst_Dequeue(targs);
77001e196c8SJohn Marino Compat_Make(gn, gn);
77101e196c8SJohn Marino
77201e196c8SJohn Marino if (gn->made == UPTODATE) {
77301e196c8SJohn Marino printf("`%s' is up to date.\n", gn->name);
77401e196c8SJohn Marino } else if (gn->made == ABORTED) {
775a34d5fb1SAntonio Huete Jimenez printf("`%s' not remade because of errors.\n",
776a34d5fb1SAntonio Huete Jimenez gn->name);
77701e196c8SJohn Marino }
778a34d5fb1SAntonio Huete Jimenez if (GNode_IsError(gn) && errorNode == NULL)
779a34d5fb1SAntonio Huete Jimenez errorNode = gn;
78001e196c8SJohn Marino }
78101e196c8SJohn Marino
782a34d5fb1SAntonio Huete Jimenez /* If the user has defined a .END target, run its commands. */
783a34d5fb1SAntonio Huete Jimenez if (errorNode == NULL) {
784a34d5fb1SAntonio Huete Jimenez GNode *endNode = Targ_GetEndNode();
785a34d5fb1SAntonio Huete Jimenez Compat_Make(endNode, endNode);
786a34d5fb1SAntonio Huete Jimenez if (GNode_IsError(endNode))
787a34d5fb1SAntonio Huete Jimenez errorNode = endNode;
78801e196c8SJohn Marino }
789a34d5fb1SAntonio Huete Jimenez
790a34d5fb1SAntonio Huete Jimenez if (errorNode != NULL) {
791a34d5fb1SAntonio Huete Jimenez if (DEBUG(GRAPH2))
792a34d5fb1SAntonio Huete Jimenez Targ_PrintGraph(2);
793a34d5fb1SAntonio Huete Jimenez else if (DEBUG(GRAPH3))
794a34d5fb1SAntonio Huete Jimenez Targ_PrintGraph(3);
795*6eef5f0cSAntonio Huete Jimenez PrintOnError(errorNode, "\nStop.\n");
796a34d5fb1SAntonio Huete Jimenez exit(1);
79701e196c8SJohn Marino }
79801e196c8SJohn Marino }
799