1 /* $OpenBSD: apm.c,v 1.5 2001/07/06 21:08:00 mickey Exp $ */ 2 3 /* 4 * Copyright (c) 1996 John T. Kohl 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 27 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 * 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <errno.h> 37 #include <err.h> 38 #include <string.h> 39 #include <sys/types.h> 40 #include <sys/socket.h> 41 #include <sys/un.h> 42 #include <sys/ioctl.h> 43 #include <machine/apmvar.h> 44 #include "pathnames.h" 45 #include "apm-proto.h" 46 47 #define FALSE 0 48 #define TRUE 1 49 50 extern char *__progname; 51 52 void usage(void); 53 void zzusage(void); 54 int do_zzz(int, enum apm_action action); 55 int open_socket(const char *pn); 56 int send_command(int fd, struct apm_command *cmd, struct apm_reply *reply); 57 58 void 59 usage(void) 60 { 61 fprintf(stderr,"usage: %s [-v] [-z | -S] [-slbam] [-f socket]\n", 62 __progname); 63 exit(1); 64 } 65 66 void 67 zzusage(void) 68 { 69 fprintf(stderr,"usage: %s [-z | -S] [-f socket]\n", 70 __progname); 71 exit(1); 72 } 73 74 int 75 send_command(int fd, 76 struct apm_command *cmd, 77 struct apm_reply *reply) 78 { 79 /* send a command to the apm daemon */ 80 cmd->vno = APMD_VNO; 81 82 if (send(fd, cmd, sizeof(*cmd), 0) == sizeof(*cmd)) { 83 if (recv(fd, reply, sizeof(*reply), 0) != sizeof(*reply)) { 84 warn("invalid reply from APM daemon"); 85 return 1; 86 } 87 } else { 88 warn("invalid send to APM daemon"); 89 return 1; 90 } 91 92 return 0; 93 } 94 95 int 96 do_zzz(int fd, enum apm_action action) 97 { 98 struct apm_command command; 99 struct apm_reply reply; 100 101 switch (action) { 102 case NONE: 103 case SUSPEND: 104 command.action = SUSPEND; 105 break; 106 case STANDBY: 107 command.action = STANDBY; 108 break; 109 default: 110 zzusage(); 111 } 112 113 printf("Suspending system...\n"); 114 exit(send_command(fd, &command, &reply)); 115 } 116 117 int 118 open_socket(const char *sockname) 119 { 120 int sock, errr; 121 struct sockaddr_un s_un; 122 123 sock = socket(AF_UNIX, SOCK_STREAM, 0); 124 if (sock == -1) 125 err(1, "cannot create local socket"); 126 127 s_un.sun_family = AF_UNIX; 128 strncpy(s_un.sun_path, sockname, sizeof(s_un.sun_path)); 129 s_un.sun_len = SUN_LEN(&s_un); 130 if (connect(sock, (struct sockaddr *)&s_un, s_un.sun_len) == -1) { 131 errr = errno; 132 close(sock); 133 errno = errr; 134 err(1, "cannot open connection to APM daemon"); 135 } 136 137 return sock; 138 } 139 140 int 141 main(int argc, char *argv[]) 142 { 143 const char *sockname = _PATH_APM_SOCKET; 144 int dostatus = FALSE; 145 int doac = FALSE; 146 int dopct = FALSE; 147 int dobstate = FALSE; 148 int domin = FALSE; 149 int verbose = FALSE; 150 int ch, fd, rval; 151 enum apm_action action = NONE; 152 struct apm_command command; 153 struct apm_reply reply; 154 155 while ((ch = getopt(argc, argv, "lmbvasSzf:")) != -1) 156 switch(ch) { 157 case 'v': 158 verbose = TRUE; 159 break; 160 case 'f': 161 sockname = optarg; 162 break; 163 case 'z': 164 if (action != NONE) 165 usage(); 166 action = SUSPEND; 167 break; 168 case 'S': 169 if (action != NONE) 170 usage(); 171 action = STANDBY; 172 break; 173 case 's': 174 if (action != NONE && action != GETSTATUS) 175 usage(); 176 dostatus = TRUE; 177 action = GETSTATUS; 178 break; 179 case 'b': 180 if (action != NONE && action != GETSTATUS) 181 usage(); 182 dobstate = TRUE; 183 action = GETSTATUS; 184 break; 185 case 'l': 186 if (action != NONE && action != GETSTATUS) 187 usage(); 188 dopct = TRUE; 189 action = GETSTATUS; 190 break; 191 case 'm': 192 if (action != NONE && action != GETSTATUS) 193 usage(); 194 domin = TRUE; 195 action = GETSTATUS; 196 break; 197 case 'a': 198 if (action != NONE && action != GETSTATUS) 199 usage(); 200 doac = TRUE; 201 action = GETSTATUS; 202 break; 203 case '?': 204 default: 205 usage(); 206 } 207 208 fd = open_socket(sockname); 209 210 if (!strcmp(__progname, "zzz")) 211 return (do_zzz(fd, action)); 212 213 switch (action) { 214 case NONE: 215 action = GETSTATUS; 216 verbose = doac = dopct = dobstate = dostatus = domin = 217 TRUE; 218 /* fallthrough */ 219 case GETSTATUS: 220 if (fd == -1) { 221 /* open the device directly and get status */ 222 fd = open(_PATH_APM_NORMAL, O_RDONLY); 223 if (ioctl(fd, APM_IOC_GETPOWER, 224 &reply.batterystate) == 0) 225 goto printval; 226 } 227 case SUSPEND: 228 case STANDBY: 229 command.action = action; 230 break; 231 default: 232 usage(); 233 } 234 235 if ((rval = send_command(fd, &command, &reply)) == 0) { 236 switch (action) { 237 case GETSTATUS: 238 printval: 239 if (verbose) { 240 if (dobstate) 241 printf("Battery state: %s\n", 242 battstate(reply.batterystate.battery_state)); 243 if (dopct) 244 printf("Battery remaining: %d percent\n", 245 reply.batterystate.battery_life); 246 if (domin) 247 printf("Battery life estimate: %d minutes\n", 248 reply.batterystate.minutes_left); 249 if (doac) 250 printf("A/C adapter state: %s\n", 251 ac_state(reply.batterystate.ac_state)); 252 if (dostatus) 253 printf("Power management enabled\n"); 254 } else { 255 if (dobstate) 256 printf("%d\n", 257 reply.batterystate.battery_state); 258 if (dopct) 259 printf("%d\n", 260 reply.batterystate.battery_life); 261 if (domin) 262 printf("%d\n", 263 reply.batterystate.minutes_left); 264 if (doac) 265 printf("%d\n", 266 reply.batterystate.ac_state); 267 if (dostatus) 268 printf("1\n"); 269 } 270 break; 271 default: 272 } 273 switch (reply.newstate) { 274 case SUSPEND: 275 printf("System will enter suspend mode momentarily.\n"); 276 break; 277 case STANDBY: 278 printf("System will enter standby mode momentarily.\n"); 279 break; 280 default: 281 } 282 } else 283 errx(rval, "cannot get reply from APM daemon"); 284 return (0); 285 } 286