GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/apm/apm.c Lines: 0 188 0.0 %
Date: 2016-12-06 Branches: 0 130 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: apm.c,v 1.32 2015/11/01 14:13:30 deraadt 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 <sys/types.h>
33
#include <sys/sysctl.h>
34
#include <sys/socket.h>
35
#include <sys/un.h>
36
#include <sys/ioctl.h>
37
#include <machine/apmvar.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <unistd.h>
41
#include <fcntl.h>
42
#include <errno.h>
43
#include <err.h>
44
#include <string.h>
45
#include "pathnames.h"
46
#include "apm-proto.h"
47
48
#define FALSE 0
49
#define TRUE 1
50
51
extern char *__progname;
52
53
void usage(void);
54
void zzusage(void);
55
int do_zzz(int, enum apm_action action);
56
int open_socket(const char *pn);
57
int send_command(int fd, struct apm_command *cmd, struct apm_reply *reply);
58
59
void
60
usage(void)
61
{
62
	fprintf(stderr,"usage: %s [-AabHLlmPSvZz] [-f sockname]\n",
63
	    __progname);
64
	exit(1);
65
}
66
67
void
68
zzusage(void)
69
{
70
	fprintf(stderr,"usage: %s [-SZz] [-f sockname]\n",
71
	    __progname);
72
	exit(1);
73
}
74
75
int
76
send_command(int fd, struct apm_command *cmd, struct apm_reply *reply)
77
{
78
	/* send a command to the apm daemon */
79
	cmd->vno = APMD_VNO;
80
81
	if (send(fd, cmd, sizeof(*cmd), 0) == sizeof(*cmd)) {
82
		if (recv(fd, reply, sizeof(*reply), 0) != sizeof(*reply)) {
83
			warn("invalid reply from APM daemon");
84
			return (1);
85
		}
86
	} else {
87
		warn("invalid send to APM daemon");
88
		return (1);
89
	}
90
	return (0);
91
}
92
93
int
94
do_zzz(int fd, enum apm_action action)
95
{
96
	struct apm_command command;
97
	struct apm_reply reply;
98
	char *msg;
99
100
	switch (action) {
101
	case NONE:
102
	case SUSPEND:
103
		command.action = SUSPEND;
104
		msg = "Suspending system";
105
		break;
106
	case STANDBY:
107
		command.action = STANDBY;
108
		msg = "System standing by";
109
		break;
110
	case HIBERNATE:
111
		command.action = HIBERNATE;
112
		msg = "Hibernating system";
113
		break;
114
	default:
115
		zzusage();
116
	}
117
118
	printf("%s...\n", msg);
119
	exit(send_command(fd, &command, &reply));
120
}
121
122
int
123
open_socket(const char *sockname)
124
{
125
	int sock, errr;
126
	struct sockaddr_un s_un;
127
128
	sock = socket(AF_UNIX, SOCK_STREAM, 0);
129
	if (sock == -1)
130
		err(1, "cannot create local socket");
131
132
	s_un.sun_family = AF_UNIX;
133
	strlcpy(s_un.sun_path, sockname, sizeof(s_un.sun_path));
134
	if (connect(sock, (struct sockaddr *)&s_un, sizeof(s_un)) == -1) {
135
		errr = errno;
136
		close(sock);
137
		errno = errr;
138
		sock = -1;
139
	}
140
	return (sock);
141
}
142
143
int
144
main(int argc, char *argv[])
145
{
146
	const char *sockname = _PATH_APM_SOCKET;
147
	int doac = FALSE;
148
	int dopct = FALSE;
149
	int dobstate = FALSE;
150
	int domin = FALSE;
151
	int doperf = FALSE;
152
	int verbose = FALSE;
153
	int ch, fd, rval;
154
	enum apm_action action = NONE;
155
	struct apm_command command;
156
	struct apm_reply reply;
157
	int cpuspeed_mib[] = { CTL_HW, HW_CPUSPEED }, cpuspeed;
158
	size_t cpuspeed_sz = sizeof(cpuspeed);
159
160
	if (sysctl(cpuspeed_mib, 2, &cpuspeed, &cpuspeed_sz, NULL, 0) < 0)
161
		err(1, "sysctl hw.cpuspeed");
162
163
	while ((ch = getopt(argc, argv, "ACHLlmbvaPSzZf:")) != -1) {
164
		switch (ch) {
165
		case 'v':
166
			verbose = TRUE;
167
			break;
168
		case 'f':
169
			sockname = optarg;
170
			break;
171
		case 'z':
172
			if (action != NONE)
173
				usage();
174
			action = SUSPEND;
175
			break;
176
		case 'S':
177
			if (action != NONE)
178
				usage();
179
			action = STANDBY;
180
			break;
181
		case 'Z':
182
			if (action != NONE)
183
				usage();
184
			action = HIBERNATE;
185
			break;
186
		case 'A':
187
			if (action != NONE)
188
				usage();
189
			action = SETPERF_AUTO;
190
			break;
191
		case 'C':
192
			if (action != NONE)
193
				usage();
194
			action = SETPERF_COOL;
195
			break;
196
		case 'H':
197
			if (action != NONE)
198
				usage();
199
			action = SETPERF_HIGH;
200
			break;
201
		case 'L':
202
			if (action != NONE)
203
				usage();
204
			action = SETPERF_LOW;
205
			break;
206
		case 'b':
207
			if (action != NONE && action != GETSTATUS)
208
				usage();
209
			dobstate = TRUE;
210
			action = GETSTATUS;
211
			break;
212
		case 'l':
213
			if (action != NONE && action != GETSTATUS)
214
				usage();
215
			dopct = TRUE;
216
			action = GETSTATUS;
217
			break;
218
		case 'm':
219
			if (action != NONE && action != GETSTATUS)
220
				usage();
221
			domin = TRUE;
222
			action = GETSTATUS;
223
			break;
224
		case 'a':
225
			if (action != NONE && action != GETSTATUS)
226
				usage();
227
			doac = TRUE;
228
			action = GETSTATUS;
229
			break;
230
		case 'P':
231
			if (action != NONE && action != GETSTATUS)
232
				usage();
233
			doperf = TRUE;
234
			action = GETSTATUS;
235
			break;
236
		default:
237
			if (!strcmp(__progname, "zzz") || !strcmp(__progname, "ZZZ"))
238
				zzusage();
239
			else
240
				usage();
241
		}
242
	}
243
244
	fd = open_socket(sockname);
245
246
	if (fd != -1) {
247
		if (pledge("stdio rpath wpath cpath", NULL) == -1)
248
			err(1, "pledge");
249
	}
250
251
	if (!strcmp(__progname, "zzz")) {
252
		if (fd < 0)
253
			err(1, "cannot connect to apmd");
254
		else
255
			return (do_zzz(fd, action));
256
	} else if (!strcmp(__progname, "ZZZ")) {
257
		if (fd < 0)
258
			err(1, "cannot connect to apmd");
259
		else
260
			return (do_zzz(fd, HIBERNATE));
261
	}
262
263
264
	bzero(&reply, sizeof reply);
265
	reply.batterystate.battery_state = APM_BATT_UNKNOWN;
266
	reply.batterystate.ac_state = APM_AC_UNKNOWN;
267
	reply.perfmode = PERF_MANUAL;
268
	reply.cpuspeed = cpuspeed;
269
270
	switch (action) {
271
	case SETPERF_LOW:
272
	case SETPERF_HIGH:
273
	case SETPERF_AUTO:
274
	case SETPERF_COOL:
275
		if (fd == -1)
276
			errx(1, "cannot connect to apmd, "
277
			    "not changing performance adjustment mode");
278
		goto balony;
279
	case NONE:
280
		action = GETSTATUS;
281
		verbose = doac = dopct = dobstate = domin = doperf = TRUE;
282
		/* FALLTHROUGH */
283
	case GETSTATUS:
284
		if (fd == -1) {
285
			/* open the device directly and get status */
286
			fd = open(_PATH_APM_NORMAL, O_RDONLY);
287
			if (ioctl(fd, APM_IOC_GETPOWER,
288
			    &reply.batterystate) == 0)
289
				goto printval;
290
		}
291
		/* FALLTHROUGH */
292
balony:
293
	case SUSPEND:
294
	case STANDBY:
295
	case HIBERNATE:
296
		command.action = action;
297
		break;
298
	default:
299
		usage();
300
	}
301
302
	if (fd != -1 && (rval = send_command(fd, &command, &reply)) != 0)
303
		errx(rval, "cannot get reply from APM daemon");
304
305
	switch (action) {
306
	case GETSTATUS:
307
	printval:
308
		if (!verbose) {
309
			if (dobstate)
310
				printf("%d\n",
311
				    reply.batterystate.battery_state);
312
			if (dopct)
313
				printf("%d\n",
314
				    reply.batterystate.battery_life);
315
			if (domin) {
316
				if (reply.batterystate.minutes_left ==
317
				    (u_int)-1)
318
					printf("unknown\n");
319
				else
320
					printf("%d\n",
321
					    reply.batterystate.minutes_left);
322
			}
323
			if (doac)
324
				printf("%d\n",
325
				    reply.batterystate.ac_state);
326
			if (doperf)
327
				printf("%d\n", reply.perfmode);
328
			break;
329
		}
330
331
		if (dobstate) {
332
			printf("Battery state: %s",
333
			    battstate(reply.batterystate.battery_state));
334
			if (!dopct && !domin)
335
				printf("\n");
336
		}
337
338
		if (dopct && !dobstate)
339
			printf("Battery remaining: %d percent",
340
			    reply.batterystate.battery_life);
341
		else if (dopct)
342
			printf(", %d%% remaining",
343
			    reply.batterystate.battery_life);
344
		if (dopct && !domin)
345
			printf("\n");
346
347
		if (domin && !dobstate && !dopct) {
348
#ifdef __powerpc__
349
			if (reply.batterystate.battery_state ==
350
			    APM_BATT_CHARGING)
351
				printf("Remaining battery recharge "
352
				    "time estimate: %d minutes\n",
353
				    reply.batterystate.minutes_left);
354
			else if (reply.batterystate.minutes_left == 0 &&
355
			    reply.batterystate.battery_life > 10)
356
				printf("Battery life estimate: "
357
				    "not available\n");
358
			else
359
#endif
360
			{
361
				printf("Battery life estimate: ");
362
				if (reply.batterystate.minutes_left ==
363
				    (u_int)-1)
364
					printf("unknown\n");
365
				else
366
					printf("%d minutes\n",
367
					    reply.batterystate.minutes_left);
368
			}
369
		} else if (domin) {
370
#ifdef __powerpc__
371
			if (reply.batterystate.battery_state ==
372
			    APM_BATT_CHARGING)
373
				printf(", %d minutes recharge time estimate\n",
374
				    reply.batterystate.minutes_left);
375
			else if (reply.batterystate.minutes_left == 0 &&
376
			    reply.batterystate.battery_life > 10)
377
				printf(", unknown life estimate\n");
378
			else
379
#endif
380
			{
381
				if (reply.batterystate.minutes_left ==
382
				    (u_int)-1)
383
					printf(", unknown");
384
				else
385
					printf(", %d minutes",
386
					    reply.batterystate.minutes_left);
387
				printf(" life estimate\n");
388
			}
389
		}
390
391
		if (doac)
392
			printf("A/C adapter state: %s\n",
393
			    ac_state(reply.batterystate.ac_state));
394
395
		if (doperf)
396
			printf("Performance adjustment mode: %s (%d MHz)\n",
397
			    perf_mode(reply.perfmode), reply.cpuspeed);
398
		break;
399
	default:
400
		break;
401
	}
402
403
	switch (reply.newstate) {
404
	case SUSPEND:
405
		printf("System will enter suspend mode momentarily.\n");
406
		break;
407
	case STANDBY:
408
		printf("System will enter standby mode momentarily.\n");
409
		break;
410
	case HIBERNATE:
411
		printf("System will enter hibernate mode momentarily.\n");
412
		break;
413
	default:
414
		break;
415
	}
416
	return (0);
417
}