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