Sat Oct 31 18:20:01 2020 UTC ()
make(1): remove unused code from needshell

Since usr.bin/xinstall no longer uses this code, there is no need to
keep the second parameter.


(rillig)
diff -r1.171 -r1.172 src/usr.bin/make/compat.c
diff -r1.10 -r1.11 src/usr.bin/make/metachar.h

cvs diff -r1.171 -r1.172 src/usr.bin/make/compat.c (switch to unified diff)

--- src/usr.bin/make/compat.c 2020/10/31 11:54:33 1.171
+++ src/usr.bin/make/compat.c 2020/10/31 18:20:00 1.172
@@ -1,706 +1,706 @@ @@ -1,706 +1,706 @@
1/* $NetBSD: compat.c,v 1.171 2020/10/31 11:54:33 rillig Exp $ */ 1/* $NetBSD: compat.c,v 1.172 2020/10/31 18:20:00 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright 15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the 16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution. 17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of the University nor the names of its contributors 18 * 3. Neither the name of the University nor the names of its contributors
19 * may be used to endorse or promote products derived from this software 19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission. 20 * without specific prior written permission.
21 * 21 *
22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE. 32 * SUCH DAMAGE.
33 */ 33 */
34 34
35/* 35/*
36 * Copyright (c) 1988, 1989 by Adam de Boor 36 * Copyright (c) 1988, 1989 by Adam de Boor
37 * Copyright (c) 1989 by Berkeley Softworks 37 * Copyright (c) 1989 by Berkeley Softworks
38 * All rights reserved. 38 * All rights reserved.
39 * 39 *
40 * This code is derived from software contributed to Berkeley by 40 * This code is derived from software contributed to Berkeley by
41 * Adam de Boor. 41 * Adam de Boor.
42 * 42 *
43 * Redistribution and use in source and binary forms, with or without 43 * Redistribution and use in source and binary forms, with or without
44 * modification, are permitted provided that the following conditions 44 * modification, are permitted provided that the following conditions
45 * are met: 45 * are met:
46 * 1. Redistributions of source code must retain the above copyright 46 * 1. Redistributions of source code must retain the above copyright
47 * notice, this list of conditions and the following disclaimer. 47 * notice, this list of conditions and the following disclaimer.
48 * 2. Redistributions in binary form must reproduce the above copyright 48 * 2. Redistributions in binary form must reproduce the above copyright
49 * notice, this list of conditions and the following disclaimer in the 49 * notice, this list of conditions and the following disclaimer in the
50 * documentation and/or other materials provided with the distribution. 50 * documentation and/or other materials provided with the distribution.
51 * 3. All advertising materials mentioning features or use of this software 51 * 3. All advertising materials mentioning features or use of this software
52 * must display the following acknowledgement: 52 * must display the following acknowledgement:
53 * This product includes software developed by the University of 53 * This product includes software developed by the University of
54 * California, Berkeley and its contributors. 54 * California, Berkeley and its contributors.
55 * 4. Neither the name of the University nor the names of its contributors 55 * 4. Neither the name of the University nor the names of its contributors
56 * may be used to endorse or promote products derived from this software 56 * may be used to endorse or promote products derived from this software
57 * without specific prior written permission. 57 * without specific prior written permission.
58 * 58 *
59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
69 * SUCH DAMAGE. 69 * SUCH DAMAGE.
70 */ 70 */
71 71
72/*- 72/*-
73 * compat.c -- 73 * compat.c --
74 * The routines in this file implement the full-compatibility 74 * The routines in this file implement the full-compatibility
75 * mode of PMake. Most of the special functionality of PMake 75 * mode of PMake. Most of the special functionality of PMake
76 * is available in this mode. Things not supported: 76 * is available in this mode. Things not supported:
77 * - different shells. 77 * - different shells.
78 * - friendly variable substitution. 78 * - friendly variable substitution.
79 * 79 *
80 * Interface: 80 * Interface:
81 * Compat_Run Initialize things for this module and recreate 81 * Compat_Run Initialize things for this module and recreate
82 * thems as need creatin' 82 * thems as need creatin'
83 */ 83 */
84 84
85#include <sys/types.h> 85#include <sys/types.h>
86#include <sys/stat.h> 86#include <sys/stat.h>
87#include <sys/wait.h> 87#include <sys/wait.h>
88 88
89#include <errno.h> 89#include <errno.h>
90#include <signal.h> 90#include <signal.h>
91 91
92#include "make.h" 92#include "make.h"
93#include "dir.h" 93#include "dir.h"
94#include "job.h" 94#include "job.h"
95#include "metachar.h" 95#include "metachar.h"
96#include "pathnames.h" 96#include "pathnames.h"
97 97
98/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */ 98/* "@(#)compat.c 8.2 (Berkeley) 3/19/94" */
99MAKE_RCSID("$NetBSD: compat.c,v 1.171 2020/10/31 11:54:33 rillig Exp $"); 99MAKE_RCSID("$NetBSD: compat.c,v 1.172 2020/10/31 18:20:00 rillig Exp $");
100 100
101static GNode *curTarg = NULL; 101static GNode *curTarg = NULL;
102static pid_t compatChild; 102static pid_t compatChild;
103static int compatSigno; 103static int compatSigno;
104 104
105/* 105/*
106 * CompatDeleteTarget -- delete a failed, interrupted, or otherwise 106 * CompatDeleteTarget -- delete a failed, interrupted, or otherwise
107 * duffed target if not inhibited by .PRECIOUS. 107 * duffed target if not inhibited by .PRECIOUS.
108 */ 108 */
109static void 109static void
110CompatDeleteTarget(GNode *gn) 110CompatDeleteTarget(GNode *gn)
111{ 111{
112 if (gn != NULL && !Targ_Precious(gn)) { 112 if (gn != NULL && !Targ_Precious(gn)) {
113 const char *file = GNode_VarTarget(gn); 113 const char *file = GNode_VarTarget(gn);
114 114
115 if (!opts.noExecute && eunlink(file) != -1) { 115 if (!opts.noExecute && eunlink(file) != -1) {
116 Error("*** %s removed", file); 116 Error("*** %s removed", file);
117 } 117 }
118 } 118 }
119} 119}
120 120
121/* Interrupt the creation of the current target and remove it if it ain't 121/* Interrupt the creation of the current target and remove it if it ain't
122 * precious. Then exit. 122 * precious. Then exit.
123 * 123 *
124 * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED. 124 * If .INTERRUPT exists, its commands are run first WITH INTERRUPTS IGNORED.
125 * 125 *
126 * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've 126 * XXX: is .PRECIOUS supposed to inhibit .INTERRUPT? I doubt it, but I've
127 * left the logic alone for now. - dholland 20160826 127 * left the logic alone for now. - dholland 20160826
128 */ 128 */
129static void 129static void
130CompatInterrupt(int signo) 130CompatInterrupt(int signo)
131{ 131{
132 GNode *gn; 132 GNode *gn;
133 133
134 CompatDeleteTarget(curTarg); 134 CompatDeleteTarget(curTarg);
135 135
136 if (curTarg != NULL && !Targ_Precious(curTarg)) { 136 if (curTarg != NULL && !Targ_Precious(curTarg)) {
137 /* 137 /*
138 * Run .INTERRUPT only if hit with interrupt signal 138 * Run .INTERRUPT only if hit with interrupt signal
139 */ 139 */
140 if (signo == SIGINT) { 140 if (signo == SIGINT) {
141 gn = Targ_FindNode(".INTERRUPT"); 141 gn = Targ_FindNode(".INTERRUPT");
142 if (gn != NULL) { 142 if (gn != NULL) {
143 Compat_Make(gn, gn); 143 Compat_Make(gn, gn);
144 } 144 }
145 } 145 }
146 } 146 }
147 147
148 if (signo == SIGQUIT) 148 if (signo == SIGQUIT)
149 _exit(signo); 149 _exit(signo);
150 150
151 /* 151 /*
152 * If there is a child running, pass the signal on. 152 * If there is a child running, pass the signal on.
153 * We will exist after it has exited. 153 * We will exist after it has exited.
154 */ 154 */
155 compatSigno = signo; 155 compatSigno = signo;
156 if (compatChild > 0) { 156 if (compatChild > 0) {
157 KILLPG(compatChild, signo); 157 KILLPG(compatChild, signo);
158 } else { 158 } else {
159 bmake_signal(signo, SIG_DFL); 159 bmake_signal(signo, SIG_DFL);
160 kill(myPid, signo); 160 kill(myPid, signo);
161 } 161 }
162} 162}
163 163
164/* Execute the next command for a target. If the command returns an error, 164/* Execute the next command for a target. If the command returns an error,
165 * the node's made field is set to ERROR and creation stops. 165 * the node's made field is set to ERROR and creation stops.
166 * 166 *
167 * Input: 167 * Input:
168 * cmdp Command to execute 168 * cmdp Command to execute
169 * gnp Node from which the command came 169 * gnp Node from which the command came
170 * 170 *
171 * Results: 171 * Results:
172 * 0 if the command succeeded, 1 if an error occurred. 172 * 0 if the command succeeded, 1 if an error occurred.
173 */ 173 */
174int 174int
175Compat_RunCommand(const char *cmdp, GNode *gn) 175Compat_RunCommand(const char *cmdp, GNode *gn)
176{ 176{
177 char *cmdStart; /* Start of expanded command */ 177 char *cmdStart; /* Start of expanded command */
178 char *bp; 178 char *bp;
179 Boolean silent; /* Don't print command */ 179 Boolean silent; /* Don't print command */
180 Boolean doIt; /* Execute even if -n */ 180 Boolean doIt; /* Execute even if -n */
181 volatile Boolean errCheck; /* Check errors */ 181 volatile Boolean errCheck; /* Check errors */
182 int reason; /* Reason for child's death */ 182 int reason; /* Reason for child's death */
183 int status; /* Description of child's death */ 183 int status; /* Description of child's death */
184 pid_t cpid; /* Child actually found */ 184 pid_t cpid; /* Child actually found */
185 pid_t retstat; /* Result of wait */ 185 pid_t retstat; /* Result of wait */
186 StringListNode *cmdNode; /* Node where current command is located */ 186 StringListNode *cmdNode; /* Node where current command is located */
187 const char **volatile av; /* Argument vector for thing to exec */ 187 const char **volatile av; /* Argument vector for thing to exec */
188 char **volatile mav; /* Copy of the argument vector for freeing */ 188 char **volatile mav; /* Copy of the argument vector for freeing */
189 Boolean useShell; /* TRUE if command should be executed 189 Boolean useShell; /* TRUE if command should be executed
190 * using a shell */ 190 * using a shell */
191 const char *volatile cmd = cmdp; 191 const char *volatile cmd = cmdp;
192 192
193 silent = (gn->type & OP_SILENT) != 0; 193 silent = (gn->type & OP_SILENT) != 0;
194 errCheck = !(gn->type & OP_IGNORE); 194 errCheck = !(gn->type & OP_IGNORE);
195 doIt = FALSE; 195 doIt = FALSE;
196 196
197 /* Luckily the commands don't end up in a string pool, otherwise 197 /* Luckily the commands don't end up in a string pool, otherwise
198 * this comparison could match too early, in a dependency using "..." 198 * this comparison could match too early, in a dependency using "..."
199 * for delayed commands, run in parallel mode, using the same shell 199 * for delayed commands, run in parallel mode, using the same shell
200 * command line more than once; see JobPrintCommand. 200 * command line more than once; see JobPrintCommand.
201 * TODO: write a unit-test to protect against this potential bug. */ 201 * TODO: write a unit-test to protect against this potential bug. */
202 cmdNode = Lst_FindDatum(gn->commands, cmd); 202 cmdNode = Lst_FindDatum(gn->commands, cmd);
203 (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart); 203 (void)Var_Subst(cmd, gn, VARE_WANTRES, &cmdStart);
204 /* TODO: handle errors */ 204 /* TODO: handle errors */
205 205
206 if (*cmdStart == '\0') { 206 if (*cmdStart == '\0') {
207 free(cmdStart); 207 free(cmdStart);
208 return 0; 208 return 0;
209 } 209 }
210 cmd = cmdStart; 210 cmd = cmdStart;
211 LstNode_Set(cmdNode, cmdStart); 211 LstNode_Set(cmdNode, cmdStart);
212 212
213 if (gn->type & OP_SAVE_CMDS) { 213 if (gn->type & OP_SAVE_CMDS) {
214 GNode *endNode = Targ_GetEndNode(); 214 GNode *endNode = Targ_GetEndNode();
215 if (gn != endNode) { 215 if (gn != endNode) {
216 Lst_Append(endNode->commands, cmdStart); 216 Lst_Append(endNode->commands, cmdStart);
217 return 0; 217 return 0;
218 } 218 }
219 } 219 }
220 if (strcmp(cmdStart, "...") == 0) { 220 if (strcmp(cmdStart, "...") == 0) {
221 gn->type |= OP_SAVE_CMDS; 221 gn->type |= OP_SAVE_CMDS;
222 return 0; 222 return 0;
223 } 223 }
224 224
225 while (*cmd == '@' || *cmd == '-' || *cmd == '+') { 225 while (*cmd == '@' || *cmd == '-' || *cmd == '+') {
226 switch (*cmd) { 226 switch (*cmd) {
227 case '@': 227 case '@':
228 silent = !DEBUG(LOUD); 228 silent = !DEBUG(LOUD);
229 break; 229 break;
230 case '-': 230 case '-':
231 errCheck = FALSE; 231 errCheck = FALSE;
232 break; 232 break;
233 case '+': 233 case '+':
234 doIt = TRUE; 234 doIt = TRUE;
235 if (!shellName) /* we came here from jobs */ 235 if (!shellName) /* we came here from jobs */
236 Shell_Init(); 236 Shell_Init();
237 break; 237 break;
238 } 238 }
239 cmd++; 239 cmd++;
240 } 240 }
241 241
242 while (ch_isspace(*cmd)) 242 while (ch_isspace(*cmd))
243 cmd++; 243 cmd++;
244 244
245 /* 245 /*
246 * If we did not end up with a command, just skip it. 246 * If we did not end up with a command, just skip it.
247 */ 247 */
248 if (!*cmd) 248 if (!*cmd)
249 return 0; 249 return 0;
250 250
251#if !defined(MAKE_NATIVE) 251#if !defined(MAKE_NATIVE)
252 /* 252 /*
253 * In a non-native build, the host environment might be weird enough 253 * In a non-native build, the host environment might be weird enough
254 * that it's necessary to go through a shell to get the correct 254 * that it's necessary to go through a shell to get the correct
255 * behaviour. Or perhaps the shell has been replaced with something 255 * behaviour. Or perhaps the shell has been replaced with something
256 * that does extra logging, and that should not be bypassed. 256 * that does extra logging, and that should not be bypassed.
257 */ 257 */
258 useShell = TRUE; 258 useShell = TRUE;
259#else 259#else
260 /* 260 /*
261 * Search for meta characters in the command. If there are no meta 261 * Search for meta characters in the command. If there are no meta
262 * characters, there's no need to execute a shell to execute the 262 * characters, there's no need to execute a shell to execute the
263 * command. 263 * command.
264 * 264 *
265 * Additionally variable assignments and empty commands 265 * Additionally variable assignments and empty commands
266 * go to the shell. Therefore treat '=' and ':' like shell 266 * go to the shell. Therefore treat '=' and ':' like shell
267 * meta characters as documented in make(1). 267 * meta characters as documented in make(1).
268 */ 268 */
269 269
270 useShell = needshell(cmd, FALSE); 270 useShell = needshell(cmd);
271#endif 271#endif
272 272
273 /* 273 /*
274 * Print the command before echoing if we're not supposed to be quiet for 274 * Print the command before echoing if we're not supposed to be quiet for
275 * this one. We also print the command if -n given. 275 * this one. We also print the command if -n given.
276 */ 276 */
277 if (!silent || NoExecute(gn)) { 277 if (!silent || NoExecute(gn)) {
278 printf("%s\n", cmd); 278 printf("%s\n", cmd);
279 fflush(stdout); 279 fflush(stdout);
280 } 280 }
281 281
282 /* 282 /*
283 * If we're not supposed to execute any commands, this is as far as 283 * If we're not supposed to execute any commands, this is as far as
284 * we go... 284 * we go...
285 */ 285 */
286 if (!doIt && NoExecute(gn)) { 286 if (!doIt && NoExecute(gn)) {
287 return 0; 287 return 0;
288 } 288 }
289 DEBUG1(JOB, "Execute: '%s'\n", cmd); 289 DEBUG1(JOB, "Execute: '%s'\n", cmd);
290 290
291 if (useShell) { 291 if (useShell) {
292 /* 292 /*
293 * We need to pass the command off to the shell, typically 293 * We need to pass the command off to the shell, typically
294 * because the command contains a "meta" character. 294 * because the command contains a "meta" character.
295 */ 295 */
296 static const char *shargv[5]; 296 static const char *shargv[5];
297 int shargc; 297 int shargc;
298 298
299 shargc = 0; 299 shargc = 0;
300 shargv[shargc++] = shellPath; 300 shargv[shargc++] = shellPath;
301 /* 301 /*
302 * The following work for any of the builtin shell specs. 302 * The following work for any of the builtin shell specs.
303 */ 303 */
304 if (errCheck && shellErrFlag) { 304 if (errCheck && shellErrFlag) {
305 shargv[shargc++] = shellErrFlag; 305 shargv[shargc++] = shellErrFlag;
306 } 306 }
307 if (DEBUG(SHELL)) 307 if (DEBUG(SHELL))
308 shargv[shargc++] = "-xc"; 308 shargv[shargc++] = "-xc";
309 else 309 else
310 shargv[shargc++] = "-c"; 310 shargv[shargc++] = "-c";
311 shargv[shargc++] = cmd; 311 shargv[shargc++] = cmd;
312 shargv[shargc] = NULL; 312 shargv[shargc] = NULL;
313 av = shargv; 313 av = shargv;
314 bp = NULL; 314 bp = NULL;
315 mav = NULL; 315 mav = NULL;
316 } else { 316 } else {
317 /* 317 /*
318 * No meta-characters, so no need to exec a shell. Break the command 318 * No meta-characters, so no need to exec a shell. Break the command
319 * into words to form an argument vector we can execute. 319 * into words to form an argument vector we can execute.
320 */ 320 */
321 Words words = Str_Words(cmd, FALSE); 321 Words words = Str_Words(cmd, FALSE);
322 mav = words.words; 322 mav = words.words;
323 bp = words.freeIt; 323 bp = words.freeIt;
324 av = (void *)mav; 324 av = (void *)mav;
325 } 325 }
326 326
327#ifdef USE_META 327#ifdef USE_META
328 if (useMeta) { 328 if (useMeta) {
329 meta_compat_start(); 329 meta_compat_start();
330 } 330 }
331#endif 331#endif
332 332
333 /* 333 /*
334 * Fork and execute the single command. If the fork fails, we abort. 334 * Fork and execute the single command. If the fork fails, we abort.
335 */ 335 */
336 compatChild = cpid = vFork(); 336 compatChild = cpid = vFork();
337 if (cpid < 0) { 337 if (cpid < 0) {
338 Fatal("Could not fork"); 338 Fatal("Could not fork");
339 } 339 }
340 if (cpid == 0) { 340 if (cpid == 0) {
341 Var_ExportVars(); 341 Var_ExportVars();
342#ifdef USE_META 342#ifdef USE_META
343 if (useMeta) { 343 if (useMeta) {
344 meta_compat_child(); 344 meta_compat_child();
345 } 345 }
346#endif 346#endif
347 (void)execvp(av[0], (char *const *)UNCONST(av)); 347 (void)execvp(av[0], (char *const *)UNCONST(av));
348 execDie("exec", av[0]); 348 execDie("exec", av[0]);
349 } 349 }
350 350
351 free(mav); 351 free(mav);
352 free(bp); 352 free(bp);
353 353
354 /* XXX: Memory management looks suspicious here. */ 354 /* XXX: Memory management looks suspicious here. */
355 /* XXX: Setting a list item to NULL is unexpected. */ 355 /* XXX: Setting a list item to NULL is unexpected. */
356 LstNode_SetNull(cmdNode); 356 LstNode_SetNull(cmdNode);
357 357
358#ifdef USE_META 358#ifdef USE_META
359 if (useMeta) { 359 if (useMeta) {
360 meta_compat_parent(cpid); 360 meta_compat_parent(cpid);
361 } 361 }
362#endif 362#endif
363 363
364 /* 364 /*
365 * The child is off and running. Now all we can do is wait... 365 * The child is off and running. Now all we can do is wait...
366 */ 366 */
367 while ((retstat = wait(&reason)) != cpid) { 367 while ((retstat = wait(&reason)) != cpid) {
368 if (retstat > 0) 368 if (retstat > 0)
369 JobReapChild(retstat, reason, FALSE); /* not ours? */ 369 JobReapChild(retstat, reason, FALSE); /* not ours? */
370 if (retstat == -1 && errno != EINTR) { 370 if (retstat == -1 && errno != EINTR) {
371 break; 371 break;
372 } 372 }
373 } 373 }
374 374
375 if (retstat < 0) 375 if (retstat < 0)
376 Fatal("error in wait: %d: %s", retstat, strerror(errno)); 376 Fatal("error in wait: %d: %s", retstat, strerror(errno));
377 377
378 if (WIFSTOPPED(reason)) { 378 if (WIFSTOPPED(reason)) {
379 status = WSTOPSIG(reason); /* stopped */ 379 status = WSTOPSIG(reason); /* stopped */
380 } else if (WIFEXITED(reason)) { 380 } else if (WIFEXITED(reason)) {
381 status = WEXITSTATUS(reason); /* exited */ 381 status = WEXITSTATUS(reason); /* exited */
382#if defined(USE_META) && defined(USE_FILEMON_ONCE) 382#if defined(USE_META) && defined(USE_FILEMON_ONCE)
383 if (useMeta) { 383 if (useMeta) {
384 meta_cmd_finish(NULL); 384 meta_cmd_finish(NULL);
385 } 385 }
386#endif 386#endif
387 if (status != 0) { 387 if (status != 0) {
388 if (DEBUG(ERROR)) { 388 if (DEBUG(ERROR)) {
389 const char *cp; 389 const char *cp;
390 debug_printf("\n*** Failed target: %s\n*** Failed command: ", 390 debug_printf("\n*** Failed target: %s\n*** Failed command: ",
391 gn->name); 391 gn->name);
392 for (cp = cmd; *cp; ) { 392 for (cp = cmd; *cp; ) {
393 if (ch_isspace(*cp)) { 393 if (ch_isspace(*cp)) {
394 debug_printf(" "); 394 debug_printf(" ");
395 while (ch_isspace(*cp)) 395 while (ch_isspace(*cp))
396 cp++; 396 cp++;
397 } else { 397 } else {
398 debug_printf("%c", *cp); 398 debug_printf("%c", *cp);
399 cp++; 399 cp++;
400 } 400 }
401 } 401 }
402 debug_printf("\n"); 402 debug_printf("\n");
403 } 403 }
404 printf("*** Error code %d", status); 404 printf("*** Error code %d", status);
405 } 405 }
406 } else { 406 } else {
407 status = WTERMSIG(reason); /* signaled */ 407 status = WTERMSIG(reason); /* signaled */
408 printf("*** Signal %d", status); 408 printf("*** Signal %d", status);
409 } 409 }
410 410
411 411
412 if (!WIFEXITED(reason) || status != 0) { 412 if (!WIFEXITED(reason) || status != 0) {
413 if (errCheck) { 413 if (errCheck) {
414#ifdef USE_META 414#ifdef USE_META
415 if (useMeta) { 415 if (useMeta) {
416 meta_job_error(NULL, gn, 0, status); 416 meta_job_error(NULL, gn, 0, status);
417 } 417 }
418#endif 418#endif
419 gn->made = ERROR; 419 gn->made = ERROR;
420 if (opts.keepgoing) { 420 if (opts.keepgoing) {
421 /* Abort the current target, but let others continue. */ 421 /* Abort the current target, but let others continue. */
422 printf(" (continuing)\n"); 422 printf(" (continuing)\n");
423 } else { 423 } else {
424 printf("\n"); 424 printf("\n");
425 } 425 }
426 if (deleteOnError) 426 if (deleteOnError)
427 CompatDeleteTarget(gn); 427 CompatDeleteTarget(gn);
428 } else { 428 } else {
429 /* 429 /*
430 * Continue executing commands for this target. 430 * Continue executing commands for this target.
431 * If we return 0, this will happen... 431 * If we return 0, this will happen...
432 */ 432 */
433 printf(" (ignored)\n"); 433 printf(" (ignored)\n");
434 status = 0; 434 status = 0;
435 } 435 }
436 } 436 }
437 437
438 free(cmdStart); 438 free(cmdStart);
439 compatChild = 0; 439 compatChild = 0;
440 if (compatSigno) { 440 if (compatSigno) {
441 bmake_signal(compatSigno, SIG_DFL); 441 bmake_signal(compatSigno, SIG_DFL);
442 kill(myPid, compatSigno); 442 kill(myPid, compatSigno);
443 } 443 }
444 444
445 return status; 445 return status;
446} 446}
447 447
448static void 448static void
449RunCommands(GNode *gn) 449RunCommands(GNode *gn)
450{ 450{
451 StringListNode *ln; 451 StringListNode *ln;
452 for (ln = gn->commands->first; ln != NULL; ln = ln->next) { 452 for (ln = gn->commands->first; ln != NULL; ln = ln->next) {
453 const char *cmd = ln->datum; 453 const char *cmd = ln->datum;
454 if (Compat_RunCommand(cmd, gn) != 0) 454 if (Compat_RunCommand(cmd, gn) != 0)
455 break; 455 break;
456 } 456 }
457} 457}
458 458
459static void 459static void
460MakeNodes(GNodeList *gnodes, GNode *pgn) 460MakeNodes(GNodeList *gnodes, GNode *pgn)
461{ 461{
462 GNodeListNode *ln; 462 GNodeListNode *ln;
463 for (ln = gnodes->first; ln != NULL; ln = ln->next) { 463 for (ln = gnodes->first; ln != NULL; ln = ln->next) {
464 GNode *cohort = ln->datum; 464 GNode *cohort = ln->datum;
465 Compat_Make(cohort, pgn); 465 Compat_Make(cohort, pgn);
466 } 466 }
467} 467}
468 468
469/* Make a target. 469/* Make a target.
470 * 470 *
471 * If an error is detected and not being ignored, the process exits. 471 * If an error is detected and not being ignored, the process exits.
472 * 472 *
473 * Input: 473 * Input:
474 * gn The node to make 474 * gn The node to make
475 * pgn Parent to abort if necessary 475 * pgn Parent to abort if necessary
476 */ 476 */
477void 477void
478Compat_Make(GNode *gn, GNode *pgn) 478Compat_Make(GNode *gn, GNode *pgn)
479{ 479{
480 if (!shellName) /* we came here from jobs */ 480 if (!shellName) /* we came here from jobs */
481 Shell_Init(); 481 Shell_Init();
482 if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) { 482 if (gn->made == UNMADE && (gn == pgn || !(pgn->type & OP_MADE))) {
483 /* 483 /*
484 * First mark ourselves to be made, then apply whatever transformations 484 * First mark ourselves to be made, then apply whatever transformations
485 * the suffix module thinks are necessary. Once that's done, we can 485 * the suffix module thinks are necessary. Once that's done, we can
486 * descend and make all our children. If any of them has an error 486 * descend and make all our children. If any of them has an error
487 * but the -k flag was given, our 'make' field will be set FALSE again. 487 * but the -k flag was given, our 'make' field will be set FALSE again.
488 * This is our signal to not attempt to do anything but abort our 488 * This is our signal to not attempt to do anything but abort our
489 * parent as well. 489 * parent as well.
490 */ 490 */
491 gn->flags |= REMAKE; 491 gn->flags |= REMAKE;
492 gn->made = BEINGMADE; 492 gn->made = BEINGMADE;
493 if (!(gn->type & OP_MADE)) 493 if (!(gn->type & OP_MADE))
494 Suff_FindDeps(gn); 494 Suff_FindDeps(gn);
495 MakeNodes(gn->children, gn); 495 MakeNodes(gn->children, gn);
496 if (!(gn->flags & REMAKE)) { 496 if (!(gn->flags & REMAKE)) {
497 gn->made = ABORTED; 497 gn->made = ABORTED;
498 pgn->flags &= ~(unsigned)REMAKE; 498 pgn->flags &= ~(unsigned)REMAKE;
499 goto cohorts; 499 goto cohorts;
500 } 500 }
501 501
502 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) 502 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL)
503 Var_Set(IMPSRC, GNode_VarTarget(gn), pgn); 503 Var_Set(IMPSRC, GNode_VarTarget(gn), pgn);
504 504
505 /* 505 /*
506 * All the children were made ok. Now youngestChild->mtime contains the 506 * All the children were made ok. Now youngestChild->mtime contains the
507 * modification time of the newest child, we need to find out if we 507 * modification time of the newest child, we need to find out if we
508 * exist and when we were modified last. The criteria for datedness 508 * exist and when we were modified last. The criteria for datedness
509 * are defined by the Make_OODate function. 509 * are defined by the Make_OODate function.
510 */ 510 */
511 DEBUG1(MAKE, "Examining %s...", gn->name); 511 DEBUG1(MAKE, "Examining %s...", gn->name);
512 if (!Make_OODate(gn)) { 512 if (!Make_OODate(gn)) {
513 gn->made = UPTODATE; 513 gn->made = UPTODATE;
514 DEBUG0(MAKE, "up-to-date.\n"); 514 DEBUG0(MAKE, "up-to-date.\n");
515 goto cohorts; 515 goto cohorts;
516 } else 516 } else
517 DEBUG0(MAKE, "out-of-date.\n"); 517 DEBUG0(MAKE, "out-of-date.\n");
518 518
519 /* 519 /*
520 * If the user is just seeing if something is out-of-date, exit now 520 * If the user is just seeing if something is out-of-date, exit now
521 * to tell him/her "yes". 521 * to tell him/her "yes".
522 */ 522 */
523 if (opts.queryFlag) { 523 if (opts.queryFlag) {
524 exit(1); 524 exit(1);
525 } 525 }
526 526
527 /* 527 /*
528 * We need to be re-made. We also have to make sure we've got a $? 528 * We need to be re-made. We also have to make sure we've got a $?
529 * variable. To be nice, we also define the $> variable using 529 * variable. To be nice, we also define the $> variable using
530 * Make_DoAllVar(). 530 * Make_DoAllVar().
531 */ 531 */
532 Make_DoAllVar(gn); 532 Make_DoAllVar(gn);
533 533
534 /* 534 /*
535 * Alter our type to tell if errors should be ignored or things 535 * Alter our type to tell if errors should be ignored or things
536 * should not be printed so CompatRunCommand knows what to do. 536 * should not be printed so CompatRunCommand knows what to do.
537 */ 537 */
538 if (Targ_Ignore(gn)) 538 if (Targ_Ignore(gn))
539 gn->type |= OP_IGNORE; 539 gn->type |= OP_IGNORE;
540 if (Targ_Silent(gn)) 540 if (Targ_Silent(gn))
541 gn->type |= OP_SILENT; 541 gn->type |= OP_SILENT;
542 542
543 if (Job_CheckCommands(gn, Fatal)) { 543 if (Job_CheckCommands(gn, Fatal)) {
544 /* 544 /*
545 * Our commands are ok, but we still have to worry about the -t 545 * Our commands are ok, but we still have to worry about the -t
546 * flag... 546 * flag...
547 */ 547 */
548 if (!opts.touchFlag || (gn->type & OP_MAKE)) { 548 if (!opts.touchFlag || (gn->type & OP_MAKE)) {
549 curTarg = gn; 549 curTarg = gn;
550#ifdef USE_META 550#ifdef USE_META
551 if (useMeta && !NoExecute(gn)) { 551 if (useMeta && !NoExecute(gn)) {
552 meta_job_start(NULL, gn); 552 meta_job_start(NULL, gn);
553 } 553 }
554#endif 554#endif
555 RunCommands(gn); 555 RunCommands(gn);
556 curTarg = NULL; 556 curTarg = NULL;
557 } else { 557 } else {
558 Job_Touch(gn, (gn->type & OP_SILENT) != 0); 558 Job_Touch(gn, (gn->type & OP_SILENT) != 0);
559 } 559 }
560 } else { 560 } else {
561 gn->made = ERROR; 561 gn->made = ERROR;
562 } 562 }
563#ifdef USE_META 563#ifdef USE_META
564 if (useMeta && !NoExecute(gn)) { 564 if (useMeta && !NoExecute(gn)) {
565 if (meta_job_finish(NULL) != 0) 565 if (meta_job_finish(NULL) != 0)
566 gn->made = ERROR; 566 gn->made = ERROR;
567 } 567 }
568#endif 568#endif
569 569
570 if (gn->made != ERROR) { 570 if (gn->made != ERROR) {
571 /* 571 /*
572 * If the node was made successfully, mark it so, update 572 * If the node was made successfully, mark it so, update
573 * its modification time and timestamp all its parents. Note 573 * its modification time and timestamp all its parents. Note
574 * that for .ZEROTIME targets, the timestamping isn't done. 574 * that for .ZEROTIME targets, the timestamping isn't done.
575 * This is to keep its state from affecting that of its parent. 575 * This is to keep its state from affecting that of its parent.
576 */ 576 */
577 gn->made = MADE; 577 gn->made = MADE;
578 pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0; 578 pgn->flags |= Make_Recheck(gn) == 0 ? FORCE : 0;
579 if (!(gn->type & OP_EXEC)) { 579 if (!(gn->type & OP_EXEC)) {
580 pgn->flags |= CHILDMADE; 580 pgn->flags |= CHILDMADE;
581 Make_TimeStamp(pgn, gn); 581 Make_TimeStamp(pgn, gn);
582 } 582 }
583 } else if (opts.keepgoing) { 583 } else if (opts.keepgoing) {
584 pgn->flags &= ~(unsigned)REMAKE; 584 pgn->flags &= ~(unsigned)REMAKE;
585 } else { 585 } else {
586 PrintOnError(gn, "\nStop."); 586 PrintOnError(gn, "\nStop.");
587 exit(1); 587 exit(1);
588 } 588 }
589 } else if (gn->made == ERROR) { 589 } else if (gn->made == ERROR) {
590 /* Already had an error when making this. Tell the parent to abort. */ 590 /* Already had an error when making this. Tell the parent to abort. */
591 pgn->flags &= ~(unsigned)REMAKE; 591 pgn->flags &= ~(unsigned)REMAKE;
592 } else { 592 } else {
593 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) { 593 if (Lst_FindDatum(gn->implicitParents, pgn) != NULL) {
594 const char *target = GNode_VarTarget(gn); 594 const char *target = GNode_VarTarget(gn);
595 Var_Set(IMPSRC, target != NULL ? target : "", pgn); 595 Var_Set(IMPSRC, target != NULL ? target : "", pgn);
596 } 596 }
597 switch(gn->made) { 597 switch(gn->made) {
598 case BEINGMADE: 598 case BEINGMADE:
599 Error("Graph cycles through %s", gn->name); 599 Error("Graph cycles through %s", gn->name);
600 gn->made = ERROR; 600 gn->made = ERROR;
601 pgn->flags &= ~(unsigned)REMAKE; 601 pgn->flags &= ~(unsigned)REMAKE;
602 break; 602 break;
603 case MADE: 603 case MADE:
604 if ((gn->type & OP_EXEC) == 0) { 604 if ((gn->type & OP_EXEC) == 0) {
605 pgn->flags |= CHILDMADE; 605 pgn->flags |= CHILDMADE;
606 Make_TimeStamp(pgn, gn); 606 Make_TimeStamp(pgn, gn);
607 } 607 }
608 break; 608 break;
609 case UPTODATE: 609 case UPTODATE:
610 if ((gn->type & OP_EXEC) == 0) { 610 if ((gn->type & OP_EXEC) == 0) {
611 Make_TimeStamp(pgn, gn); 611 Make_TimeStamp(pgn, gn);
612 } 612 }
613 break; 613 break;
614 default: 614 default:
615 break; 615 break;
616 } 616 }
617 } 617 }
618 618
619cohorts: 619cohorts:
620 MakeNodes(gn->cohorts, pgn); 620 MakeNodes(gn->cohorts, pgn);
621} 621}
622 622
623/* Initialize this module and start making. 623/* Initialize this module and start making.
624 * 624 *
625 * Input: 625 * Input:
626 * targs The target nodes to re-create 626 * targs The target nodes to re-create
627 */ 627 */
628void 628void
629Compat_Run(GNodeList *targs) 629Compat_Run(GNodeList *targs)
630{ 630{
631 GNode *gn = NULL; /* Current root target */ 631 GNode *gn = NULL; /* Current root target */
632 int errors; /* Number of targets not remade due to errors */ 632 int errors; /* Number of targets not remade due to errors */
633 633
634 if (!shellName) 634 if (!shellName)
635 Shell_Init(); 635 Shell_Init();
636 636
637 if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN) 637 if (bmake_signal(SIGINT, SIG_IGN) != SIG_IGN)
638 bmake_signal(SIGINT, CompatInterrupt); 638 bmake_signal(SIGINT, CompatInterrupt);
639 if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN) 639 if (bmake_signal(SIGTERM, SIG_IGN) != SIG_IGN)
640 bmake_signal(SIGTERM, CompatInterrupt); 640 bmake_signal(SIGTERM, CompatInterrupt);
641 if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN) 641 if (bmake_signal(SIGHUP, SIG_IGN) != SIG_IGN)
642 bmake_signal(SIGHUP, CompatInterrupt); 642 bmake_signal(SIGHUP, CompatInterrupt);
643 if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN) 643 if (bmake_signal(SIGQUIT, SIG_IGN) != SIG_IGN)
644 bmake_signal(SIGQUIT, CompatInterrupt); 644 bmake_signal(SIGQUIT, CompatInterrupt);
645 645
646 /* Create the .END node now, to keep the (debug) output of the 646 /* Create the .END node now, to keep the (debug) output of the
647 * counter.mk test the same as before 2020-09-23. This implementation 647 * counter.mk test the same as before 2020-09-23. This implementation
648 * detail probably doesn't matter though. */ 648 * detail probably doesn't matter though. */
649 (void)Targ_GetEndNode(); 649 (void)Targ_GetEndNode();
650 /* 650 /*
651 * If the user has defined a .BEGIN target, execute the commands attached 651 * If the user has defined a .BEGIN target, execute the commands attached
652 * to it. 652 * to it.
653 */ 653 */
654 if (!opts.queryFlag) { 654 if (!opts.queryFlag) {
655 gn = Targ_FindNode(".BEGIN"); 655 gn = Targ_FindNode(".BEGIN");
656 if (gn != NULL) { 656 if (gn != NULL) {
657 Compat_Make(gn, gn); 657 Compat_Make(gn, gn);
658 if (gn->made == ERROR) { 658 if (gn->made == ERROR) {
659 PrintOnError(gn, "\nStop."); 659 PrintOnError(gn, "\nStop.");
660 exit(1); 660 exit(1);
661 } 661 }
662 } 662 }
663 } 663 }
664 664
665 /* 665 /*
666 * Expand .USE nodes right now, because they can modify the structure 666 * Expand .USE nodes right now, because they can modify the structure
667 * of the tree. 667 * of the tree.
668 */ 668 */
669 Make_ExpandUse(targs); 669 Make_ExpandUse(targs);
670 670
671 /* 671 /*
672 * For each entry in the list of targets to create, call Compat_Make on 672 * For each entry in the list of targets to create, call Compat_Make on
673 * it to create the thing. Compat_Make will leave the 'made' field of gn 673 * it to create the thing. Compat_Make will leave the 'made' field of gn
674 * in one of several states: 674 * in one of several states:
675 * UPTODATE gn was already up-to-date 675 * UPTODATE gn was already up-to-date
676 * MADE gn was recreated successfully 676 * MADE gn was recreated successfully
677 * ERROR An error occurred while gn was being created 677 * ERROR An error occurred while gn was being created
678 * ABORTED gn was not remade because one of its inferiors 678 * ABORTED gn was not remade because one of its inferiors
679 * could not be made due to errors. 679 * could not be made due to errors.
680 */ 680 */
681 errors = 0; 681 errors = 0;
682 while (!Lst_IsEmpty(targs)) { 682 while (!Lst_IsEmpty(targs)) {
683 gn = Lst_Dequeue(targs); 683 gn = Lst_Dequeue(targs);
684 Compat_Make(gn, gn); 684 Compat_Make(gn, gn);
685 685
686 if (gn->made == UPTODATE) { 686 if (gn->made == UPTODATE) {
687 printf("`%s' is up to date.\n", gn->name); 687 printf("`%s' is up to date.\n", gn->name);
688 } else if (gn->made == ABORTED) { 688 } else if (gn->made == ABORTED) {
689 printf("`%s' not remade because of errors.\n", gn->name); 689 printf("`%s' not remade because of errors.\n", gn->name);
690 errors++; 690 errors++;
691 } 691 }
692 } 692 }
693 693
694 /* 694 /*
695 * If the user has defined a .END target, run its commands. 695 * If the user has defined a .END target, run its commands.
696 */ 696 */
697 if (errors == 0) { 697 if (errors == 0) {
698 GNode *endNode = Targ_GetEndNode(); 698 GNode *endNode = Targ_GetEndNode();
699 Compat_Make(endNode, endNode); 699 Compat_Make(endNode, endNode);
700 /* XXX: Did you mean endNode->made instead of gn->made? */ 700 /* XXX: Did you mean endNode->made instead of gn->made? */
701 if (gn->made == ERROR) { 701 if (gn->made == ERROR) {
702 PrintOnError(gn, "\nStop."); 702 PrintOnError(gn, "\nStop.");
703 exit(1); 703 exit(1);
704 } 704 }
705 } 705 }
706} 706}

