Invoke a command and return the exit code, stdout, and stderr. # Arguments `executable` - The command to execute `args` - Optional arguments to pass to the command # Errors Error message then exit if the command fails to execute or stdin/stdout/stderr cannot be opened.
(executable: &str, args: Option<Vec<String>>)
| 120 | /// |
| 121 | /// Error message then exit if the command fails to execute or stdin/stdout/stderr cannot be opened. |
| 122 | pub fn invoke_command(executable: &str, args: Option<Vec<String>>) -> (i32, String, String) { |
| 123 | // originally implemented in dsc_lib/src/dscresources/command_resource.rs |
| 124 | trace!("Invoking command {} with args {:?}", executable, args); |
| 125 | let mut command = Command::new(executable); |
| 126 | |
| 127 | command.stdout(Stdio::piped()); |
| 128 | command.stderr(Stdio::piped()); |
| 129 | if let Some(args) = args { |
| 130 | command.args(args); |
| 131 | } |
| 132 | |
| 133 | let mut child = match command.spawn() { |
| 134 | Ok(child) => child, |
| 135 | Err(e) => { |
| 136 | error!("{} '{executable}': {e}", t!("utils.failedToExecute")); |
| 137 | exit(EXIT_DSC_ERROR); |
| 138 | } |
| 139 | }; |
| 140 | |
| 141 | let Some(mut child_stdout) = child.stdout.take() else { |
| 142 | error!("{} {executable}", t!("utils.failedOpenStdout")); |
| 143 | exit(EXIT_DSC_ERROR); |
| 144 | }; |
| 145 | let mut stdout_buf = Vec::new(); |
| 146 | match child_stdout.read_to_end(&mut stdout_buf) { |
| 147 | Ok(_) => (), |
| 148 | Err(e) => { |
| 149 | error!("{} '{executable}': {e}", t!("utils.failedReadStdout")); |
| 150 | exit(EXIT_DSC_ERROR); |
| 151 | } |
| 152 | } |
| 153 | |
| 154 | let Some(mut child_stderr) = child.stderr.take() else { |
| 155 | error!("{} {executable}", t!("utils.failedOpenStderr")); |
| 156 | exit(EXIT_DSC_ERROR); |
| 157 | }; |
| 158 | let mut stderr_buf = Vec::new(); |
| 159 | match child_stderr.read_to_end(&mut stderr_buf) { |
| 160 | Ok(_) => (), |
| 161 | Err(e) => { |
| 162 | error!("{} '{executable}': {e}", t!("utils.failedReadStderr")); |
| 163 | exit(EXIT_DSC_ERROR); |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | let exit_status = match child.wait() { |
| 168 | Ok(exit_status) => exit_status, |
| 169 | Err(e) => { |
| 170 | error!("{} '{executable}': {e}", t!("utils.failedWait")); |
| 171 | exit(EXIT_DSC_ERROR); |
| 172 | } |
| 173 | }; |
| 174 | |
| 175 | let exit_code = exit_status.code().unwrap_or(EXIT_PROCESS_TERMINATED); |
| 176 | let stdout = String::from_utf8_lossy(&stdout_buf).to_string(); |
| 177 | let stderr = String::from_utf8_lossy(&stderr_buf).to_string(); |
| 178 | (exit_code, stdout, stderr) |
| 179 | } |