2023-02-15 05:54:18 +08:00
|
|
|
use crate::wchar;
|
2023-02-24 23:55:49 +08:00
|
|
|
use crate::wchar_ffi::WCharToFFI;
|
|
|
|
#[rustfmt::skip]
|
|
|
|
use ::std::pin::Pin;
|
|
|
|
#[rustfmt::skip]
|
|
|
|
use ::std::slice;
|
2023-03-19 11:11:18 +08:00
|
|
|
use crate::env::flags::EnvMode;
|
2023-03-14 10:23:31 +08:00
|
|
|
pub use crate::wait_handle::{
|
|
|
|
WaitHandleRef, WaitHandleRefFFI, WaitHandleStore, WaitHandleStoreFFI,
|
|
|
|
};
|
2023-03-19 11:11:18 +08:00
|
|
|
use crate::wchar::{wstr, WString};
|
|
|
|
use crate::wchar_ffi::WCharFromFFI;
|
2023-01-15 06:56:24 +08:00
|
|
|
use autocxx::prelude::*;
|
2023-01-16 11:52:08 +08:00
|
|
|
use cxx::SharedPtr;
|
2023-02-12 04:31:08 +08:00
|
|
|
use libc::pid_t;
|
2023-01-15 06:56:24 +08:00
|
|
|
|
|
|
|
// autocxx has been hacked up to know about this.
|
|
|
|
pub type wchar_t = u32;
|
|
|
|
|
|
|
|
include_cpp! {
|
2023-02-25 07:44:20 +08:00
|
|
|
#include "builtin.h"
|
|
|
|
#include "common.h"
|
2023-02-24 23:55:49 +08:00
|
|
|
#include "env.h"
|
2023-02-25 07:44:20 +08:00
|
|
|
#include "event.h"
|
|
|
|
#include "fallback.h"
|
2023-01-15 06:56:24 +08:00
|
|
|
#include "fds.h"
|
|
|
|
#include "flog.h"
|
|
|
|
#include "io.h"
|
2023-02-24 23:55:49 +08:00
|
|
|
#include "parse_constants.h"
|
2023-01-15 06:56:24 +08:00
|
|
|
#include "parser.h"
|
2023-02-25 07:44:20 +08:00
|
|
|
#include "parse_util.h"
|
2023-01-15 06:56:24 +08:00
|
|
|
#include "proc.h"
|
2023-02-25 07:44:20 +08:00
|
|
|
#include "tokenizer.h"
|
|
|
|
#include "wildcard.h"
|
|
|
|
#include "wutil.h"
|
2023-01-15 06:56:24 +08:00
|
|
|
|
2023-03-14 10:23:31 +08:00
|
|
|
// We need to block these types so when exposing C++ to Rust.
|
|
|
|
block!("WaitHandleStoreFFI")
|
|
|
|
block!("WaitHandleRefFFI")
|
|
|
|
|
2023-01-15 06:56:24 +08:00
|
|
|
safety!(unsafe_ffi)
|
|
|
|
|
|
|
|
generate_pod!("wcharz_t")
|
|
|
|
generate!("make_fd_nonblocking")
|
|
|
|
generate!("wperror")
|
|
|
|
|
|
|
|
generate_pod!("pipes_ffi_t")
|
2023-03-19 11:11:18 +08:00
|
|
|
generate!("environment_t")
|
2023-02-25 00:00:05 +08:00
|
|
|
generate!("env_stack_t")
|
2023-03-19 11:11:18 +08:00
|
|
|
generate!("env_var_t")
|
2023-01-15 06:56:24 +08:00
|
|
|
generate!("make_pipes_ffi")
|
|
|
|
|
|
|
|
generate!("get_flog_file_fd")
|
2023-03-28 23:59:51 +08:00
|
|
|
generate!("log_extra_to_flog_file")
|
2023-01-15 06:56:24 +08:00
|
|
|
|
|
|
|
generate!("parse_util_unescape_wildcards")
|
|
|
|
|
2023-02-05 16:35:06 +08:00
|
|
|
generate!("fish_wcwidth")
|
|
|
|
generate!("fish_wcswidth")
|
|
|
|
|
2023-01-15 06:56:24 +08:00
|
|
|
generate!("wildcard_match")
|
2023-01-16 05:18:52 +08:00
|
|
|
generate!("wgettext_ptr")
|
2023-01-15 06:56:24 +08:00
|
|
|
|
2023-02-25 03:21:27 +08:00
|
|
|
generate!("block_t")
|
2023-01-16 11:52:08 +08:00
|
|
|
generate!("parser_t")
|
2023-03-14 10:23:31 +08:00
|
|
|
|
2023-01-16 11:52:08 +08:00
|
|
|
generate!("job_t")
|
|
|
|
generate!("process_t")
|
2023-02-19 00:13:58 +08:00
|
|
|
generate!("library_data_t")
|
2023-02-12 01:15:27 +08:00
|
|
|
generate_pod!("library_data_pod_t")
|
2023-01-16 11:52:08 +08:00
|
|
|
|
|
|
|
generate!("proc_wait_any")
|
|
|
|
|
|
|
|
generate!("output_stream_t")
|
|
|
|
generate!("io_streams_t")
|
|
|
|
|
|
|
|
generate_pod!("RustFFIJobList")
|
|
|
|
generate_pod!("RustFFIProcList")
|
|
|
|
generate_pod!("RustBuiltin")
|
|
|
|
|
|
|
|
generate!("builtin_missing_argument")
|
|
|
|
generate!("builtin_unknown_option")
|
|
|
|
generate!("builtin_print_help")
|
2023-02-19 00:13:58 +08:00
|
|
|
generate!("builtin_print_error_trailer")
|
2023-01-16 11:52:08 +08:00
|
|
|
|
2023-02-11 23:51:43 +08:00
|
|
|
generate!("escape_string")
|
2023-02-12 00:36:08 +08:00
|
|
|
generate!("sig2wcs")
|
|
|
|
generate!("wcs2sig")
|
|
|
|
generate!("signal_get_desc")
|
2023-02-18 09:21:44 +08:00
|
|
|
|
|
|
|
generate!("fd_event_signaller_t")
|
2023-02-24 23:55:49 +08:00
|
|
|
|
2023-02-12 04:31:08 +08:00
|
|
|
generate!("signal_handle")
|
|
|
|
generate!("signal_check_cancel")
|
|
|
|
|
|
|
|
generate!("block_t")
|
|
|
|
generate!("block_type_t")
|
|
|
|
generate!("statuses_t")
|
|
|
|
generate!("io_chain_t")
|
|
|
|
|
2023-03-01 13:05:27 +08:00
|
|
|
generate!("env_var_t")
|
2023-01-16 11:52:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl parser_t {
|
2023-03-14 10:23:31 +08:00
|
|
|
pub fn get_wait_handles_mut(&mut self) -> &mut WaitHandleStore {
|
|
|
|
let ptr = self.get_wait_handles_void() as *mut Box<WaitHandleStoreFFI>;
|
|
|
|
assert!(!ptr.is_null());
|
|
|
|
unsafe { (*ptr).from_ffi_mut() }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_wait_handles(&self) -> &WaitHandleStore {
|
|
|
|
let ptr = self.get_wait_handles_void() as *const Box<WaitHandleStoreFFI>;
|
|
|
|
assert!(!ptr.is_null());
|
|
|
|
unsafe { (*ptr).from_ffi() }
|
|
|
|
}
|
|
|
|
|
2023-02-12 04:31:08 +08:00
|
|
|
pub fn get_block_at_index(&self, i: usize) -> Option<&block_t> {
|
|
|
|
let b = self.block_at_index(i);
|
|
|
|
unsafe { b.as_ref() }
|
|
|
|
}
|
|
|
|
|
2023-01-16 11:52:08 +08:00
|
|
|
pub fn get_jobs(&self) -> &[SharedPtr<job_t>] {
|
|
|
|
let ffi_jobs = self.ffi_jobs();
|
|
|
|
unsafe { slice::from_raw_parts(ffi_jobs.jobs, ffi_jobs.count) }
|
|
|
|
}
|
2023-02-12 01:15:27 +08:00
|
|
|
|
|
|
|
pub fn libdata_pod(&mut self) -> &mut library_data_pod_t {
|
|
|
|
let libdata = self.pin().ffi_libdata_pod();
|
|
|
|
|
|
|
|
unsafe { &mut *libdata }
|
|
|
|
}
|
2023-02-25 00:00:05 +08:00
|
|
|
|
|
|
|
pub fn remove_var(&mut self, var: &wstr, flags: c_int) -> c_int {
|
|
|
|
self.pin().remove_var_ffi(&var.to_ffi(), flags)
|
|
|
|
}
|
2023-02-12 04:31:08 +08:00
|
|
|
|
|
|
|
pub fn job_get_from_pid(&self, pid: pid_t) -> Option<&job_t> {
|
|
|
|
let job = self.ffi_job_get_from_pid(pid.into());
|
|
|
|
unsafe { job.as_ref() }
|
|
|
|
}
|
2023-03-19 11:11:18 +08:00
|
|
|
|
|
|
|
/// Helper to get a variable as a string, using the default flags.
|
|
|
|
pub fn var_as_string(&mut self, name: &wstr) -> Option<WString> {
|
|
|
|
self.pin().vars().unpin().get_as_string(name)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_var_stack(&mut self) -> &mut env_stack_t {
|
|
|
|
self.pin().vars().unpin()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_var_stack_env(&mut self) -> &environment_t {
|
|
|
|
self.vars_env_ffi()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_var(&mut self, name: &wstr, value: &[&wstr], flags: EnvMode) -> libc::c_int {
|
|
|
|
self.get_var_stack().set_var(name, value, flags)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl environment_t {
|
|
|
|
/// Helper to get a variable as a string, using the default flags.
|
|
|
|
pub fn get_as_string(&self, name: &wstr) -> Option<WString> {
|
|
|
|
self.get_as_string_flags(name, EnvMode::DEFAULT)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper to get a variable as a string, using the given flags.
|
|
|
|
pub fn get_as_string_flags(&self, name: &wstr, flags: EnvMode) -> Option<WString> {
|
|
|
|
self.get_or_null(&name.to_ffi(), flags.bits())
|
|
|
|
.as_ref()
|
|
|
|
.map(|s| s.as_string().from_ffi())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl env_stack_t {
|
|
|
|
/// Helper to get a variable as a string, using the default flags.
|
|
|
|
pub fn get_as_string(&self, name: &wstr) -> Option<WString> {
|
|
|
|
self.get_as_string_flags(name, EnvMode::DEFAULT)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper to get a variable as a string, using the given flags.
|
|
|
|
pub fn get_as_string_flags(&self, name: &wstr, flags: EnvMode) -> Option<WString> {
|
|
|
|
self.get_or_null(&name.to_ffi(), flags.bits())
|
|
|
|
.as_ref()
|
|
|
|
.map(|s| s.as_string().from_ffi())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Helper to set a value.
|
|
|
|
pub fn set_var(&mut self, name: &wstr, value: &[&wstr], flags: EnvMode) -> libc::c_int {
|
|
|
|
use crate::wchar_ffi::{wstr_to_u32string, W0String};
|
|
|
|
let strings: Vec<W0String> = value.iter().map(wstr_to_u32string).collect();
|
|
|
|
let ptrs: Vec<*const u32> = strings.iter().map(|s| s.as_ptr()).collect();
|
|
|
|
self.pin()
|
|
|
|
.set_ffi(
|
|
|
|
&name.to_ffi(),
|
|
|
|
flags.bits(),
|
|
|
|
ptrs.as_ptr() as *const c_void,
|
|
|
|
ptrs.len(),
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
}
|
2023-01-16 11:52:08 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl job_t {
|
2023-02-06 04:52:21 +08:00
|
|
|
#[allow(clippy::mut_from_ref)]
|
2023-01-16 11:52:08 +08:00
|
|
|
pub fn get_procs(&self) -> &mut [UniquePtr<process_t>] {
|
|
|
|
let ffi_procs = self.ffi_processes();
|
|
|
|
unsafe { slice::from_raw_parts_mut(ffi_procs.procs, ffi_procs.count) }
|
|
|
|
}
|
2023-01-15 06:56:24 +08:00
|
|
|
}
|
|
|
|
|
2023-03-14 10:23:31 +08:00
|
|
|
impl process_t {
|
|
|
|
/// \return the wait handle for the process, if it exists.
|
|
|
|
pub fn get_wait_handle(&self) -> Option<WaitHandleRef> {
|
|
|
|
let handle_ptr = self.get_wait_handle_void() as *const Box<WaitHandleRefFFI>;
|
|
|
|
if handle_ptr.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let handle: &WaitHandleRefFFI = unsafe { &*handle_ptr };
|
|
|
|
Some(handle.from_ffi().clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \return the wait handle for the process, creating it if necessary.
|
|
|
|
pub fn make_wait_handle(&mut self, jid: u64) -> Option<WaitHandleRef> {
|
|
|
|
let handle_ref = self.pin().make_wait_handle_void(jid) as *const Box<WaitHandleRefFFI>;
|
|
|
|
if handle_ref.is_null() {
|
|
|
|
None
|
|
|
|
} else {
|
|
|
|
let handle: &WaitHandleRefFFI = unsafe { &*handle_ref };
|
|
|
|
Some(handle.from_ffi().clone())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-15 06:56:24 +08:00
|
|
|
/// Allow wcharz_t to be "into" wstr.
|
|
|
|
impl From<wcharz_t> for &wchar::wstr {
|
|
|
|
fn from(w: wcharz_t) -> Self {
|
|
|
|
let len = w.length();
|
|
|
|
let v = unsafe { slice::from_raw_parts(w.str_ as *const u32, len) };
|
|
|
|
wchar::wstr::from_slice(v).expect("Invalid UTF-32")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Allow wcharz_t to be "into" WString.
|
|
|
|
impl From<wcharz_t> for wchar::WString {
|
|
|
|
fn from(w: wcharz_t) -> Self {
|
|
|
|
let len = w.length();
|
|
|
|
let v = unsafe { slice::from_raw_parts(w.str_ as *const u32, len).to_vec() };
|
|
|
|
Self::from_vec(v).expect("Invalid UTF-32")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-16 11:52:08 +08:00
|
|
|
/// A bogus trait for turning &mut Foo into Pin<&mut Foo>.
|
|
|
|
/// autocxx enforces that non-const methods must be called through Pin,
|
|
|
|
/// but this means we can't pass around mutable references to types like parser_t.
|
|
|
|
/// We also don't want to assert that parser_t is Unpin.
|
|
|
|
/// So we just allow constructing a pin from a mutable reference; none of the C++ code.
|
|
|
|
/// It's worth considering disabling this in cxx; for now we use this trait.
|
|
|
|
/// Eventually parser_t and io_streams_t will not require Pin so we just unsafe-it away.
|
|
|
|
pub trait Repin {
|
|
|
|
fn pin(&mut self) -> Pin<&mut Self> {
|
|
|
|
unsafe { Pin::new_unchecked(self) }
|
|
|
|
}
|
|
|
|
|
|
|
|
fn unpin(self: Pin<&mut Self>) -> &mut Self {
|
|
|
|
unsafe { self.get_unchecked_mut() }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implement Repin for our types.
|
2023-02-25 03:21:27 +08:00
|
|
|
impl Repin for block_t {}
|
2023-02-24 23:55:49 +08:00
|
|
|
impl Repin for env_stack_t {}
|
2023-01-16 11:52:08 +08:00
|
|
|
impl Repin for io_streams_t {}
|
2023-02-25 07:44:20 +08:00
|
|
|
impl Repin for job_t {}
|
2023-01-16 11:52:08 +08:00
|
|
|
impl Repin for output_stream_t {}
|
2023-02-25 07:44:20 +08:00
|
|
|
impl Repin for parser_t {}
|
|
|
|
impl Repin for process_t {}
|
2023-01-16 11:52:08 +08:00
|
|
|
|
2023-01-15 06:56:24 +08:00
|
|
|
pub use autocxx::c_int;
|
|
|
|
pub use ffi::*;
|
|
|
|
pub use libc::c_char;
|
2023-02-18 09:21:44 +08:00
|
|
|
|
|
|
|
/// A version of [`* const core::ffi::c_void`] (or [`* const libc::c_void`], if you prefer) that
|
|
|
|
/// implements `Copy` and `Clone`, because those two don't. Used to represent a `void *` ptr for ffi
|
|
|
|
/// purposes.
|
|
|
|
#[repr(transparent)]
|
|
|
|
#[derive(Copy, Clone)]
|
|
|
|
pub struct void_ptr(pub *const core::ffi::c_void);
|
|
|
|
|
|
|
|
impl core::fmt::Debug for void_ptr {
|
|
|
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
|
|
write!(f, "{:p}", &self.0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe impl Send for void_ptr {}
|
|
|
|
unsafe impl Sync for void_ptr {}
|
2023-02-19 02:52:58 +08:00
|
|
|
|
|
|
|
impl core::convert::From<*const core::ffi::c_void> for void_ptr {
|
|
|
|
fn from(value: *const core::ffi::c_void) -> Self {
|
|
|
|
Self(value as *const _)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl core::convert::From<*const u8> for void_ptr {
|
|
|
|
fn from(value: *const u8) -> Self {
|
|
|
|
Self(value as *const _)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl core::convert::From<*const autocxx::c_void> for void_ptr {
|
|
|
|
fn from(value: *const autocxx::c_void) -> Self {
|
|
|
|
Self(value as *const _)
|
|
|
|
}
|
|
|
|
}
|