| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| //===-- Linux implementation of execve ------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/unistd/execve.h" | ||
| #include "src/unistd/environ.h" | ||
|
|
||
| #include "src/__support/OSUtil/syscall.h" // For internal syscall function. | ||
| #include "src/__support/common.h" | ||
|
|
||
| #include <errno.h> | ||
| #include <sys/syscall.h> // For syscall numbers. | ||
|
|
||
| namespace __llvm_libc { | ||
|
|
||
| LLVM_LIBC_FUNCTION(int, execve, | ||
| (const char *path, char *const argv[], char *const envp[])) { | ||
| long ret = __llvm_libc::syscall_impl(SYS_execve, path, argv, envp); | ||
| if (ret < 0) { | ||
| errno = -ret; | ||
| return -1; | ||
| } | ||
|
|
||
| // Control will not reach here on success but have a return statement will | ||
| // keep the compilers happy. | ||
| return ret; | ||
| } | ||
|
|
||
| } // namespace __llvm_libc |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| //===-- Unittests for execv -----------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/sys/wait/waitpid.h" | ||
| #include "src/unistd/execv.h" | ||
| #include "src/unistd/fork.h" | ||
|
|
||
| #include "utils/IntegrationTest/test.h" | ||
|
|
||
| #include <signal.h> | ||
| #include <sys/wait.h> | ||
|
|
||
| void fork_and_execv_normal_exit() { | ||
| pid_t pid = __llvm_libc::fork(); | ||
| if (pid == 0) { | ||
| const char *path = "libc_execv_test_normal_exit"; | ||
| char *const argv[] = { | ||
| const_cast<char *>("execv_test_normal_exit"), | ||
| nullptr, | ||
| }; | ||
| __llvm_libc::execv(path, argv); | ||
| } | ||
| ASSERT_TRUE(pid > 0); | ||
| int status; | ||
| pid_t cpid = __llvm_libc::waitpid(pid, &status, 0); | ||
| ASSERT_TRUE(cpid > 0); | ||
| ASSERT_EQ(cpid, pid); | ||
| ASSERT_TRUE(WIFEXITED(status)); | ||
| } | ||
|
|
||
| void fork_and_execv_signal_exit() { | ||
| pid_t pid = __llvm_libc::fork(); | ||
| if (pid == 0) { | ||
| const char *path = "libc_execv_test_signal_exit"; | ||
| char *const argv[] = { | ||
| const_cast<char *>("execv_test_normal_exit"), | ||
| nullptr, | ||
| }; | ||
| __llvm_libc::execv(path, argv); | ||
| } | ||
| ASSERT_TRUE(pid > 0); | ||
| int status; | ||
| pid_t cpid = __llvm_libc::waitpid(pid, &status, 0); | ||
| ASSERT_TRUE(cpid > 0); | ||
| ASSERT_EQ(cpid, pid); | ||
| ASSERT_FALSE(WIFEXITED(status)); | ||
| ASSERT_TRUE(WTERMSIG(status) == SIGUSR1); | ||
| } | ||
|
|
||
| TEST_MAIN(int argc, char **argv, char **envp) { | ||
| fork_and_execv_normal_exit(); | ||
| fork_and_execv_signal_exit(); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #include <signal.h> | ||
| #include <stdlib.h> | ||
| #include <unistd.h> | ||
|
|
||
| int main() { | ||
| char *env = getenv("EXECV_TEST"); | ||
| if (env == nullptr) | ||
| raise(SIGUSR1); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| #include <signal.h> | ||
| #include <stdlib.h> | ||
| #include <unistd.h> | ||
|
|
||
| int main() { | ||
| char *env = getenv("__MISSING_ENV_VAR__"); | ||
| if (env == nullptr) | ||
| raise(SIGUSR1); | ||
| return 0; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| //===-- Unittests for execve ----------------------------------------------===// | ||
| // | ||
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | ||
| // See https://llvm.org/LICENSE.txt for license information. | ||
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #include "src/sys/wait/waitpid.h" | ||
| #include "src/unistd/execve.h" | ||
| #include "src/unistd/fork.h" | ||
|
|
||
| #include "utils/IntegrationTest/test.h" | ||
|
|
||
| #include <signal.h> | ||
| #include <sys/wait.h> | ||
|
|
||
| void fork_and_execv_normal_exit(char **envp) { | ||
| pid_t pid = __llvm_libc::fork(); | ||
| if (pid == 0) { | ||
| const char *path = "libc_execv_test_normal_exit"; | ||
| char *const argv[] = { | ||
| const_cast<char *>("execv_test_normal_exit"), | ||
| nullptr, | ||
| }; | ||
| __llvm_libc::execve(path, argv, envp); | ||
| } | ||
| ASSERT_TRUE(pid > 0); | ||
| int status; | ||
| pid_t cpid = __llvm_libc::waitpid(pid, &status, 0); | ||
| ASSERT_TRUE(cpid > 0); | ||
| ASSERT_EQ(cpid, pid); | ||
| ASSERT_TRUE(WIFEXITED(status)); | ||
| } | ||
|
|
||
| void fork_and_execv_signal_exit(char **envp) { | ||
| pid_t pid = __llvm_libc::fork(); | ||
| if (pid == 0) { | ||
| const char *path = "libc_execv_test_signal_exit"; | ||
| char *const argv[] = { | ||
| const_cast<char *>("execv_test_normal_exit"), | ||
| nullptr, | ||
| }; | ||
| __llvm_libc::execve(path, argv, envp); | ||
| } | ||
| ASSERT_TRUE(pid > 0); | ||
| int status; | ||
| pid_t cpid = __llvm_libc::waitpid(pid, &status, 0); | ||
| ASSERT_TRUE(cpid > 0); | ||
| ASSERT_EQ(cpid, pid); | ||
| ASSERT_FALSE(WIFEXITED(status)); | ||
| ASSERT_TRUE(WTERMSIG(status) == SIGUSR1); | ||
| } | ||
|
|
||
| TEST_MAIN(int argc, char **argv, char **envp) { | ||
| fork_and_execv_normal_exit(envp); | ||
| fork_and_execv_signal_exit(envp); | ||
| return 0; | ||
| } |