summary history branches tags files
commit:ee37b99e0a49f40316683fd89f12a57634743056
author:Trevor Bentley
committer:Trevor Bentley
date:Tue Nov 14 00:24:07 2017 +0100
parents:715661e5277b6fa2dda29bde4e9879cf00d143c4
Main loop logic -- idle detection.
diff --git a/resources/circadian.conf.in b/resources/circadian.conf.in
line changes: +24/-15
index 4c25a50..da124bd
--- a/resources/circadian.conf.in
+++ b/resources/circadian.conf.in
@@ -8,6 +8,8 @@
 # virtual terminals, SSH sessions, etc.  Resets whenever a TTY determines
 # that it has input, which is typically keypresses.
 #
+# At least one of tty_input or x11_input must be 'yes'.
+#
 # Monitors the idle column of the 'w' command.
 #
 # Default: yes
@@ -19,6 +21,8 @@ tty_input = yes
 # by certain programs.  Typically, any program that prevents the screensaver
 # from displaying will also reset this.
 #
+# At least one of tty_input or x11_input must be 'yes'.
+#
 # Monitors xprintidle and xssstate
 #
 # Default: yes
@@ -33,12 +37,15 @@ x11_input = yes
 # Default: yes
 ssh_block = yes
 
-# Whether active Samba connections block the system from being idle.
+# Whether active Samba connections block the system from being idle.  Note
+# that GVfs sometimes makes local loopback connections to a local Samba
+# share, which will prevent idle.  This is disabled by default because of
+# the aggressiveness of SMB browsing clients.
 #
 # Monitors netstat
 #
-# Default: yes
-smb_block = yes
+# Default: no
+smb_block = no
 
 # Whether active audio playback blocks the system from being idle.
 #
@@ -89,18 +96,6 @@ process_block = ^dd$,^rsync$,^apt-get$,^dpkg$,^cp$,^mv$
 # Default: 120 minutes
 idle_time = 120m
 
-# Time of day (in local timezone) to automatically wake the machine if it
-# is sleeping.  Specify in 24-hour time format with a colon.  Leave blank
-# or comment out for no wake time.
-#
-# This depends on the hardware RTC being enabled and supported by your kernel.
-#
-# Example:
-#   auto_wake = 16:00
-#
-# Default: disabled
-auto_wake =
-
 # Command to execute when the system is determined to have been idle for at
 # least idle_time.  Typically a suspend or hibernate command.
 #
@@ -116,5 +111,19 @@ auto_wake =
 # Default: pm-suspend
 on_idle = ""
 
+# Time of day (in local timezone) to automatically wake the machine if it
+# is sleeping.  Specify in 24-hour time format with a colon.  Leave blank
+# or comment out for no wake time.
+#
+# This depends on the hardware RTC being enabled and supported by your kernel.
+#
+# Example:
+#   auto_wake = 16:00
+#
+# Default: disabled
+auto_wake =
+
 # Command to execute after waking from a sleep.
+#
+# Default: <empty>
 on_wake = ""

diff --git a/src/main.rs b/src/main.rs
line changes: +92/-13
index 27f5204..071fce0
--- a/src/main.rs
+++ b/src/main.rs
@@ -369,22 +369,101 @@ fn read_cmdline() -> CircadianLaunchOptions {
     }
 }
 
