diff --git a/src/header/spawn/mod.rs b/src/header/spawn/mod.rs index 7290714e08..f7b6feca2f 100644 --- a/src/header/spawn/mod.rs +++ b/src/header/spawn/mod.rs @@ -47,6 +47,7 @@ unsafe fn spawn( ERRNO.get() ); + let mut path_path = None; if use_path { let path = unsafe { getenv(c"PATH".as_ptr()) }; let path_env = unsafe { CStr::from_nullable_ptr(path).unwrap().to_str().unwrap() }; @@ -70,10 +71,12 @@ unsafe fn spawn( CStr::from_ptr(dir_ent.d_name.as_ptr() as *const c_char) .to_str() .unwrap() + .to_string() }; if dir_ent_name == program { flag = true; program = format!("{}/{}", path_element, program); + path_path = Some(path_element.to_string()); break 'a; } } @@ -93,7 +96,7 @@ unsafe fn spawn( spawn_attr, argv, envp, - use_path, + path_path, ) .map(|v| { if let Some(pid) = pid { diff --git a/src/platform/linux/mod.rs b/src/platform/linux/mod.rs index 856e5128ad..bc3cb308ab 100644 --- a/src/platform/linux/mod.rs +++ b/src/platform/linux/mod.rs @@ -1,6 +1,8 @@ #[cfg(target_arch = "x86_64")] use core::arch::asm; +use alloc::string::String; + use super::{Pal, types::*}; use crate::{ c_str::CStr, @@ -800,7 +802,7 @@ impl Pal for Sys { fat: Option<&crate::header::spawn::posix_spawnattr_t>, argv: crate::iter::NulTerminated<*mut c_char>, envp: Option>, - use_path: bool, + dir_ent_name: Option, ) -> Result { todo!() } diff --git a/src/platform/mod.rs b/src/platform/mod.rs index d9ec7cfee6..36cf5c01b6 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -24,7 +24,7 @@ pub use self::sys::Sys; #[path = "linux/mod.rs"] pub(crate) mod sys; -#[cfg(target_os = "redox")] +// #[cfg(target_os = "redox")] #[path = "redox/mod.rs"] pub(crate) mod sys; diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 194535eb17..75a706605d 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -1,5 +1,7 @@ use core::num::NonZeroU64; +use alloc::string::String; + use super::types::*; use crate::{ c_str::CStr, @@ -440,7 +442,7 @@ pub trait Pal { fat: Option<&crate::header::spawn::posix_spawnattr_t>, argv: NulTerminated<*mut c_char>, envp: Option>, - use_path: bool, + dir_ent_name: Option, ) -> Result; /// Platform implementation of [`symlink()`](crate::header::unistd::symlink) from [`unistd.h`](crate::header::unistd). diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 50346fce4c..f496b4d2ab 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -1207,7 +1207,7 @@ impl Pal for Sys { fat: Option<&crate::header::spawn::posix_spawnattr_t>, argv: NulTerminated<*mut c_char>, envp: Option>, - use_path: bool, + dir_ent_name: Option, ) -> Result { use crate::header::spawn::Flags; @@ -1242,11 +1242,20 @@ impl Pal for Sys { let mut program_name = String::new(); - program_name = redox_path::canonicalize_using_cwd( - Some(original_cwd.as_str()), - str::from_utf8(args[0]).unwrap(), - ) - .ok_or(Errno(ENOENT))?; + if let Some(ent) = dir_ent_name { + let mut binary = str::from_utf8(args[0]).unwrap().to_string(); + binary.insert_str(0, "./"); + + program_name = redox_path::canonicalize_using_cwd(Some(ent.as_str()), binary.as_str()) + .ok_or(Errno(ENOENT))?; + } else { + program_name = redox_path::canonicalize_using_cwd( + Some(original_cwd.as_str()), + str::from_utf8(args[0]).unwrap(), + ) + .ok_or(Errno(ENOENT))?; + } + args[0] = program_name.as_bytes(); let new_file_table = child.thr_fd.dup(b"filetable")?; diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk index dddebeed2d..5f62e1f8cc 100644 --- a/tests/Makefile.tests.mk +++ b/tests/Makefile.tests.mk @@ -11,7 +11,7 @@ FAILING_TESTS += malloc/usable_size FAILING_TESTS += mkfifo # Waitpid had EINTR FAILING_TESTS += sigchld -# not triggering ERANGE +# not triggering ERANGE FAILING_TESTS += stdlib/ptsname # Hang FAILING_TESTS += sys_epoll/epollet @@ -77,7 +77,8 @@ EXPECT_NAMES=\ sigaltstack \ signal \ sigsetjmp \ - spawn \ + spawn/file_actions \ + spawn/spawn_attr \ stdio/all \ stdio/buffer \ stdio/dprintf \ diff --git a/tests/expected/spawn/file_actions.stdout b/tests/expected/spawn/file_actions.stdout new file mode 100644 index 0000000000..f0ad0dec66 --- /dev/null +++ b/tests/expected/spawn/file_actions.stdout @@ -0,0 +1 @@ +hello.txt diff --git a/tests/expected/spawn/spawn_attr.stdout b/tests/expected/spawn/spawn_attr.stdout new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/spawn.c b/tests/spawn.c deleted file mode 100644 index b55f1d4286..0000000000 --- a/tests/spawn.c +++ /dev/null @@ -1,92 +0,0 @@ -#include -#include -#include -#include -#include - -#include "test_helpers.h" - -#define CHECK(cond, msg) \ - if (!cond) \ - { \ - fprintf(stderr, "Error in spawn.h: %s\n", msg); \ - _exit(EXIT_FAILURE); \ - } - -#define CHECK_WHEN_NULL(call, name) \ - if (!(call)) \ - { \ - fprintf(stderr, "Error in spawn.h: %s expected to fail when passing NULL\n", name); \ - _exit(EXIT_FAILURE); \ - } - -int main() -{ - posix_spawn_file_actions_t fa_t; - CHECK((posix_spawn_file_actions_init(&fa_t) == 0), "posix_spawn_file_actions_init failed") - CHECK_WHEN_NULL(posix_spawn_file_actions_init(NULL), "posix_spawn_file_actions_init") - CHECK((posix_spawn_file_actions_addopen(&fa_t, 1, ".", O_RDONLY, 1) == 0), "Error while adding open action") - CHECK((posix_spawn_file_actions_addclose(&fa_t, 1) == 0), "Error while adding close action") - CHECK((posix_spawn_file_actions_adddup2(&fa_t, -1, 3) == EBADF), "Adding dup2 with negative fd must fail") - CHECK((fa_t.size == 64), "Size remains unchanged") - CHECK_WHEN_NULL(posix_spawn_file_actions_destroy(NULL), "posix_spawn_file_actions_destroy") - CHECK_WHEN_NULL(posix_spawn_file_actions_addclose(NULL, 1), "posix_spawn_file_actions_addclose") - CHECK((posix_spawn_file_actions_destroy(&fa_t) == 0), "posix_spawn_file_actions_destroy failed") - CHECK((fa_t.size == 0), "Expected 0 size in posix_spawn_file_actions_t after destruction") - - posix_spawnattr_t sa; - CHECK((posix_spawnattr_init(&sa) == 0), "posix_spawnattr_init failed") - CHECK((sa.param.sched_priority == 0 && sa.flags == 0 && sa.pgroup == 0 && sa.policy == 0 && sa.sigdefault == 0 && sa.sigmask == 0), "All fields expected to be zero after init in posix_spawnattr_t") - CHECK_WHEN_NULL(posix_spawnattr_init(NULL), "posix_spawnattr_init") - CHECK_WHEN_NULL(posix_spawnattr_destroy(NULL), "posix_spawnattr_destroy") - - struct sched_param sp1; - sp1.sched_priority = 2; - struct sched_param sp2; - sp2.sched_priority = 0; - CHECK_WHEN_NULL(posix_spawnattr_setschedparam(NULL, &sp1), "posix_spawnattr_setschedparam") - CHECK_WHEN_NULL(posix_spawnattr_setschedparam(&sa, NULL), "posix_spawnattr_setschedparam") - CHECK((posix_spawnattr_setschedparam(&sa, &sp1) == 0), "posix_spawnattr_setschedparam failed") - CHECK_WHEN_NULL(posix_spawnattr_getschedparam(NULL, &sp2), "posix_spawnattr_getschedparam") - CHECK_WHEN_NULL(posix_spawnattr_getschedparam(&sa, NULL), "posix_spawnattr_getschedparam") - CHECK((posix_spawnattr_getschedparam(&sa, &sp2) == 0 && sp2.sched_priority == 2), "posix_spawnattr_getschedparam failed") - - CHECK_WHEN_NULL(posix_spawnattr_setschedpolicy(NULL, 0), "posix_spawnattr_setschedpolicy") - CHECK((posix_spawnattr_setschedpolicy(&sa, 1) == 0), "posix_spawnattr_setschedpolicy failed") - int pol = 0; - CHECK_WHEN_NULL(posix_spawnattr_getschedpolicy(NULL, &pol), "posix_spawnattr_getschedpolicy") - CHECK_WHEN_NULL(posix_spawnattr_getschedpolicy(&sa, NULL), "posix_spawnattr_getschedpolicy") - CHECK((posix_spawnattr_getschedpolicy(&sa, &pol) == 0 && pol == 1), "posix_spawnattr_getschedpolicy failed") - - sigset_t sst = 1; - sigset_t sst2 = 0; - CHECK_WHEN_NULL(posix_spawnattr_setsigdefault(NULL, &sst), "posix_spawnattr_setsigdefault") - CHECK_WHEN_NULL(posix_spawnattr_setsigdefault(&sa, NULL), "posix_spawnattr_setsigdefault") - CHECK((posix_spawnattr_setsigdefault(&sa, &sst) == 0), "posix_spawnattr_setsigdefault failed") - CHECK((posix_spawnattr_getsigdefault(&sa, &sst2) == 0 && sst2 == 1), "posix_spawnattr_getsigdefault failed") - CHECK_WHEN_NULL(posix_spawnattr_getsigdefault(NULL, &sst2), "posix_spawnattr_getsigdefault") - CHECK_WHEN_NULL(posix_spawnattr_getsigdefault(&sa, NULL), "posix_spawnattr_getsigdefault") - - sst = 3; - CHECK_WHEN_NULL(posix_spawnattr_setsigmask(NULL, &sst), "posix_spawnattr_setsigmask") - CHECK_WHEN_NULL(posix_spawnattr_setsigmask(&sa, NULL), "posix_spawnattr_setsigmask") - CHECK((posix_spawnattr_setsigmask(&sa, &sst) == 0), "posix_spawnattr_setsigmask failed") - CHECK_WHEN_NULL(posix_spawnattr_getsigmask(NULL, &sst2), "posix_spawnattr_getsigmask") - CHECK_WHEN_NULL(posix_spawnattr_getsigmask(&sa, NULL), "posix_spawnattr_getsigmask") - CHECK((posix_spawnattr_getsigmask(&sa, &sst2) == 0 && sst2 == 3), "posix_spawnattr_getsigmask failed") - - CHECK_WHEN_NULL(posix_spawnattr_setflags(NULL, 0), "posix_spawnattr_setflags") - CHECK((posix_spawnattr_setflags(&sa, 1) == 0), "posix_spawnattr_setflags failed") - short int pf = 0; - CHECK_WHEN_NULL(posix_spawnattr_getflags(NULL, &pf), "posix_spawnattr_getflags") - CHECK_WHEN_NULL(posix_spawnattr_getflags(&sa, NULL), "posix_spawnattr_getflags") - CHECK((posix_spawnattr_getflags(&sa, &pf) == 0 && pf == 1), "posix_spawnattr_getflags failed") - CHECK((posix_spawnattr_setflags(&sa, 7565) == EINVAL), "posix_spawnattr_setflags expected to fail when passing invalid bits") - - pid_t id = 0; - CHECK_WHEN_NULL(posix_spawnattr_setpgroup(NULL, 3), "posix_spawnattr_setpgroup") - CHECK((posix_spawnattr_setpgroup(&sa, 3) == 0), "posix_spawnattr_setpgroup failed") - CHECK_WHEN_NULL(posix_spawnattr_getpgroup(NULL, &id), "posix_spawnattr_getpgroup") - CHECK_WHEN_NULL(posix_spawnattr_getpgroup(&sa, NULL), "posix_spawnattr_getpgroup") - CHECK((posix_spawnattr_getpgroup(&sa, &id) == 0 && id == 3), "posix_spawnattr_getpgroup failed") -} diff --git a/tests/spawn/file_actions.c b/tests/spawn/file_actions.c new file mode 100644 index 0000000000..d22ef9bfdc --- /dev/null +++ b/tests/spawn/file_actions.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ERROR_IF(func, status, condition) \ + do { \ + if (status condition) { \ + fprintf(stderr, "%s:%s:%d: '%s' failed: %s (%d)\n", __FILE__, __func__, \ + __LINE__, #func, strerror(errno), errno); \ + _exit(EXIT_FAILURE); \ + } \ + } while (0) + +#define OPTIONALLY_ERROR(function, args, cond) \ + { \ + int x = function args; \ + if (!(x cond)) { \ + printf("%s failed with error: %s\n", #function, strerror(x)); \ + exit(EXIT_FAILURE); \ + } \ + } + +extern char **environ; + +int main() { + pid_t pid = 0; + char cwd[PATH_MAX]; + int status = 0; + char *__cwd = getcwd(cwd, PATH_MAX); + ERROR_IF(getcwd, __cwd, == NULL); + char target[PATH_MAX]; + strcpy(target, cwd); + strcat(target, "/hello"); + + // TEST: chdir and open + char *argv1[] = {"ls", target, NULL}; + posix_spawn_file_actions_t fa; + posix_spawn_file_actions_init(&fa); + status = mkdir("./hello", S_IRUSR | S_IWUSR); + ERROR_IF(mkdir, status, != 0); + OPTIONALLY_ERROR(posix_spawn_file_actions_addchdir, (&fa, "./hello"), == 0); + OPTIONALLY_ERROR(posix_spawn_file_actions_addopen, + (&fa, 2, "./hello.txt", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR), + == 0); + OPTIONALLY_ERROR(posix_spawnp, (&pid, "ls", &fa, NULL, argv1, environ), == 0); + assert(pid != 0); + waitpid(pid, NULL, 0); + OPTIONALLY_ERROR(posix_spawn_file_actions_destroy, (&fa), == 0); + + pid = 0; + + // TEST: close + argv1[0] = "/usr/bin/ls"; + OPTIONALLY_ERROR(posix_spawn_file_actions_init, (&fa), == 0); + OPTIONALLY_ERROR(posix_spawn_file_actions_addclose, (&fa, 1), == 0); + OPTIONALLY_ERROR(posix_spawn, + (&pid, "/usr/bin/ls", &fa, NULL, argv1, environ), == 0); + assert(pid != 0); + waitpid(pid, NULL, 0); + OPTIONALLY_ERROR(posix_spawn_file_actions_destroy, (&fa), == 0); + status = unlink("./hello/hello.txt"); + ERROR_IF(unlink, status, != 0); + status = rmdir("./hello"); + ERROR_IF(rmdir, status, != 0); +} diff --git a/tests/spawn/spawn_attr.c b/tests/spawn/spawn_attr.c new file mode 100644 index 0000000000..237c8ce181 --- /dev/null +++ b/tests/spawn/spawn_attr.c @@ -0,0 +1 @@ +int main() {}