diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 022f8737d1..f9ac9c3017 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -655,7 +655,7 @@ pub fn setup_sighandler(tcb: &RtTcb, first_thread: bool) { #[cfg(target_arch = "x86_64")] { - let cpuid_eax1_ecx = unsafe { core::arch::x86_64::__cpuid(1) }.ecx; + let cpuid_eax1_ecx = core::arch::x86_64::__cpuid(1).ecx; CPUID_EAX1_ECX.store(cpuid_eax1_ecx, core::sync::atomic::Ordering::Relaxed); SUPPORTS_AVX.store(u8::from(cpuid_eax1_ecx & 1 << 28 != 0), Ordering::Relaxed); } diff --git a/src/header/err/mod.rs b/src/header/err/mod.rs index 5e47ee4e7c..9cc963d4b3 100644 --- a/src/header/err/mod.rs +++ b/src/header/err/mod.rs @@ -65,9 +65,9 @@ pub unsafe extern "C" fn err_set_exit(ef: ExitCallback) { /// # Return /// Does not return. Exits with `eval` as an error code. #[unsafe(no_mangle)] -pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, mut va_list: ...) -> ! { +pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, va_list: ...) -> ! { let code = Some(ERRNO.get()); - err_exit(eval, code, fmt, va_list.as_va_list()) + err_exit(eval, code, fmt, va_list) } /// Print a user message then an error message for `code` before exiting with `eval` as a return. @@ -77,8 +77,8 @@ pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, mut va_list: ...) /// # Return /// Exits with `eval` as an error code. #[unsafe(no_mangle)] -pub unsafe extern "C" fn errc(eval: c_int, code: c_int, fmt: *const c_char, mut va_list: ...) -> ! { - err_exit(eval, Some(code), fmt, va_list.as_va_list()) +pub unsafe extern "C" fn errc(eval: c_int, code: c_int, fmt: *const c_char, va_list: ...) -> ! { + err_exit(eval, Some(code), fmt, va_list) } /// Print a user message then exits with `eval` as a return. @@ -88,33 +88,33 @@ pub unsafe extern "C" fn errc(eval: c_int, code: c_int, fmt: *const c_char, mut /// # Return /// Exits with `eval` as an error code. #[unsafe(no_mangle)] -pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, mut va_list: ...) -> ! { - err_exit(eval, None, fmt, va_list.as_va_list()) +pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, va_list: ...) -> ! { + err_exit(eval, None, fmt, va_list) } /// Print a user message and then an error message for [`ERRNO`]. /// /// The message format is `progname: fmt: strerror(ERRNO)` #[unsafe(no_mangle)] -pub unsafe extern "C" fn warn(fmt: *const c_char, mut va_list: ...) { +pub unsafe extern "C" fn warn(fmt: *const c_char, va_list: ...) { let code = Some(ERRNO.get()); - display_message(code, fmt, va_list.as_va_list()); + display_message(code, fmt, va_list); } /// Print a user message then an error message for `code`. /// /// The message format is `progname: fmt: strerror(code)` #[unsafe(no_mangle)] -pub unsafe extern "C" fn warnc(code: c_int, fmt: *const c_char, mut va_list: ...) { - display_message(Some(code), fmt, va_list.as_va_list()); +pub unsafe extern "C" fn warnc(code: c_int, fmt: *const c_char, va_list: ...) { + display_message(Some(code), fmt, va_list); } /// Print a user message as a warning. /// /// The message format is `progname: fmt` #[unsafe(no_mangle)] -pub unsafe extern "C" fn warnx(fmt: *const c_char, mut va_list: ...) { - display_message(None, fmt, va_list.as_va_list()); +pub unsafe extern "C" fn warnx(fmt: *const c_char, va_list: ...) { + display_message(None, fmt, va_list); } /// See [`err`]. diff --git a/src/header/fcntl/mod.rs b/src/header/fcntl/mod.rs index 972575fff4..4baf961139 100644 --- a/src/header/fcntl/mod.rs +++ b/src/header/fcntl/mod.rs @@ -71,7 +71,7 @@ pub unsafe extern "C" fn fcntl(fildes: c_int, cmd: c_int, mut __valist: ...) -> // c_ulonglong let arg = match cmd { F_DUPFD | F_SETFD | F_SETFL | F_GETLK | F_SETLK | F_SETLKW | F_OFD_GETLK | F_OFD_SETLK - | F_OFD_SETLKW | F_DUPFD_CLOEXEC => unsafe { __valist.arg::() }, + | F_OFD_SETLKW | F_DUPFD_CLOEXEC => unsafe { __valist.next_arg::() }, _ => 0, }; @@ -112,7 +112,7 @@ pub unsafe extern "C" fn openat( let mode = if oflag & O_CREAT == O_CREAT /* || oflag & O_TMPFILE == O_TMPFILE */ { - unsafe { __valist.arg::() } + unsafe { __valist.next_arg::() } } else { 0 }; diff --git a/src/header/mod.rs b/src/header/mod.rs index 3eecb0057e..6e65c4b23e 100644 --- a/src/header/mod.rs +++ b/src/header/mod.rs @@ -76,7 +76,7 @@ pub mod setjmp; pub mod sgtty; pub mod shadow; pub mod signal; -// TODO: spawn.h +pub mod spawn; // TODO: stdalign.h (likely C implementation) // stdarg.h implemented in C // stdatomic.h implemented in C diff --git a/src/header/monetary/strfmon.rs b/src/header/monetary/strfmon.rs index c0f380604e..eae658362c 100644 --- a/src/header/monetary/strfmon.rs +++ b/src/header/monetary/strfmon.rs @@ -122,7 +122,7 @@ pub unsafe extern "C" fn strfmon( Some('i') => { // International formatting flags.international = true; - let value = unsafe { args.arg::() }; // Get the argument as f64 + let value = unsafe { args.next_arg::() }; // Get the argument as f64 if let Some(written) = format_monetary(&mut buffer[pos..], value, &DEFAULT_MONETARY, &flags) { @@ -133,7 +133,7 @@ pub unsafe extern "C" fn strfmon( } Some('n') => { // Locale-specific formatting - let value = unsafe { args.arg::() }; // Get the argument as f64 + let value = unsafe { args.next_arg::() }; // Get the argument as f64 if let Some(written) = format_monetary(&mut buffer[pos..], value, &DEFAULT_MONETARY, &flags) { diff --git a/src/header/spawn/cbindgen.toml b/src/header/spawn/cbindgen.toml new file mode 100644 index 0000000000..1b170fbc45 --- /dev/null +++ b/src/header/spawn/cbindgen.toml @@ -0,0 +1,21 @@ +sys_includes = ["sys/types.h", "signal.h", "sched.h"] +include_guard = "_RELIBC_SPAWN_H" +language = "C" +style = "Tag" +no_includes = true +cpp_compat = true + +[enum] +prefix_with_name = true + +[export] +include = [ + "posix_spawn_file_actions_t", + "posix_spawnattr_t", + "POSIX_SPAWN_RESETIDS", + "POSIX_SPAWN_SETPGROUP", + "POSIX_SPAWN_SETSIGDEF", + "POSIX_SPAWN_SETSIGMASK", + "POSIX_SPAWN_SETSCHEDULER", + "POSIX_SPAWN_SETSCHEDPARAM", +] diff --git a/src/header/spawn/mod.rs b/src/header/spawn/mod.rs new file mode 100644 index 0000000000..f44bf2d79a --- /dev/null +++ b/src/header/spawn/mod.rs @@ -0,0 +1,625 @@ +// POSIX spawn.h implementation +// Spec: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/spawn.h.html +// +// posix_spawn / posix_spawnp are implemented as fork + file actions + exec. +// File actions and spawn attributes are stored in opaque buffers embedded +// directly in the public types (no heap indirection for the struct itself; +// action entries use a linked list allocated on the heap). + +use alloc::boxed::Box; +use alloc::ffi::CString; +use core::mem; +use core::ptr; + +use crate::{ + c_str::CStr, + header::{ + errno::EINVAL, + signal, + unistd, + }, + platform::{self, Pal, Sys, types::*}, +}; + +// ─── Flags ─────────────────────────────────────────────────────────────────── + +pub const POSIX_SPAWN_RESETIDS: c_short = 0x01; +pub const POSIX_SPAWN_SETPGROUP: c_short = 0x02; +pub const POSIX_SPAWN_SETSIGDEF: c_short = 0x04; +pub const POSIX_SPAWN_SETSIGMASK: c_short = 0x08; +pub const POSIX_SPAWN_SETSCHEDULER: c_short = 0x10; +pub const POSIX_SPAWN_SETSCHEDPARAM: c_short = 0x20; + +// ─── Internal types ────────────────────────────────────────────────────────── + +const ACTION_KIND_OPEN: c_int = 1; +const ACTION_KIND_CLOSE: c_int = 2; +const ACTION_KIND_DUP2: c_int = 3; + +#[repr(C)] +struct ActionNode { + kind: c_int, + fd: c_int, + newfd: c_int, + oflag: c_int, + mode: c_int, + path_ptr: *mut c_char, + next: *mut ActionNode, +} + +#[repr(C)] +struct ActionsInner { + magic: u32, + head: *mut ActionNode, + tail: *mut ActionNode, +} + +#[repr(C)] +struct AttrsInner { + magic: u32, + flags: c_short, + pgroup: pid_t, + sigdefault: c_ulonglong, + sigmask: c_ulonglong, +} + +const ACTIONS_MAGIC: u32 = 0x53504641; // "SPFA" +const ATTRS_MAGIC: u32 = 0x53504154; // "SPAT" + +// ─── Public opaque types ───────────────────────────────────────────────────── +// Sized to hold their respective Inner types with room to spare. + +/// See . +#[repr(C)] +pub struct posix_spawn_file_actions_t { + __data: [u64; 8], +} + +/// See . +#[repr(C)] +pub struct posix_spawnattr_t { + __data: [u64; 16], +} + +const _: () = assert!(mem::size_of::() <= mem::size_of::()); +const _: () = assert!(mem::size_of::() <= mem::size_of::()); + +fn actions_as_inner(a: *mut posix_spawn_file_actions_t) -> *mut ActionsInner { + a.cast() +} + +fn attrs_as_inner(a: *mut posix_spawnattr_t) -> *mut AttrsInner { + a.cast() +} + +unsafe fn free_action_list(head: *mut ActionNode) { + let mut cur = head; + while !cur.is_null() { + let node = unsafe { Box::from_raw(cur) }; + if !node.path_ptr.is_null() { + drop(unsafe { CString::from_raw(node.path_ptr) }); + } + cur = node.next; + } +} + +// ─── File actions API ──────────────────────────────────────────────────────── + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn_file_actions_init( + actions: *mut posix_spawn_file_actions_t, +) -> c_int { + if actions.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = actions_as_inner(actions); + unsafe { + (*inner).magic = ACTIONS_MAGIC; + (*inner).head = ptr::null_mut(); + (*inner).tail = ptr::null_mut(); + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn_file_actions_destroy( + actions: *mut posix_spawn_file_actions_t, +) -> c_int { + if actions.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = actions_as_inner(actions); + unsafe { + if (*inner).magic != ACTIONS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + free_action_list((*inner).head); + (*inner).magic = 0; + (*inner).head = ptr::null_mut(); + (*inner).tail = ptr::null_mut(); + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn_file_actions_addclose( + actions: *mut posix_spawn_file_actions_t, + fd: c_int, +) -> c_int { + if actions.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = actions_as_inner(actions); + unsafe { + if (*inner).magic != ACTIONS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + } + + let node = Box::into_raw(Box::new(ActionNode { + kind: ACTION_KIND_CLOSE, + fd, + newfd: -1, + oflag: 0, + mode: 0, + path_ptr: ptr::null_mut(), + next: ptr::null_mut(), + })); + + unsafe { append_action(inner, node) } +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn_file_actions_adddup2( + actions: *mut posix_spawn_file_actions_t, + fd: c_int, + newfd: c_int, +) -> c_int { + if actions.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = actions_as_inner(actions); + unsafe { + if (*inner).magic != ACTIONS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + } + + let node = Box::into_raw(Box::new(ActionNode { + kind: ACTION_KIND_DUP2, + fd, + newfd, + oflag: 0, + mode: 0, + path_ptr: ptr::null_mut(), + next: ptr::null_mut(), + })); + + unsafe { append_action(inner, node) } +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn_file_actions_addopen( + actions: *mut posix_spawn_file_actions_t, + fd: c_int, + path: *const c_char, + oflag: c_int, + mode: mode_t, +) -> c_int { + if actions.is_null() || path.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = actions_as_inner(actions); + unsafe { + if (*inner).magic != ACTIONS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + } + + let path_owned = CString::new(unsafe { CStr::from_ptr(path) }.to_bytes()).unwrap(); + let path_dup = CString::into_raw(path_owned); + + let node = Box::into_raw(Box::new(ActionNode { + kind: ACTION_KIND_OPEN, + fd, + newfd: -1, + oflag, + mode: mode as c_int, + path_ptr: path_dup, + next: ptr::null_mut(), + })); + + unsafe { append_action(inner, node) } +} + +unsafe fn append_action(inner: *mut ActionsInner, node: *mut ActionNode) -> c_int { + unsafe { + if (*inner).tail.is_null() { + (*inner).head = node; + } else { + (*(*inner).tail).next = node; + } + (*inner).tail = node; + } + 0 +} + +// ─── Spawn attributes API ──────────────────────────────────────────────────── + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int { + if attr.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + ptr::write_bytes(inner as *mut u8, 0, mem::size_of::()); + (*inner).magic = ATTRS_MAGIC; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int { + if attr.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + (*inner).magic = 0; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_getflags( + attr: *const posix_spawnattr_t, + flags: *mut c_short, +) -> c_int { + if attr.is_null() || flags.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr as *mut posix_spawnattr_t); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + *flags = (*inner).flags; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_setflags( + attr: *mut posix_spawnattr_t, + flags: c_short, +) -> c_int { + if attr.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + let valid = POSIX_SPAWN_RESETIDS + | POSIX_SPAWN_SETPGROUP + | POSIX_SPAWN_SETSIGDEF + | POSIX_SPAWN_SETSIGMASK + | POSIX_SPAWN_SETSCHEDULER + | POSIX_SPAWN_SETSCHEDPARAM; + if (flags & !valid) != 0 { + platform::ERRNO.set(EINVAL); + return -1; + } + (*inner).flags = flags; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_getpgroup( + attr: *const posix_spawnattr_t, + pgroup: *mut pid_t, +) -> c_int { + if attr.is_null() || pgroup.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr as *mut posix_spawnattr_t); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + *pgroup = (*inner).pgroup; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_setpgroup( + attr: *mut posix_spawnattr_t, + pgroup: pid_t, +) -> c_int { + if attr.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + (*inner).pgroup = pgroup; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_getsigmask( + attr: *const posix_spawnattr_t, + sigmask: *mut c_ulonglong, +) -> c_int { + if attr.is_null() || sigmask.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr as *mut posix_spawnattr_t); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + *sigmask = (*inner).sigmask; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_setsigmask( + attr: *mut posix_spawnattr_t, + sigmask: *const c_ulonglong, +) -> c_int { + if attr.is_null() || sigmask.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + (*inner).sigmask = *sigmask; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_getsigdefault( + attr: *const posix_spawnattr_t, + sigdefault: *mut c_ulonglong, +) -> c_int { + if attr.is_null() || sigdefault.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr as *mut posix_spawnattr_t); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + *sigdefault = (*inner).sigdefault; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnattr_setsigdefault( + attr: *mut posix_spawnattr_t, + sigdefault: *const c_ulonglong, +) -> c_int { + if attr.is_null() || sigdefault.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + let inner = attrs_as_inner(attr); + unsafe { + if (*inner).magic != ATTRS_MAGIC { + platform::ERRNO.set(EINVAL); + return -1; + } + (*inner).sigdefault = *sigdefault; + } + 0 +} + +// ─── Core spawn implementation ─────────────────────────────────────────────── + +unsafe fn do_spawn( + path: *const c_char, + search_path: bool, + actions: *const posix_spawn_file_actions_t, + attr: *const posix_spawnattr_t, + argv: *const *mut c_char, + envp: *const *mut c_char, +) -> c_int { + if path.is_null() || argv.is_null() || envp.is_null() { + platform::ERRNO.set(EINVAL); + return -1; + } + + // Validate optional actions / attrs + let actions_valid = actions.is_null() + || unsafe { (*actions_as_inner(actions as *mut _)).magic == ACTIONS_MAGIC }; + let attrs_valid = attr.is_null() + || unsafe { (*attrs_as_inner(attr as *mut _)).magic == ATTRS_MAGIC }; + + if !actions_valid || !attrs_valid { + platform::ERRNO.set(EINVAL); + return -1; + } + + // Read spawnattr flags + let flags: c_short = if attr.is_null() { + 0 + } else { + unsafe { (*attrs_as_inner(attr as *mut _)).flags } + }; + + // Fork + let pid = unsafe { unistd::fork() }; + if pid == -1 { + return -1; + } + + if pid == 0 { + // Child process: apply attributes and file actions, then exec + + if flags & POSIX_SPAWN_RESETIDS != 0 { + unistd::seteuid(unistd::getuid()); + unistd::setegid(unistd::getgid()); + } + + if flags & POSIX_SPAWN_SETPGROUP != 0 { + let pgrp = if attr.is_null() { + 0 + } else { + unsafe { (*attrs_as_inner(attr as *mut _)).pgroup } + }; + unistd::setpgid(0, pgrp); + } + + if flags & POSIX_SPAWN_SETSIGMASK != 0 && !attr.is_null() { + let mask = unsafe { (*attrs_as_inner(attr as *mut _)).sigmask }; + unsafe { + signal::sigprocmask(signal::SIG_SETMASK, &mask, ptr::null_mut()); + } + } + + if flags & POSIX_SPAWN_SETSIGDEF != 0 && !attr.is_null() { + let default_set = unsafe { (*attrs_as_inner(attr as *mut _)).sigdefault }; + let mut i = 1; + while i < 32 { + if (default_set & (1u64 << i)) != 0 { + signal::signal(i, None); + } + i += 1; + } + } + + if !actions.is_null() { + let inner = actions_as_inner(actions as *mut _); + let mut node = unsafe { (*inner).head }; + while !node.is_null() { + let n = unsafe { &*node }; + match n.kind { + ACTION_KIND_CLOSE => { + unistd::close(n.fd); + } + ACTION_KIND_DUP2 => { + unistd::dup2(n.fd, n.newfd); + if n.fd != n.newfd { + unistd::close(n.fd); + } + } + ACTION_KIND_OPEN => unsafe { + let path_cstr = CStr::from_ptr(n.path_ptr); + if let Ok(new_fd) = Sys::open(path_cstr, n.oflag, n.mode) { + if new_fd != n.fd { + unistd::dup2(new_fd, n.fd); + unistd::close(new_fd); + } + } + }, + _ => {} + } + node = n.next; + } + } + + if search_path { + unsafe { unistd::execvp(path, argv) }; + } else { + unsafe { unistd::execve(path, argv, envp) }; + } + + unistd::_exit(127); + } + + // ── Parent process ──────────────────────────────────────────────────────── + pid +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawn( + pid: *mut pid_t, + path: *const c_char, + actions: *const posix_spawn_file_actions_t, + attr: *const posix_spawnattr_t, + argv: *const *mut c_char, + envp: *const *mut c_char, +) -> c_int { + let child = unsafe { do_spawn(path, false, actions, attr, argv, envp) }; + if child == -1 { + return platform::ERRNO.get(); + } + if !pid.is_null() { + unsafe { *pid = child }; + } + 0 +} + +/// See . +#[unsafe(no_mangle)] +pub unsafe extern "C" fn posix_spawnp( + pid: *mut pid_t, + file: *const c_char, + actions: *const posix_spawn_file_actions_t, + attr: *const posix_spawnattr_t, + argv: *const *mut c_char, + envp: *const *mut c_char, +) -> c_int { + let child = unsafe { do_spawn(file, true, actions, attr, argv, envp) }; + if child == -1 { + return platform::ERRNO.get(); + } + if !pid.is_null() { + unsafe { *pid = child }; + } + 0 +} diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 8cb689ec54..2a234e85a5 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -1415,7 +1415,7 @@ pub unsafe extern "C" fn fprintf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vfprintf(file, format, __valist.as_va_list()) } + unsafe { vfprintf(file, format, __valist) } } /// See . @@ -1433,7 +1433,7 @@ pub unsafe extern "C" fn vdprintf(fd: c_int, format: *const c_char, ap: va_list) /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn dprintf(fd: c_int, format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vdprintf(fd, format, __valist.as_va_list()) } + unsafe { vdprintf(fd, format, __valist) } } /// See . @@ -1445,7 +1445,7 @@ pub unsafe extern "C" fn vprintf(format: *const c_char, ap: va_list) -> c_int { /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn printf(format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vfprintf(&raw mut *stdout, format, __valist.as_va_list()) } + unsafe { vfprintf(&raw mut *stdout, format, __valist) } } /// See . @@ -1470,7 +1470,7 @@ pub unsafe extern "C" fn asprintf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vasprintf(strp, format, __valist.as_va_list()) } + unsafe { vasprintf(strp, format, __valist) } } /// See . @@ -1502,7 +1502,7 @@ pub unsafe extern "C" fn snprintf( printf::printf( &mut platform::StringWriter(s.cast::(), n), CStr::from_ptr(format), - __valist.as_va_list(), + __valist, ) } } @@ -1530,7 +1530,7 @@ pub unsafe extern "C" fn sprintf( printf::printf( &mut platform::UnsafeStringWriter(s.cast::()), CStr::from_ptr(format), - __valist.as_va_list(), + __valist, ) } } @@ -1558,7 +1558,7 @@ pub unsafe extern "C" fn fscanf( format: *const c_char, mut __valist: ... ) -> c_int { - unsafe { vfscanf(file, format, __valist.as_va_list()) } + unsafe { vfscanf(file, format, __valist) } } /// See . @@ -1570,7 +1570,7 @@ pub unsafe extern "C" fn vscanf(format: *const c_char, ap: va_list) -> c_int { /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn scanf(format: *const c_char, mut __valist: ...) -> c_int { - unsafe { vfscanf(&raw mut *stdin, format, __valist.as_va_list()) } + unsafe { vfscanf(&raw mut *stdin, format, __valist) } } /// See . @@ -1593,7 +1593,7 @@ pub unsafe extern "C" fn sscanf( unsafe { let format = CStr::from_ptr(format); let s = CStr::from_ptr(s); - scanf::scanf(s.into(), format.into(), __valist.as_va_list()) + scanf::scanf(s.into(), format.into(), __valist) } } diff --git a/src/header/stdio/printf.rs b/src/header/stdio/printf.rs index 2f63b420ed..ac2c190988 100644 --- a/src/header/stdio/printf.rs +++ b/src/header/stdio/printf.rs @@ -127,36 +127,36 @@ impl VaArg { (FmtKind::Percent, _) => panic!("Can't call arg_from on %"), (FmtKind::Char, IntKind::Long) | (FmtKind::Char, IntKind::LongLong) => { - VaArg::wint_t(unsafe { ap.arg::() }) + VaArg::wint_t(unsafe { ap.next_arg::() }) } (FmtKind::Char, _) | (FmtKind::Unsigned, IntKind::Byte) | (FmtKind::Signed, IntKind::Byte) => { // c_int is passed but truncated to c_char - VaArg::c_char(unsafe { ap.arg::() } as c_char) + VaArg::c_char(unsafe { ap.next_arg::() } as c_char) } (FmtKind::Unsigned, IntKind::Short) | (FmtKind::Signed, IntKind::Short) => { // c_int is passed but truncated to c_short - VaArg::c_short(unsafe { ap.arg::() } as c_short) + VaArg::c_short(unsafe { ap.next_arg::() } as c_short) } (FmtKind::Unsigned, IntKind::Int) | (FmtKind::Signed, IntKind::Int) => { - VaArg::c_int(unsafe { ap.arg::() }) + VaArg::c_int(unsafe { ap.next_arg::() }) } (FmtKind::Unsigned, IntKind::Long) | (FmtKind::Signed, IntKind::Long) => { - VaArg::c_long(unsafe { ap.arg::() }) + VaArg::c_long(unsafe { ap.next_arg::() }) } (FmtKind::Unsigned, IntKind::LongLong) | (FmtKind::Signed, IntKind::LongLong) => { - VaArg::c_longlong(unsafe { ap.arg::() }) + VaArg::c_longlong(unsafe { ap.next_arg::() }) } (FmtKind::Unsigned, IntKind::IntMax) | (FmtKind::Signed, IntKind::IntMax) => { - VaArg::intmax_t(unsafe { ap.arg::() }) + VaArg::intmax_t(unsafe { ap.next_arg::() }) } (FmtKind::Unsigned, IntKind::PtrDiff) | (FmtKind::Signed, IntKind::PtrDiff) => { - VaArg::ptrdiff_t(unsafe { ap.arg::() }) + VaArg::ptrdiff_t(unsafe { ap.next_arg::() }) } (FmtKind::Unsigned, IntKind::Size) | (FmtKind::Signed, IntKind::Size) => { - VaArg::ssize_t(unsafe { ap.arg::() }) + VaArg::ssize_t(unsafe { ap.next_arg::() }) } (FmtKind::AnyNotation, IntKind::LongLong) @@ -165,11 +165,11 @@ impl VaArg { VaArg::c_longdouble(unsafe { VaArg::extract_longdouble(ap) }) } (FmtKind::AnyNotation, _) | (FmtKind::Decimal, _) | (FmtKind::Scientific, _) => { - VaArg::c_double(unsafe { ap.arg::() }) + VaArg::c_double(unsafe { ap.next_arg::() }) } (FmtKind::GetWritten, _) | (FmtKind::Pointer, _) | (FmtKind::String, _) => { - VaArg::pointer(unsafe { ap.arg::<*const c_void>() }) + VaArg::pointer(unsafe { ap.next_arg::<*const c_void>() }) } } } @@ -193,7 +193,7 @@ impl VaArg { let ap_impl = unsafe { // The double deconstruct is intended - let ptr_to_struct = *(ap as *mut core::ffi::VaList as *mut *mut VaListImpl); + let ptr_to_struct = (ap as *mut core::ffi::VaList as *mut VaListImpl); &mut *ptr_to_struct }; @@ -220,7 +220,7 @@ impl VaArg { let ap_impl: &mut VaListImpl = unsafe { // The double deconstruct is intended - let ptr_to_struct = *(ap as *mut core::ffi::VaList as *mut *mut VaListImpl); + let ptr_to_struct = (ap as *mut core::ffi::VaList as *mut VaListImpl); &mut *ptr_to_struct }; @@ -348,13 +348,13 @@ impl VaListCache { // point. Reaching here means there are unused gaps in the // arguments. Ultimately we'll have to settle down with // defaulting to c_int. - self.args.push(VaArg::c_int(unsafe { ap.arg::() })) + self.args.push(VaArg::c_int(unsafe { ap.next_arg::() })) } // Add the value to the cache self.args.push(match default { Some((fmtkind, intkind)) => unsafe { VaArg::arg_from(fmtkind, intkind, ap) }, - None => VaArg::c_int(unsafe { ap.arg::() }), + None => VaArg::c_int(unsafe { ap.next_arg::() }), }); // Return the value @@ -774,7 +774,7 @@ pub(crate) unsafe fn inner_printf( match num { Number::Next => varargs .args - .push(VaArg::c_int(unsafe { ap.arg::() })), + .push(VaArg::c_int(unsafe { ap.next_arg::() })), Number::Index(i) => { positional.insert(i - 1, (FmtKind::Signed, IntKind::Int)); } diff --git a/src/header/stdio/scanf.rs b/src/header/stdio/scanf.rs index 1d89cc54e6..1adbe6e4e0 100644 --- a/src/header/stdio/scanf.rs +++ b/src/header/stdio/scanf.rs @@ -244,7 +244,7 @@ pub unsafe fn inner_scanf( n.parse::<$type>().map_err(|_| 0)? }; if !ignore { - unsafe { *ap.arg::<*mut $type>() = n }; + unsafe { *ap.next_arg::<*mut $type>() = n }; matched += 1; } }}; @@ -264,7 +264,7 @@ pub unsafe fn inner_scanf( $type::from_str_radix(&n, radix).map_err(|_| 0)? }; if !ignore { - unsafe { *ap.arg::<*mut $final>() = n as $final }; + unsafe { *ap.next_arg::<*mut $final>() = n as $final }; matched += 1; } }}; @@ -346,7 +346,7 @@ pub unsafe fn inner_scanf( } let mut ptr: Option<*mut $type> = - if ignore { None } else { Some(ap.arg()) }; + if ignore { None } else { Some(ap.next_arg()) }; while width.map(|w| w > 0).unwrap_or(true) && !character.is_whitespace() { @@ -391,7 +391,7 @@ pub unsafe fn inner_scanf( let ptr: Option<*mut $type> = if ignore { None } else { - Some(unsafe { ap.arg() }) + Some(unsafe { ap.next_arg() }) }; for i in 0..width.unwrap_or(1) { @@ -456,7 +456,7 @@ pub unsafe fn inner_scanf( let mut ptr: Option<*mut c_char> = if ignore { None } else { - Some(unsafe { ap.arg() }) + Some(unsafe { ap.next_arg() }) }; // While we haven't used up all the width, and it matches @@ -486,7 +486,7 @@ pub unsafe fn inner_scanf( } 'n' => { if !ignore { - unsafe { *ap.arg::<*mut c_int>() = count as c_int }; + unsafe { *ap.next_arg::<*mut c_int>() = count as c_int }; } } _ => return Err(-1), diff --git a/src/header/sys_mman/mod.rs b/src/header/sys_mman/mod.rs index 0930c9660c..555ea94bda 100644 --- a/src/header/sys_mman/mod.rs +++ b/src/header/sys_mman/mod.rs @@ -112,7 +112,7 @@ pub unsafe extern "C" fn mremap( flags: c_int, mut __valist: ... ) -> *mut c_void { - let new_address = unsafe { __valist.arg::<*mut c_void>() }; + let new_address = unsafe { __valist.next_arg::<*mut c_void>() }; match unsafe { Sys::mremap(old_address, old_size, new_size, flags, new_address) } { Ok(ptr) => ptr, Err(Errno(errno)) => { diff --git a/src/header/sys_ptrace/mod.rs b/src/header/sys_ptrace/mod.rs index 772182d9cc..4c3f5ec38a 100644 --- a/src/header/sys_ptrace/mod.rs +++ b/src/header/sys_ptrace/mod.rs @@ -4,7 +4,7 @@ use crate::{ error::ResultExt, - platform::{PalPtrace, Sys, types::c_int}, + platform::{PalPtrace, Sys, types::{c_int, c_void, pid_t}}, }; pub const PTRACE_TRACEME: c_int = 0; @@ -29,7 +29,8 @@ pub const PTRACE_SYSEMU_SINGLESTEP: c_int = 32; /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn ptrace(request: c_int, mut __valist: ...) -> c_int { - // Musl also just grabs the arguments from the varargs... - unsafe { Sys::ptrace(request, __valist.arg(), __valist.arg(), __valist.arg()) } - .or_minus_one_errno() + let pid = unsafe { __valist.next_arg::() }; + let addr = unsafe { __valist.next_arg::<*mut c_void>() }; + let data = unsafe { __valist.next_arg::<*mut c_void>() }; + unsafe { Sys::ptrace(request, pid, addr, data) }.or_minus_one_errno() } diff --git a/src/header/sys_syslog/mod.rs b/src/header/sys_syslog/mod.rs index 9aea6ed58a..fd149ecd91 100644 --- a/src/header/sys_syslog/mod.rs +++ b/src/header/sys_syslog/mod.rs @@ -136,7 +136,7 @@ pub unsafe extern "C" fn vsyslog(priority: c_int, message: *const c_char, ap: Va /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn syslog(priority: c_int, message: *const c_char, mut __valist: ...) { - unsafe { vsyslog(priority, message, __valist.as_va_list()) }; + unsafe { vsyslog(priority, message, __valist) }; } /// See . diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index f44a52eaa0..89607cc6ae 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -4,7 +4,7 @@ use core::{ convert::TryFrom, - ffi::VaListImpl, + ffi::VaList, mem::{self, MaybeUninit}, ptr, slice, }; @@ -322,7 +322,7 @@ pub unsafe extern "C" fn execle( ) -> c_int { unsafe { with_argv(__valist, arg0, |args, mut remaining_va| { - let envp = remaining_va.arg::<*const *mut c_char>(); + let envp = remaining_va.next_arg::<*const *mut c_char>(); execve(path, args.as_ptr().cast(), envp) }) } @@ -1267,16 +1267,15 @@ pub extern "C" fn vfork() -> pid_t { } unsafe fn with_argv( - mut va: VaListImpl, + mut va: VaList<'_>, arg0: *const c_char, - f: impl FnOnce(&[*const c_char], VaListImpl) -> c_int, + f: impl FnOnce(&[*const c_char], VaList<'_>) -> c_int, ) -> c_int { - let argc = 1 + unsafe { - va.with_copy(|mut copy| { - core::iter::from_fn(|| Some(copy.arg::<*const c_char>())) - .position(|p| p.is_null()) - .unwrap() - }) + let argc = 1 + { + let mut copy = va.clone(); + core::iter::from_fn(|| Some(unsafe { copy.next_arg::<*const c_char>() })) + .position(|p| p.is_null()) + .unwrap() }; let mut stack: [MaybeUninit<*const c_char>; 32] = [MaybeUninit::uninit(); 32]; @@ -1299,11 +1298,11 @@ unsafe fn with_argv( out[0].write(arg0); for inner in out.iter_mut().take(argc).skip(1) { - (*inner).write(unsafe { va.arg::<*const c_char>() }); + (*inner).write(unsafe { va.next_arg::<*const c_char>() }); } out[argc].write(core::ptr::null()); // NULL - unsafe { va.arg::<*const c_char>() }; + unsafe { va.next_arg::<*const c_char>() }; f(unsafe { (&*out).assume_init_ref() }, va); diff --git a/src/header/unistd/syscall.rs b/src/header/unistd/syscall.rs index d9d00218bf..f97e649543 100644 --- a/src/header/unistd/syscall.rs +++ b/src/header/unistd/syscall.rs @@ -3,12 +3,12 @@ use crate::platform::types::c_long; /// Non-POSIX, see . #[unsafe(no_mangle)] pub unsafe extern "C" fn syscall(sysno: c_long, mut args: ...) -> c_long { - let a1 = unsafe { args.arg::() }; - let a2 = unsafe { args.arg::() }; - let a3 = unsafe { args.arg::() }; - let a4 = unsafe { args.arg::() }; - let a5 = unsafe { args.arg::() }; - let a6 = unsafe { args.arg::() }; + let a1 = unsafe { args.next_arg::() }; + let a2 = unsafe { args.next_arg::() }; + let a3 = unsafe { args.next_arg::() }; + let a4 = unsafe { args.next_arg::() }; + let a5 = unsafe { args.next_arg::() }; + let a6 = unsafe { args.next_arg::() }; (unsafe { sc::syscall6(sysno as usize, a1, a2, a3, a4, a5, a6) }) as c_long } diff --git a/src/header/wchar/mod.rs b/src/header/wchar/mod.rs index fa4ff454f3..5ef3ca862e 100644 --- a/src/header/wchar/mod.rs +++ b/src/header/wchar/mod.rs @@ -183,7 +183,7 @@ pub unsafe extern "C" fn fwscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vfwscanf(stream, format, __valist.as_va_list()) } + unsafe { vfwscanf(stream, format, __valist) } } /// See . @@ -342,7 +342,7 @@ pub unsafe extern "C" fn swscanf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vswscanf(s, format, __valist.as_va_list()) } + unsafe { vswscanf(s, format, __valist) } } /// See . @@ -396,7 +396,7 @@ pub unsafe extern "C" fn fwprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vfwprintf(stream, format, __valist.as_va_list()) } + unsafe { vfwprintf(stream, format, __valist) } } /// See . @@ -408,7 +408,7 @@ pub unsafe extern "C" fn vwprintf(format: *const wchar_t, arg: va_list) -> c_int /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wprintf(format: *const wchar_t, mut __valist: ...) -> c_int { - unsafe { vfwprintf(&raw mut *stdout, format, __valist.as_va_list()) } + unsafe { vfwprintf(&raw mut *stdout, format, __valist) } } /// See . @@ -433,7 +433,7 @@ pub unsafe extern "C" fn swprintf( format: *const wchar_t, mut __valist: ... ) -> c_int { - unsafe { vswprintf(s, n, format, __valist.as_va_list()) } + unsafe { vswprintf(s, n, format, __valist) } } /// See . @@ -1053,7 +1053,7 @@ pub unsafe extern "C" fn vwscanf(format: *const wchar_t, __valist: va_list) -> c /// See . #[unsafe(no_mangle)] pub unsafe extern "C" fn wscanf(format: *const wchar_t, mut __valist: ...) -> c_int { - unsafe { vfwscanf(stdin, format, __valist.as_va_list()) } + unsafe { vfwscanf(stdin, format, __valist) } } /// See .