* Correctly determine argv[0]
- If the function called is `posix_spawnp`, and the passed program name **does not** contain a slash, the path is used unmodified, and the path to the directory containing the program on $PATH is prepended to the program's path and assigned to `argv[0]. If the program name **does** contain a slash, the path is absolutised relative to CWD, and assigned to argv[0]
- If the function called is `posix_spawn`, the behaviour is as described above in the case where path contains a slash
* Add initial tests
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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<crate::iter::NulTerminated<*mut c_char>>,
|
||||
use_path: bool,
|
||||
dir_ent_name: Option<String>,
|
||||
) -> Result<pid_t> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
@@ -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<NulTerminated<*mut c_char>>,
|
||||
use_path: bool,
|
||||
dir_ent_name: Option<String>,
|
||||
) -> Result<pid_t>;
|
||||
|
||||
/// Platform implementation of [`symlink()`](crate::header::unistd::symlink) from [`unistd.h`](crate::header::unistd).
|
||||
|
||||
@@ -1207,7 +1207,7 @@ impl Pal for Sys {
|
||||
fat: Option<&crate::header::spawn::posix_spawnattr_t>,
|
||||
argv: NulTerminated<*mut c_char>,
|
||||
envp: Option<NulTerminated<*mut c_char>>,
|
||||
use_path: bool,
|
||||
dir_ent_name: Option<String>,
|
||||
) -> Result<pid_t> {
|
||||
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")?;
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
hello.txt
|
||||
@@ -1,92 +0,0 @@
|
||||
#include <spawn.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <bits/sigset-t.h>
|
||||
#include <sched.h>
|
||||
|
||||
#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")
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <assert.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sched.h>
|
||||
#include <spawn.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
int main() {}
|
||||
Reference in New Issue
Block a user