1
0
Fork 0
mirror of https://github.com/hermitcore/libhermit.git synced 2025-03-09 00:00:03 +01:00

Added connect command and redirect output.

This commit is contained in:
bytesnake 2017-07-22 23:39:12 +02:00
parent 9f8357f564
commit c3b21897e1
10 changed files with 263 additions and 120 deletions

View file

@ -3,11 +3,14 @@ use std::path::Path;
use std::result;
use std::thread;
use std::process;
use std::sync::Mutex;
use std::net::Shutdown;
use log;
use log::{LogMetadata, LogRecord, SetLoggerError, LogLevel, LogLevelFilter};
use nix::unistd::{fork, ForkResult};
use hermit::Isle;
use std::sync::RwLock;
use std::sync::Arc;
use std::io::Write;
use std::io::Read;
use bincode::{serialize, deserialize, Infinite};
@ -69,6 +72,8 @@ impl Connection {
loop {
if let Ok(socket) = UnixStream::connect("/tmp/hermit_daemon") {
socket.set_nonblocking(true).unwrap();
return Connection { socket: socket };
}
}
@ -79,26 +84,45 @@ impl Connection {
self.socket.write(&encoded).unwrap();
let mut tmp = vec![0; 1024];
let mut buf = Vec::new();
if let Err(err) = self.socket.read_to_end(&mut buf) {
if let Action::KillDaemon = action {
return ActionResult::KillDaemon(Ok(()));
loop {
match self.socket.read(&mut tmp) {
Ok(nread) => buf.extend_from_slice(&tmp[0..nread]),
Err(err) => {
if buf.len() > 0 {
break;
}
}
}
panic!("The daemon seem to be crashed!");
}
if buf.len() == 0 {
if let Action::KillDaemon = action {
return ActionResult::KillDaemon(Ok(()));
} else {
panic!("he result was empty!");
panic!("The result was empty!");
}
}
deserialize(&buf).unwrap()
}
pub fn output(&mut self) {
let mut buf = vec![0; 1024];
loop {
if let Ok(nread) = self.socket.read(&mut buf) {
let obj = deserialize(&buf).unwrap();
if let ActionResult::Output(out) = obj {
print!("{}", out);
} else if let ActionResult::OutputErr(out) = obj {
print!("{}", out);
}
}
}
}
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@ -106,6 +130,7 @@ pub enum Action {
CreateIsle(String, IsleParameter),
StopIsle(u32),
RemoveIsle(u32),
Connect(u32),
Log(Option<u32>),
List,
KillDaemon
@ -116,10 +141,13 @@ pub enum ActionResult {
CreateIsle(Result<u32>),
StopIsle(Result<i32>),
RemoveIsle(Result<i32>),
Connect(Result<()>),
Log(Vec<Log>),
IsleLog(Result<String>),
List(Vec<(Result<bool>, IsleParameter)>),
KillDaemon(Result<()>)
KillDaemon(Result<()>),
Output(String),
OutputErr(String)
}
#[derive(Serialize, Deserialize, Debug, Clone)]
@ -215,6 +243,12 @@ impl State {
Err(Error::WrongIsleNumber)
}
}
fn add_endpoint(&mut self, id: u32, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
self.exist_isle(id)?;
self.isles[id as usize].add_endpoint(stream)
}
}
pub fn daemon_handler() {
@ -224,13 +258,16 @@ pub fn daemon_handler() {
LocalLogger::init();
let listener = UnixListener::bind("/tmp/hermit_daemon").unwrap();
//for stream in listener.incoming() {
// match stream {
// Ok(mut stream) => {
'outer: loop { match listener.accept() {
Ok((mut stream, addr)) => {
// loop {
if let Ok(nread) = stream.read(&mut buf) {
for stream in listener.incoming() {
match stream {
Ok(mut stream) => {
let mut stream = Arc::new(Mutex::new(stream));
loop {
//println!("READ");
let nread = stream.lock().unwrap().read(&mut buf);
println!("{:?}", nread);
if let Ok(nread) = nread {
if nread > 0 {
let action:Action = deserialize(&buf).unwrap();
@ -239,10 +276,16 @@ pub fn daemon_handler() {
let ret = match action {
Action::KillDaemon => {
fs::remove_file("/tmp/hermit_daemon").unwrap();
break 'outer;
break;
},
Action::CreateIsle(path, specs) => ActionResult::CreateIsle(state.create_isle(path,specs)),
Action::List => ActionResult::List(state.list()),
Action::Connect(id) => {
let res = ActionResult::Connect(state.add_endpoint(id, stream.clone()));
let buf: Vec<u8> = serialize(&res, Infinite).unwrap();
stream.lock().unwrap().write(&buf);
break;
},
Action::Log(id) => {
match id {
Some(id) => ActionResult::IsleLog(state.log_isle(id)),
@ -254,17 +297,17 @@ pub fn daemon_handler() {
_ => { panic!(""); }
};
println!("WRITE");
let buf: Vec<u8> = serialize(&ret, Infinite).unwrap();
stream.write(&buf);
stream.lock().unwrap().write(&buf);
} else {
break;
}
} else {
break;
}
// }
},
Err(err) => {
println!("ERR: {:?}", err);
}
}
}
}
},
Err(err) => { println!("ERR: {:?}", err); }
}}
}

View file

@ -11,6 +11,9 @@ use std::path::Path;
use std::io::{Write, Read, BufReader, BufRead};
use inotify::{Inotify, watch_mask};
use std::env;
use std::os::unix::net::UnixStream;
use std::sync::Arc;
use std::sync::Mutex;
use hermit::qemu::QEmu;
use hermit::multi::Multi;
@ -106,6 +109,8 @@ pub trait Isle {
fn is_running(&mut self) -> Result<bool>;
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()>;
fn is_available(&self) -> Result<bool> {
let log = match self.log_file() {
Some(f) => f,

View file

@ -1,14 +1,19 @@
use std::fs::File;
use std::env;
use std::io::{Write, Read};
use std::sync::Arc;
use std::sync::Mutex;
use std::thread;
use hermit::Isle;
use hermit::error::*;
use hermit::socket::Socket;
use std::os::unix::net::UnixStream;
pub struct Multi {
num: u8,
socket: Socket
socket: Option<Socket>
}
impl Multi {
@ -46,7 +51,7 @@ impl Multi {
return Err(Error::MultiIsleFailed);
}
Ok(Multi { num: num, socket: Socket::new_multi(num) })
Ok(Multi { num: num, socket: Some(Socket::new()) })
}
}
@ -68,7 +73,13 @@ impl Isle for Multi {
}
fn run(&mut self) -> Result<()> {
self.socket.connect().run();
let mut socket = self.socket.take().ok_or(Error::InternalError)?;
socket.connect()?;
thread::spawn(move || {
socket.run();
});
Ok(())
}
@ -96,4 +107,8 @@ impl Isle for Multi {
fn is_running(&mut self) -> Result<bool> {
Ok(true)
}
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
Ok(())
}
}

View file

@ -7,11 +7,14 @@ use std::process::{ChildStdout, ChildStderr};
use std::thread;
use std::os::unix::net::UnixStream;
use std::io::Write;
use std::time::Duration;
use std::sync::Arc;
use std::sync::Mutex;
use hermit::{Isle, IsleParameterQEmu};
use hermit::utils;
use hermit::error::*;
use hermit::socket::Socket;
use hermit::socket::{Socket, Console};
const PIDNAME: &'static str = "/tmp/hpid-XXXXXX";
const TMPNAME: &'static str = "/tmp/hermit-XXXXXX";
@ -24,6 +27,7 @@ pub struct QEmu {
stderr: ChildStderr,
tmp_file: String,
pid_file: String,
console: Console
}
impl QEmu {
@ -35,20 +39,22 @@ impl QEmu {
let stdout = child.stdout.take().unwrap();
let stderr = child.stderr.take().unwrap();
println!("{}", pidf);
let socket = Socket::new();
let console = socket.console();
Ok(QEmu {
socket: Some(Socket::new_qemu()),
socket: Some(socket),
child: child,
stdout: stdout,
stderr: stderr,
tmp_file: tmpf,
pid_file: pidf,
console: console
})
}
pub fn start_with(path: &str, mem_size: u64, num_cpus: u32, add: IsleParameterQEmu, tmp_file: &str, pid_file: &str) -> Result<Command> {
let hostfwd = format!("user,hostfwd=tcp:127.0.0.1:{}-:{}", add.port, add.port);
//let monitor_str = format!("telnet:127.0.0.1:{},server,nowait", add.port+1);
let monitor_str = format!("unix:{}_monitor,server,nowait", pid_file);
let chardev = format!("file,id=gnc0,path={}",&tmp_file);
let freq = format!("\"-freq{} -proxy\"",(utils::cpufreq().unwrap()/1000).to_string());
@ -126,15 +132,29 @@ impl QEmu {
let mut control = UnixStream::connect(&file)
.map_err(|_| Error::InvalidFile(file.clone()))?;
control.set_read_timeout(Some(Duration::new(0,500))).unwrap();
control.write_all(cmd.as_bytes())
.map_err(|_| Error::InvalidFile(file.clone()))?;
control.write_all("\n".as_bytes())
.map_err(|_| Error::InvalidFile(file))?;
let mut buf = String::new();
let mut response = [0u8; 256];
let mut buf = Vec::new();
loop {
if let Ok(nread) = control.read(&mut response) {
buf.extend_from_slice(&response[..nread]);
} else {
break;
}
}
let res = String::from_utf8(buf).unwrap();
let res: String = res.lines().filter(|x| !x.starts_with("QEMU") && !x.starts_with("(qemu)")).collect();
control.read_to_string(&mut buf);
Ok(buf)
Ok(res)
}
}
@ -151,21 +171,17 @@ impl Isle for QEmu {
}
fn run(&mut self) -> Result<()> {
let socket = self.socket.take();
let mut socket = self.socket.take().ok_or(Error::InternalError)?;
socket.connect()?;
thread::spawn(|| {
socket.unwrap().connect().run();
thread::spawn(move || {
socket.run();
});
Ok(())
}
fn output(&self) -> Result<String> {
/*if let &Socket::Connected { ref stdout, ref stderr, .. } = &self.socket.unwrap() {
Ok(stdout.clone())
} else {
Err(Error::InternalError)
}*/
let mut file = File::open(&self.tmp_file).unwrap();
let mut content = String::new();
@ -175,7 +191,7 @@ impl Isle for QEmu {
}
fn stop(&mut self) -> Result<i32> {
self.send_cmd("system_powerdown")?;
self.send_cmd("stop")?;
Ok(0)
}
@ -183,7 +199,13 @@ impl Isle for QEmu {
fn is_running(&mut self) -> Result<bool> {
let state = self.send_cmd("info status")?;
Ok(state == "running")
Ok(state == "VM status: running")
}
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
self.console.lock().unwrap().push(stream);
Ok(())
}
}

View file

@ -6,34 +6,42 @@ use std::ffi::CString;
use std::ffi::CStr;
use std::process;
use byteorder::{ReadBytesExt, WriteBytesExt, LittleEndian};
use std::sync::Arc;
use std::sync::Mutex;
use std::os::unix::net::UnixStream;
use bincode::{serialize, Infinite};
use hermit::proto;
use hermit::proto::Packet;
use hermit::error::{Error, Result};
use daemon::ActionResult;
use libc;
const HERMIT_MAGIC: u32 = 0x7E317;
pub type Console = Arc<Mutex<Vec<Arc<Mutex<UnixStream>>>>>;
#[derive(Debug)]
pub enum Socket {
QEmu,
Multi(u8),
Connected { stream: TcpStream, stdout: String, stderr: String }
pub struct Socket {
stream: Option<TcpStream>,
console: Console
}
impl Socket {
pub fn new_qemu() -> Socket {
Socket::QEmu
pub fn new() -> Socket {
Socket { stream: None, console: Arc::new(Mutex::new(Vec::new())) }
}
pub fn new_multi(id: u8) -> Socket {
Socket::Multi(id)
}
pub fn connect(&self) -> Socket {
pub fn connect(&mut self) -> Result<()> {
// prepare the initializing struct
let length: usize = 4 + env::args().skip(2).map(|x| 4+x.len()).sum::<usize>()+ 4 + env::vars().map(|(x,y)| 5 + x.len()+ y.len()).sum::<usize>();
let length: usize = 4 + env::args().skip(2).map(|x| 4+x.len()).sum::<usize>() +
4 + env::vars().map(|(x,y)| 5 + x.len()+ y.len()).sum::<usize>();
let mut buf = Cursor::new(vec![0u8;length]);
// initialize the connection with the magic number
buf.write_u32::<LittleEndian>(HERMIT_MAGIC);
// send all arguments (skip first)
buf.write_u32::<LittleEndian>(env::args().count() as u32 - 2);
@ -52,47 +60,38 @@ impl Socket {
let mut stream;
loop {
match *self {
Socket::QEmu => {
match TcpStream::connect(("127.0.0.1", 0x494E)) {
Ok(mut s) => {
match s.write(buf.get_ref()) {
Ok(_) => { stream = s; break; },
Err(_) => {}
}
},
match TcpStream::connect(("127.0.0.1", 0x494E)) {
Ok(mut s) => {
match s.write(buf.get_ref()) {
Ok(_) => { stream = s; break; },
Err(_) => {}
}
},
Err(_) => {}
}
},
Socket::Multi(id) => {
match TcpStream::connect((format!("127.0.0.{}", id).as_ref(), 0x494E)) {
Ok(mut s) => {
match s.write(buf.get_ref()) {
Ok(_) => { stream = s; break; },
Err(_) => {}
}
},
Err(_) => {}
}
},
_ => panic!("")
Err(_) => {}
}
}
debug!("Connected to {}", stream.peer_addr().unwrap());
self.stream = Some(stream);
debug!("Connected to {}", self.stream()?.peer_addr().unwrap());
debug!("Transmitted environment and arguments with length {}", length);
Socket::Connected { stream: stream, stdout: String::new(), stderr: String::new() }
Ok(())
}
pub fn run(&mut self) {
pub fn console(&self) -> Console {
self.console.clone()
}
pub fn stream(&self) -> Result<&TcpStream> {
self.stream.as_ref().ok_or(Error::InternalError)
}
pub fn run(&mut self) -> Result<()> {
debug!("Initializing protocol state machine");
let mut state = proto::State::Id;
let (mut stream, mut stdout, mut stderr) = match self {
&mut Socket::Connected { ref mut stream, ref mut stdout, ref mut stderr } => (stream, stdout, stderr),
_ => return
};
let mut stream = self.stream()?;
let mut cur = Cursor::new(vec![]);
let mut buf = [0u8; 4096];
@ -122,9 +121,21 @@ impl Socket {
let buf_ret: [u8;8] = transmute(libc::write(fd as i32, buf.as_ptr() as *const libc::c_void, buf.len()).to_le());
if fd == 1 {
stdout.push_str(&String::from_utf8_unchecked(buf));
let ret = ActionResult::Output(String::from_utf8_unchecked(buf));
let buf: Vec<u8> = serialize(&ret, Infinite).unwrap();
for stream in self.console.lock().unwrap().iter_mut() {
stream.lock().unwrap().write(&buf).unwrap();
}
//stdout.push_str(&String::from_utf8_unchecked(buf));
} else if fd == 2 {
stderr.push_str(&String::from_utf8_unchecked(buf));
let ret = ActionResult::OutputErr(String::from_utf8_unchecked(buf));
let buf: Vec<u8> = serialize(&ret, Infinite).unwrap();
for stream in self.console.lock().unwrap().iter_mut() {
stream.lock().unwrap().write(&buf).unwrap();
}
//stderr.push_str(&String::from_utf8_unchecked(buf));
} else {
stream.write(&buf_ret);
}
@ -171,5 +182,6 @@ impl Socket {
}
}
}
Ok(())
}
}

View file

@ -1,8 +1,12 @@
use libc::{write, read, lseek, exit, open, close, c_int, c_void};
use libc::{write, read, lseek, exit, open, close, c_int, c_void, c_char};
use super::kvm_header::{kvm_run, KVM_EXIT_IO, KVM_EXIT_HLT, KVM_EXIT_MMIO,KVM_EXIT_FAIL_ENTRY, KVM_EXIT_INTERNAL_ERROR, KVM_EXIT_SHUTDOWN };
use std::ffi::CStr;
use std::ffi::CString;
use bincode::{serialize, Infinite};
use super::{Error, Result};
use hermit::socket::Console;
use daemon::ActionResult;
const PORT_WRITE: u16 = 0x499;
const PORT_OPEN: u16 = 0x500;
@ -91,12 +95,21 @@ impl Syscall {
}
pub unsafe fn run(&self, guest_mem: *mut u8) -> Result<Return> {
pub unsafe fn run(&self, guest_mem: *mut u8, console: Console) -> Result<Return> {
debug!("{:?}", *self);
match *self {
Syscall::Write(obj) => {
if (*obj).fd == 1 {
use std::io::Write;
let cstr = CString::from_raw((*obj).buf as *mut c_char);
let ret = ActionResult::Output(cstr.into_string().unwrap_or("".into()));
let buf: Vec<u8> = serialize(&ret, Infinite).unwrap();
for stream in console.lock().unwrap().iter_mut() {
stream.lock().unwrap().write(&buf).unwrap();
}
} else if (*obj).fd == 2 {
}
(*obj).length = write((*obj).fd, guest_mem.offset((*obj).buf) as *const c_void, (*obj).length as usize);

View file

@ -5,11 +5,16 @@ use std::ptr;
use std::fs::{File,OpenOptions};
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::sync::Arc;
use std::sync::Mutex;
use libc;
use hermit::Isle;
use super::{Error, Result, NameIOCTL};
use super::vm::VirtualMachine;
use hermit::socket::Console;
use std::os::unix::net::UnixStream;
/// The normal way of defining a IOCTL interface is provided by C macros. In Rust we have our own
/// flawed macro system. The module below wraps a bunch of functions which are generated by the
@ -106,19 +111,22 @@ impl KVM {
pub struct Uhyve {
kvm: KVM,
vm: VirtualMachine
vm: VirtualMachine,
console: Console
}
impl Uhyve {
pub fn new(path: &str, mem_size: u64, num_cpus: u32) -> Result<Uhyve> {
let kvm = KVM::new();
let mut vm = kvm.create_vm(mem_size as usize, num_cpus)?;
let console = vm.console();
vm.load_kernel(path)?;
vm.init()?;
Ok(Uhyve {
kvm: kvm,
vm: vm
vm: vm,
console: console
})
}
}
@ -155,4 +163,10 @@ impl Isle for Uhyve {
fn is_running(&mut self) -> Result<bool> {
self.vm.is_running()
}
fn add_endpoint(&mut self, stream: Arc<Mutex<UnixStream>>) -> Result<()> {
self.console.lock().unwrap().push(stream);
Ok(())
}
}

View file

@ -19,6 +19,7 @@ use super::kvm_header::{kvm_sregs, kvm_regs, kvm_segment, kvm_cpuid2,kvm_cpuid2_
use super::{Result, Error, NameIOCTL};
use super::gdt;
use super::proto;
use hermit::socket::Console;
pub const GUEST_OFFSET: usize = 0x0;
pub const CPUID_FUNC_PERFMON: usize = 0x0A;
@ -54,7 +55,8 @@ pub struct SharedState {
run_mem: Mmap,
mboot:*mut u8,
guest_mem: *mut u8,
running_state: Arc<AtomicBool>
running_state: Arc<AtomicBool>,
console: Console
}
pub struct VirtualCPU {
@ -66,7 +68,7 @@ pub struct VirtualCPU {
}
impl VirtualCPU {
pub fn new(kvm_fd: RawFd, vm_fd: RawFd, id: u32, entry: u64, mem: &mut Mmap, mboot: *mut u8, running_state: Arc<AtomicBool>) -> Result<VirtualCPU> {
pub fn new(kvm_fd: RawFd, vm_fd: RawFd, id: u32, entry: u64, mem: &mut Mmap, mboot: *mut u8, running_state: Arc<AtomicBool>, console: Console) -> Result<VirtualCPU> {
// create a new VCPU and save the file descriptor
let fd = VirtualCPU::create_vcpu(vm_fd, id as u32)?;
@ -87,7 +89,8 @@ impl VirtualCPU {
run_mem: run_mem,
mboot: mboot,
guest_mem: mem.mut_ptr(),
running_state: running_state
running_state: running_state,
console: console
};
let cpu = VirtualCPU {
@ -207,7 +210,7 @@ impl VirtualCPU {
}
unsafe {
let a = proto::Syscall::from_mem(state.run_mem.ptr(), state.guest_mem).run(state.guest_mem);
let a = proto::Syscall::from_mem(state.run_mem.ptr(), state.guest_mem).run(state.guest_mem, state.console.clone());
a
}

View file

@ -10,7 +10,7 @@ use elf;
use elf::types::{ELFCLASS64, OSABI, PT_LOAD};
use std::ffi::CStr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::thread::JoinHandle;
use hermit::utils;
@ -18,6 +18,7 @@ use hermit::uhyve;
use super::kvm_header::{kvm_userspace_memory_region, KVM_CAP_SYNC_MMU, KVM_32BIT_GAP_START, KVM_32BIT_GAP_SIZE, kvm_sregs};
use super::{Result, Error, NameIOCTL};
use super::vcpu::{ExitCode, VirtualCPU};
use hermit::socket::Console;
//use byteorder::ByteOrder;
// guest offset?
@ -34,7 +35,8 @@ pub struct VirtualMachine {
num_cpus: u32,
sregs: kvm_sregs,
running_state: Arc<AtomicBool>,
thread_handles: Vec<JoinHandle<ExitCode>>
thread_handles: Vec<JoinHandle<ExitCode>>,
console: Console
}
impl VirtualMachine {
@ -53,7 +55,7 @@ impl VirtualMachine {
unsafe { libc::mprotect((mem.mut_ptr() as *mut libc::c_void).offset(KVM_32BIT_GAP_START as isize), KVM_32BIT_GAP_START, libc::PROT_NONE); }
}
Ok(VirtualMachine { kvm_fd: kvm_fd, vm_fd: fd, mem: mem, elf_header: None, klog: None, vcpus: Vec::new(), mboot: None, num_cpus: num_cpus, sregs: kvm_sregs::default(), running_state: Arc::new(AtomicBool::new(false)), thread_handles: Vec::new() })
Ok(VirtualMachine { kvm_fd: kvm_fd, vm_fd: fd, mem: mem, elf_header: None, klog: None, vcpus: Vec::new(), mboot: None, num_cpus: num_cpus, sregs: kvm_sregs::default(), running_state: Arc::new(AtomicBool::new(false)), thread_handles: Vec::new(), console: Arc::new(Mutex::new(Vec::new())) })
}
/// Loads a kernel from path and initialite mem and elf_entry
@ -200,7 +202,7 @@ impl VirtualMachine {
pub fn create_vcpu(&mut self, id: u32) -> Result<()> {
let entry = self.elf_header.ok_or(Error::KernelNotLoaded)?.entry;
let cpu = VirtualCPU::new(self.kvm_fd, self.vm_fd, id, entry, &mut self.mem,self.mboot.unwrap(), self.running_state.clone())?;
let cpu = VirtualCPU::new(self.kvm_fd, self.vm_fd, id, entry, &mut self.mem,self.mboot.unwrap(), self.running_state.clone(), self.console.clone())?;
if id == 0 {
self.sregs = cpu.init_sregs()?;
@ -221,6 +223,9 @@ impl VirtualMachine {
Ok(c_str.into())
}
pub fn console(&self) -> Console {
self.console.clone()
}
pub fn run(&mut self) -> Result<()> {
let mut guest_mem = unsafe { self.mem.as_mut_slice() };
@ -257,17 +262,6 @@ impl VirtualMachine {
if self.running_state.load(Ordering::Relaxed) {
return Ok(true);
} else {
/*while let Some(handle) = self.thread_handles.pop() {
if let Ok(ret) = handle.join() {
match ret {
ExitCode::Innocent => continue,
ExitCode::Cause(cause) => {
cause?;
}
}
}
}*/
return Ok(false);
}
}

View file

@ -56,6 +56,9 @@ fn main() {
(@subcommand list =>
(about: "Lists all Hermit isles")
)
(@subcommand start_daemon =>
(about: "Starts the daemon in foreground")
)
(@subcommand kill_daemon =>
(about: "Stops the daemon and deletes the unix socket")
)
@ -63,6 +66,10 @@ fn main() {
(about: "Stops an Hermit isle")
(@arg name: +required "The corresponding name")
)
(@subcommand connect =>
(about: "Connects to an hermit isle")
(@arg name: +required "The corresponding name")
)
(@subcommand log =>
(about: "Acquire logging information")
(@arg name: "Focus on a single instance")
@ -73,6 +80,12 @@ fn main() {
)
).get_matches();
if let Some(_) = matches.subcommand_matches("start_daemon") {
daemon::daemon_handler();
return;
}
let mut daemon = daemon::Connection::connect();
// list all isles
@ -160,6 +173,23 @@ fn main() {
}
}
if let Some(matches) = matches.subcommand_matches("connect") {
match matches.value_of("name").unwrap().parse::<u32>() {
Ok(id) => {
let res = daemon.send(Action::Connect(id));
if let ActionResult::Connect(Ok(_)) = res {
daemon.output();
} else if let ActionResult::Connect(Err(err)) = res {
println!("Connect failed: {:?}", err);
}
},
Err(_) => {
println!("Invalid number!");
}
}
}
// create the isle, wait to be available and start it
if let Some(matches) = matches.subcommand_matches("run") {
if let Some(isle) = matches.value_of("isle") {
@ -197,13 +227,5 @@ fn main() {
));
println!("Created Isle with number: {:?}", res);
// hermit::new_isle(&matches.value_of("file").unwrap())
// .and_then(|mut isle| {
// isle.wait_until_available()?;
// isle.run()?;
//
// Ok(())
// }).unwrap();
}
}