[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#774247: sleepd: Option to prevent sleep on open TCP connections



Package: sleepd
Severity: wishlist
Tags: patch

I just scratched an itch: I want my home server to stay up as long as
there are open ssh (or scp, sftp) connections (even if these connections
are idle).

I thus added a command-line option "-p <port>" (for my use case, -p 22).
It scans /proc/net/tcp for users of the port, and if there is more than
one (i.e., the listening sshd plus at least one forked child), it counts
it as an activity.

The included patch applies to sleepd 2.08.

Sleepd 2.08 does not run on my home server (wheezy, amd64) because it
does not provide /sys/class/power_supply (I did not investigate why not;
it does provide functional ACPI).  Thus, the patch includes another,
unrelated option "-C" to force use of ACPI.  I can tease these two
options apart into separate patches if necessary, but both are trivial.

I'd like to see this patch (or an improved version) applied upstream
(whatever this means, as it is "dead and buried" according to
http://joeyh.name/code/).  Or else, please let me know about an
alive-and-well alternative to sleepd.

Justus


-- System Information:
Debian Release: 8.0
  APT prefers testing
  APT policy: (500, 'testing')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 3.16.0-4-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)


--- a/sleepd.c
+++ b/sleepd.c
@@ -58,9 +58,11 @@
 #endif
 int use_acpi=0;
 int force_hal=0;
+int force_acpi=0;
 int require_unused_and_battery=0;	/* --and or -A option */
 double max_loadavg = 0;
 int use_utmp=0;
+int port=0;
 int use_net=0;
 int min_tx=TXRATE;
 int min_rx=RXRATE;
@@ -69,7 +71,7 @@
 int debug=0;
 
 void usage () {
-	fprintf(stderr, "Usage: sleepd [-s command] [-d command] [-u n] [-U n] [-I] [-i n] [-E] [-e filename] [-a] [-l n] [-w] [-n] [-v] [-c n] [-b n] [-A] [-H] [-N [dev] [-t n] [-r n]]\n");
+	fprintf(stderr, "Usage: sleepd [-s command] [-d command] [-u n] [-U n] [-I] [-i n] [-E] [-e filename] [-a] [-l n] [-p n] [-w] [-n] [-v] [-c n] [-b n] [-A] [-C] [-H] [-N [dev] [-t n] [-r n]]\n");
 }
 
 void parse_command_line (int argc, char **argv) {
@@ -95,7 +97,9 @@
 		{"netdev", 2, NULL, 'N'},
 		{"rx-min", 1, NULL, 'r'},
 		{"tx-min", 1, NULL, 't'},
+		{"port", 1, NULL, 'p'},
 		{"force-hal", 0, NULL, 'H'},
+		{"force-acpi", 0, NULL, 'C'},
 		{"force-upower", 0, NULL, 1},
 		{0, 0, 0, 0}
 	};
@@ -111,7 +115,7 @@
 	char rx_statfile[44];
 
 	while (c != -1) {
-		c=getopt_long(argc,argv, "s:d:nvu:U:l:wIi:Ee:hac:b:AN::r:t:H", long_options, NULL);
+		c=getopt_long(argc,argv, "s:d:nvu:U:l:p:wIi:Ee:hac:b:AN::r:t:HC", long_options, NULL);
 		switch (c) {
 			case 's':
 				sleep_command=strdup(optarg);
@@ -141,6 +145,9 @@
 			case 'H':
 				force_hal=1;
 				break;
+			case 'C':
+				force_acpi=1;
+				break;
 			case 'i':
 				i = atoi(optarg);
 				if ((i < 0) || (i >= MAX_IRQS)) {
@@ -231,6 +238,9 @@
 			case 'r':
 				min_rx = atoi(optarg);
 				break;
+			case 'p':
+				port = atoi(optarg);
+				break;
 			case 'A':
 				require_unused_and_battery=1;
 				break;
@@ -388,6 +398,24 @@
 	return activity;
 }
 
+int check_port (int activity) {
+  FILE *f = fopen(TCPFILE, "r");
+  if (!f) {
+    syslog(LOG_ERR, "cannot open %s", TCPFILE);
+    return activity;
+  }
+  char tcpbuf[1024];
+  int portusers = 0;
+  while (fgets(tcpbuf, sizeof(tcpbuf), f)) {
+    int tcpport;
+    if (sscanf(tcpbuf, "%*d:%*x:%x", &tcpport) == 1 && tcpport == port)
+      portusers++;
+  }
+  fclose(f);
+  if (debug)  printf("sleepd: %d users of port %d\n", portusers, port);
+  return (portusers > 1) ? 1 : activity;
+}
+
 int check_utmp (int total_unused) {
 	/* replace total_unused with the minimum of
 	 * total_unused and the shortest utmp idle time. */
@@ -515,6 +543,10 @@
 			activity=check_net(activity);
 		}
 
+		if (port) {
+			activity=check_port(activity);
+		}
+
 		if ((max_loadavg != 0) &&
 		    (getloadavg(loadavg, 1) == 1) &&
 		    (loadavg[0] >= max_loadavg)) {
@@ -636,8 +668,10 @@
 			fclose(f);
 		}
 	}
-	
-	if (force_hal
+
+	if (force_acpi)
+	  use_acpi = 1;
+	else if (force_hal
 #ifdef USE_APM
 		|| apm_exists() != 0
 #else
--- a/sleepd.h
+++ b/sleepd.h
@@ -8,3 +8,4 @@
 #define TXRATE 15
 #define RXFILE "/sys/class/net/%s/statistics/rx_packets"
 #define RXRATE 25
+#define TCPFILE "/proc/net/tcp"
--- a/sleepd.8
+++ b/sleepd.8
@@ -3,7 +3,7 @@
 sleepd \- puts a laptop to sleep during inactivity or on low battery
 .SH SYNOPSIS
 .B sleepd
-.I "[-s command] [-d command] [-u n] [-U n] [-I] [-i n] [-E] [-e filename] [-a] [-l n] [-w] [-n] [-v] [-c n] [-b n] [-A] [-H] [-N [device] [-r n] [-t n]]"
+.I "[-s command] [-d command] [-u n] [-U n] [-I] [-i n] [-E] [-e filename] [-a] [-l n] [-p n] [-w] [-n] [-v] [-c n] [-b n] [-A] [-C] [-H] [-N [device] [-r n] [-t n]]"
 .SH DESCRIPTION
 .BR sleepd
 is a daemon to force laptops to go to sleep after some period of
@@ -97,6 +97,11 @@
 Set a baseline receive traffic rate in packets per second for network
 monitoring. Requires \-N.
 .TP
+.B \-p, \-\-port
+Monitor an IPv4 port for an open TCP connection.  For example, "-p 22"
+prevents the system from sleeping as long as any incoming ssh, scp or
+sftp are open.
+.TP
 .B \-A, \-\-and
 Only go to sleep if all specified conditions are met. For example, only
 sleep if idle and if the battery is low.
@@ -105,8 +110,11 @@
 Number of seconds between check on system status. Defaults to 10
 seconds, which should be fine generally.
 .TP
-.B \-H, \-\-force-upower
-Force UPower to be used instead of ACPI or other methods to query battery status.
+.B \-H, \-\-force-hal
+Force HAL to be used instead of ACPI or other methods to query battery status.
+.TP
+.B \-C, \-\-force-acpi
+Force ACPI to be used even if battery status cannot be queried via ACPI.
 .SH "SEE ALSO"
 .BR sleepctl (1)
 .P

Reply to: