1use libc::{__errno_location, c_int};
2use std::ffi::{CStr, NulError};
3use thiserror::Error;
4
5use crate::process::ProcessError;
6
7#[cfg(unix)]
9#[derive(Error, Debug, PartialEq)]
10pub enum RashError {
11 #[error("Null byte found in command at pos {}", pos)]
17 NullByteInCommand {
18 pos: usize,
19 },
20 #[error("{:?}", message)]
25 KernelError {
26 message: String,
27 },
28 #[error("Couldn't read stdout: {:?}", message)]
35 FailedToReadStdout {
36 message: String,
37 },
38 #[error("Couldn't read stderr: {:?}", message)]
45 FailedToReadStderr {
46 message: String,
47 },
48}
49
50impl From<ProcessError> for RashError {
51 fn from(v: ProcessError) -> Self {
52 fn into_kernel_error<S: AsRef<str>>(s: S) -> RashError {
53 RashError::KernelError {
54 message: unsafe { RashError::format_kernel_error_message(s) },
55 }
56 }
57 match v {
58 ProcessError::CouldNotFork
59 | ProcessError::CouldNotCreatePipe
60 | ProcessError::CouldNotDupFd(_)
61 | ProcessError::OpenDidNotCloseNormally => into_kernel_error(v.to_string()),
62 ProcessError::CouldNotGetStderr => RashError::FailedToReadStderr {
63 message: v.to_string(),
64 },
65 ProcessError::CouldNotGetStdout => RashError::FailedToReadStdout {
66 message: v.to_string(),
67 },
68 }
69 }
70}
71
72impl From<NulError> for RashError {
73 fn from(v: NulError) -> Self {
74 RashError::NullByteInCommand {
75 pos: v.nul_position(),
76 }
77 }
78}
79
80impl RashError {
81 pub(crate) unsafe fn format_kernel_error_message<S: AsRef<str>>(description: S) -> String {
82 let errno = *__errno_location();
83 let strerror = Self::strerror(errno);
84 format!(
85 "Received errno {}, Description: {}, strerror output: {strerror}.",
86 errno.to_string(),
87 description.as_ref()
88 )
89 }
90
91 unsafe fn strerror(errno: c_int) -> String {
92 let strerror = libc::strerror(errno);
93 if strerror.is_null() {
94 return "Couldn't get strerror - libc::strerror returned null.".to_string();
95 }
96 return match CStr::from_ptr(strerror).to_str() {
97 Ok(s) => s.to_string(),
98 Err(e) => e.to_string(),
99 };
100 }
101}