diff --git a/src/imp/linux_raw/syscalls.rs b/src/imp/linux_raw/syscalls.rs index 7e87f8bea..2da00e948 100644 --- a/src/imp/linux_raw/syscalls.rs +++ b/src/imp/linux_raw/syscalls.rs @@ -83,19 +83,20 @@ use linux_raw_sys::general::{ use linux_raw_sys::general::{__NR_arch_prctl, ARCH_SET_FS}; use linux_raw_sys::general::{ __NR_chdir, __NR_clock_getres, __NR_clock_nanosleep, __NR_close, __NR_dup, __NR_dup3, - __NR_epoll_create1, __NR_epoll_ctl, __NR_exit, __NR_exit_group, __NR_faccessat, __NR_fallocate, - __NR_fchdir, __NR_fchmod, __NR_fchmodat, __NR_fdatasync, __NR_flock, __NR_fsync, __NR_futex, - __NR_getcwd, __NR_getdents64, __NR_getpid, __NR_getppid, __NR_getpriority, __NR_gettid, - __NR_ioctl, __NR_linkat, __NR_madvise, __NR_mkdirat, __NR_mknodat, __NR_mlock, __NR_mprotect, - __NR_munlock, __NR_munmap, __NR_nanosleep, __NR_openat, __NR_pipe2, __NR_prctl, __NR_pread64, - __NR_preadv, __NR_pwrite64, __NR_pwritev, __NR_read, __NR_readlinkat, __NR_readv, - __NR_sched_getaffinity, __NR_sched_setaffinity, __NR_sched_yield, __NR_set_tid_address, - __NR_setpriority, __NR_symlinkat, __NR_uname, __NR_unlinkat, __NR_utimensat, __NR_wait4, - __NR_write, __NR_writev, __kernel_gid_t, __kernel_pid_t, __kernel_timespec, __kernel_uid_t, - epoll_event, sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un, socklen_t, AT_FDCWD, - AT_REMOVEDIR, AT_SYMLINK_NOFOLLOW, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, FIONBIO, - FIONREAD, F_DUPFD, F_DUPFD_CLOEXEC, F_GETFD, F_GETFL, F_GETLEASE, F_GETOWN, F_GETSIG, F_SETFD, - F_SETFL, PR_SET_NAME, SIGCHLD, TCGETS, TIMER_ABSTIME, TIOCEXCL, TIOCGWINSZ, TIOCNXCL, + __NR_epoll_create1, __NR_epoll_ctl, __NR_execve, __NR_exit, __NR_exit_group, __NR_faccessat, + __NR_fallocate, __NR_fchdir, __NR_fchmod, __NR_fchmodat, __NR_fdatasync, __NR_flock, + __NR_fsync, __NR_futex, __NR_getcwd, __NR_getdents64, __NR_getpid, __NR_getppid, + __NR_getpriority, __NR_gettid, __NR_ioctl, __NR_linkat, __NR_madvise, __NR_mkdirat, + __NR_mknodat, __NR_mlock, __NR_mprotect, __NR_munlock, __NR_munmap, __NR_nanosleep, + __NR_openat, __NR_pipe2, __NR_prctl, __NR_pread64, __NR_preadv, __NR_pwrite64, __NR_pwritev, + __NR_read, __NR_readlinkat, __NR_readv, __NR_sched_getaffinity, __NR_sched_setaffinity, + __NR_sched_yield, __NR_set_tid_address, __NR_setpriority, __NR_symlinkat, __NR_uname, + __NR_unlinkat, __NR_utimensat, __NR_wait4, __NR_write, __NR_writev, __kernel_gid_t, + __kernel_pid_t, __kernel_timespec, __kernel_uid_t, epoll_event, sockaddr, sockaddr_in, + sockaddr_in6, sockaddr_un, socklen_t, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_NOFOLLOW, + EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, FIONBIO, FIONREAD, F_DUPFD, F_DUPFD_CLOEXEC, + F_GETFD, F_GETFL, F_GETLEASE, F_GETOWN, F_GETSIG, F_SETFD, F_SETFL, PR_SET_NAME, SIGCHLD, + TCGETS, TIMER_ABSTIME, TIOCEXCL, TIOCGWINSZ, TIOCNXCL, }; #[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))] use linux_raw_sys::general::{__NR_dup2, __NR_open, __NR_pipe, __NR_poll}; @@ -118,6 +119,7 @@ use linux_raw_sys::v5_4::general::{ __NR_memfd_create, __NR_mlock2, __NR_preadv2, __NR_prlimit64, __NR_pwritev2, __NR_renameat2, __NR_statx, __NR_userfaultfd, statx, F_GETPIPE_SZ, F_GET_SEALS, F_SETPIPE_SZ, }; +use std::borrow::Cow; use std::convert::TryInto; use std::ffi::CStr; use std::io::{IoSlice, IoSliceMut, SeekFrom}; @@ -3590,6 +3592,24 @@ pub(crate) unsafe fn fork() -> io::Result { Ok(Pid::from_raw(pid)) } +pub fn execve(path: &CStr, args: &[Cow<'_, CStr>], env_vars: &[Cow<'_, CStr>]) -> io::Result<()> { + let mut argv: Vec<_> = args.into_iter().map(|cstr| CStr::as_ptr(cstr)).collect(); + let mut envs: Vec<_> = env_vars + .into_iter() + .map(|cstr| CStr::as_ptr(cstr)) + .collect(); + argv.push(std::ptr::null()); + envs.push(std::ptr::null()); + unsafe { + ret(syscall3_readonly( + nr(__NR_execve), + c_str(path), + slice_just_addr(&argv), + slice_just_addr(&envs), + )) + } +} + #[inline] pub fn waitpid(pid: RawPid, waitopts: WaitOptions) -> io::Result> { unsafe { diff --git a/src/runtime.rs b/src/runtime.rs index 0c7dec250..d2e3c926e 100644 --- a/src/runtime.rs +++ b/src/runtime.rs @@ -17,8 +17,10 @@ #![allow(unsafe_code)] +use crate::path::Arg; use crate::process::Pid; use crate::{imp, io}; +use std::borrow::Cow; use std::ffi::{c_void, CStr}; #[cfg(target_arch = "x86")] @@ -117,3 +119,20 @@ pub use imp::thread::tls::StartupTlsInfo; pub unsafe fn fork() -> io::Result { imp::syscalls::fork() } + +/// Executes the program pointed to by `path`, with the arguments `args`, +/// and the environment variables `env_vars`. +/// +/// The first argument, by convention, +/// should be the filename associated with the file being executed. +pub fn execve(path: P, args: &[P], env_vars: &[P]) -> io::Result<()> { + let arg_vec: Vec> = args + .into_iter() + .map(Arg::as_cow_c_str) + .collect::>()?; + let env_vec: Vec> = env_vars + .into_iter() + .map(Arg::as_cow_c_str) + .collect::>()?; + path.into_with_c_str(|path_cstr| imp::syscalls::execve(path_cstr, &arg_vec, &env_vec)) +}