blob: b5f4bc4e39d89a97322c0ba9c49a64e0cc8937e7 [file] [log] [blame]
// Copyright 2020 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// Very crude interactive console to allow the test host to run shell commands
/// in the guest and receive the output.
mod wire_format;
use std::fs::File;
use std::io;
use std::io::prelude::*;
#[cfg(any(target_os = "android", target_os = "linux"))]
use std::os::unix::process::ExitStatusExt;
use std::path::Path;
use std::process::Command;
use std::str;
use serde_json::Deserializer;
use crate::wire_format::DelegateMessage;
use crate::wire_format::GuestToHostMessage;
use crate::wire_format::HostToGuestMessage;
use crate::wire_format::ProgramExit;
/// Device file to read from and write to.
const CONSOLE_FILE: &str = "/dev/ttyS1";
fn listen(
input: &mut dyn Iterator<Item = Result<DelegateMessage, serde_json::Error>>,
mut output: Box<dyn io::Write>,
) -> io::Result<()> {
output.write_all(
serde_json::to_string_pretty(&DelegateMessage::GuestToHost(GuestToHostMessage::Ready))
.unwrap()
.as_bytes(),
)?;
loop {
if let Some(command) = input.next() {
match command?.assume_host_to_guest() {
HostToGuestMessage::Exit => {
break;
}
HostToGuestMessage::RunCommand {
command: command_string,
} => {
println!("-> {}", &command_string);
let result = Command::new("/bin/sh")
.args(["-c", &command_string])
.output()
.unwrap();
let command_result = GuestToHostMessage::ProgramExit(ProgramExit {
stdout: String::from_utf8_lossy(&result.stdout).into_owned(),
stderr: String::from_utf8_lossy(&result.stderr).into_owned(),
exit_status: match result.status.code() {
Some(code) => wire_format::ExitStatus::Code(code),
#[cfg(any(target_os = "android", target_os = "linux"))]
None => match result.status.signal() {
Some(signal) => wire_format::ExitStatus::Signal(signal),
None => wire_format::ExitStatus::None,
},
#[cfg(not(unix))]
_ => wire_format::ExitStatus::None,
},
});
println!(
"<- {}",
serde_json::to_string_pretty(&command_result).unwrap()
);
output.write_all(
serde_json::to_string_pretty(&DelegateMessage::GuestToHost(command_result))
.unwrap()
.as_bytes(),
)?;
}
}
}
}
Ok(())
}
fn main() {
let path = Path::new(CONSOLE_FILE);
let mut command_stream =
Deserializer::from_reader(File::open(path).unwrap()).into_iter::<DelegateMessage>();
listen(&mut command_stream, Box::new(File::create(path).unwrap())).unwrap();
}