GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.bin/systat/sensors.c Lines: 0 144 0.0 %
Date: 2017-11-13 Branches: 0 93 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: sensors.c,v 1.30 2015/01/16 00:03:38 deraadt Exp $	*/
2
3
/*
4
 * Copyright (c) 2007 Deanna Phillips <deanna@openbsd.org>
5
 * Copyright (c) 2003 Henning Brauer <henning@openbsd.org>
6
 * Copyright (c) 2006 Constantine A. Murenin <cnst+openbsd@bugmail.mojo.ru>
7
 *
8
 * Permission to use, copy, modify, and distribute this software for any
9
 * purpose with or without fee is hereby granted, provided that the above
10
 * copyright notice and this permission notice appear in all copies.
11
 *
12
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
 *
20
 */
21
22
#include <sys/types.h>
23
#include <sys/signal.h>
24
#include <sys/sysctl.h>
25
#include <sys/sensors.h>
26
27
#include <err.h>
28
#include <errno.h>
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include "systat.h"
33
34
struct sensor sensor;
35
struct sensordev sensordev;
36
37
struct sensinfo {
38
	int sn_dev;
39
	struct sensor sn_sensor;
40
};
41
#define sn_type sn_sensor.type
42
#define sn_numt sn_sensor.numt
43
#define sn_desc sn_sensor.desc
44
#define sn_status sn_sensor.status
45
#define sn_value sn_sensor.value
46
47
#define SYSTAT_MAXSENSORDEVICES 1024
48
char *devnames[SYSTAT_MAXSENSORDEVICES];
49
50
#define ADD_ALLOC 100
51
static size_t sensor_cnt = 0;
52
static size_t num_alloc = 0;
53
static struct sensinfo *sensors = NULL;
54
55
static char *fmttime(double);
56
static void showsensor(struct sensinfo *s);
57
58
void print_sn(void);
59
int read_sn(void);
60
int select_sn(void);
61
62
const char *drvstat[] = {
63
	NULL,
64
	"empty", "ready", "powering up", "online", "idle", "active",
65
	"rebuilding", "powering down", "failed", "degraded"
66
};
67
68
69
field_def fields_sn[] = {
70
	{"SENSOR", 16, 32, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0},
71
	{"VALUE", 16, 20, 1, FLD_ALIGN_RIGHT, -1, 0, 0, 0},
72
	{"STATUS", 5, 8, 1, FLD_ALIGN_CENTER, -1, 0, 0, 0},
73
	{"DESCRIPTION", 20, 45, 1, FLD_ALIGN_LEFT, -1, 0, 0, 0}
74
};
75
76
#define FLD_SN_SENSOR	FIELD_ADDR(fields_sn,0)
77
#define FLD_SN_VALUE	FIELD_ADDR(fields_sn,1)
78
#define FLD_SN_STATUS	FIELD_ADDR(fields_sn,2)
79
#define FLD_SN_DESCR	FIELD_ADDR(fields_sn,3)
80
81
/* Define views */
82
field_def *view_sn_0[] = {
83
	FLD_SN_SENSOR, FLD_SN_VALUE, FLD_SN_STATUS, FLD_SN_DESCR, NULL
84
};
85
86
87
/* Define view managers */
88
struct view_manager sensors_mgr = {
89
	"Sensors", select_sn, read_sn, NULL, print_header,
90
	print_sn, keyboard_callback, NULL, NULL
91
};
92
93
field_view views_sn[] = {
94
	{view_sn_0, "sensors", '3', &sensors_mgr},
95
	{NULL, NULL, 0, NULL}
96
};
97
98
struct sensinfo *
99
next_sn(void)
100
{
101
	if (num_alloc <= sensor_cnt) {
102
		struct sensinfo *s;
103
		size_t a = num_alloc + ADD_ALLOC;
104
		if (a < num_alloc)
105
			return NULL;
106
		s = reallocarray(sensors, a, sizeof(struct sensinfo));
107
		if (s == NULL)
108
			return NULL;
109
		sensors = s;
110
		num_alloc = a;
111
	}
112
113
	return &sensors[sensor_cnt++];
114
}
115
116
117
int
118
select_sn(void)
119
{
120
	num_disp = sensor_cnt;
121
	return (0);
122
}
123
124
int
125
read_sn(void)
126
{
127
	enum sensor_type type;
128
	size_t		 slen, sdlen;
129
	int		 mib[5], dev, numt;
130
	struct sensinfo	*s;
131
132
	mib[0] = CTL_HW;
133
	mib[1] = HW_SENSORS;
134
135
	sensor_cnt = 0;
136
137
	for (dev = 0; dev < SYSTAT_MAXSENSORDEVICES; dev++) {
138
		mib[2] = dev;
139
		sdlen = sizeof(struct sensordev);
140
		if (sysctl(mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
141
			if (errno == ENOENT)
142
				break;
143
			if (errno == ENXIO)
144
				continue;
145
			error("sysctl: %s", strerror(errno));
146
		}
147
148
		if (devnames[dev] && strcmp(devnames[dev], sensordev.xname)) {
149
			free(devnames[dev]);
150
			devnames[dev] = NULL;
151
		}
152
		if (devnames[dev] == NULL)
153
			devnames[dev] = strdup(sensordev.xname);
154
155
		for (type = 0; type < SENSOR_MAX_TYPES; type++) {
156
			mib[3] = type;
157
			for (numt = 0; numt < sensordev.maxnumt[type]; numt++) {
158
				mib[4] = numt;
159
				slen = sizeof(struct sensor);
160
				if (sysctl(mib, 5, &sensor, &slen, NULL, 0)
161
				    == -1) {
162
					if (errno != ENOENT)
163
						error("sysctl: %s", strerror(errno));
164
					continue;
165
				}
166
				if (sensor.flags & SENSOR_FINVALID)
167
					continue;
168
169
				s = next_sn();
170
				s->sn_sensor = sensor;
171
				s->sn_dev = dev;
172
			}
173
		}
174
	}
175
176
	num_disp = sensor_cnt;
177
	return 0;
178
}
179
180
181
void
182
print_sn(void)
183
{
184
	int n, count = 0;
185
186
	for (n = dispstart; n < num_disp; n++) {
187
		showsensor(sensors + n);
188
		count++;
189
		if (maxprint > 0 && count >= maxprint)
190
			break;
191
	}
192
}
193
194
int
195
initsensors(void)
196
{
197
	field_view *v;
198
199
	memset(devnames, 0, sizeof(devnames));
200
201
	for (v = views_sn; v->name != NULL; v++)
202
		add_view(v);
203
204
	return(1);
205
}
206
207
static void
208
showsensor(struct sensinfo *s)
209
{
210
	tb_start();
211
	tbprintf("%s.%s%d", devnames[s->sn_dev],
212
		 sensor_type_s[s->sn_type], s->sn_numt);
213
	print_fld_tb(FLD_SN_SENSOR);
214
215
	if (s->sn_desc[0] != '\0')
216
		print_fld_str(FLD_SN_DESCR, s->sn_desc);
217
218
	tb_start();
219
220
	switch (s->sn_type) {
221
	case SENSOR_TEMP:
222
		tbprintf("%10.2f degC",
223
		    (s->sn_value - 273150000) / 1000000.0);
224
		break;
225
	case SENSOR_FANRPM:
226
		tbprintf("%11lld RPM", s->sn_value);
227
		break;
228
	case SENSOR_VOLTS_DC:
229
		tbprintf("%10.2f V DC",
230
		    s->sn_value / 1000000.0);
231
		break;
232
	case SENSOR_VOLTS_AC:
233
		tbprintf("%10.2f V AC",
234
		    s->sn_value / 1000000.0);
235
		break;
236
	case SENSOR_OHMS:
237
		tbprintf("%11lld ohm", s->sn_value);
238
		break;
239
	case SENSOR_WATTS:
240
		tbprintf("%10.2f W", s->sn_value / 1000000.0);
241
		break;
242
	case SENSOR_AMPS:
243
		tbprintf("%10.2f A", s->sn_value / 1000000.0);
244
		break;
245
	case SENSOR_WATTHOUR:
246
		tbprintf("%12.2f Wh", s->sn_value / 1000000.0);
247
		break;
248
	case SENSOR_AMPHOUR:
249
		tbprintf("%10.2f Ah", s->sn_value / 1000000.0);
250
		break;
251
	case SENSOR_INDICATOR:
252
		tbprintf("%15s", s->sn_value ? "On" : "Off");
253
		break;
254
	case SENSOR_INTEGER:
255
		tbprintf("%11lld raw", s->sn_value);
256
		break;
257
	case SENSOR_PERCENT:
258
		tbprintf("%14.2f%%", s->sn_value / 1000.0);
259
		break;
260
	case SENSOR_LUX:
261
		tbprintf("%15.2f lx", s->sn_value / 1000000.0);
262
		break;
263
	case SENSOR_DRIVE:
264
		if (0 < s->sn_value &&
265
		    s->sn_value < sizeof(drvstat)/sizeof(drvstat[0])) {
266
			tbprintf("%15s", drvstat[s->sn_value]);
267
			break;
268
		}
269
		break;
270
	case SENSOR_TIMEDELTA:
271
		tbprintf("%15s", fmttime(s->sn_value / 1000000000.0));
272
		break;
273
	case SENSOR_HUMIDITY:
274
		tbprintf("%3.2f%%", s->sn_value / 1000.0);
275
		break;
276
	case SENSOR_FREQ:
277
		tbprintf("%11.2f Hz", s->sn_value / 1000000.0);
278
		break;
279
	case SENSOR_ANGLE:
280
		tbprintf("%3.4f degrees", s->sn_value / 1000000.0);
281
		break;
282
	case SENSOR_DISTANCE:
283
		tbprintf("%.2f mm", s->sn_value / 1000.0);
284
		break;
285
	case SENSOR_PRESSURE:
286
		tbprintf("%.2f Pa", s->sn_value / 1000.0);
287
		break;
288
	case SENSOR_ACCEL:
289
		tbprintf("%2.4f m/s^2", s->sn_value / 1000000.0);
290
		break;
291
	default:
292
		tbprintf("%10lld", s->sn_value);
293
		break;
294
	}
295
296
	print_fld_tb(FLD_SN_VALUE);
297
298
	switch (s->sn_status) {
299
	case SENSOR_S_UNSPEC:
300
		break;
301
	case SENSOR_S_UNKNOWN:
302
		print_fld_str(FLD_SN_STATUS, "unknown");
303
		break;
304
	case SENSOR_S_WARN:
305
		print_fld_str(FLD_SN_STATUS, "WARNING");
306
		break;
307
	case SENSOR_S_CRIT:
308
		print_fld_str(FLD_SN_STATUS, "CRITICAL");
309
		break;
310
	case SENSOR_S_OK:
311
		print_fld_str(FLD_SN_STATUS, "OK");
312
		break;
313
	}
314
	end_line();
315
}
316
317
#define SECS_PER_DAY 86400
318
#define SECS_PER_HOUR 3600
319
#define SECS_PER_MIN 60
320
321
static char *
322
fmttime(double in)
323
{
324
	int signbit = 1;
325
	int tiny = 0;
326
	char *unit;
327
#define LEN 32
328
	static char outbuf[LEN];
329
330
	if (in < 0){
331
		signbit = -1;
332
		in *= -1;
333
	}
334
335
	if (in >= SECS_PER_DAY ){
336
		unit = "days";
337
		in /= SECS_PER_DAY;
338
	} else if (in >= SECS_PER_HOUR ){
339
		unit = "hr";
340
		in /= SECS_PER_HOUR;
341
	} else if (in >= SECS_PER_MIN ){
342
		unit = "min";
343
		in /= SECS_PER_MIN;
344
	} else if (in >= 1 ){
345
		unit = "s";
346
		/* in *= 1; */ /* no op */
347
	} else if (in == 0 ){ /* direct comparisons to floats are scary */
348
		unit = "s";
349
	} else if (in >= 1e-3 ){
350
		unit = "ms";
351
		in *= 1e3;
352
	} else if (in >= 1e-6 ){
353
		unit = "us";
354
		in *= 1e6;
355
	} else if (in >= 1e-9 ){
356
		unit = "ns";
357
		in *= 1e9;
358
	} else {
359
		unit = "ps";
360
		if (in < 1e-13)
361
			tiny = 1;
362
		in *= 1e12;
363
	}
364
365
	snprintf(outbuf, LEN,
366
	    tiny ? "%s%f %s" : "%s%.3f %s",
367
	    signbit == -1 ? "-" : "", in, unit);
368
369
	return outbuf;
370
}