Sync usage with man page.
[netbsd-mini2440.git] / usr.sbin / apm / apm.c
blob2d46b734fb5f616dbf5da55793a390ee2ca72afc
1 /* $NetBSD: apm.c,v 1.19 2008/04/28 20:24:15 martin Exp $ */
3 /*-
4 * Copyright (c) 1996 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by John Kohl.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/types.h>
33 #include <sys/ioctl.h>
34 #include <sys/socket.h>
35 #include <sys/time.h>
36 #include <sys/un.h>
38 #include <machine/apmvar.h>
40 #include <err.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <unistd.h>
48 #include "pathnames.h"
49 #include "apm-proto.h"
51 #define FALSE 0
52 #define TRUE 1
54 void usage(void);
55 void zzusage(void);
56 int do_zzz(const char *, enum apm_action);
57 int open_socket(const char *);
58 int send_command(int, struct apm_command *, struct apm_reply *);
60 void
61 usage(void)
64 fprintf(stderr,"usage: %s [-v] [-z | -S] [-abdlms] [-f socket]\n",
65 getprogname());
66 exit(1);
69 void
70 zzusage(void)
73 fprintf(stderr,"usage: %s [-z | -S] [-f socket]\n",
74 getprogname());
75 exit(1);
78 int
79 send_command(int fd,
80 struct apm_command *cmd,
81 struct apm_reply *reply)
84 /* send a command to the apm daemon */
85 cmd->vno = APMD_VNO;
87 if (send(fd, cmd, sizeof(*cmd), 0) == sizeof(*cmd)) {
88 if (recv(fd, reply, sizeof(*reply), 0) != sizeof(*reply)) {
89 warn("invalid reply from APM daemon");
90 return (1);
92 } else {
93 warn("invalid send to APM daemon");
94 return (1);
96 return (0);
99 int
100 do_zzz(const char *pn, enum apm_action action)
102 struct apm_command command;
103 struct apm_reply reply;
104 int fd;
106 switch (action) {
107 case NONE:
108 case SUSPEND:
109 command.action = SUSPEND;
110 break;
111 case STANDBY:
112 command.action = STANDBY;
113 break;
114 default:
115 zzusage();
118 fd = open_socket(pn);
119 if (fd == -1)
120 err(1, "cannot open connection to APM daemon");
121 printf("Suspending system...\n");
122 exit(send_command(fd, &command, &reply));
126 open_socket(const char *sockname)
128 struct sockaddr_un s_un;
129 int sock, errr;
131 sock = socket(AF_LOCAL, SOCK_STREAM, 0);
132 if (sock == -1)
133 err(1, "cannot create local socket");
135 s_un.sun_family = AF_LOCAL;
136 strncpy(s_un.sun_path, sockname, sizeof(s_un.sun_path));
137 s_un.sun_len = SUN_LEN(&s_un);
138 if (connect(sock, (struct sockaddr *)&s_un, s_un.sun_len) == -1) {
139 errr = errno;
140 close(sock);
141 errno = errr;
142 return (-1);
144 return (sock);
148 main(int argc, char *argv[])
150 struct apm_command command;
151 struct apm_reply reply;
152 struct apm_power_info *api = &reply.batterystate;
153 const char *sockname = _PATH_APM_SOCKET;
154 enum apm_action action = NONE;
155 int ch, doac, dobstate, domin, dopct, dostatus, fd, nodaemon,
156 rval, verbose;
158 doac = dobstate = domin = dopct = dostatus = nodaemon =
159 verbose = FALSE;
160 while ((ch = getopt(argc, argv, "Sabdf:lmsvz")) != -1)
161 switch (ch) {
162 case 'v':
163 verbose = TRUE;
164 break;
165 case 'f':
166 sockname = optarg;
167 break;
168 case 'z':
169 if (action != NONE)
170 usage();
171 action = SUSPEND;
172 break;
173 case 'S':
174 if (action != NONE)
175 usage();
176 action = STANDBY;
177 break;
178 case 's':
179 if (action != NONE && action != GETSTATUS)
180 usage();
181 dostatus = TRUE;
182 action = GETSTATUS;
183 break;
184 case 'b':
185 if (action != NONE && action != GETSTATUS)
186 usage();
187 dobstate = TRUE;
188 action = GETSTATUS;
189 break;
190 case 'l':
191 if (action != NONE && action != GETSTATUS)
192 usage();
193 dopct = TRUE;
194 action = GETSTATUS;
195 break;
196 case 'm':
197 if (action != NONE && action != GETSTATUS)
198 usage();
199 domin = TRUE;
200 action = GETSTATUS;
201 break;
202 case 'a':
203 if (action != NONE && action != GETSTATUS)
204 usage();
205 doac = TRUE;
206 action = GETSTATUS;
207 break;
208 case 'd':
209 nodaemon = TRUE;
210 break;
211 case '?':
212 default:
213 usage();
216 if (strcmp(getprogname(), "zzz") == 0)
217 exit(do_zzz(sockname, action));
219 if (nodaemon)
220 fd = -1;
221 else
222 fd = open_socket(sockname);
224 switch (action) {
225 case NONE:
226 verbose = doac = dopct = domin = dobstate = dostatus = TRUE;
227 action = GETSTATUS;
228 /* FALLTHROUGH */
229 case GETSTATUS:
230 if (fd == -1) {
231 /* open the device directly and get status */
232 fd = open(_PATH_APM_NORMAL, O_RDONLY);
233 if (fd == -1) {
234 err(1, "cannot contact APM daemon and "
235 "cannot open "
236 _PATH_APM_NORMAL);
238 memset(&reply, 0, sizeof(reply));
239 if (ioctl(fd, APM_IOC_GETPOWER,
240 &reply.batterystate) == -1)
241 err(1, "ioctl(APM_IOC_GETPOWER)");
242 goto printval;
244 /* FALLTHROUGH */
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 "
251 _PATH_APM_CTLDEV);
252 sync();
253 sync();
254 sleep(1);
255 if (ioctl(fd, action == SUSPEND ?
256 APM_IOC_SUSPEND : APM_IOC_STANDBY, 0) == -1)
257 err(1, "cannot enter requested power state");
258 printf("System will enter %s in a moment.\n",
259 action == SUSPEND ? "suspend mode" :
260 "standby mode");
261 exit(0);
262 } else if (fd == -1)
263 err(1, "cannot contact APM daemon at socket "
264 _PATH_APM_SOCKET);
265 command.action = action;
266 break;
267 default:
268 usage();
271 if ((rval = send_command(fd, &command, &reply)) == 0) {
272 switch (action) {
273 case GETSTATUS:
274 printval:
275 if (verbose) {
276 if (dobstate)
277 printf("Battery charge state: %s\n",
278 battstate(api->battery_state));
280 if (dopct && domin && api->minutes_left == 0)
281 domin = FALSE;
283 if (dopct || domin) {
284 printf("Battery remaining: ");
285 if (dopct)
286 printf("%d percent",
287 api->battery_life);
288 if (dopct && domin)
289 printf(" (");
290 if (domin)
291 printf("%d minutes",
292 api->minutes_left);
293 if (dopct && domin)
294 printf(")");
295 printf("\n");
297 if (doac)
298 printf("A/C adapter state: %s\n",
299 ac_state(api->ac_state));
300 if (dostatus)
301 printf("Power management enabled\n");
302 if (api->nbattery) {
303 printf("Number of batteries: %u\n",
304 api->nbattery);
306 } else {
307 if (dobstate)
308 printf("%d\n", api->battery_state);
309 if (dopct)
310 printf("%d\n", api->battery_life);
311 if (domin)
312 printf("%d\n", api->minutes_left);
313 if (doac)
314 printf("%d\n", api->ac_state);
315 if (dostatus)
316 printf("1\n");
318 break;
319 default:
320 break;
322 switch (reply.newstate) {
323 case SUSPEND:
324 printf("System will enter suspend mode "
325 "in a moment.\n");
326 break;
327 case STANDBY:
328 printf("System will enter standby mode "
329 "in a moment.\n");
330 break;
331 default:
332 break;
334 } else
335 errx(rval, "cannot get reply from APM daemon");
337 exit(0);