diff options
author | bnewbold <bnewbold@robocracy.org> | 2016-10-12 00:22:29 -0700 |
---|---|---|
committer | bnewbold <bnewbold@robocracy.org> | 2016-10-12 00:22:29 -0700 |
commit | 2dca737392a208e094b6f054f39100b8d31ed80d (patch) | |
tree | 8f7918eb82f7ed3ca2903e56410949fb7577bd7c /src/bin | |
parent | 3b8e08cec49a5d60daf3afaa552a41e696b8de93 (diff) | |
download | einhyrningsins-2dca737392a208e094b6f054f39100b8d31ed80d.tar.gz einhyrningsins-2dca737392a208e094b6f054f39100b8d31ed80d.zip |
partially working shell command
Diffstat (limited to 'src/bin')
-rw-r--r-- | src/bin/einhyrningsinsctl.rs | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/src/bin/einhyrningsinsctl.rs b/src/bin/einhyrningsinsctl.rs new file mode 100644 index 0000000..c057b9e --- /dev/null +++ b/src/bin/einhyrningsinsctl.rs @@ -0,0 +1,136 @@ +/* + * einhyrningsinsctl: controller/shell for einhyrningsins + * Copyright (C) 2016 Bryan Newbold <bnewbold@robocracy.org> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#[macro_use] +extern crate json; + +extern crate getopts; +extern crate log; +extern crate env_logger; +extern crate nix; +extern crate timer; +extern crate time; +extern crate chan_signal; +extern crate url; +extern crate rustyline; + + +use std::io::prelude::*; +use std::io::{BufReader, BufWriter}; +use std::env; +use std::path::Path; +use std::process::exit; +use std::os::unix::net::UnixStream; +use getopts::Options; + +use rustyline::error::ReadlineError; +use rustyline::Editor; + + +// This is the main event loop +fn shell(ctrl_stream: UnixStream) { + + let mut reader = BufReader::new(&ctrl_stream); + let mut writer = BufWriter::new(&ctrl_stream); + + // `()` can be used when no completer is required + let mut rl = Editor::<()>::new(); + + loop { + let readline = rl.readline("> "); + match readline { + Ok(line) => { + rl.add_history_entry(&line); + if line.len() == 0 { continue; }; + let mut chunks = line.split(' '); + let cmd = chunks.nth(0).unwrap(); + let args = chunks.collect(); + send_msg(&mut reader, &mut writer, cmd, args).unwrap(); + }, + Err(ReadlineError::Interrupted) | Err(ReadlineError::Eof) => { + println!("Quitting..."); + break + }, + Err(err) => { + println!("Shell Error: {:?}", err); + break + } + } + } +} + +fn send_msg(reader: &mut BufRead, writer: &mut Write, cmd: &str, args: Vec<&str>) -> Result<String, String> { + let mut buffer = String::new(); + let mut arg_list = json::JsonValue::new_array(); + for a in args { + arg_list.push(a).unwrap(); + } + let req = object!{ + "command" => cmd, + "args" => arg_list + }; + //println!("Sending: {}", req.dump()); + writer.write_all(req.dump().as_bytes()).unwrap(); + writer.write_all("\n".as_bytes()).unwrap(); + writer.flush().unwrap(); + + reader.read_line(&mut buffer).unwrap(); + //println!("Got: {}", buffer); + let reply = json::parse(&buffer).unwrap(); + println!("{}", reply.as_str().unwrap()); + Ok(reply.as_str().unwrap().to_string()) +} + +fn print_usage(opts: Options) { + let brief = "usage:\teinhyrningsinsctl [options] program"; + println!(""); + print!("{}", opts.usage(&brief)); +} + +fn main() { + + let args: Vec<String> = env::args().collect(); + + let mut opts = Options::new(); + opts.optflag("h", "help", "print this help menu"); + + let matches = match opts.parse(&args[1..]) { + Ok(m) => { m } + Err(f) => { println!("{}", f.to_string()); print_usage(opts); exit(-1); } + }; + + if matches.opt_present("h") { + print_usage(opts); + return; + } + + // Bind to Control Socket + let ctrl_path = Path::new("/tmp/einhorn.sock"); + // XXX: handle this more gracefully (per-process) + if !ctrl_path.exists() { + println!("Couldn't find control socket: {:?}", ctrl_path); + exit(-1); + } + println!("Connecting to control socket: {:?}", ctrl_path); + let ctrl_stream = UnixStream::connect(ctrl_path).unwrap(); + + send_msg(&mut BufReader::new(&ctrl_stream), &mut BufWriter::new(&ctrl_stream), "ehlo", vec![]).unwrap(); + + shell(ctrl_stream); + exit(0); +} |