#include "makeint.h"
#include <assert.h>
+#include <string.h>
#include "job.h"
#include "debug.h"
#include "variable.h"
#include "os.h"
-#include <string.h>
-
/* Default shell to use. */
#ifdef WINDOWS32
# ifdef HAVE_STRINGS_H
#ifdef USE_POSIX_SPAWN
# include <spawn.h>
+# include "findprog.h"
#endif
#if !defined (wait) && !defined (POSIX)
environ = parent_environ; /* Restore value child may have clobbered. */
jobserver_post_child (flags & COMMANDS_RECURSE);
- free (child->cmd_name);
- child->cmd_name = child->pid > 0 ? xstrdup(argv[0]) : NULL;
#endif /* !VMS */
}
pid_t pid;
int r;
#if defined(USE_POSIX_SPAWN)
- short flags = 0;
+ char *cmd;
posix_spawnattr_t attr;
posix_spawn_file_actions_t fa;
+ short flags = 0;
#endif
/* Divert child output if we want to capture it. */
/* Run the command. */
exec_command (argv, child->environment);
-#else /* use posix_spawn() */
+#else /* USE_POSIX_SPAWN */
if ((r = posix_spawnattr_init (&attr)) != 0)
goto done;
if ((r = posix_spawnattr_setflags (&attr, flags)) != 0)
goto cleanup;
+ /* Look up the program on the child's PATH, if needed. */
+ {
+ const char *p = NULL;
+ char **pp;
+
+ for (pp = child->environment; *pp != NULL; ++pp)
+ if ((*pp)[0] == 'P' && (*pp)[1] == 'A' && (*pp)[2] == 'T'
+ && (*pp)[3] == 'H' &&(*pp)[4] == '=')
+ {
+ p = (*pp) + 5;
+ break;
+ }
+
+ cmd = (char *)find_in_given_path (argv[0], p);
+ }
+
+ if (!cmd)
+ {
+ r = ENOENT;
+ goto cleanup;
+ }
+
/* Start the program. */
- while ((r = posix_spawnp (&pid, argv[0], &fa, &attr, argv, child->environment)) == EINTR)
+ while ((r = posix_spawn (&pid, cmd, &fa, &attr, argv,
+ child->environment)) == EINTR)
;
+ /* posix_spawn() doesn't provide sh fallback like exec() does; implement
+ it here. POSIX doesn't specify the path to sh so use the default. */
+
+ if (r == ENOEXEC)
+ {
+ char **nargv;
+ char **pp;
+ size_t l = 0;
+
+ for (pp = argv; *pp != NULL; ++pp)
+ ++l;
+
+ nargv = xmalloc (sizeof (char *) * (l + 2));
+ nargv[0] = (char *)default_shell;
+ nargv[1] = cmd;
+ memcpy (&nargv[2], &argv[1], sizeof (char *) * l);
+
+ while ((r = posix_spawn (&pid, nargv[0], &fa, &attr, nargv,
+ child->environment)) == EINTR)
+ ;
+
+ free (nargv);
+ }
+
+ if (r == 0)
+ {
+ /* Spawn succeeded but may fail later: remember the command. */
+ free (child->cmd_name);
+ if (cmd != argv[0])
+ child->cmd_name = cmd;
+ else
+ child->cmd_name = xstrdup(cmd);
+ }
+
cleanup:
posix_spawn_file_actions_destroy (&fa);
posix_spawnattr_destroy (&attr);
if (r != 0)
pid = -1;
-#endif /* have posix_spawn() */
+#endif /* USE_POSIX_SPAWN */
if (pid < 0)
OSS (error, NILF, "%s: %s", argv[0], strerror (r));
!,
'', "hello; world\n");
+# TEST #21: SV-56834 Ensure setting PATH in a target var works properly
+mkdir('sd', 0775);
+open(my $fh, '>', 'sd/foobar');
+print $fh "exit 0";
+close($fh);
+chmod 0755, 'sd/foobar';
+
+run_make_test(q!
+all: PATH := sd
+all: ; foobar
+!,
+ '', "foobar\n");
+
+# Don't use the general PATH if not found on the target path
+
+$extraENV{PATH} = "$ENV{PATH}:sd";
+
+run_make_test(q!
+all: PATH := ..
+all: ; foobar
+!,
+ '', "foobar\n#MAKE#: foobar: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#;3: all] Error 127", 512);
+
+unlink('sd/foobar');
+rmdir ('sd');
+
# TEST #19: Test define/endef variables as target-specific vars
# run_make_test('
",
'', "hi\n");
+# SV-56834 Ensure setting PATH in the makefile works properly
+mkdir('sd', 0775);
+open(my $fh, '>', 'sd/foobar');
+print $fh "exit 0\n";
+close($fh);
+chmod 0755, 'sd/foobar';
+
+run_make_test(q!
+PATH := sd
+all: ; foobar
+!,
+ '', "foobar\n");
+
+# Don't use the general PATH if not found on the target path
+
+$extraENV{PATH} = "$ENV{PATH}:sd";
+
+run_make_test(q!
+PATH := ..
+all: ; foobar
+!,
+ '', "foobar\n#MAKE#: foobar: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#;3: all] Error 127", 512);
+
+unlink('sd/foobar');
+rmdir('sd');
+
+# Ensure that local programs are not found if "." is not on the PATH
+
+open(my $fh, '>', 'foobar');
+print $fh "exit 0\n";
+close($fh);
+chmod 0755, 'foobar';
+
+run_make_test(q!
+PATH := ..
+all: ; foobar
+!,
+ '', "foobar\n#MAKE#: foobar: $ERR_no_such_file\n#MAKE#: *** [#MAKEFILE#;3: all] Error 127", 512);
+
+unlink('foobar');
+
1;