bin/97896: [patch] proper system shut down on low battery level

Beat Gaetzi beat at chruetertee.ch
Thu May 25 12:30:25 UTC 2006


>Number:         97896
>Category:       bin
>Synopsis:       [patch] proper system shut down on low battery level
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu May 25 12:30:23 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator:     Beat Gätzi
>Release:        FreeBSD 6.1-RELEASE i386
>Organization:
>Environment:
System: FreeBSD daedalus.network.local 6.1-RELEASE FreeBSD 6.1-RELEASE #0: Sat May 6 12:37:33 CEST 2006 beat at daedalus.network.local:/usr/obj/usr/src/sys/BEASTIE i386


	
>Description:
If the notebook battery is empty, the system switches off without a proper system shut down. The attached patch adds two new options to the powerd which give the user a warning if the battery level is low and shut down the system if the user doesn't care about the warning.

	
>How-To-Repeat:
	
>Fix:

	

--- powerd.patch begins here ---
diff -ruN /usr/src/usr.sbin/powerd.ori/powerd.8 /usr/src/usr.sbin/powerd/powerd.8
--- /usr/src/usr.sbin/powerd.ori/powerd.8	Thu May 25 13:16:20 2006
+++ /usr/src/usr.sbin/powerd/powerd.8	Thu May 25 13:04:53 2006
@@ -39,7 +39,9 @@
 .Op Fl p Ar ival
 .Op Fl P Ar pidfile
 .Op Fl r Ar percent
+.Op Fl s Ar percent
 .Op Fl v
+.Op Fl w Ar percent
 .Sh DESCRIPTION
 The
 .Nm
@@ -92,11 +94,17 @@
 adaptive
 mode should consider the CPU running and increase performance.
 The default is 65% or lower.
+.It Fl s Ar percent
+Specifies the battery level on which a warning message will be sent to all
+user terminals.
 .It Fl v
 Verbose mode.
 Messages about power changes will be printed to stdout and
 .Nm
 will operate in the foreground.
+.It Fl w Ar percent
+Specifies the battery level on which the system will be shut down
+automatically.
 .El
 .Sh SEE ALSO
 .Xr acpi 4 ,
diff -ruN /usr/src/usr.sbin/powerd.ori/powerd.c /usr/src/usr.sbin/powerd/powerd.c
--- /usr/src/usr.sbin/powerd.ori/powerd.c	Thu May 25 13:16:20 2006
+++ /usr/src/usr.sbin/powerd/powerd.c	Thu May 25 13:39:24 2006
@@ -31,6 +31,7 @@
 #include <sys/param.h>
 #include <sys/ioctl.h>
 #include <sys/sysctl.h>
+#include <sys/syslog.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/time.h>
@@ -39,11 +40,14 @@
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <getopt.h>
 #include <libutil.h>
+#include <paths.h>
 #include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <time.h>
 #include <unistd.h>
 
 #ifdef USE_APM
@@ -357,7 +361,7 @@
 {
 
 	fprintf(stderr,
-"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-P pidfile]\n");
+"usage: powerd [-v] [-a mode] [-b mode] [-i %%] [-n mode] [-p ival] [-r %%] [-s %%] [-w %%] [-P pidfile]\n");
 	exit(1);
 }
 
@@ -368,26 +372,33 @@
 	fd_set fdset;
 	int nfds;
 	struct pidfh *pfh = NULL;
+	char wcmd[MAXPATHLEN + 4];
 	const char *pidfile = NULL;
 	long idle, total;
-	int curfreq, *freqs, i, *mwatts, numfreqs;
-	int ch, mode, mode_ac, mode_battery, mode_none;
+	int batt, curfreq, *freqs, i, *mwatts, numfreqs;
+	int ch, mode, mode_ac, mode_battery, mode_none, sflag;
+	int batt_shutdown, batt_warning, shutdown_status;
 	uint64_t mjoules_used;
 	size_t len;
