use std::ffi::CStr; use std::os::raw::{c_char}; use std::io::Write; #[derive(Debug)] enum Error { IOError { error: std::io::Error }, StringError { error: std::str::Utf8Error }, PopenError { error: subprocess::PopenError }, Other { message: String }, } impl From for Error { fn from(err: std::str::Utf8Error) -> Error { Error::StringError { error: err } } } impl From for Error { fn from(err: std::io::Error) -> Error { Error::IOError { error: err } } } impl From for Error { fn from(err: subprocess::PopenError) -> Error { Error::PopenError { error: err } } } #[no_mangle] pub extern "C" fn rs_add_mcookie( cookie: *const c_char, display: *const c_char, xauth_cmd: *const c_char, authfile: *const c_char, ) -> c_char { let result = unsafe { add_mcookie( CStr::from_ptr(cookie), CStr::from_ptr(display), CStr::from_ptr(xauth_cmd), CStr::from_ptr(authfile), ) }; match result { Ok(()) => 1, Err(err) => { eprintln!("{:?}", err); 0 } } } fn add_mcookie(cookie: &CStr, display: &CStr, xauth_cmd: &CStr,authfile: &CStr) -> Result<(), Error> { let cmd = format!("{} -f {} -q", xauth_cmd.to_str()?, authfile.to_str()?); let mut p = subprocess::Popen::create(&[cmd], subprocess::PopenConfig { stdin: subprocess::Redirection::Pipe, ..Default::default() })?; if let Some(stdin) = &mut p.stdin { stdin.write(format!("remove {}\n", display.to_str()?).as_bytes())?; stdin.write(format!("add {} . {}\n", display.to_str()?, cookie.to_str()?).as_bytes())?; stdin.write("exit\n".as_bytes())?; } else { return Err(Error::Other { message: format!("unable to get pipe for writing") }); } Ok(()) }