diff options
Diffstat (limited to 'src/tasks.rs')
| -rw-r--r-- | src/tasks.rs | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/src/tasks.rs b/src/tasks.rs new file mode 100644 index 0000000..3d9d940 --- /dev/null +++ b/src/tasks.rs @@ -0,0 +1,171 @@ +pub struct Task { + pub name: &'static str, + pub exec: fn(&[String]) -> Result<String, String>, +} + +impl PartialEq for &Task { + fn eq(&self, other: &Self) -> bool { + self.name == other.name + } +} + +pub const TASKS: &[Task] = &[ + Task { + name: "nop", + exec: no_op, + }, + Task { + name: "exec", + exec: exec, + }, + Task { + name: "network", + exec: network, + }, +]; + +fn no_op(_: &[String]) -> Result<String, String> { + Ok("".to_string()) +} + +fn exec(cmds: &[String]) -> Result<String, String> { + use std::process::Command; + // TODO: fmt and add exit code, and add support for both stdout and stderr, and support for no output + match Command::new(cmds[0].as_str()).args(&cmds[1..]).output() { + Ok(o) => { + if o.status.success() { + Ok(String::from_utf8_lossy(&o.stdout).to_string()) + } else { + Err(String::from_utf8_lossy(&o.stderr).to_string()) + } + } + Err(e) => Err(e.to_string()), + } +} + +fn network(switch: &[String]) -> Result<String, String> { + use std::process::{Command, Stdio}; + let switch: bool = match switch[0].parse() { + Ok(s) => s, + Err(e) => return Err(e.to_string()), + }; + + // TODO: windows and linux + + // todo let .. = Command::new('networksetup') + #[cfg(target_os = "macos")] + { + use std::io::Read; + match Command::new("networksetup") + .arg("-listallhardwareports") + .stdout(Stdio::piped()) + .spawn() + { + Ok(devs) => { + match Command::new("awk") + .arg(r#"/Wi-Fi|AirPort/{getline; print $2}"#) + .stdin(Stdio::from(match devs.stdout { + Some(s) => s, + None => match devs.stderr { + Some(mut e) => { + let mut reason = String::new(); + match e.read_to_string(&mut reason) { + Ok(_) => {} + Err(e) => return Err(format!("networksetup failed to list hardware: {e}")) + } + return Err(format!( + "networksetup failed to list hardware: {reason}" + )); + } + None => Err("networksetup failed to list hardware".to_string())?, + }, + })) + .stdout(Stdio::piped()) + .spawn() + { + Ok(dev) => match Command::new("networksetup").arg("-setairportpower").arg( + match dev.stdout { + Some(mut o) => { + let mut output = String::new(); + match o.read_to_string(&mut output) { + Ok(_) => (), + Err(e) => return Err(format!("awk failed to get device from networksetup list hardware: {e}")) + }; + output + } + None => match dev.stderr { + Some(mut e) => { + let mut reason = String::new(); + match e.read_to_string(&mut reason) { + Ok(_) => {} + Err(e) => return Err(format!("awk failed to get device from networksetup list hardware: {e}")) + } + return Err(format!("awk failed to get device from networksetup list hardware: {reason}")); + } + None => Err("awk failed to get device from networksetup list hardware".to_string())?, + }, + }, + ).arg(if switch { "on" } else { "off" }).output() { + Ok(o) => { + if o.status.success() { + Ok(String::from_utf8_lossy(&o.stdout) + .to_string()) + } else { + Err(String::from_utf8_lossy(&o.stderr) + .to_string()) + } + } + Err(e) => Err(e.to_string()), + }, + Err(e) => Err(e.to_string()), + } + } + Err(e) => Err(e.to_string()), + } + } + + #[cfg(not(target_os = "macos"))] + Err("not implemented".to_string()) +} + +#[derive(Debug)] +pub enum IntoTaskErr { + NotFound(String), +} + +pub trait IntoTask { + fn into_task<'a>(self) -> Result<&'a Task, IntoTaskErr>; +} + +impl IntoTask for String { + fn into_task<'a>(self) -> Result<&'a Task, IntoTaskErr> { + for task in TASKS { + if task.name == self { + return Ok(task); + } + } + Err(IntoTaskErr::NotFound(self)) + } +} + +impl IntoTask for &str { + fn into_task<'a>(self) -> Result<&'a Task, IntoTaskErr> { + for task in TASKS { + if task.name == self { + return Ok(task); + } + } + Err(IntoTaskErr::NotFound(self.to_string())) + } +} + +impl IntoTask for &Task { + fn into_task<'a>(self) -> Result<&'a Task, IntoTaskErr> { + for task in TASKS { + if task == self { + return Ok(task); + } + } + Err(IntoTaskErr::NotFound(self.name.to_string())) + } +} |
