summaryrefslogtreecommitdiff
path: root/src/systemd/unit.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemd/unit.rs')
-rw-r--r--src/systemd/unit.rs67
1 files changed, 67 insertions, 0 deletions
diff --git a/src/systemd/unit.rs b/src/systemd/unit.rs
new file mode 100644
index 0000000..3be7fa5
--- /dev/null
+++ b/src/systemd/unit.rs
@@ -0,0 +1,67 @@
+use std::collections::HashMap;
+use std::process::Command;
+
+use std::io;
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct Unit {
+ pub name: String,
+ pub type_: String
+}
+
+pub fn parse_key_value(line: &str) -> Option<(String, String)> {
+ let pos = line.find('=');
+ pos.map(|pos| {
+ let (k, v) = line.split_at(pos);
+ (k.to_owned(), v[1..].to_owned())
+ })
+}
+
+#[test]
+fn test_parse_key_value() {
+ assert_eq!(None, parse_key_value("ab"));
+ assert_eq!(Some(("a".to_owned(), "b".to_owned())), parse_key_value("a=b"));
+ assert_eq!(Some(("a".to_owned(), "b=c".to_owned())), parse_key_value("a=b=c"));
+}
+
+fn make_unit(info: HashMap<String, String>) -> Option<Unit> {
+ fn from_id(id: &str) -> Option<String> {
+ id.rsplit('.').next().map(|t| t.to_owned())
+ };
+ let id = info.get("Id").map(|id| id.clone());
+ let type_ = id.as_ref().and_then(|id| from_id(&id));
+
+ if let (Some(id), Some(type_)) = (id, type_) {
+ Some(Unit { name: id, type_: type_ })
+ } else {
+ None
+ }
+}
+
+#[test]
+fn test_make_unit() {
+ let s = |s: &str| -> String { s.to_owned() };
+ let info = [(s("Id"), s("Test.service"))]
+ .iter().cloned().collect::<HashMap<String, String>>();
+ assert_eq!(Some(Unit { name: s("Test.service"), type_: s("service") }), make_unit(info));
+
+ let info = HashMap::new();
+ assert_eq!(None, make_unit(info));
+}
+
+pub fn get_units() -> io::Result<Vec<Unit>> {
+ let mut units = Vec::new();
+ let status = try!(Command::new("systemctl")
+ .args(&["show", "*"]).output());
+
+ let mut unit_info = HashMap::new();
+ for line in String::from_utf8_lossy(&status.stdout).split('\n') {
+ if let Some((k, v)) = parse_key_value(line) {
+ unit_info.insert(k, v);
+ } else {
+ make_unit(unit_info).map(|u| units.push(u));
+ unit_info = HashMap::new();
+ }
+ }
+ return Ok(units);
+}