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