+	FILE *pf;
 
 	/* Default mode for all AC states is adaptive. */
 	mode_ac = mode_battery = mode_none = MODE_ADAPTIVE;
 	cpu_running_mark = DEFAULT_ACTIVE_PERCENT;
 	cpu_idle_mark = DEFAULT_IDLE_PERCENT;
 	poll_ival = DEFAULT_POLL_INTERVAL;
+	batt_shutdown = 0;
+	batt_warning = 0;
 	mjoules_used = 0;
+	sflag = 0;
+	shutdown_status = 0;
 	vflag = 0;
 
 	/* User must be root to control frequencies. */
 	if (geteuid() != 0)
 		errx(1, "must be root to run");
 
-	while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:v")) != EOF)
+	while ((ch = getopt(argc, argv, "a:b:i:n:p:P:r:s:vw:")) != EOF)
 		switch (ch) {
 		case 'a':
 			parse_mode(optarg, &mode_ac, ch);
@@ -424,6 +435,28 @@
 				usage();
 			}
 			break;
+		case 's':
+			batt_shutdown = atoi(optarg);
+			sflag = 1;
+			batt_warning = batt_shutdown + 2;
+			if (batt_shutdown < 0 || batt_shutdown > 100) {
+				warnx("%d is not a valid percent",
+					batt_shutdown);
+				usage();
+			}
+			break;
+		case 'w':
+			batt_warning = atoi(optarg);
+			if (batt_warning < 0 || batt_warning> 100) {
+				warnx("%d is not a valid percent",
+					batt_warning);
+				usage();
+			}
+			if (batt_warning <= batt_shutdown) {
+				warnx("battery warning value must be greater than battery shut down value");
+				usage();
+			}
+			break;
 		case 'v':
 			vflag = 1;
 			break;
@@ -446,6 +479,13 @@
 	len = 4;
 	if (sysctlnametomib("dev.cpu.0.freq_levels", levels_mib, &len))
 		err(1, "lookup freq_levels");
+	if (sflag == 1) {
+		len = sizeof(batt);
+		if (sysctlbyname("hw.acpi.battery.life", &batt, &len, NULL, 0)) {
+			err(1, "lookup battery life");
+			sflag = 0;
+		}
+	}
 
 	/* Check if we can read the idle time and supported freqs. */
 	if (read_usage_times(NULL, NULL))
@@ -519,6 +559,40 @@
 			break;
 		default:
 			errx(1, "invalid AC line status %d", acline_status);
+		}
+
+		if (sflag == 1) {
+			if (acline_status == SRC_BATTERY) {
+				len = sizeof(batt);
+				if (sysctlbyname("hw.acpi.battery.life", &batt, &len, NULL, 0))
+					err(1, "lookup battery life");
+				if (batt <= batt_warning) {
+					if (shutdown_status == 0) {
+						if (vflag)
+							warnx("Running out of battery! System will shut down automatically");
+						(void)snprintf(wcmd, sizeof(wcmd), "%s -n", _PATH_WALL);
+						if (!(pf = popen(wcmd, "w"))) {
+							syslog(LOG_ERR, "powerd: can't find %s: %m", 
+								_PATH_WALL);
+						}
+						(void)fprintf(pf,
+							"\nReconnect power IMMEDIATELY or system will shut down\n\n");
+						(void)pclose(pf);
+						shutdown_status = 1;
+					}
+				}
+				if (batt <= batt_shutdown) {
+					if (shutdown_status == 1) {
+						if (vflag)
+							warnx("The System is shutting down");
+						sflag = 0;
+						syslog(LOG_ERR,
+							"system shut down by powerd because of low battery");
+						system("shutdown -p now Automatic system shut down by powerd &");
+						shutdown_status = 2;
+					}
+				}
+			}
 		}
 
 		/* Read the current frequency. */
--- powerd.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list