Change io crate & add a small shell
This commit is contained in:
@@ -14,12 +14,13 @@ REAL_CP_FILES := "\
|
||||
sys/random/mod.rs \
|
||||
sys/thread_local/mod.rs"
|
||||
STD_FILES := "\
|
||||
../tests ../benches \
|
||||
alloc.rs ascii.rs backtrace.rs bstr.rs env.rs error.rs fs.rs \
|
||||
keyword_docs.rs lib.rs macros.rs panic.rs panicking.rs pat.rs \
|
||||
path.rs process.rs random.rs rt.rs tests_helpers.rs time.rs \
|
||||
backtrace collections ffi fs hash io net num os/raw/mod.rs \
|
||||
os/raw/tests.rs os/mod.rs prelude process sync sys/alloc/mod.rs \
|
||||
sys/args/unsupported.rs sys/env/mod.rs sys/env/common.rs \
|
||||
sys/args/unsupported.rs sys/args/common.rs sys/env/mod.rs sys/env/common.rs \
|
||||
sys/env/unsupported.rs sys/fd/mod.rs sys/fs/mod.rs \
|
||||
sys/fs/common.rs sys/fs/unsupported.rs sys/helpers/mod.rs \
|
||||
sys/helpers/small_c_string.rs sys/helpers/tests.rs sys/helpers/wstr.rs \
|
||||
@@ -44,7 +45,7 @@ STD_FILES := "\
|
||||
sys/thread_local/no_threads.rs sys/thread_local/os.rs sys/time/mod.rs \
|
||||
sys/time/unsupported.rs sys/backtrace.rs sys/cmath.rs \
|
||||
sys/configure_builtins.rs sys/env_consts.rs sys/exit.rs sys/mod.rs thread"
|
||||
KEEP_FILES := "survos.rs"
|
||||
KEEP_FILES := "survos.rs ffi.rs"
|
||||
|
||||
setup-std:
|
||||
@echo "🔗 Linking root directories..."
|
||||
@@ -74,7 +75,8 @@ patch-std:
|
||||
done
|
||||
|
||||
build-sysroot:
|
||||
cargo clean
|
||||
rm -rf target/riscv64/debug/deps/
|
||||
rm -rf ../target/riscv64/
|
||||
RUSTFLAGS="-Zforce-unstable-if-unmarked -C relocation-model=pic -C link-arg=-pie" \
|
||||
cargo build --package std --target ../riscv64.json --features compiler-builtins-mem
|
||||
mkdir -p ../sysroot/lib/rustlib/riscv64/lib
|
||||
|
||||
7
library/std/.gitignore
vendored
7
library/std/.gitignore
vendored
@@ -2,6 +2,8 @@ Cargo.lock
|
||||
Cargo.toml
|
||||
build.rs
|
||||
target
|
||||
tests
|
||||
benches
|
||||
src/random.rs
|
||||
src/num
|
||||
src/prelude
|
||||
@@ -18,7 +20,6 @@ src/tests_helpers.rs
|
||||
src/error.rs
|
||||
src/net
|
||||
src/rt.rs
|
||||
src/sys/args
|
||||
src/sys/args/mod.rs
|
||||
src/sys/args/unsupported.rs
|
||||
src/sys/thread_local
|
||||
@@ -56,9 +57,7 @@ src/sys/sync/thread_parking/unsupported.rs
|
||||
src/sys/sync/once
|
||||
src/sys/sync/once/no_threads.rs
|
||||
src/sys/sync/once/mod.rs
|
||||
src/sys/fd
|
||||
src/sys/fd/mod.rs
|
||||
src/sys/process
|
||||
src/sys/process/mod.rs
|
||||
src/sys/process/env.rs
|
||||
src/sys/process/unsupported.rs
|
||||
@@ -100,7 +99,6 @@ src/sys/helpers/mod.rs
|
||||
src/sys/helpers/wstr.rs
|
||||
src/sys/helpers/tests.rs
|
||||
src/sys/helpers/small_c_string.rs
|
||||
src/sys/fs
|
||||
src/sys/fs/mod.rs
|
||||
src/sys/fs/common.rs
|
||||
src/sys/fs/unsupported.rs
|
||||
@@ -124,7 +122,6 @@ src/sys/os_str/bytes
|
||||
src/sys/os_str/bytes/tests.rs
|
||||
src/sys/os_str/bytes.rs
|
||||
src/macros.rs
|
||||
src/os
|
||||
src/os/mod.rs
|
||||
src/os/raw
|
||||
src/os/raw/mod.rs
|
||||
|
||||
5
library/std/patches/os/mod.sed
Normal file
5
library/std/patches/os/mod.sed
Normal file
@@ -0,0 +1,5 @@
|
||||
185a \#[cfg(target_os = "survos")]\
|
||||
pub mod survos;\
|
||||
#[cfg(target_os = "survos")]\
|
||||
#[unstable(feature = "survos_std", issue = "none")]\
|
||||
pub use survos::fd;
|
||||
@@ -1,4 +1,5 @@
|
||||
# 55a \ target_os = "survos" => { \
|
||||
# mod survos; \
|
||||
# pub use survos::*; \
|
||||
# }
|
||||
55a \ target_os = "survos" => { \
|
||||
mod survos; \
|
||||
pub use survos::*; \
|
||||
}
|
||||
12a \ target_os = "survos",
|
||||
|
||||
4
library/std/patches/sys/fd/mod.sed
Normal file
4
library/std/patches/sys/fd/mod.sed
Normal file
@@ -0,0 +1,4 @@
|
||||
21a \ target_os = "survos" => { \
|
||||
mod survos; \
|
||||
pub use survos::*; \
|
||||
}
|
||||
4
library/std/patches/sys/fs/mod.sed
Normal file
4
library/std/patches/sys/fs/mod.sed
Normal file
@@ -0,0 +1,4 @@
|
||||
47a \ target_os = "survos" => { \
|
||||
mod survos; \
|
||||
use survos as imp; \
|
||||
}
|
||||
4
library/std/patches/sys/process/mod.sed
Normal file
4
library/std/patches/sys/process/mod.sed
Normal file
@@ -0,0 +1,4 @@
|
||||
17a \ target_os = "survos" => { \
|
||||
mod survos; \
|
||||
use survos as imp; \
|
||||
}
|
||||
18
library/std/src/os/survos.rs
Normal file
18
library/std/src/os/survos.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
#![unstable(feature = "survos_std", issue = "none")]
|
||||
|
||||
#[unstable(feature = "survos_std", issue = "none")]
|
||||
pub mod fd {
|
||||
pub type RawFd = u64;
|
||||
|
||||
pub trait FromRawFd {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self;
|
||||
}
|
||||
|
||||
pub trait AsRawFd {
|
||||
// Required method
|
||||
fn as_raw_fd(&self) -> RawFd;
|
||||
}
|
||||
}
|
||||
|
||||
pub mod ffi;
|
||||
pub mod syscall;
|
||||
70
library/std/src/os/survos/ffi.rs
Normal file
70
library/std/src/os/survos/ffi.rs
Normal file
@@ -0,0 +1,70 @@
|
||||
use crate::ffi::{OsStr, OsString};
|
||||
use crate::mem;
|
||||
use crate::sealed::Sealed;
|
||||
use crate::sys::os_str::Buf;
|
||||
use crate::sys::{AsInner, FromInner, IntoInner};
|
||||
|
||||
// Note: this file is currently reused in other `std::os::{platform}::ffi` modules to reduce duplication.
|
||||
// Keep this in mind when applying changes to this file that only apply to `unix`.
|
||||
|
||||
/// Platform-specific extensions to [`OsString`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStringExt: Sealed {
|
||||
/// Creates an [`OsString`] from a byte vector.
|
||||
///
|
||||
/// See the module documentation for an example.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_vec(vec: Vec<u8>) -> Self;
|
||||
|
||||
/// Yields the underlying byte vector of this [`OsString`].
|
||||
///
|
||||
/// See the module documentation for an example.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into_vec(self) -> Vec<u8>;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStringExt for OsString {
|
||||
#[inline]
|
||||
fn from_vec(vec: Vec<u8>) -> OsString {
|
||||
FromInner::from_inner(Buf { inner: vec })
|
||||
}
|
||||
#[inline]
|
||||
fn into_vec(self) -> Vec<u8> {
|
||||
self.into_inner().inner
|
||||
}
|
||||
}
|
||||
|
||||
/// Platform-specific extensions to [`OsStr`].
|
||||
///
|
||||
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||
/// This is so that future additional methods are not breaking changes.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait OsStrExt: Sealed {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
/// Creates an [`OsStr`] from a byte slice.
|
||||
///
|
||||
/// See the module documentation for an example.
|
||||
fn from_bytes(slice: &[u8]) -> &Self;
|
||||
|
||||
/// Gets the underlying byte view of the [`OsStr`] slice.
|
||||
///
|
||||
/// See the module documentation for an example.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_bytes(&self) -> &[u8];
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl OsStrExt for OsStr {
|
||||
#[inline]
|
||||
fn from_bytes(slice: &[u8]) -> &OsStr {
|
||||
unsafe { mem::transmute(slice) }
|
||||
}
|
||||
#[inline]
|
||||
fn as_bytes(&self) -> &[u8] {
|
||||
&self.as_inner().inner
|
||||
}
|
||||
}
|
||||
1
library/std/src/os/survos/syscall.rs
Symbolic link
1
library/std/src/os/survos/syscall.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
../../../../../crates/shared/src/syscall.rs
|
||||
1
library/std/src/sys/args/common.rs
Symbolic link
1
library/std/src/sys/args/common.rs
Symbolic link
@@ -0,0 +1 @@
|
||||
/home/julien/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/args/common.rs
|
||||
42
library/std/src/sys/args/survos.rs
Normal file
42
library/std/src/sys/args/survos.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
pub use super::common::Args;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{Atomic, AtomicIsize, AtomicPtr, Ordering};
|
||||
|
||||
pub fn args() -> Args {
|
||||
let (argc, argv) = argc_argv();
|
||||
|
||||
let mut vec = Vec::with_capacity(argc as usize);
|
||||
|
||||
for i in 0..argc {
|
||||
let ptr = unsafe { argv.offset(i).read() };
|
||||
|
||||
if ptr.is_null() {
|
||||
break;
|
||||
}
|
||||
|
||||
let cstr = unsafe { CStr::from_ptr(ptr) };
|
||||
vec.push(unsafe { OsStr::from_encoded_bytes_unchecked(cstr.to_bytes()) }.to_owned());
|
||||
}
|
||||
|
||||
Args::new(vec)
|
||||
}
|
||||
|
||||
static ARGC: Atomic<isize> = AtomicIsize::new(0);
|
||||
static ARGV: Atomic<*mut *const u8> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
ARGC.store(argc, Ordering::Relaxed);
|
||||
ARGV.store(argv as *mut _, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
pub fn argc_argv() -> (isize, *const *const u8) {
|
||||
let argv = ARGV.load(Ordering::Relaxed);
|
||||
let argc = if argv.is_null() {
|
||||
0
|
||||
} else {
|
||||
ARGC.load(Ordering::Relaxed)
|
||||
};
|
||||
|
||||
(argc, argv.cast())
|
||||
}
|
||||
1
library/std/src/sys/fd/survos.rs
Normal file
1
library/std/src/sys/fd/survos.rs
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
145
library/std/src/sys/fs/survos.rs
Normal file
145
library/std/src/sys/fs/survos.rs
Normal file
@@ -0,0 +1,145 @@
|
||||
#[path = "unsupported.rs"]
|
||||
mod unsupported;
|
||||
use core::io::BorrowedCursor;
|
||||
|
||||
pub use self::unsupported::*;
|
||||
|
||||
use crate::fs::TryLockError;
|
||||
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom, prelude::*};
|
||||
use crate::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
use crate::os::survos::syscall;
|
||||
use crate::sys::FromInner;
|
||||
use crate::sys::fs::Path;
|
||||
use crate::sys::unsupported;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct File(RawFd);
|
||||
|
||||
impl File {
|
||||
pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<File> {
|
||||
unsafe {
|
||||
Ok(File::from_raw_fd(syscall::open(
|
||||
path.as_os_str().to_str().unwrap(),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
Ok(syscall::write(self.as_raw_fd(), buf) as usize)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<io::Result<u64>> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for File {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
syscall::close(self.as_raw_fd());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for File {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
Self(fd)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "survos_std", issue = "none")]
|
||||
impl FromRawFd for crate::fs::File {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
unsafe { Self::from_inner(File::from_raw_fd(fd)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for File {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,8 @@
|
||||
#[path = "unsupported/mod.rs"]
|
||||
mod unsupported;
|
||||
pub use self::unsupported::*;
|
||||
use crate::os::survos::syscall;
|
||||
|
||||
#[path = "../../../../../crates/shared/src/syscall.rs"]
|
||||
mod syscall;
|
||||
pub use self::unsupported::*;
|
||||
|
||||
/// # Safety
|
||||
/// `argc` and `argv` are passed by the kernel
|
||||
@@ -17,6 +16,10 @@ pub unsafe extern "C" fn _start(argc: isize, argv: *const *const u8) -> isize {
|
||||
unsafe { main(argc, argv) }
|
||||
}
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
|
||||
crate::sys::args::init(argc, argv);
|
||||
}
|
||||
|
||||
pub fn abort_internal() -> ! {
|
||||
// todo real abort
|
||||
syscall::exit()
|
||||
|
||||
392
library/std/src/sys/process/survos.rs
Normal file
392
library/std/src/sys/process/survos.rs
Normal file
@@ -0,0 +1,392 @@
|
||||
use core::mem::ManuallyDrop;
|
||||
|
||||
use alloc_crate::ffi::CString;
|
||||
|
||||
use super::env::{CommandEnv, CommandEnvs};
|
||||
pub use crate::ffi::OsString as EnvKey;
|
||||
use crate::ffi::{CStr, OsStr, OsString};
|
||||
use crate::num::NonZero;
|
||||
use crate::os::survos::{ffi::OsStrExt, syscall};
|
||||
use crate::path::Path;
|
||||
use crate::process::StdioPipes;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::unsupported;
|
||||
use crate::{fmt, io};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct Command {
|
||||
program: CString,
|
||||
args: Vec<*const u8>,
|
||||
env: CommandEnv,
|
||||
|
||||
cwd: Option<OsString>,
|
||||
stdin: Option<Stdio>,
|
||||
stdout: Option<Stdio>,
|
||||
stderr: Option<Stdio>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
ParentStdout,
|
||||
ParentStderr,
|
||||
#[allow(dead_code)] // This variant exists only for the Debug impl
|
||||
InheritFile(File),
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(program: &OsStr) -> Command {
|
||||
Command {
|
||||
program: CString::new(program.as_bytes()).unwrap(),
|
||||
args: vec![
|
||||
CString::new(program.as_bytes()).unwrap().into_raw(),
|
||||
crate::ptr::null(),
|
||||
],
|
||||
env: Default::default(),
|
||||
cwd: None,
|
||||
stdin: None,
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &OsStr) {
|
||||
let argc = self.args.len() - 1;
|
||||
// Replace the null pointer at the end of the array...
|
||||
self.args[argc] = CString::new(arg.as_bytes()).unwrap().into_raw();
|
||||
// ... and recreate it to restore the data structure invariant.
|
||||
self.args.push(crate::ptr::null());
|
||||
}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
&mut self.env
|
||||
}
|
||||
|
||||
pub fn cwd(&mut self, dir: &OsStr) {
|
||||
self.cwd = Some(dir.to_owned());
|
||||
}
|
||||
|
||||
pub fn stdin(&mut self, stdin: Stdio) {
|
||||
self.stdin = Some(stdin);
|
||||
}
|
||||
|
||||
pub fn stdout(&mut self, stdout: Stdio) {
|
||||
self.stdout = Some(stdout);
|
||||
}
|
||||
|
||||
pub fn stderr(&mut self, stderr: Stdio) {
|
||||
self.stderr = Some(stderr);
|
||||
}
|
||||
|
||||
pub fn get_program(&self) -> &OsStr {
|
||||
OsStr::from_bytes(self.program.as_bytes())
|
||||
}
|
||||
|
||||
pub fn get_args(&self) -> CommandArgs<'_> {
|
||||
let mut iter = CStringIter {
|
||||
iter: self.args.iter(),
|
||||
};
|
||||
iter.next();
|
||||
CommandArgs { iter }
|
||||
}
|
||||
|
||||
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
||||
self.env.iter()
|
||||
}
|
||||
|
||||
pub fn get_env_clear(&self) -> bool {
|
||||
self.env.does_clear()
|
||||
}
|
||||
|
||||
pub fn get_current_dir(&self) -> Option<&Path> {
|
||||
self.cwd.as_ref().map(|cs| Path::new(cs))
|
||||
}
|
||||
|
||||
pub fn spawn(
|
||||
&mut self,
|
||||
_default: Stdio,
|
||||
_needs_stdin: bool,
|
||||
) -> io::Result<(Process, StdioPipes)> {
|
||||
let (args, ..) = Vec::into_raw_parts(self.args.clone());
|
||||
let child_pid = syscall::spawn(
|
||||
self.program.to_str().unwrap(),
|
||||
(self.args.len() - 1) as isize,
|
||||
args,
|
||||
);
|
||||
Ok((
|
||||
Process(child_pid as usize),
|
||||
StdioPipes {
|
||||
stdin: None,
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
impl From<ChildPipe> for Stdio {
|
||||
fn from(pipe: ChildPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Stdout> for Stdio {
|
||||
fn from(_: io::Stdout) -> Stdio {
|
||||
Stdio::ParentStdout
|
||||
}
|
||||
}
|
||||
|
||||
impl From<io::Stderr> for Stdio {
|
||||
fn from(_: io::Stderr) -> Stdio {
|
||||
Stdio::ParentStderr
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
Stdio::InheritFile(file)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
// show all attributes
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.alternate() {
|
||||
let mut debug_command = f.debug_struct("Command");
|
||||
debug_command
|
||||
.field("program", &self.program)
|
||||
.field("args", &self.args);
|
||||
if !self.env.is_unchanged() {
|
||||
debug_command.field("env", &self.env);
|
||||
}
|
||||
|
||||
if self.cwd.is_some() {
|
||||
debug_command.field("cwd", &self.cwd);
|
||||
}
|
||||
|
||||
if self.stdin.is_some() {
|
||||
debug_command.field("stdin", &self.stdin);
|
||||
}
|
||||
if self.stdout.is_some() {
|
||||
debug_command.field("stdout", &self.stdout);
|
||||
}
|
||||
if self.stderr.is_some() {
|
||||
debug_command.field("stderr", &self.stderr);
|
||||
}
|
||||
|
||||
debug_command.finish()
|
||||
} else {
|
||||
if let Some(ref cwd) = self.cwd {
|
||||
write!(f, "cd {cwd:?} && ")?;
|
||||
}
|
||||
if self.env.does_clear() {
|
||||
write!(f, "env -i ")?;
|
||||
// Altered env vars will be printed next, that should exactly work as expected.
|
||||
} else {
|
||||
// Removed env vars need the command to be wrapped in `env`.
|
||||
let mut any_removed = false;
|
||||
for (key, value_opt) in self.get_envs() {
|
||||
if value_opt.is_none() {
|
||||
if !any_removed {
|
||||
write!(f, "env ")?;
|
||||
any_removed = true;
|
||||
}
|
||||
write!(f, "-u {} ", key.to_string_lossy())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Altered env vars can just be added in front of the program.
|
||||
for (key, value_opt) in self.get_envs() {
|
||||
if let Some(value) = value_opt {
|
||||
write!(f, "{}={value:?} ", key.to_string_lossy())?;
|
||||
}
|
||||
}
|
||||
// if self.program != self.args[0] {
|
||||
// write!(f, "[{:?}] ", self.program)?;
|
||||
// }
|
||||
// write!(f, "{:?}", self.args[0])?;
|
||||
|
||||
// for arg in &self.args[1..] {
|
||||
// write!(f, " {:?}", arg)?;
|
||||
// }
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct ExitStatus();
|
||||
|
||||
impl ExitStatus {
|
||||
pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn code(&self) -> Option<i32> {
|
||||
Some(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExitStatus {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "<dummy exit status>")
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExitStatusError(!);
|
||||
|
||||
impl Clone for ExitStatusError {
|
||||
fn clone(&self) -> ExitStatusError {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for ExitStatusError {}
|
||||
|
||||
impl PartialEq for ExitStatusError {
|
||||
fn eq(&self, _other: &ExitStatusError) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExitStatusError {}
|
||||
|
||||
impl fmt::Debug for ExitStatusError {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<ExitStatus> for ExitStatusError {
|
||||
fn into(self) -> ExitStatus {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ExitStatusError {
|
||||
pub fn code(self) -> Option<NonZero<i32>> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(u8);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(0);
|
||||
pub const FAILURE: ExitCode = ExitCode(1);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
impl From<u8> for ExitCode {
|
||||
fn from(code: u8) -> Self {
|
||||
Self(code)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(usize);
|
||||
|
||||
impl Process {
|
||||
pub fn id(&self) -> u32 {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn kill(&mut self) -> io::Result<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
syscall::waitpid(self.0);
|
||||
Ok(ExitStatus())
|
||||
}
|
||||
|
||||
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CommandArgs<'a> {
|
||||
iter: CStringIter<'a>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CommandArgs<'a> {
|
||||
type Item = &'a OsStr;
|
||||
fn next(&mut self) -> Option<&'a OsStr> {
|
||||
self.iter.next().map(|os| OsStr::from_bytes(os.to_bytes()))
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ExactSizeIterator for CommandArgs<'a> {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Debug for CommandArgs<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter.clone()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
pub type ChildPipe = crate::sys::pipe::Pipe;
|
||||
|
||||
pub fn read_output(
|
||||
out: ChildPipe,
|
||||
_stdout: &mut Vec<u8>,
|
||||
_err: ChildPipe,
|
||||
_stderr: &mut Vec<u8>,
|
||||
) -> io::Result<()> {
|
||||
match out.diverge() {}
|
||||
}
|
||||
|
||||
pub fn getpid() -> u32 {
|
||||
panic!("no pids on this platform")
|
||||
}
|
||||
|
||||
/// An iterator over all `CStr`s contained in a `CStringArray`.
|
||||
#[derive(Clone)]
|
||||
pub struct CStringIter<'a> {
|
||||
iter: crate::slice::Iter<'a, *const u8>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for CStringIter<'a> {
|
||||
type Item = &'a CStr;
|
||||
fn next(&mut self) -> Option<&'a CStr> {
|
||||
// SAFETY:
|
||||
// `CStringArray` owns all of its strings. Also, this is not the null
|
||||
// pointer since the last element is excluded when creating `iter`.
|
||||
self.iter.next().map(|&p| unsafe { CStr::from_ptr(p) })
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ExactSizeIterator for CStringIter<'a> {
|
||||
fn len(&self) -> usize {
|
||||
self.iter.len()
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.iter.is_empty()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user