-fn main() {
-    let launch_opts = read_cmdline();
-    let config = read_config(&launch_opts.config_file);
-    println!("{:?}", config);
+#[allow(dead_code)]
+fn test() {
     println!("Sec: {:?}", parse_w_time("10.45s"));
     println!("Sec: {:?}", parse_w_time("1:11"));
     println!("Sec: {:?}", parse_w_time("0:10m"));
+    println!("w min: {:?}", idle_w());
+    println!("xssstate min: {:?}", idle_xssstate());
+    println!("xprintidle min: {:?}", idle_xprintidle());
+    println!("cpu: {:?}", thresh_cpu(CpuHistory::Min5, 0.3, std::cmp::PartialOrd::lt));
+    println!("ssh: {:?}", exist_net_connection(NetConnection::SSH));
+    println!("smb: {:?}", exist_net_connection(NetConnection::SMB));
+    println!("iotop: {:?}", exist_process("^iotop$"));
+    println!("audio: {:?}", exist_audio());
+}
+
+fn main() {
+    println!("Circadian launching.");
+    let launch_opts = read_cmdline();
+    let config = read_config(&launch_opts.config_file)
+        .unwrap_or_else(|x| {
+            println!("{}", x);
+            println!("Could not open config file.  Exiting.");
+            std::process::exit(1);
+        });
+    println!("{:?}", config);
+    if !config.tty_input && !config.x11_input {
+        println!("tty_input or x11_input must be enabled.  Exiting.");
+        std::process::exit(1);
+    }
+    if config.tty_input && idle_w().is_err() {
+        println!("'w' command required by tty_input failed.  Exiting.");
+        std::process::exit(1);
+    }
+    if config.x11_input &&
+        idle_xssstate().is_err() &&
+        idle_xprintidle().is_err() {
+            println!("Both 'xssstate' and 'xprintidle' commands required by x11_input failed.  Exiting.");
+            std::process::exit(1);
+        }
+    if config.max_cpu_load.is_some() &&
+        thresh_cpu(CpuHistory::Min1, 0.0, std::cmp::PartialOrd::lt).is_err() {
+            println!("'uptime' command required by max_cpu_load failed.  Exiting.");
+            std::process::exit(1);
+        }
+    if (config.ssh_block || config.smb_block) &&
+        exist_net_connection(NetConnection::SSH).is_err() {
+        println!("'netstat' command required by ssh/smb_block failed.  Exiting.");
+        std::process::exit(1);
+        }
+    if config.audio_block && exist_audio().is_err() {
+        println!("'/proc/asound/' required by audio_block is unreadable.  Exiting.");
+        std::process::exit(1);
+    }
+    if config.process_block.len() > 0 && exist_process("").is_err() {
+        println!("'pgrep' required by process_block failed.  Exiting.");
+        std::process::exit(1);
+    }
+    if config.idle_time == 0 {
+        println!("Idle time disabled.  Nothing to do.  Exiting.");
+        std::process::exit(1);
+    }
+
+    println!("Configuration valid.  Idle detection starting.");
     loop {
-        println!("w min: {:?}", idle_w());
-        println!("xssstate min: {:?}", idle_xssstate());
-        println!("xprintidle min: {:?}", idle_xprintidle());
-        println!("cpu: {:?}", thresh_cpu(CpuHistory::Min5, 0.3, std::cmp::PartialOrd::lt));
-        println!("ssh: {:?}", exist_net_connection(NetConnection::SSH));
-        println!("smb: {:?}", exist_net_connection(NetConnection::SMB));
-        println!("iotop: {:?}", exist_process("^iotop$"));
-        println!("audio: {:?}", exist_audio());
-        std::thread::sleep(std::time::Duration::from_millis(2000));
+        let tty_idle = idle_w().unwrap_or(0);
+        let x11_idle = std::cmp::min(idle_xssstate().unwrap_or(0),
+                                     idle_xprintidle().unwrap_or(0));
+        let min_idle: u64 = match (config.tty_input, config.x11_input) {
+            (true,true) => std::cmp::min(tty_idle, x11_idle) as u64,
+            (true,false) => tty_idle as u64,
+            (false,_) => x11_idle as u64,
+        };
+        let idle_remain: u64 =
+            std::cmp::max(config.idle_time as i64 - min_idle as i64, 0) as u64;
+        if idle_remain == 0 {
+            let pass_cpu = thresh_cpu(CpuHistory::Min1,
+                                      config.max_cpu_load.unwrap_or(999.0),
+                                      std::cmp::PartialOrd::lt).unwrap_or(false);
+            let pass_ssh = !exist_net_connection(NetConnection::SSH).unwrap_or(false);
+            let pass_smb = !exist_net_connection(NetConnection::SMB).unwrap_or(false);
+            let pass_audio = !exist_audio().unwrap_or(false);
+            let pass_proc = !config.process_block.iter()
+                .map(|p| exist_process(p).unwrap_or(false))
+                .fold(false, |acc,p| acc || p);
+            println!("cpu: {}, ssh {}, smb: {}, audio: {}, proc: {}",
+                     pass_cpu, pass_ssh, pass_smb, pass_audio, pass_proc);
+            if (config.max_cpu_load.is_none() || pass_cpu) &&
+                (!config.ssh_block || pass_ssh) &&
+                (!config.smb_block || pass_smb) &&
+                (!config.audio_block || pass_audio) {
+                    println!("IDLE DETECTED.");
+                    // TODO: on_idle()
+            }
+        }
+        let sleep_time = std::cmp::max(idle_remain, 5000);
+        std::thread::sleep(std::time::Duration::from_millis(sleep_time));
     }
 }