1use std::{
17 io,
18 process::{Command, Stdio},
19 string::FromUtf8Error,
20};
21
22#[cfg(test)]
23mod tests;
24
25#[cfg(not(any(
26 target_os = "android",
27 target_os = "linux",
28 target_os = "macos",
29 target_os = "freebsd"
30)))]
31compile_error!("This platform is not supported. See https://github.com/Aloso/to-html/issues/3");
32
33pub fn bash_command(command: &str) -> io::Result<Command> {
40 let mut command = make_script_command(command, Some("bash"))?;
41 command.stdout(Stdio::piped()).stderr(Stdio::piped());
42
43 Ok(command)
44}
45
46pub fn command(command: &str, shell: Option<&str>) -> io::Result<Command> {
53 let mut command = make_script_command(command, shell)?;
54 command.stdout(Stdio::piped()).stderr(Stdio::piped());
55
56 Ok(command)
57}
58
59pub fn make_script_command(c: &str, shell: Option<&str>) -> io::Result<Command> {
80 let shell = which_shell(shell.unwrap_or("bash"))?;
81
82 #[cfg(any(target_os = "linux", target_os = "android"))]
83 {
84 let mut command = Command::new("script");
85 command.args(["-qec", c, "/dev/null"]);
86 command.env("SHELL", shell.trim());
87
88 Ok(command)
89 }
90
91 #[cfg(any(target_os = "macos", target_os = "freebsd"))]
92 {
93 let mut command = Command::new("script");
94 command.args(&["-q", "/dev/null", shell.trim(), "-c", c]);
95 Ok(command)
96 }
97}
98
99pub fn get_stdout(stdout: Vec<u8>) -> Result<String, FromUtf8Error> {
101 let out = String::from_utf8(stdout)?;
102
103 #[cfg(any(target_os = "linux", target_os = "android"))]
104 {
105 Ok(out.replace("\r\n", "\n"))
106 }
107
108 #[cfg(any(target_os = "macos", target_os = "freebsd"))]
109 {
110 let mut out = out.replace("\r\n", "\n");
111 if out.starts_with("^D\u{8}\u{8}") {
112 out = out["^D\u{8}\u{8}".len()..].to_string()
113 }
114 Ok(out)
115 }
116}
117
118fn which_shell(shell: &str) -> io::Result<String> {
119 let which = Command::new("which")
120 .arg(shell)
121 .stdout(Stdio::piped())
122 .output()?;
123
124 if which.status.success() {
125 Ok(String::from_utf8(which.stdout).unwrap())
126 } else {
127 Err(io::Error::other(String::from_utf8(which.stderr).unwrap()))
128 }
129}