On Sun, Aug 13, 2017 at 02:13:42PM +0200, Jesper Wallin wrote:
> On Sun, Aug 13, 2017 at 09:52:22AM +0200, Martijn van Duren wrote:
> > I've also been bitten by this a couple of times, but you can also solve
> > this via the sensorsd framework, which is how I've done it.
>
> Yeah, someone on IRC also suggested sensorsd or even ksh and a cronjob.
> I personally find it a bit too ducttapey though, especially for a
> feature one would expect on a laptop. This also saves me from running an
> extra daemon just in case my battery runs out.
>
> > I'm no expert in this area and I'm not going to make any statements on
> > whether we should add this or not, but two (non functionality) nits
> > inline for future reference.
>
> Thanks for the feedback, greatly appreciated! I've done a few changes
> and also rewrote some of the manual, as my previous patch was lying.
>
>
> Jesper Wallin
>
>
> Index: usr.sbin/apmd/apmd.8
> ===================================================================
> RCS file: /cvs/src/usr.sbin/apmd/apmd.8,v
> retrieving revision 1.47
> diff -u -p -r1.47 apmd.8
> --- usr.sbin/apmd/apmd.8 12 Feb 2015 14:03:49 -0000 1.47
> +++ usr.sbin/apmd/apmd.8 13 Aug 2017 11:50:16 -0000
> @@ -113,6 +113,20 @@ The polling rate defaults to
> once per 10 minutes, but may be specified using the
> .Fl t
> command-line flag.
> +.It Fl z Ar percent
> +Automatically suspend the system if no AC is connected and the
> +estimated battery life is equal or below
> +.Ar percent .
> +.It Fl Z Ar percent
> +Automatically hibernate the system if no AC is connected and the
> +estimated battery life is equal or below
> +.Ar percent .
> +.Pp
> +If both
> +.Fl Z
> +and
> +.Fl z
> +are specified, the first one will supersede the other.
> .El
> .Pp
> When a client requests a suspend or stand-by state,
> Index: usr.sbin/apmd/apmd.c
> ===================================================================
> RCS file: /cvs/src/usr.sbin/apmd/apmd.c,v
> retrieving revision 1.79
> diff -u -p -r1.79 apmd.c
> --- usr.sbin/apmd/apmd.c 16 Nov 2015 17:35:05 -0000 1.79
> +++ usr.sbin/apmd/apmd.c 13 Aug 2017 11:50:16 -0000
> @@ -56,6 +56,9 @@
> #define TRUE 1
> #define FALSE 0
>
> +#define AUTO_SUSPEND 1
> +#define AUTO_HIBERNATE 2
> +
> const char apmdev[] = _PATH_APM_CTLDEV;
> const char sockfile[] = _PATH_APM_SOCKET;
>
> @@ -94,8 +97,8 @@ void
> usage(void)
> {
> fprintf(stderr,
> - "usage: %s [-AadHLs] [-f devname] [-S sockname] [-t seconds]\n",
> - __progname);
> + "usage: %s [-AadHLs] [-f devname] [-S sockname] [-t seconds] "
> + "[-z percent] [-Z percent]\n", __progname);
> exit(1);
> }
>
> @@ -348,6 +351,8 @@ main(int argc, char *argv[])
> {
> const char *fname = apmdev;
> int ctl_fd, sock_fd, ch, suspends, standbys, hibernates, resumes;
> + int autoaction = 0;
> + int autolimit = 0;
> int statonly = 0;
> int powerstatus = 0, powerbak = 0, powerchange = 0;
> int noacsleep = 0;
> @@ -355,13 +360,14 @@ main(int argc, char *argv[])
> struct apm_power_info pinfo;
> time_t apmtimeout = 0;
> const char *sockname = sockfile;
> + const char *errstr;
> int kq, nchanges;
> struct kevent ev[2];
> int ncpu_mib[2] = { CTL_HW, HW_NCPU };
> int ncpu;
> size_t ncpu_sz = sizeof(ncpu);
>
> - while ((ch = getopt(argc, argv, "aACdHLsf:t:S:")) != -1)
> + while ((ch = getopt(argc, argv, "aACdHLsf:t:S:z:Z:")) != -1)
> switch(ch) {
> case 'a':
> noacsleep = 1;
> @@ -402,6 +408,18 @@ main(int argc, char *argv[])
> doperf = PERF_MANUAL;
> setperfpolicy("high");
> break;
> + case 'z':
> + autoaction = AUTO_SUSPEND;
> + autolimit = strtonum(optarg, 1, 100, &errstr);
> + if (errstr != NULL)
> + error("invalid percent: %s", errstr);
> + break;
> + case 'Z':
> + autoaction = AUTO_HIBERNATE;
> + autolimit = strtonum(optarg, 1, 100, &errstr);
> + if (errstr != NULL)
> + error("invalid percent: %s", errstr);
> + break;
> case '?':
> default:
> usage();
> @@ -479,6 +497,20 @@ main(int argc, char *argv[])
> if (powerstatus != powerbak) {
> powerstatus = powerbak;
> powerchange = 1;
> + }
> +
> + if (!powerstatus && autoaction &&
> + autolimit > (int)pinfo.battery_life) {
> + syslog(LOG_NOTICE, "estimated battery life
> %d%%, "
> + "autoaction limit set to %d%% .",
> + pinfo.battery_life,
> + autolimit
> + );
> +
> + if (autoaction == AUTO_SUSPEND)
> + suspend(ctl_fd);
> + else
> + hibernate(ctl_fd);
> }
> }
>
>
Personally I'd also prefer having this in apmd(8) rather than some other
daemon or script. Some comments:
You should pass optarg instead of errstr to error(). Either ways error()
will still append since it uses err(3). This leads to
$ obj/apmd -dz0
apmd: invalid percent: too small: Result too large
apmd.8's SYNOPSIS does not reflect your changes.