cvs diff -r1.10 -r1.11 src/usr.bin/make/metachar.h (switch to unified diff)

--- src/usr.bin/make/metachar.h 2020/10/31 18:17:08 1.10
+++ src/usr.bin/make/metachar.h 2020/10/31 18:20:00 1.11
@@ -1,52 +1,48 @@ @@ -1,52 +1,48 @@
1/* $NetBSD: metachar.h,v 1.10 2020/10/31 18:17:08 rillig Exp $ */ 1/* $NetBSD: metachar.h,v 1.11 2020/10/31 18:20:00 rillig Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2015 The NetBSD Foundation, Inc. 4 * Copyright (c) 2015 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Christos Zoulas. 8 * by Christos Zoulas.
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 * 18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE. 29 * POSSIBILITY OF SUCH DAMAGE.
30 */ 30 */
31#ifndef MAKE_METACHAR_H 31#ifndef MAKE_METACHAR_H
32#define MAKE_METACHAR_H 32#define MAKE_METACHAR_H
33 33
34#include "make.h" 34#include "make.h"
35 35
36extern unsigned char _metachar[]; 36extern unsigned char _metachar[];
37 37
38#define is_shell_metachar(c) _metachar[(c) & 0x7f] 38#define is_shell_metachar(c) _metachar[(c) & 0x7f]
39 39
40static inline MAKE_ATTR_UNUSED int 40static inline MAKE_ATTR_UNUSED int
41needshell(const char *cmd, int white) 41needshell(const char *cmd)
42{ 42{
43 while (!is_shell_metachar(*cmd) && *cmd != ':' && *cmd != '=') { 43 while (!is_shell_metachar(*cmd) && *cmd != ':' && *cmd != '=')
44 if (white && ch_isspace(*cmd)) 
45 break; 
46 cmd++; 44 cmd++;
47 } 
48 
49 return *cmd != '\0'; 45 return *cmd != '\0';
50} 46}
51 47
52#endif /* MAKE_METACHAR_H */ 48#endif /* MAKE_METACHAR_H */