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::{
8    processes::{AbiStructures, TaskStdio},
9    Optional,
10};
11
12use crate::Lazy;
13
14pub(super) struct StaticAbiStructures(UnsafeCell<MaybeUninit<AbiStructures>>);
15
16impl StaticAbiStructures {
17    pub unsafe fn init(&self, structures: AbiStructures) {
18        let ptr = self.0.get();
19        ptr.write(MaybeUninit::new(structures));
20    }
21
22    unsafe fn get(&'static self) -> &'static AbiStructures {
23        let ptr = self.0.get();
24        MaybeUninit::assume_init_ref(&*ptr)
25    }
26}
27
28unsafe impl Sync for StaticAbiStructures {}
29
30pub(super) static ABI_STRUCTURES: StaticAbiStructures =
31    StaticAbiStructures(UnsafeCell::new(MaybeUninit::zeroed()));
32
33static STDIO: Lazy<TaskStdio> = Lazy::new(|| unsafe { ABI_STRUCTURES.get().stdio });
34static STDIN: Lazy<usize> = Lazy::new(|| {
35    let stdin: Option<usize> = STDIO.stdin.into();
36    if let Some(stdin) = stdin {
37        stdin
38    } else {
39        syscalls::fs::open_all("dev:/tty").expect("failed to fall back to `dev:/tty` for stdin")
40    }
41});
42
43static STDOUT: Lazy<usize> = Lazy::new(|| {
44    let stdout: Option<usize> = STDIO.stdout.into();
45    if let Some(stdout) = stdout {
46        stdout
47    } else {
48        syscalls::fs::open_all("dev:/tty").expect("failed to fall back to `dev:/tty` for stdout")
49    }
50});
51
52static STDERR: Lazy<usize> = Lazy::new(|| {
53    let stderr: Option<usize> = STDIO.stderr.into();
54    if let Some(stderr) = stderr {
55        stderr
56    } else {
57        syscalls::fs::open_all("dev:/tty").expect("failed to fall back to `dev:/tty` for stderr")
58    }
59});
60
61/// Returns the resource id of the stdout file descriptor (if available)
62#[cfg_attr(
63    not(any(feature = "std", feature = "rustc-dep-of-std")),
64    unsafe(no_mangle)
65)]
66#[inline(always)]
67pub extern "C" fn systry_get_stdout() -> Optional<usize> {
68    STDIO.stdout.clone()
69}
70
71/// Returns the resource id of the stderr file descriptor (if available)
72#[cfg_attr(
73    not(any(feature = "std", feature = "rustc-dep-of-std")),
74    unsafe(no_mangle)
75)]
76#[inline(always)]
77pub extern "C" fn systry_get_stderr() -> Optional<usize> {
78    STDIO.stderr.clone()
79}
80
81/// Returns the resource id of the stdin file descriptor (if available)
82#[cfg_attr(
83    not(any(feature = "std", feature = "rustc-dep-of-std")),
84    unsafe(no_mangle)
85)]
86#[inline(always)]
87pub extern "C" fn systry_get_stdin() -> Optional<usize> {
88    STDIO.stdin.clone()
89}
90
91/// Returns the resource id of the stdout file descriptor
92///
93/// if there is no stdout file descriptor, it will fall back to `dev:/tty`
94#[cfg_attr(
95    not(any(feature = "std", feature = "rustc-dep-of-std")),
96    unsafe(no_mangle)
97)]
98#[inline(always)]
99pub extern "C" fn sysget_stdout() -> usize {
100    **STDOUT
101}
102
103/// Returns the resource id of the stderr file descriptor
104///
105/// if there is no stderr file descriptor, it will fall back to `dev:/tty`
106#[cfg_attr(
107    not(any(feature = "std", feature = "rustc-dep-of-std")),
108    unsafe(no_mangle)
109)]
110#[inline(always)]
111pub extern "C" fn sysget_stderr() -> usize {
112    **STDERR
113}
114
115/// Returns the resource id of the stdin file descriptor
116///
117/// if there is no stdin file descriptor, it will fall back to `dev:/tty`
118#[cfg_attr(
119    not(any(feature = "std", feature = "rustc-dep-of-std")),
120    unsafe(no_mangle)
121)]
122#[inline(always)]
123pub extern "C" fn sysget_stdin() -> usize {
124    **STDIN
125}
126
127pub fn init_meta(abi_structures: AbiStructures) {
128    unsafe { ABI_STRUCTURES.init(abi_structures) };
129}