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