Add posix_spawn and posix_spawnp for RedoxOS

This commit is contained in:
R Aadarsh
2026-05-14 18:47:42 +05:30
parent df78820f01
commit 1bc472e7e1
6 changed files with 190 additions and 35 deletions
+3 -3
View File
@@ -1086,10 +1086,10 @@ pub fn fork_inner(initial_rsp: *mut usize, args: &ForkArgs) -> Result<usize> {
}
pub struct NewChildProc {
proc_fd: Option<FdGuardUpper>,
pub proc_fd: Option<FdGuardUpper>,
thr_fd: FdGuardUpper,
pid: usize,
pub thr_fd: FdGuardUpper,
pub pid: usize,
}
pub fn new_child_process(args: &ForkArgs<'_>) -> Result<NewChildProc> {
+13 -16
View File
@@ -20,7 +20,7 @@ const FCHDIR: c_char = 4;
const DUP2: c_char = 5;
#[repr(C)]
enum Operation {
pub enum Operation {
Open {
fd: c_int,
path: *const c_char,
@@ -76,14 +76,13 @@ fn copy_op(file_actions: *mut posix_spawn_file_actions_t, op: Operation) -> Resu
pub unsafe extern "C" fn posix_spawn_file_actions_init(
file_actions: *mut posix_spawn_file_actions_t,
) -> c_int {
if file_actions.is_null() {
return EINVAL;
}
let file_actions = match unsafe { file_actions.as_mut().ok_or(Errno(EINVAL)) } {
Ok(v) => v,
Err(_) => return EINVAL,
};
unsafe {
(*file_actions).operation = null();
(*file_actions).size = 0;
}
(*file_actions).operation = null();
(*file_actions).size = 0;
0
}
@@ -92,15 +91,13 @@ pub unsafe extern "C" fn posix_spawn_file_actions_init(
pub unsafe extern "C" fn posix_spawn_file_actions_destroy(
file_actions: *mut posix_spawn_file_actions_t,
) -> c_int {
if file_actions.is_null() {
return EINVAL;
}
let file_actions = match unsafe { file_actions.as_mut().ok_or(Errno(EINVAL)) } {
Ok(v) => v,
Err(_) => return EINVAL,
};
unsafe {
free((*file_actions).operation as *mut c_void);
(*file_actions).operation = null();
(*file_actions).size = 0;
}
(*file_actions).operation = null();
(*file_actions).size = 0;
0
}
+92 -8
View File
@@ -5,21 +5,105 @@
mod file_actions;
mod spawn_attr;
use core::ffi::c_char;
pub use file_actions::{Operation, posix_spawn_file_actions_t};
pub use spawn_attr::{Flags, posix_spawnattr_t};
use crate::{
header::spawn::{file_actions::posix_spawn_file_actions_t, spawn_attr::posix_spawnattr_t},
platform::types::{c_int, pid_t},
c_str::CStr,
error::{Errno, Result},
header::{errno::ENOENT, stdlib::getenv},
platform::{
self, Pal,
types::{c_char, c_int, pid_t},
},
};
fn spawn(
mut program: &str,
file_actions: Option<&posix_spawn_file_actions_t>,
spawn_attr: Option<&posix_spawnattr_t>,
argv: *const *mut c_char,
envp: *const *mut c_char,
use_path: bool,
) -> Result<pid_t> {
if use_path {
let path_env = unsafe {
CStr::from_ptr(getenv("PATH".as_ptr() as *const c_char))
.to_str()
.unwrap()
};
let path_elements = path_env.split(':');
let program_name = program.split("/").last().unwrap();
let mut flag = false;
for element in path_elements {
if element.split("/").last().unwrap() == program_name {
flag = true;
program = element;
break;
}
if !flag {
return Err(Errno(ENOENT));
}
}
}
unsafe {
platform::Sys::spawn(
CStr::from_bytes_with_nul_unchecked(program.as_bytes()),
file_actions,
spawn_attr,
argv,
envp,
use_path,
)
}
}
#[unsafe(no_mangle)]
pub fn posix_spawn(
pub extern "C" fn posix_spawn(
pid: *const pid_t,
path: *const c_char,
program: *const c_char,
file_actions: *const posix_spawn_file_actions_t,
spawn_attr: *const posix_spawnattr_t,
argv: *const *const c_char,
envp: *const *const c_char,
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
todo!()
let program = unsafe { CStr::from_ptr(program).to_str().unwrap() };
match spawn(
program,
unsafe { file_actions.as_ref() },
unsafe { spawn_attr.as_ref() },
argv,
envp,
false,
) {
Ok(v) => v,
Err(e) => e.0,
}
}
#[unsafe(no_mangle)]
pub extern "C" fn posix_spawnp(
pid: *const pid_t,
program: *const c_char,
file_actions: *const posix_spawn_file_actions_t,
spawn_attr: *const posix_spawnattr_t,
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
let program = unsafe { CStr::from_ptr(program).to_str().unwrap() };
match spawn(
program,
unsafe { file_actions.as_ref() },
unsafe { spawn_attr.as_ref() },
argv,
envp,
true,
) {
Ok(v) => v,
Err(e) => e.0,
}
}
+5 -7
View File
@@ -13,7 +13,7 @@ use crate::header::{
};
bitflags::bitflags! {
struct Flags: c_short
pub struct Flags: c_short
{
const POSIX_SPAWN_RESETIDS = 1;
const POSIX_SPAWN_SETPGROUP = 2;
@@ -34,11 +34,11 @@ pub const POSIX_SPAWN_SETSCHEDULER: c_short = 6;
#[repr(C)]
pub struct posix_spawnattr_t {
pub(crate) param: sched_param,
flags: c_short,
pgroup: c_int,
pub(crate) flags: c_short,
pub(crate) pgroup: c_int,
policy: c_int,
sigdefault: sigset_t,
sigmask: sigset_t,
pub(crate) sigmask: sigset_t,
}
#[unsafe(no_mangle)]
@@ -217,9 +217,7 @@ pub unsafe extern "C" fn posix_spawnattr_getflags(
return EINVAL;
}
unsafe {
*flags = (*attr).flags;
}
unsafe { *flags = (*attr).flags }
0
}
+9
View File
@@ -433,6 +433,15 @@ pub trait Pal {
/// Platform implementation of [`setsid()`](crate::header::unistd::setsid) from [`unistd.h`](crate::header::unistd).
fn setsid() -> Result<c_int>;
unsafe fn spawn(
program: CStr,
fac: Option<&crate::header::spawn::posix_spawn_file_actions_t>,
fat: Option<&crate::header::spawn::posix_spawnattr_t>,
argv: *const *mut c_char,
envp: *const *mut c_char,
use_path: bool,
) -> Result<pid_t>;
/// Platform implementation of [`symlink()`](crate::header::unistd::symlink) from [`unistd.h`](crate::header::unistd).
fn symlink(path1: CStr, path2: CStr) -> Result<()> {
Self::symlinkat(path1, AT_FDCWD, path2)
+68 -1
View File
@@ -39,6 +39,7 @@ use crate::{
signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent},
stdio::RENAME_NOREPLACE,
stdlib::posix_memalign,
string::strlen,
sys_file,
sys_mman::{MAP_ANONYMOUS, PROT_READ, PROT_WRITE},
sys_random,
@@ -67,7 +68,7 @@ pub use redox_rt::proc::FdGuard;
mod epoll;
mod event;
mod exec;
pub(crate) mod exec;
mod extra;
mod libcscheme;
mod libredox;
@@ -1192,6 +1193,72 @@ impl Pal for Sys {
Ok(())
}
unsafe fn spawn(
program: CStr,
fac: Option<&crate::header::spawn::posix_spawn_file_actions_t>,
fat: Option<&crate::header::spawn::posix_spawnattr_t>,
mut argv: *const *mut c_char,
mut envp: *const *mut c_char,
use_path: bool,
) -> Result<pid_t> {
let child = redox_rt::proc::new_child_process(&redox_rt::proc::ForkArgs::Managed)?;
let executable = File::open(program, fcntl::O_RDONLY)?;
let cwd = path::clone_cwd().unwrap();
let proc_fd = child.proc_fd.unwrap();
let extra_info = redox_rt::proc::ExtraInfo {
cwd: Some(cwd.as_bytes()),
sigignmask: redox_rt::signal::get_sigignmask_to_inherit(),
sigprocmask: if let Some(fat) = fat
&& crate::header::spawn::Flags::from_bits(fat.flags)
.unwrap()
.contains(crate::header::spawn::Flags::POSIX_SPAWN_SETSIGMASK)
{
fat.sigmask
} else {
redox_rt::signal::get_sigmask().unwrap()
},
umask: redox_rt::sys::get_umask(),
thr_fd: child.thr_fd.as_raw_fd(),
proc_fd: proc_fd.as_raw_fd(),
ns_fd: redox_rt::current_namespace_fd().ok(),
cwd_fd: path::current_dir()
.ok()
.map(|fd| fd.as_ref().unwrap().fd.as_raw_fd()),
};
let mut args = Vec::new();
let mut envs = Vec::new();
while unsafe { !(*argv).is_null() } {
let arg = unsafe { *argv };
let len = unsafe { strlen(arg) };
args.push(unsafe { slice::from_raw_parts(arg as *const u8, len) });
argv = unsafe { argv.add(1) };
}
while unsafe { !(*envp).is_null() } {
let env = unsafe { *envp };
let len = unsafe { strlen(env) };
envs.push(unsafe { slice::from_raw_parts(env as *const u8, len) });
envp = unsafe { envp.add(1) };
}
redox_rt::proc::fexec_impl(
FdGuard::new(executable.fd as usize).to_upper().unwrap(),
&child.thr_fd,
&proc_fd,
program.to_bytes(),
args.as_slice(),
envs.as_slice(),
&extra_info,
None,
)
.map_err(|_| syscall::error::Error::new(syscall::error::ENOEXEC))?;
Ok(i32::try_from(child.pid).unwrap())
}
fn symlinkat(path1: CStr, fd: c_int, path2: CStr) -> Result<()> {
let mut file = File::createat(
fd,