Add posix_spawn and posix_spawnp for RedoxOS
This commit is contained in:
@@ -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> {
|
||||
|
||||
@@ -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
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user