safa_api/process/
stdio.rs

1//! contains functions related to standard input/output/error streams descriptors
2//! api must be initialized before using these functions, see [`super::init`]
3
4use core::{cell::UnsafeCell, mem::MaybeUninit};
5
6use crate::syscalls::{self};
7use safa_abi::raw::processes::{AbiStructures, TaskStdio};
8
9use crate::Lazy;
10
11pub(super) struct StaticAbiStructures(UnsafeCell<MaybeUninit<AbiStructures>>);
12
13impl StaticAbiStructures {
14    pub unsafe fn init(&self, structures: AbiStructures) {
15        let ptr = self.0.get();
16        ptr.write(MaybeUninit::new(structures));
17    }
18
19    unsafe fn get(&'static self) -> &'static AbiStructures {
20        let ptr = self.0.get();
21        MaybeUninit::assume_init_ref(&*ptr)
22    }
23}
24
25unsafe impl Sync for StaticAbiStructures {}
26
27pub(super) static ABI_STRUCTURES: StaticAbiStructures =
28    StaticAbiStructures(UnsafeCell::new(MaybeUninit::zeroed()));
29
30static STDIO: Lazy<TaskStdio> = Lazy::new(|| unsafe { ABI_STRUCTURES.get().stdio });
31static STDIN: Lazy<usize> = Lazy::new(|| {
32    let stdin: Option<usize> = STDIO.stdin.into();
33    if let Some(stdin) = stdin {
34        stdin
35    } else {
36        syscalls::open("dev:/tty").expect("failed to fall back to `dev:/tty` for stdin")
37    }
38});
39
40static STDOUT: Lazy<usize> = Lazy::new(|| {
41    let stdout: Option<usize> = STDIO.stdout.into();
42    if let Some(stdout) = stdout {
43        stdout
44    } else {
45        syscalls::open("dev:/tty").expect("failed to fall back to `dev:/tty` for stdout")
46    }
47});
48
49static STDERR: Lazy<usize> = Lazy::new(|| {
50    let stderr: Option<usize> = STDIO.stderr.into();
51    if let Some(stderr) = stderr {
52        stderr
53    } else {
54        syscalls::open("dev:/tty").expect("failed to fall back to `dev:/tty` for stderr")
55    }
56});
57
58/// Returns the resource id of the stdout file descriptor
59///
60/// if there is no stdout file descriptor, it will fall back to `dev:/tty`
61#[cfg_attr(
62    not(any(feature = "std", feature = "rustc-dep-of-std")),
63    unsafe(no_mangle)
64)]
65#[inline(always)]
66pub extern "C" fn sysmeta_stdout() -> usize {
67    **STDOUT
68}
69
70/// Returns the resource id of the stderr file descriptor
71///
72/// if there is no stderr file descriptor, it will fall back to `dev:/tty`
73#[cfg_attr(
74    not(any(feature = "std", feature = "rustc-dep-of-std")),
75    unsafe(no_mangle)
76)]
77#[inline(always)]
78pub extern "C" fn sysmeta_stderr() -> usize {
79    **STDERR
80}
81
82/// Returns the resource id of the stdin file descriptor
83///
84/// if there is no stdin file descriptor, it will fall back to `dev:/tty`
85#[cfg_attr(
86    not(any(feature = "std", feature = "rustc-dep-of-std")),
87    unsafe(no_mangle)
88)]
89#[inline(always)]
90pub extern "C" fn sysmeta_stdin() -> usize {
91    **STDIN
92}
93
94pub fn init_meta(abi_structures: AbiStructures) {
95    unsafe { ABI_STRUCTURES.init(abi_structures) };
96}