use std::io::{self, Write}; use std::net::Shutdown; use std::os::unix::net::UnixStream; use std::path::PathBuf; use byteorder::{BigEndian, ReadBytesExt}; use serde::{Deserialize, Serialize}; use structopt::StructOpt; pub fn socket_path() -> String { format!( "{}/.twfss/sock", dirs::home_dir().unwrap().to_str().unwrap().to_owned() ) } #[derive(StructOpt, Serialize, Deserialize)] #[structopt(about = "CLI for the two-way file system sync client")] pub struct Options { #[structopt(long)] pub verbose: bool, #[structopt(subcommand)] pub command: Command, } #[derive(StructOpt, Serialize, Deserialize)] pub enum Command { ListDirectories { status: bool, }, AddDirectory { // TODO: Login information. local_directory: PathBuf, remote_url: String, }, RemoveDirectory { local_directory: PathBuf, }, // TODO: Command to update login information in case of login problems. } // The file is included in the sync client, where main() is unused. #[allow(unused)] fn main() { let options = Options::from_args(); // We simply send the options to the server and print whatever the server returns. let mut client = match SyncClient::connect() { Ok(client) => client, Err(err) => { println!( "Could not connect to the sync client. Make sure that the sync client is running." ); println!("Error: {:?}", err); std::process::exit(-1); } }; let return_code = client.execute(options).unwrap(); std::process::exit(return_code); } struct SyncClient { stream: UnixStream, } impl SyncClient { fn connect() -> Result { let stream = UnixStream::connect(socket_path()).unwrap(); Ok(SyncClient { stream }) } fn execute(&mut self, options: Options) -> Result { let json = serde_json::to_string(&options)?; self.stream.write_all(json.as_bytes())?; self.stream.shutdown(Shutdown::Write).unwrap(); // The first 4 bytes are the return value. let return_value = self.stream.read_i32::()?; // Print all the output returned by the server. io::copy(&mut self.stream, &mut io::stdout())?; Ok(return_value) } } #[derive(Debug)] enum Error { Json(serde_json::error::Error), Io(std::io::Error), } impl From for Error { fn from(e: serde_json::error::Error) -> Error { Error::Json(e) } } impl From for Error { fn from(e: io::Error) -> Error { Error::Io(e) } }