Mon Jun 6 20:48:56 2011 UTC ()
1. Don't print blank for Integer sensors with value of zero
2. Properly print percentages in -T statistics mode
3. Always set Sensor Type (units) to a non-NULL value
4. Enable printing of percentages for Integer sensors


(pgoyette)
diff -r1.86 -r1.87 src/usr.sbin/envstat/envstat.c

cvs diff -r1.86 -r1.87 src/usr.sbin/envstat/envstat.c (switch to unified diff)

--- src/usr.sbin/envstat/envstat.c 2011/06/04 13:29:02 1.86
+++ src/usr.sbin/envstat/envstat.c 2011/06/06 20:48:56 1.87
@@ -1,1055 +1,1069 @@ @@ -1,1055 +1,1069 @@
1/* $NetBSD: envstat.c,v 1.86 2011/06/04 13:29:02 pgoyette Exp $ */ 1/* $NetBSD: envstat.c,v 1.87 2011/06/06 20:48:56 pgoyette Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007, 2008 Juan Romero Pardines. 4 * Copyright (c) 2007, 2008 Juan Romero Pardines.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29#ifndef lint 29#ifndef lint
30__RCSID("$NetBSD: envstat.c,v 1.86 2011/06/04 13:29:02 pgoyette Exp $"); 30__RCSID("$NetBSD: envstat.c,v 1.87 2011/06/06 20:48:56 pgoyette Exp $");
31#endif /* not lint */ 31#endif /* not lint */
32 32
33#include <stdio.h> 33#include <stdio.h>
34#include <stdlib.h> 34#include <stdlib.h>
35#include <stdbool.h> 35#include <stdbool.h>
36#include <stdarg.h> 36#include <stdarg.h>
37#include <string.h> 37#include <string.h>
38#include <unistd.h> 38#include <unistd.h>
39#include <fcntl.h> 39#include <fcntl.h>
40#include <err.h> 40#include <err.h>
41#include <errno.h> 41#include <errno.h>
42#include <paths.h> 42#include <paths.h>
43#include <syslog.h> 43#include <syslog.h>
44#include <sys/envsys.h> 44#include <sys/envsys.h>
45#include <sys/ioctl.h> 45#include <sys/ioctl.h>
46#include <sys/types.h> 46#include <sys/types.h>
47#include <sys/queue.h> 47#include <sys/queue.h>
48#include <prop/proplib.h> 48#include <prop/proplib.h>
49 49
50#include "envstat.h" 50#include "envstat.h"
51#include "prog_ops.h" 51#include "prog_ops.h"
52 52
53#define ENVSYS_DFLAG 0x00000001 /* list registered devices */ 53#define ENVSYS_DFLAG 0x00000001 /* list registered devices */
54#define ENVSYS_FFLAG 0x00000002 /* show temp in farenheit */ 54#define ENVSYS_FFLAG 0x00000002 /* show temp in farenheit */
55#define ENVSYS_LFLAG 0x00000004 /* list sensors */ 55#define ENVSYS_LFLAG 0x00000004 /* list sensors */
56#define ENVSYS_XFLAG 0x00000008 /* externalize dictionary */ 56#define ENVSYS_XFLAG 0x00000008 /* externalize dictionary */
57#define ENVSYS_IFLAG 0x00000010 /* skip invalid sensors */ 57#define ENVSYS_IFLAG 0x00000010 /* skip invalid sensors */
58#define ENVSYS_SFLAG 0x00000020 /* remove all properties set */ 58#define ENVSYS_SFLAG 0x00000020 /* remove all properties set */
59#define ENVSYS_TFLAG 0x00000040 /* make statistics */ 59#define ENVSYS_TFLAG 0x00000040 /* make statistics */
60#define ENVSYS_KFLAG 0x00000100 /* show temp in kelvin */ 60#define ENVSYS_KFLAG 0x00000100 /* show temp in kelvin */
61 61
62/* Sensors */ 62/* Sensors */
63typedef struct envsys_sensor { 63typedef struct envsys_sensor {
64 SIMPLEQ_ENTRY(envsys_sensor) entries; 64 SIMPLEQ_ENTRY(envsys_sensor) entries;
65 int32_t cur_value; 65 int32_t cur_value;
66 int32_t max_value; 66 int32_t max_value;
67 int32_t min_value; 67 int32_t min_value;
68 int32_t critmin_value; 68 int32_t critmin_value;
69 int32_t critmax_value; 69 int32_t critmax_value;
70 int32_t warnmin_value; 70 int32_t warnmin_value;
71 int32_t warnmax_value; 71 int32_t warnmax_value;
72 char desc[ENVSYS_DESCLEN]; 72 char desc[ENVSYS_DESCLEN];
73 char type[ENVSYS_DESCLEN]; 73 char type[ENVSYS_DESCLEN];
74 char drvstate[ENVSYS_DESCLEN]; 74 char drvstate[ENVSYS_DESCLEN];
75 char battcap[ENVSYS_DESCLEN]; 75 char battcap[ENVSYS_DESCLEN];
76 char dvname[ENVSYS_DESCLEN]; 76 char dvname[ENVSYS_DESCLEN];
77 bool invalid; 77 bool invalid;
78 bool visible; 78 bool visible;
79 bool percentage; 79 bool percentage;
80} *sensor_t; 80} *sensor_t;
81 81
82/* Sensor statistics */ 82/* Sensor statistics */
83typedef struct envsys_sensor_stats { 83typedef struct envsys_sensor_stats {
84 SIMPLEQ_ENTRY(envsys_sensor_stats) entries; 84 SIMPLEQ_ENTRY(envsys_sensor_stats) entries;
85 int32_t max; 85 int32_t max;
86 int32_t min; 86 int32_t min;
87 int32_t avg; 87 int32_t avg;
88 char desc[ENVSYS_DESCLEN]; 88 char desc[ENVSYS_DESCLEN];
89} *sensor_stats_t; 89} *sensor_stats_t;
90 90
91/* Device properties */ 91/* Device properties */
92typedef struct envsys_dvprops { 92typedef struct envsys_dvprops {
93 uint64_t refresh_timo; 93 uint64_t refresh_timo;
94 /* more members could be added in the future */ 94 /* more members could be added in the future */
95} *dvprops_t; 95} *dvprops_t;
96 96
97/* A simple queue to manage all sensors */ 97/* A simple queue to manage all sensors */
98static SIMPLEQ_HEAD(, envsys_sensor) sensors_list = 98static SIMPLEQ_HEAD(, envsys_sensor) sensors_list =
99 SIMPLEQ_HEAD_INITIALIZER(sensors_list); 99 SIMPLEQ_HEAD_INITIALIZER(sensors_list);
100 100
101/* A simple queue to manage statistics for all sensors */ 101/* A simple queue to manage statistics for all sensors */
102static SIMPLEQ_HEAD(, envsys_sensor_stats) sensor_stats_list = 102static SIMPLEQ_HEAD(, envsys_sensor_stats) sensor_stats_list =
103 SIMPLEQ_HEAD_INITIALIZER(sensor_stats_list); 103 SIMPLEQ_HEAD_INITIALIZER(sensor_stats_list);
104 104
105static unsigned int interval, flags, width; 105static unsigned int interval, flags, width;
106static char *mydevname, *sensors; 106static char *mydevname, *sensors;
107static bool statistics; 107static bool statistics;
108static u_int header_passes; 108static u_int header_passes;
109 109
110static int parse_dictionary(int); 110static int parse_dictionary(int);
111static int send_dictionary(FILE *); 111static int send_dictionary(FILE *);
112static int find_sensors(prop_array_t, const char *, dvprops_t); 112static int find_sensors(prop_array_t, const char *, dvprops_t);
113static void print_sensors(void); 113static void print_sensors(void);
114static int check_sensors(char *); 114static int check_sensors(char *);
115static int usage(void); 115static int usage(void);
116 116
117static int sysmonfd; /* fd of /dev/sysmon */ 117static int sysmonfd; /* fd of /dev/sysmon */
118 118
119int main(int argc, char **argv) 119int main(int argc, char **argv)
120{ 120{
121 prop_dictionary_t dict; 121 prop_dictionary_t dict;
122 int c, rval = 0; 122 int c, rval = 0;
123 char *endptr, *configfile = NULL; 123 char *endptr, *configfile = NULL;
124 FILE *cf; 124 FILE *cf;
125 125
126 if (prog_init && prog_init() == -1) 126 if (prog_init && prog_init() == -1)
127 err(1, "init failed"); 127 err(1, "init failed");
128 128
129 setprogname(argv[0]); 129 setprogname(argv[0]);
130 130
131 while ((c = getopt(argc, argv, "c:Dd:fIi:klrSs:Tw:Wx")) != -1) { 131 while ((c = getopt(argc, argv, "c:Dd:fIi:klrSs:Tw:Wx")) != -1) {
132 switch (c) { 132 switch (c) {
133 case 'c': /* configuration file */ 133 case 'c': /* configuration file */
134 configfile = strdup(optarg); 134 configfile = strdup(optarg);
135 if (configfile == NULL) 135 if (configfile == NULL)
136 err(EXIT_FAILURE, "strdup"); 136 err(EXIT_FAILURE, "strdup");
137 break; 137 break;
138 case 'D': /* list registered devices */ 138 case 'D': /* list registered devices */
139 flags |= ENVSYS_DFLAG; 139 flags |= ENVSYS_DFLAG;
140 break; 140 break;
141 case 'd': /* show sensors of a specific device */ 141 case 'd': /* show sensors of a specific device */
142 mydevname = strdup(optarg); 142 mydevname = strdup(optarg);
143 if (mydevname == NULL) 143 if (mydevname == NULL)
144 err(EXIT_FAILURE, "strdup"); 144 err(EXIT_FAILURE, "strdup");
145 break; 145 break;
146 case 'f': /* display temperature in Farenheit */ 146 case 'f': /* display temperature in Farenheit */
147 flags |= ENVSYS_FFLAG; 147 flags |= ENVSYS_FFLAG;
148 break; 148 break;
149 case 'I': /* Skips invalid sensors */ 149 case 'I': /* Skips invalid sensors */
150 flags |= ENVSYS_IFLAG; 150 flags |= ENVSYS_IFLAG;
151 break; 151 break;
152 case 'i': /* wait time between intervals */ 152 case 'i': /* wait time between intervals */
153 interval = (unsigned int)strtoul(optarg, &endptr, 10); 153 interval = (unsigned int)strtoul(optarg, &endptr, 10);
154 if (*endptr != '\0') 154 if (*endptr != '\0')
155 errx(EXIT_FAILURE, "bad interval '%s'", optarg); 155 errx(EXIT_FAILURE, "bad interval '%s'", optarg);
156 break; 156 break;
157 case 'k': /* display temperature in Kelvin */ 157 case 'k': /* display temperature in Kelvin */
158 flags |= ENVSYS_KFLAG; 158 flags |= ENVSYS_KFLAG;
159 break; 159 break;
160 case 'l': /* list sensors */ 160 case 'l': /* list sensors */
161 flags |= ENVSYS_LFLAG; 161 flags |= ENVSYS_LFLAG;
162 break; 162 break;
163 case 'r': 163 case 'r':
164 /* 164 /*
165 * This flag is noop.. it's only here for 165 * This flag is noop.. it's only here for
166 * compatibility with the old implementation. 166 * compatibility with the old implementation.
167 */ 167 */
168 break; 168 break;
169 case 'S': 169 case 'S':
170 flags |= ENVSYS_SFLAG; 170 flags |= ENVSYS_SFLAG;
171 break; 171 break;
172 case 's': /* only show specified sensors */ 172 case 's': /* only show specified sensors */
173 sensors = strdup(optarg); 173 sensors = strdup(optarg);
174 if (sensors == NULL) 174 if (sensors == NULL)
175 err(EXIT_FAILURE, "strdup"); 175 err(EXIT_FAILURE, "strdup");
176 break; 176 break;
177 case 'T': /* make statistics */ 177 case 'T': /* make statistics */
178 flags |= ENVSYS_TFLAG; 178 flags |= ENVSYS_TFLAG;
179 break; 179 break;
180 case 'w': /* width value for the lines */ 180 case 'w': /* width value for the lines */
181 width = (unsigned int)strtoul(optarg, &endptr, 10); 181 width = (unsigned int)strtoul(optarg, &endptr, 10);
182 if (*endptr != '\0') 182 if (*endptr != '\0')
183 errx(EXIT_FAILURE, "bad width '%s'", optarg); 183 errx(EXIT_FAILURE, "bad width '%s'", optarg);
184 break; 184 break;
185 case 'x': /* print the dictionary in raw format */ 185 case 'x': /* print the dictionary in raw format */
186 flags |= ENVSYS_XFLAG; 186 flags |= ENVSYS_XFLAG;
187 break; 187 break;
188 case 'W': /* No longer used, retained for campatability */ 188 case 'W': /* No longer used, retained for campatability */
189 break; 189 break;
190 case '?': 190 case '?':
191 default: 191 default:
192 usage(); 192 usage();
193 /* NOTREACHED */ 193 /* NOTREACHED */
194 } 194 }
195 } 195 }
196 196
197 argc -= optind; 197 argc -= optind;
198 argv += optind; 198 argv += optind;
199 199
200 if (argc > 0) 200 if (argc > 0)
201 usage(); 201 usage();
202 202
203 /* Check if we want to make statistics */ 203 /* Check if we want to make statistics */
204 if (flags & ENVSYS_TFLAG) { 204 if (flags & ENVSYS_TFLAG) {
205 if (!interval) 205 if (!interval)
206 errx(EXIT_FAILURE, 206 errx(EXIT_FAILURE,
207 "-T cannot be used without an interval (-i)"); 207 "-T cannot be used without an interval (-i)");
208 else 208 else
209 statistics = true; 209 statistics = true;
210 } 210 }
211 211
212 if (mydevname && sensors) 212 if (mydevname && sensors)
213 errx(EXIT_FAILURE, "-d flag cannot be used with -s"); 213 errx(EXIT_FAILURE, "-d flag cannot be used with -s");
214 214
215 /* Open the device in ro mode */ 215 /* Open the device in ro mode */
216 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDONLY)) == -1) 216 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDONLY)) == -1)
217 err(EXIT_FAILURE, "%s", _PATH_SYSMON); 217 err(EXIT_FAILURE, "%s", _PATH_SYSMON);
218 218
219 /* Print dictionary in raw mode */ 219 /* Print dictionary in raw mode */
220 if (flags & ENVSYS_XFLAG) { 220 if (flags & ENVSYS_XFLAG) {
221 rval = prop_dictionary_recv_ioctl(sysmonfd, 221 rval = prop_dictionary_recv_ioctl(sysmonfd,
222 ENVSYS_GETDICTIONARY, 222 ENVSYS_GETDICTIONARY,
223 &dict); 223 &dict);
224 if (rval) 224 if (rval)
225 errx(EXIT_FAILURE, "%s", strerror(rval)); 225 errx(EXIT_FAILURE, "%s", strerror(rval));
226 226
227 config_dict_dump(dict); 227 config_dict_dump(dict);
228 228
229 /* Remove all properties set in dictionary */ 229 /* Remove all properties set in dictionary */
230 } else if (flags & ENVSYS_SFLAG) { 230 } else if (flags & ENVSYS_SFLAG) {
231 /* Close the ro descriptor */ 231 /* Close the ro descriptor */
232 (void)prog_close(sysmonfd); 232 (void)prog_close(sysmonfd);
233 233
234 /* open the fd in rw mode */ 234 /* open the fd in rw mode */
235 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDWR)) == -1) 235 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDWR)) == -1)
236 err(EXIT_FAILURE, "%s", _PATH_SYSMON); 236 err(EXIT_FAILURE, "%s", _PATH_SYSMON);
237 237
238 dict = prop_dictionary_create(); 238 dict = prop_dictionary_create();
239 if (!dict) 239 if (!dict)
240 err(EXIT_FAILURE, "prop_dictionary_create"); 240 err(EXIT_FAILURE, "prop_dictionary_create");
241 241
242 rval = prop_dictionary_set_bool(dict, 242 rval = prop_dictionary_set_bool(dict,
243 "envsys-remove-props", 243 "envsys-remove-props",
244 true); 244 true);
245 if (!rval) 245 if (!rval)
246 err(EXIT_FAILURE, "prop_dict_set_bool"); 246 err(EXIT_FAILURE, "prop_dict_set_bool");
247 247
248 /* send the dictionary to the kernel now */ 248 /* send the dictionary to the kernel now */
249 rval = prop_dictionary_send_ioctl(dict, sysmonfd, 249 rval = prop_dictionary_send_ioctl(dict, sysmonfd,
250 ENVSYS_REMOVEPROPS); 250 ENVSYS_REMOVEPROPS);
251 if (rval) 251 if (rval)
252 warnx("%s", strerror(rval)); 252 warnx("%s", strerror(rval));
253 253
254 /* Set properties in dictionary */ 254 /* Set properties in dictionary */
255 } else if (configfile) { 255 } else if (configfile) {
256 /* 256 /*
257 * Parse the configuration file. 257 * Parse the configuration file.
258 */ 258 */
259 if ((cf = fopen(configfile, "r")) == NULL) { 259 if ((cf = fopen(configfile, "r")) == NULL) {
260 syslog(LOG_ERR, "fopen failed: %s", strerror(errno)); 260 syslog(LOG_ERR, "fopen failed: %s", strerror(errno));
261 errx(EXIT_FAILURE, "%s", strerror(errno)); 261 errx(EXIT_FAILURE, "%s", strerror(errno));
262 } 262 }
263 263
264 rval = send_dictionary(cf); 264 rval = send_dictionary(cf);
265 (void)fclose(cf); 265 (void)fclose(cf);
266 266
267 /* Show sensors with interval */ 267 /* Show sensors with interval */
268 } else if (interval) { 268 } else if (interval) {
269 for (;;) { 269 for (;;) {
270 rval = parse_dictionary(sysmonfd); 270 rval = parse_dictionary(sysmonfd);
271 if (rval) 271 if (rval)
272 break; 272 break;
273 273
274 (void)fflush(stdout); 274 (void)fflush(stdout);
275 (void)sleep(interval); 275 (void)sleep(interval);
276 } 276 }
277 /* Show sensors without interval */ 277 /* Show sensors without interval */
278 } else { 278 } else {
279 rval = parse_dictionary(sysmonfd); 279 rval = parse_dictionary(sysmonfd);
280 } 280 }
281 281
282 if (sensors) 282 if (sensors)
283 free(sensors); 283 free(sensors);
284 if (mydevname) 284 if (mydevname)
285 free(mydevname); 285 free(mydevname);
286 (void)prog_close(sysmonfd); 286 (void)prog_close(sysmonfd);
287 287
288 return rval ? EXIT_FAILURE : EXIT_SUCCESS; 288 return rval ? EXIT_FAILURE : EXIT_SUCCESS;
289} 289}
290 290
291static int 291static int
292send_dictionary(FILE *cf) 292send_dictionary(FILE *cf)
293{ 293{
294 prop_dictionary_t kdict, udict; 294 prop_dictionary_t kdict, udict;
295 int error = 0; 295 int error = 0;
296 296
297 /* Retrieve dictionary from kernel */ 297 /* Retrieve dictionary from kernel */
298 error = prop_dictionary_recv_ioctl(sysmonfd, 298 error = prop_dictionary_recv_ioctl(sysmonfd,
299 ENVSYS_GETDICTIONARY, &kdict); 299 ENVSYS_GETDICTIONARY, &kdict);
300 if (error) 300 if (error)
301 return error; 301 return error;
302 302
303 config_parse(cf, kdict); 303 config_parse(cf, kdict);
304 304
305 /* 305 /*
306 * Dictionary built by the parser from the configuration file. 306 * Dictionary built by the parser from the configuration file.
307 */ 307 */
308 udict = config_dict_parsed(); 308 udict = config_dict_parsed();
309 309
310 /* 310 /*
311 * Close the read only descriptor and open a new one read write. 311 * Close the read only descriptor and open a new one read write.
312 */ 312 */
313 (void)prog_close(sysmonfd); 313 (void)prog_close(sysmonfd);
314 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDWR)) == -1) { 314 if ((sysmonfd = prog_open(_PATH_SYSMON, O_RDWR)) == -1) {
315 error = errno; 315 error = errno;
316 warn("%s", _PATH_SYSMON); 316 warn("%s", _PATH_SYSMON);
317 return error; 317 return error;
318 } 318 }
319 319
320 /* 320 /*
321 * Send our sensor properties dictionary to the kernel then. 321 * Send our sensor properties dictionary to the kernel then.
322 */ 322 */
323 error = prop_dictionary_send_ioctl(udict, 323 error = prop_dictionary_send_ioctl(udict,
324 sysmonfd, ENVSYS_SETDICTIONARY); 324 sysmonfd, ENVSYS_SETDICTIONARY);
325 if (error) 325 if (error)
326 warnx("%s", strerror(error)); 326 warnx("%s", strerror(error));
327 327
328 prop_object_release(udict); 328 prop_object_release(udict);
329 return error; 329 return error;
330} 330}
331 331
332static sensor_stats_t 332static sensor_stats_t
333find_stats_sensor(const char *desc) 333find_stats_sensor(const char *desc)
334{ 334{
335 sensor_stats_t stats; 335 sensor_stats_t stats;
336 336
337 /* 337 /*
338 * If we matched a sensor by its description return it, otherwise 338 * If we matched a sensor by its description return it, otherwise
339 * allocate a new one. 339 * allocate a new one.
340 */ 340 */
341 SIMPLEQ_FOREACH(stats, &sensor_stats_list, entries) 341 SIMPLEQ_FOREACH(stats, &sensor_stats_list, entries)
342 if (strcmp(stats->desc, desc) == 0) 342 if (strcmp(stats->desc, desc) == 0)
343 return stats; 343 return stats;
344 344
345 stats = calloc(1, sizeof(*stats)); 345 stats = calloc(1, sizeof(*stats));
346 if (stats == NULL) 346 if (stats == NULL)
347 return NULL; 347 return NULL;
348 348
349 (void)strlcpy(stats->desc, desc, sizeof(stats->desc)); 349 (void)strlcpy(stats->desc, desc, sizeof(stats->desc));
350 SIMPLEQ_INSERT_TAIL(&sensor_stats_list, stats, entries); 350 SIMPLEQ_INSERT_TAIL(&sensor_stats_list, stats, entries);
351 351
352 return stats; 352 return stats;
353} 353}
354 354
355static int 355static int
356parse_dictionary(int fd) 356parse_dictionary(int fd)
357{ 357{
358 sensor_t sensor = NULL; 358 sensor_t sensor = NULL;
359 dvprops_t edp = NULL; 359 dvprops_t edp = NULL;
360 prop_array_t array; 360 prop_array_t array;
361 prop_dictionary_t dict; 361 prop_dictionary_t dict;
362 prop_object_iterator_t iter; 362 prop_object_iterator_t iter;
363 prop_object_t obj; 363 prop_object_t obj;
364 const char *dnp = NULL; 364 const char *dnp = NULL;
365 int rval = 0; 365 int rval = 0;
366 366
367 /* receive dictionary from kernel */ 367 /* receive dictionary from kernel */
368 rval = prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &dict); 368 rval = prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, &dict);
369 if (rval) 369 if (rval)
370 return rval; 370 return rval;
371 371
372 /* No drivers registered? */ 372 /* No drivers registered? */
373 if (prop_dictionary_count(dict) == 0) { 373 if (prop_dictionary_count(dict) == 0) {
374 warnx("no drivers registered"); 374 warnx("no drivers registered");
375 goto out; 375 goto out;
376 } 376 }
377 377
378 if (mydevname) { 378 if (mydevname) {
379 /* -d flag specified, print sensors only for this device */ 379 /* -d flag specified, print sensors only for this device */
380 obj = prop_dictionary_get(dict, mydevname); 380 obj = prop_dictionary_get(dict, mydevname);
381 if (prop_object_type(obj) != PROP_TYPE_ARRAY) { 381 if (prop_object_type(obj) != PROP_TYPE_ARRAY) {
382 warnx("unknown device `%s'", mydevname); 382 warnx("unknown device `%s'", mydevname);
383 rval = EINVAL; 383 rval = EINVAL;
384 goto out; 384 goto out;
385 } 385 }
386 386
387 rval = find_sensors(obj, mydevname, NULL); 387 rval = find_sensors(obj, mydevname, NULL);
388 if (rval) 388 if (rval)
389 goto out; 389 goto out;
390 390
391 } else { 391 } else {
392 /* print sensors for all devices registered */ 392 /* print sensors for all devices registered */
393 iter = prop_dictionary_iterator(dict); 393 iter = prop_dictionary_iterator(dict);
394 if (iter == NULL) { 394 if (iter == NULL) {
395 rval = EINVAL; 395 rval = EINVAL;
396 goto out; 396 goto out;
397 } 397 }
398 398
399 /* iterate over the dictionary returned by the kernel */ 399 /* iterate over the dictionary returned by the kernel */
400 while ((obj = prop_object_iterator_next(iter)) != NULL) { 400 while ((obj = prop_object_iterator_next(iter)) != NULL) {
401 array = prop_dictionary_get_keysym(dict, obj); 401 array = prop_dictionary_get_keysym(dict, obj);
402 if (prop_object_type(array) != PROP_TYPE_ARRAY) { 402 if (prop_object_type(array) != PROP_TYPE_ARRAY) {
403 warnx("no sensors found"); 403 warnx("no sensors found");
404 rval = EINVAL; 404 rval = EINVAL;
405 goto out; 405 goto out;
406 } 406 }
407 407
408 edp = calloc(1, sizeof(*edp)); 408 edp = calloc(1, sizeof(*edp));
409 if (!edp) { 409 if (!edp) {
410 rval = ENOMEM; 410 rval = ENOMEM;
411 goto out; 411 goto out;
412 } 412 }
413 413
414 dnp = prop_dictionary_keysym_cstring_nocopy(obj); 414 dnp = prop_dictionary_keysym_cstring_nocopy(obj);
415 rval = find_sensors(array, dnp, edp); 415 rval = find_sensors(array, dnp, edp);
416 if (rval) 416 if (rval)
417 goto out; 417 goto out;
418 418
419 if (((flags & ENVSYS_LFLAG) == 0) && 419 if (((flags & ENVSYS_LFLAG) == 0) &&
420 (flags & ENVSYS_DFLAG)) { 420 (flags & ENVSYS_DFLAG)) {
421 (void)printf("%s (checking events every ", 421 (void)printf("%s (checking events every ",
422 dnp); 422 dnp);
423 if (edp->refresh_timo == 1) 423 if (edp->refresh_timo == 1)
424 (void)printf("second)\n"); 424 (void)printf("second)\n");
425 else 425 else
426 (void)printf("%d seconds)\n", 426 (void)printf("%d seconds)\n",
427 (int)edp->refresh_timo); 427 (int)edp->refresh_timo);
428 } 428 }
429 429
430 free(edp); 430 free(edp);
431 edp = NULL; 431 edp = NULL;
432 } 432 }
433 prop_object_iterator_release(iter); 433 prop_object_iterator_release(iter);
434 } 434 }
435 435
436 /* print sensors now */ 436 /* print sensors now */
437 if (sensors) { 437 if (sensors) {
438 char *str = strdup(sensors); 438 char *str = strdup(sensors);
439 if (!str) { 439 if (!str) {
440 rval = ENOMEM; 440 rval = ENOMEM;
441 goto out; 441 goto out;
442 } 442 }
443 rval = check_sensors(str); 443 rval = check_sensors(str);
444 free(str); 444 free(str);
445 } 445 }
446 if ((flags & ENVSYS_LFLAG) == 0 && (flags & ENVSYS_DFLAG) == 0) 446 if ((flags & ENVSYS_LFLAG) == 0 && (flags & ENVSYS_DFLAG) == 0)
447 print_sensors(); 447 print_sensors();
448 if (interval) 448 if (interval)
449 (void)printf("\n"); 449 (void)printf("\n");
450 450
451out: 451out:
452 while ((sensor = SIMPLEQ_FIRST(&sensors_list))) { 452 while ((sensor = SIMPLEQ_FIRST(&sensors_list))) {
453 SIMPLEQ_REMOVE_HEAD(&sensors_list, entries); 453 SIMPLEQ_REMOVE_HEAD(&sensors_list, entries);
454 free(sensor); 454 free(sensor);
455 } 455 }
456 if (edp) 456 if (edp)
457 free(edp); 457 free(edp);
458 prop_object_release(dict); 458 prop_object_release(dict);
459 return rval; 459 return rval;
460} 460}
461 461
462static int 462static int
463find_sensors(prop_array_t array, const char *dvname, dvprops_t edp) 463find_sensors(prop_array_t array, const char *dvname, dvprops_t edp)
464{ 464{
465 prop_object_iterator_t iter; 465 prop_object_iterator_t iter;
466 prop_object_t obj, obj1, obj2; 466 prop_object_t obj, obj1, obj2;
467 prop_string_t state, desc = NULL; 467 prop_string_t state, desc = NULL;
468 sensor_t sensor = NULL; 468 sensor_t sensor = NULL;
469 sensor_stats_t stats = NULL; 469 sensor_stats_t stats = NULL;
470 470
471 iter = prop_array_iterator(array); 471 iter = prop_array_iterator(array);
472 if (!iter) 472 if (!iter)
473 return ENOMEM; 473 return ENOMEM;
474 474
475 /* iterate over the array of dictionaries */ 475 /* iterate over the array of dictionaries */
476 while ((obj = prop_object_iterator_next(iter)) != NULL) { 476 while ((obj = prop_object_iterator_next(iter)) != NULL) {
477 /* get the refresh-timeout property */ 477 /* get the refresh-timeout property */
478 obj2 = prop_dictionary_get(obj, "device-properties"); 478 obj2 = prop_dictionary_get(obj, "device-properties");
479 if (obj2) { 479 if (obj2) {
480 if (!edp) 480 if (!edp)
481 continue; 481 continue;
482 if (!prop_dictionary_get_uint64(obj2, 482 if (!prop_dictionary_get_uint64(obj2,
483 "refresh-timeout", 483 "refresh-timeout",
484 &edp->refresh_timo)) 484 &edp->refresh_timo))
485 continue; 485 continue;
486 } 486 }
487 487
488 /* new sensor coming */ 488 /* new sensor coming */
489 sensor = calloc(1, sizeof(*sensor)); 489 sensor = calloc(1, sizeof(*sensor));
490 if (sensor == NULL) { 490 if (sensor == NULL) {
491 prop_object_iterator_release(iter); 491 prop_object_iterator_release(iter);
492 return ENOMEM; 492 return ENOMEM;
493 } 493 }
494 494
495 /* copy device name */ 495 /* copy device name */
496 (void)strlcpy(sensor->dvname, dvname, sizeof(sensor->dvname)); 496 (void)strlcpy(sensor->dvname, dvname, sizeof(sensor->dvname));
497 497
498 /* description string */ 498 /* description string */
499 desc = prop_dictionary_get(obj, "description"); 499 desc = prop_dictionary_get(obj, "description");
500 if (desc) { 500 if (desc) {
501 /* copy description */ 501 /* copy description */
502 (void)strlcpy(sensor->desc, 502 (void)strlcpy(sensor->desc,
503 prop_string_cstring_nocopy(desc), 503 prop_string_cstring_nocopy(desc),
504 sizeof(sensor->desc)); 504 sizeof(sensor->desc));
505 } else { 505 } else {
506 free(sensor); 506 free(sensor);
507 continue; 507 continue;
508 } 508 }
509 509
510 /* type string */ 510 /* type string */
511 obj1 = prop_dictionary_get(obj, "type"); 511 obj1 = prop_dictionary_get(obj, "type");
512 if (obj1) { 512 if (obj1) {
513 /* copy type */ 513 /* copy type */
514 (void)strlcpy(sensor->type, 514 (void)strlcpy(sensor->type,
515 prop_string_cstring_nocopy(obj1), 515 prop_string_cstring_nocopy(obj1),
516 sizeof(sensor->type)); 516 sizeof(sensor->type));
517 } else { 517 } else {
518 free(sensor); 518 free(sensor);
519 continue; 519 continue;
520 } 520 }
521 521
522 /* check sensor's state */ 522 /* check sensor's state */
523 state = prop_dictionary_get(obj, "state"); 523 state = prop_dictionary_get(obj, "state");
524 524
525 /* mark sensors with invalid/unknown state */ 525 /* mark sensors with invalid/unknown state */
526 if ((prop_string_equals_cstring(state, "invalid") || 526 if ((prop_string_equals_cstring(state, "invalid") ||
527 prop_string_equals_cstring(state, "unknown"))) 527 prop_string_equals_cstring(state, "unknown")))
528 sensor->invalid = true; 528 sensor->invalid = true;
529 529
530 /* get current drive state string */ 530 /* get current drive state string */
531 obj1 = prop_dictionary_get(obj, "drive-state"); 531 obj1 = prop_dictionary_get(obj, "drive-state");
532 if (obj1) { 532 if (obj1) {
533 (void)strlcpy(sensor->drvstate, 533 (void)strlcpy(sensor->drvstate,
534 prop_string_cstring_nocopy(obj1), 534 prop_string_cstring_nocopy(obj1),
535 sizeof(sensor->drvstate)); 535 sizeof(sensor->drvstate));
536 } 536 }
537 537
538 /* get current battery capacity string */ 538 /* get current battery capacity string */
539 obj1 = prop_dictionary_get(obj, "battery-capacity"); 539 obj1 = prop_dictionary_get(obj, "battery-capacity");
540 if (obj1) { 540 if (obj1) {
541 (void)strlcpy(sensor->battcap, 541 (void)strlcpy(sensor->battcap,
542 prop_string_cstring_nocopy(obj1), 542 prop_string_cstring_nocopy(obj1),
543 sizeof(sensor->battcap)); 543 sizeof(sensor->battcap));
544 } 544 }
545 545
546 /* get current value */ 546 /* get current value */
547 obj1 = prop_dictionary_get(obj, "cur-value"); 547 obj1 = prop_dictionary_get(obj, "cur-value");
548 if (obj1) 548 if (obj1)
549 sensor->cur_value = prop_number_integer_value(obj1); 549 sensor->cur_value = prop_number_integer_value(obj1);
550 550
551 /* get max value */ 551 /* get max value */
552 obj1 = prop_dictionary_get(obj, "max-value"); 552 obj1 = prop_dictionary_get(obj, "max-value");
553 if (obj1) 553 if (obj1)
554 sensor->max_value = prop_number_integer_value(obj1); 554 sensor->max_value = prop_number_integer_value(obj1);
555 555
556 /* get min value */ 556 /* get min value */
557 obj1 = prop_dictionary_get(obj, "min-value"); 557 obj1 = prop_dictionary_get(obj, "min-value");
558 if (obj1) 558 if (obj1)
559 sensor->min_value = prop_number_integer_value(obj1); 559 sensor->min_value = prop_number_integer_value(obj1);
560 560
561 /* get percentage flag */ 561 /* get percentage flag */
562 obj1 = prop_dictionary_get(obj, "want-percentage"); 562 obj1 = prop_dictionary_get(obj, "want-percentage");
563 if (obj1) 563 if (obj1)
564 sensor->percentage = prop_bool_true(obj1); 564 sensor->percentage = prop_bool_true(obj1);
565 565
566 /* get critical max value if available */ 566 /* get critical max value if available */
567 obj1 = prop_dictionary_get(obj, "critical-max"); 567 obj1 = prop_dictionary_get(obj, "critical-max");
568 if (obj1) 568 if (obj1)
569 sensor->critmax_value = prop_number_integer_value(obj1); 569 sensor->critmax_value = prop_number_integer_value(obj1);
570 570
571 /* get maximum capacity value if available */ 571 /* get maximum capacity value if available */
572 obj1 = prop_dictionary_get(obj, "maximum-capacity"); 572 obj1 = prop_dictionary_get(obj, "maximum-capacity");
573 if (obj1) 573 if (obj1)
574 sensor->critmax_value = prop_number_integer_value(obj1); 574 sensor->critmax_value = prop_number_integer_value(obj1);
575 575
576 /* get critical min value if available */ 576 /* get critical min value if available */
577 obj1 = prop_dictionary_get(obj, "critical-min"); 577 obj1 = prop_dictionary_get(obj, "critical-min");
578 if (obj1) 578 if (obj1)
579 sensor->critmin_value = prop_number_integer_value(obj1); 579 sensor->critmin_value = prop_number_integer_value(obj1);
580 580
581 /* get critical capacity value if available */ 581 /* get critical capacity value if available */
582 obj1 = prop_dictionary_get(obj, "critical-capacity"); 582 obj1 = prop_dictionary_get(obj, "critical-capacity");
583 if (obj1) 583 if (obj1)
584 sensor->critmin_value = prop_number_integer_value(obj1); 584 sensor->critmin_value = prop_number_integer_value(obj1);
585 585
586 /* get warning max value if available */ 586 /* get warning max value if available */
587 obj1 = prop_dictionary_get(obj, "warning-max"); 587 obj1 = prop_dictionary_get(obj, "warning-max");
588 if (obj1) 588 if (obj1)
589 sensor->warnmax_value = prop_number_integer_value(obj1); 589 sensor->warnmax_value = prop_number_integer_value(obj1);
590 590
591 /* get high capacity value if available */ 591 /* get high capacity value if available */
592 obj1 = prop_dictionary_get(obj, "high-capacity"); 592 obj1 = prop_dictionary_get(obj, "high-capacity");
593 if (obj1) 593 if (obj1)
594 sensor->warnmax_value = prop_number_integer_value(obj1); 594 sensor->warnmax_value = prop_number_integer_value(obj1);
595 595
596 /* get warning min value if available */ 596 /* get warning min value if available */
597 obj1 = prop_dictionary_get(obj, "warning-min"); 597 obj1 = prop_dictionary_get(obj, "warning-min");
598 if (obj1) 598 if (obj1)
599 sensor->warnmin_value = prop_number_integer_value(obj1); 599 sensor->warnmin_value = prop_number_integer_value(obj1);
600 600
601 /* get warning capacity value if available */ 601 /* get warning capacity value if available */
602 obj1 = prop_dictionary_get(obj, "warning-capacity"); 602 obj1 = prop_dictionary_get(obj, "warning-capacity");
603 if (obj1) 603 if (obj1)
604 sensor->warnmin_value = prop_number_integer_value(obj1); 604 sensor->warnmin_value = prop_number_integer_value(obj1);
605 605
606 /* print sensor names if -l was given */ 606 /* print sensor names if -l was given */
607 if (flags & ENVSYS_LFLAG) { 607 if (flags & ENVSYS_LFLAG) {
608 if (width) 608 if (width)
609 (void)printf("%*s\n", width, 609 (void)printf("%*s\n", width,
610 prop_string_cstring_nocopy(desc)); 610 prop_string_cstring_nocopy(desc));
611 else 611 else
612 (void)printf("%s\n", 612 (void)printf("%s\n",
613 prop_string_cstring_nocopy(desc)); 613 prop_string_cstring_nocopy(desc));
614 } 614 }
615 615
616 /* Add the sensor into the list */ 616 /* Add the sensor into the list */
617 SIMPLEQ_INSERT_TAIL(&sensors_list, sensor, entries); 617 SIMPLEQ_INSERT_TAIL(&sensors_list, sensor, entries);
618 618
619 /* Collect statistics if flag enabled */ 619 /* Collect statistics if flag enabled */
620 if (statistics) { 620 if (statistics) {
621 /* ignore sensors not relevant for statistics */ 621 /* ignore sensors not relevant for statistics */
622 if ((strcmp(sensor->type, "Indicator") == 0) || 622 if ((strcmp(sensor->type, "Indicator") == 0) ||
623 (strcmp(sensor->type, "Battery charge") == 0) || 623 (strcmp(sensor->type, "Battery charge") == 0) ||
624 (strcmp(sensor->type, "Drive") == 0)) 624 (strcmp(sensor->type, "Drive") == 0))
625 continue; 625 continue;
626 626
627 /* ignore invalid data */ 627 /* ignore invalid data */
628 if (sensor->invalid || !sensor->cur_value) 628 if (sensor->invalid || !sensor->cur_value)
629 continue; 629 continue;
630 630
631 /* find or allocate a new statistics sensor */ 631 /* find or allocate a new statistics sensor */
632 stats = find_stats_sensor(sensor->desc); 632 stats = find_stats_sensor(sensor->desc);
633 if (stats == NULL) { 633 if (stats == NULL) {
634 free(sensor); 634 free(sensor);
635 prop_object_iterator_release(iter); 635 prop_object_iterator_release(iter);
636 return ENOMEM; 636 return ENOMEM;
637 } 637 }
638 638
639 /* collect data */ 639 /* collect data */
640 if (!stats->max) 640 if (!stats->max)
641 stats->max = sensor->cur_value; 641 stats->max = sensor->cur_value;
642 if (!stats->min) 642 if (!stats->min)
643 stats->min = sensor->cur_value; 643 stats->min = sensor->cur_value;
644 644
645 if (sensor->cur_value > stats->max) 645 if (sensor->cur_value > stats->max)
646 stats->max = sensor->cur_value; 646 stats->max = sensor->cur_value;
647 647
648 if (sensor->cur_value < stats->min) 648 if (sensor->cur_value < stats->min)
649 stats->min = sensor->cur_value; 649 stats->min = sensor->cur_value;
650 650
651 /* compute avg value */ 651 /* compute avg value */
652 if (stats->max && stats->min) 652 if (stats->max && stats->min)
653 stats->avg = 653 stats->avg =
654 (sensor->cur_value + stats->max + 654 (sensor->cur_value + stats->max +
655 stats->min) / 3; 655 stats->min) / 3;
656 } 656 }
657 } 657 }
658 658
659 /* free memory */ 659 /* free memory */
660 prop_object_iterator_release(iter); 660 prop_object_iterator_release(iter);
661 return 0; 661 return 0;
662} 662}
663 663
664static int 664static int
665check_sensors(char *str) 665check_sensors(char *str)
666{ 666{
667 sensor_t sensor = NULL; 667 sensor_t sensor = NULL;
668 char *dvstring, *sstring, *p, *last; 668 char *dvstring, *sstring, *p, *last;
669 bool sensor_found = false; 669 bool sensor_found = false;
670 670
671 /* 671 /*
672 * Parse device name and sensor description and find out 672 * Parse device name and sensor description and find out
673 * if the sensor is valid. 673 * if the sensor is valid.
674 */ 674 */
675 for ((p = strtok_r(str, ",", &last)); p; 675 for ((p = strtok_r(str, ",", &last)); p;
676 (p = strtok_r(NULL, ",", &last))) { 676 (p = strtok_r(NULL, ",", &last))) {
677 /* get device name */ 677 /* get device name */
678 dvstring = strtok(p, ":"); 678 dvstring = strtok(p, ":");
679 if (dvstring == NULL) { 679 if (dvstring == NULL) {
680 warnx("missing device name"); 680 warnx("missing device name");
681 return EINVAL; 681 return EINVAL;
682 } 682 }
683 683
684 /* get sensor description */ 684 /* get sensor description */
685 sstring = strtok(NULL, ":"); 685 sstring = strtok(NULL, ":");
686 if (sstring == NULL) { 686 if (sstring == NULL) {
687 warnx("missing sensor description"); 687 warnx("missing sensor description");
688 return EINVAL; 688 return EINVAL;
689 } 689 }
690 690
691 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) { 691 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) {
692 /* skip until we match device */ 692 /* skip until we match device */
693 if (strcmp(dvstring, sensor->dvname)) 693 if (strcmp(dvstring, sensor->dvname))
694 continue; 694 continue;
695 if (strcmp(sstring, sensor->desc) == 0) { 695 if (strcmp(sstring, sensor->desc) == 0) {
696 sensor->visible = true; 696 sensor->visible = true;
697 sensor_found = true; 697 sensor_found = true;
698 break; 698 break;
699 } 699 }
700 } 700 }
701 if (sensor_found == false) { 701 if (sensor_found == false) {
702 warnx("unknown sensor `%s' for device `%s'", 702 warnx("unknown sensor `%s' for device `%s'",
703 sstring, dvstring); 703 sstring, dvstring);
704 return EINVAL; 704 return EINVAL;
705 } 705 }
706 sensor_found = false; 706 sensor_found = false;
707 } 707 }
708 708
709 /* check if all sensors were ok, and error out if not */ 709 /* check if all sensors were ok, and error out if not */
710 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) 710 SIMPLEQ_FOREACH(sensor, &sensors_list, entries)
711 if (sensor->visible) 711 if (sensor->visible)
712 return 0; 712 return 0;
713 713
714 warnx("no sensors selected to display"); 714 warnx("no sensors selected to display");
715 return EINVAL; 715 return EINVAL;
716} 716}
717 717
718static void 718static void
719print_sensors(void) 719print_sensors(void)
720{ 720{
721 sensor_t sensor; 721 sensor_t sensor;
722 sensor_stats_t stats = NULL; 722 sensor_stats_t stats = NULL;
723 size_t maxlen = 0, ilen; 723 size_t maxlen = 0, ilen;
724 double temp = 0; 724 double temp = 0;
725 const char *invalid = "N/A", *degrees, *tmpstr, *stype; 725 const char *invalid = "N/A", *degrees, *tmpstr, *stype;
726 const char *a, *b, *c, *d, *e, *units; 726 const char *a, *b, *c, *d, *e, *units;
727 727
728 tmpstr = stype = d = e = NULL; 728 tmpstr = stype = d = e = NULL;
729 729
730 /* find the longest description */ 730 /* find the longest description */
731 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) 731 SIMPLEQ_FOREACH(sensor, &sensors_list, entries)
732 if (strlen(sensor->desc) > maxlen) 732 if (strlen(sensor->desc) > maxlen)
733 maxlen = strlen(sensor->desc); 733 maxlen = strlen(sensor->desc);
734 734
735 if (width) 735 if (width)
736 maxlen = width; 736 maxlen = width;
737 737
738 /* 738 /*
739 * Print a header at the bottom only once showing different 739 * Print a header at the bottom only once showing different
740 * members if the statistics flag is set or not. 740 * members if the statistics flag is set or not.
741 * 741 *
742 * As bonus if -s is set, only print this header every 10 iterations 742 * As bonus if -s is set, only print this header every 10 iterations
743 * to avoid redundancy... like vmstat(1). 743 * to avoid redundancy... like vmstat(1).
744 */ 744 */
745 745
746 a = "Current"; 746 a = "Current";
747 units = "Unit"; 747 units = "Unit";
748 if (statistics) { 748 if (statistics) {
749 b = "Max"; 749 b = "Max";
750 c = "Min"; 750 c = "Min";
751 d = "Avg"; 751 d = "Avg";
752 } else { 752 } else {
753 b = "CritMax"; 753 b = "CritMax";
754 c = "WarnMax"; 754 c = "WarnMax";
755 d = "WarnMin"; 755 d = "WarnMin";
756 e = "CritMin"; 756 e = "CritMin";
757 } 757 }
758 758
759 if (!sensors || (!header_passes && sensors) || 759 if (!sensors || (!header_passes && sensors) ||
760 (header_passes == 10 && sensors)) { 760 (header_passes == 10 && sensors)) {
761 if (statistics) 761 if (statistics)
762 (void)printf("%s%*s %9s %8s %8s %8s %6s\n", 762 (void)printf("%s%*s %9s %8s %8s %8s %6s\n",
763 mydevname ? "" : " ", (int)maxlen, 763 mydevname ? "" : " ", (int)maxlen,
764 "", a, b, c, d, units); 764 "", a, b, c, d, units);
765 else 765 else
766 (void)printf("%s%*s %9s %8s %8s %8s %8s %4s\n", 766 (void)printf("%s%*s %9s %8s %8s %8s %8s %5s\n",
767 mydevname ? "" : " ", (int)maxlen, 767 mydevname ? "" : " ", (int)maxlen,
768 "", a, b, c, d, e, units); 768 "", a, b, c, d, e, units);
769 if (sensors && header_passes == 10) 769 if (sensors && header_passes == 10)
770 header_passes = 0; 770 header_passes = 0;
771 } 771 }
772 if (sensors) 772 if (sensors)
773 header_passes++; 773 header_passes++;
774 774
775 /* print the sensors */ 775 /* print the sensors */
776 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) { 776 SIMPLEQ_FOREACH(sensor, &sensors_list, entries) {
777 /* skip sensors that were not marked as visible */ 777 /* skip sensors that were not marked as visible */
778 if (sensors && !sensor->visible) 778 if (sensors && !sensor->visible)
779 continue; 779 continue;
780 780
781 /* skip invalid sensors if -I is set */ 781 /* skip invalid sensors if -I is set */
782 if ((flags & ENVSYS_IFLAG) && sensor->invalid) 782 if ((flags & ENVSYS_IFLAG) && sensor->invalid)
783 continue; 783 continue;
784 784
785 /* print device name */ 785 /* print device name */
786 if (!mydevname) { 786 if (!mydevname) {
787 if (tmpstr == NULL || strcmp(tmpstr, sensor->dvname)) 787 if (tmpstr == NULL || strcmp(tmpstr, sensor->dvname))
788 printf("[%s]\n", sensor->dvname); 788 printf("[%s]\n", sensor->dvname);
789 789
790 tmpstr = sensor->dvname; 790 tmpstr = sensor->dvname;
791 } 791 }
792 792
793 /* find out the statistics sensor */ 793 /* find out the statistics sensor */
794 if (statistics) { 794 if (statistics) {
795 stats = find_stats_sensor(sensor->desc); 795 stats = find_stats_sensor(sensor->desc);
796 if (stats == NULL) { 796 if (stats == NULL) {
797 /* No statistics for this sensor */ 797 /* No statistics for this sensor */
798 continue; 798 continue;
799 } 799 }
800 } 800 }
801 801
802 /* print sensor description */ 802 /* print sensor description */
803 (void)printf("%s%*.*s", mydevname ? "" : " ", (int)maxlen, 803 (void)printf("%s%*.*s", mydevname ? "" : " ", (int)maxlen,
804 (int)maxlen, sensor->desc); 804 (int)maxlen, sensor->desc);
805 805
806 /* print invalid string */ 806 /* print invalid string */
807 if (sensor->invalid) { 807 if (sensor->invalid) {
808 (void)printf(": %9s\n", invalid); 808 (void)printf(": %9s\n", invalid);
809 continue; 809 continue;
810 } 810 }
811 811
812 /* 812 /*
813 * Indicator and Battery charge sensors. 813 * Indicator and Battery charge sensors.
814 */ 814 */
815 if ((strcmp(sensor->type, "Indicator") == 0) || 815 if ((strcmp(sensor->type, "Indicator") == 0) ||
816 (strcmp(sensor->type, "Battery charge") == 0)) { 816 (strcmp(sensor->type, "Battery charge") == 0)) {
817 817
818 (void)printf(":%10s", sensor->cur_value ? "ON" : "OFF"); 818 (void)printf(":%10s", sensor->cur_value ? "ON" : "OFF");
819 819
820/* convert and print a temp value in degC, degF, or Kelvin */ 820/* convert and print a temp value in degC, degF, or Kelvin */
821#define PRINTTEMP(a) \ 821#define PRINTTEMP(a) \
822do { \ 822do { \
823 if (a) { \ 823 if (a) { \
824 temp = ((a) / 1000000.0); \ 824 temp = ((a) / 1000000.0); \
825 if (flags & ENVSYS_FFLAG) { \ 825 if (flags & ENVSYS_FFLAG) { \
826 temp = temp * (9.0 / 5.0) - 459.67; \ 826 temp = temp * (9.0 / 5.0) - 459.67; \
827 degrees = "degF"; \ 827 degrees = "degF"; \
828 } else if (flags & ENVSYS_KFLAG) { \ 828 } else if (flags & ENVSYS_KFLAG) { \
829 degrees = "K"; \ 829 degrees = "K"; \
830 } else { \ 830 } else { \
831 temp = temp - 273.15; \ 831 temp = temp - 273.15; \
832 degrees = "degC"; \ 832 degrees = "degC"; \
833 } \ 833 } \
834 (void)printf("%*.3f ", (int)ilen, temp); \ 834 (void)printf("%*.3f ", (int)ilen, temp); \
835 ilen = 8; \ 835 ilen = 8; \
836 } else \ 836 } else \
837 ilen += 9; \ 837 ilen += 9; \
838} while (/* CONSTCOND */ 0) 838} while (/* CONSTCOND */ 0)
839 839
840 /* temperatures */ 840 /* temperatures */
841 } else if (strcmp(sensor->type, "Temperature") == 0) { 841 } else if (strcmp(sensor->type, "Temperature") == 0) {
842 842
843 ilen = 10; 843 ilen = 10;
844 degrees = ""; 844 degrees = "";
845 (void)printf(":"); 845 (void)printf(":");
846 PRINTTEMP(sensor->cur_value); 846 PRINTTEMP(sensor->cur_value);
847 stype = degrees; 847 stype = degrees;
848 848
849 if (statistics) { 849 if (statistics) {
850 /* show statistics if flag set */ 850 /* show statistics if flag set */
851 PRINTTEMP(stats->max); 851 PRINTTEMP(stats->max);
852 PRINTTEMP(stats->min); 852 PRINTTEMP(stats->min);
853 PRINTTEMP(stats->avg); 853 PRINTTEMP(stats->avg);
854 ilen += 2; 854 ilen += 2;
855 } else { 855 } else {
856 PRINTTEMP(sensor->critmax_value); 856 PRINTTEMP(sensor->critmax_value);
857 PRINTTEMP(sensor->warnmax_value); 857 PRINTTEMP(sensor->warnmax_value);
858 PRINTTEMP(sensor->warnmin_value); 858 PRINTTEMP(sensor->warnmin_value);
859 PRINTTEMP(sensor->critmin_value); 859 PRINTTEMP(sensor->critmin_value);
860 } 860 }
861 (void)printf("%*s", (int)ilen - 4, stype); 861 (void)printf("%*s", (int)ilen - 4, stype);
862#undef PRINTTEMP 862#undef PRINTTEMP
863 863
864 /* fans */ 864 /* fans */
865 } else if (strcmp(sensor->type, "Fan") == 0) { 865 } else if (strcmp(sensor->type, "Fan") == 0) {
866 stype = "RPM"; 866 stype = "RPM";
867 867
868 (void)printf(":%10u ", sensor->cur_value); 868 (void)printf(":%10u ", sensor->cur_value);
869 869
870 ilen = 8; 870 ilen = 8;
871 if (statistics) { 871 if (statistics) {
872 /* show statistics if flag set */ 872 /* show statistics if flag set */
873 (void)printf("%8u %8u %8u ", 873 (void)printf("%8u %8u %8u ",
874 stats->max, stats->min, stats->avg); 874 stats->max, stats->min, stats->avg);
875 ilen += 2; 875 ilen += 2;
876 } else { 876 } else {
877 if (sensor->critmax_value) { 877 if (sensor->critmax_value) {
878 (void)printf("%*u ", (int)ilen, 878 (void)printf("%*u ", (int)ilen,
879 sensor->critmax_value); 879 sensor->critmax_value);
880 ilen = 8; 880 ilen = 8;
881 } else 881 } else
882 ilen += 9; 882 ilen += 9;
883 883
884 if (sensor->warnmax_value) { 884 if (sensor->warnmax_value) {
885 (void)printf("%*u ", (int)ilen, 885 (void)printf("%*u ", (int)ilen,
886 sensor->warnmax_value); 886 sensor->warnmax_value);
887 ilen = 8; 887 ilen = 8;
888 } else 888 } else
889 ilen += 9; 889 ilen += 9;
890 890
891 if (sensor->warnmin_value) { 891 if (sensor->warnmin_value) {
892 (void)printf("%*u ", (int)ilen, 892 (void)printf("%*u ", (int)ilen,
893 sensor->warnmin_value); 893 sensor->warnmin_value);
894 ilen = 8; 894 ilen = 8;
895 } else 895 } else
896 ilen += 9; 896 ilen += 9;
897 897
898 if (sensor->critmin_value) { 898 if (sensor->critmin_value) {
899 (void)printf( "%*u ", (int)ilen, 899 (void)printf( "%*u ", (int)ilen,
900 sensor->critmin_value); 900 sensor->critmin_value);
901 ilen = 8; 901 ilen = 8;
902 } else 902 } else
903 ilen += 9; 903 ilen += 9;
904 904
905 } 905 }
906 906
907 (void)printf("%*s", (int)ilen - 4, stype); 907 (void)printf("%*s", (int)ilen - 4, stype);
908 908
909 /* integers */ 909 /* integers */
910 } else if (strcmp(sensor->type, "Integer") == 0) { 910 } else if (strcmp(sensor->type, "Integer") == 0) {
911 911
912 stype = "none"; 912 stype = "none";
913 913
914 (void)printf(":%10d ", sensor->cur_value); 914 (void)printf(":%10d ", sensor->cur_value);
915 915
916 ilen = 8; 916 ilen = 8;
917 if (statistics) { 
918 /* show statistics if flag set */ 
919 (void)printf("%8u %8u %8u ", 
920 stats->max, stats->min, stats->avg); 
921 ilen += 2; 
922 } else { 
923 if (sensor->critmax_value) { 
924 (void)printf("%*u ", (int)ilen, 
925 sensor->critmax_value); 
926 ilen = 8; 
927 } else 
928 ilen += 9; 
929 
930 if (sensor->warnmax_value) { 
931 (void)printf("%*u ", (int)ilen, 
932 sensor->warnmax_value); 
933 ilen = 8; 
934 } else 
935 ilen += 9; 
936 917
937 if (sensor->warnmin_value) { 918/* Print percentage of max_value */
938 (void)printf("%*u ", (int)ilen, 919#define PRINTPCT(a) \
939 sensor->warnmin_value); 920do { \
940 ilen = 8; 921 if (sensor->max_value) { \
941 } else 922 (void)printf("%*.3f%%", (int)ilen, \
942 ilen += 9; 923 ((a) * 100.0) / sensor->max_value); \
 924 ilen = 8; \
 925 } else \
 926 ilen += 9; \
 927} while ( /* CONSTCOND*/ 0 )
943 928
944 if (sensor->critmin_value) { 929/* Print an integer sensor value */
945 (void)printf( "%*u ", (int)ilen, 930#define PRINTINT(a) \
946 sensor->critmin_value); 931do { \
947 ilen = 8; 932 (void)printf("%*u ", (int)ilen, (a)); \
948 } else 933 ilen = 8; \
949 ilen += 9; 934} while ( /* CONSTCOND*/ 0 )
950 935
 936 if (!statistics) {
 937 if (sensor->percentage) {
 938 PRINTPCT(sensor->critmax_value);
 939 PRINTPCT(sensor->warnmax_value);
 940 PRINTPCT(sensor->warnmin_value);
 941 PRINTPCT(sensor->critmin_value);
 942 } else {
 943 PRINTINT(sensor->critmax_value);
 944 PRINTINT(sensor->warnmax_value);
 945 PRINTINT(sensor->warnmin_value);
 946 PRINTINT(sensor->critmin_value);
 947 }
 948 } else {
 949 if (sensor->percentage) {
 950 PRINTPCT(stats->max);
 951 PRINTPCT(stats->min);
 952 PRINTPCT(stats->avg);
 953 } else {
 954 PRINTINT(stats->max);
 955 PRINTINT(stats->min);
 956 PRINTINT(stats->avg);
 957 }
 958 ilen += 2;
951 } 959 }
952 960
953 (void)printf("%*s", (int)ilen - 4, stype); 961 (void)printf("%*s", (int)ilen - 4, stype);
954 962
 963#undef PRINTINT
 964#undef PRINTPCT
 965
955 /* drives */ 966 /* drives */
956 } else if (strcmp(sensor->type, "Drive") == 0) { 967 } else if (strcmp(sensor->type, "Drive") == 0) {
957 968
958 (void)printf(":%10s", sensor->drvstate); 969 (void)printf(":%10s", sensor->drvstate);
959 970
960 /* Battery capacity */ 971 /* Battery capacity */
961 } else if (strcmp(sensor->type, "Battery capacity") == 0) { 972 } else if (strcmp(sensor->type, "Battery capacity") == 0) {
962 973
963 (void)printf(":%10s", sensor->battcap); 974 (void)printf(":%10s", sensor->battcap);
964 975
965 /* everything else */ 976 /* everything else */
966 } else { 977 } else {
967 if (strcmp(sensor->type, "Voltage DC") == 0) 978 if (strcmp(sensor->type, "Voltage DC") == 0)
968 stype = "V"; 979 stype = "V";
969 else if (strcmp(sensor->type, "Voltage AC") == 0) 980 else if (strcmp(sensor->type, "Voltage AC") == 0)
970 stype = "VAC"; 981 stype = "VAC";
971 else if (strcmp(sensor->type, "Ampere") == 0) 982 else if (strcmp(sensor->type, "Ampere") == 0)
972 stype = "A"; 983 stype = "A";
973 else if (strcmp(sensor->type, "Watts") == 0) 984 else if (strcmp(sensor->type, "Watts") == 0)
974 stype = "W"; 985 stype = "W";
975 else if (strcmp(sensor->type, "Ohms") == 0) 986 else if (strcmp(sensor->type, "Ohms") == 0)
976 stype = "Ohms"; 987 stype = "Ohms";
977 else if (strcmp(sensor->type, "Watt hour") == 0) 988 else if (strcmp(sensor->type, "Watt hour") == 0)
978 stype = "Wh"; 989 stype = "Wh";
979 else if (strcmp(sensor->type, "Ampere hour") == 0) 990 else if (strcmp(sensor->type, "Ampere hour") == 0)
980 stype = "Ah"; 991 stype = "Ah";
 992 else
 993 stype = "?";
981 994
982 (void)printf(":%10.3f ", 995 (void)printf(":%10.3f ",
983 sensor->cur_value / 1000000.0); 996 sensor->cur_value / 1000000.0);
984 997
985 ilen = 8; 998 ilen = 8;
986 if (!statistics) { 
987 999
988/* Print percentage of max_value */ 1000/* Print percentage of max_value */
989#define PRINTPCT(a) \ 1001#define PRINTPCT(a) \
990do { \ 1002do { \
991 if (sensor->a && sensor->max_value) { \ 1003 if ((a) && sensor->max_value) { \
992 (void)printf("%*.3f%%", (int)ilen, \ 1004 (void)printf("%*.3f%%", (int)ilen, \
993 (sensor->a * 100.0) / sensor->max_value); \ 1005 ((a) * 100.0) / sensor->max_value); \
994 ilen = 8; \ 1006 ilen = 8; \
995 } else \ 1007 } else \
996 ilen += 9; \ 1008 ilen += 9; \
997} while ( /* CONSTCOND*/ 0 ) 1009} while ( /* CONSTCOND*/ 0 )
998 1010
999/* Print a generic sensor value */ 1011/* Print a generic sensor value */
1000#define PRINTVAL(a) \ 1012#define PRINTVAL(a) \
1001do { \ 1013do { \
1002 if (sensor->a) { \ 1014 if ((a)) { \
1003 (void)printf("%*.3f ", (int)ilen, sensor->a / 1000000.0); \ 1015 (void)printf("%*.3f ", (int)ilen, (a) / 1000000.0); \
1004 ilen = 8; \ 1016 ilen = 8; \
1005 } else \ 1017 } else \
1006 ilen += 9; \ 1018 ilen += 9; \
1007} while ( /* CONSTCOND*/ 0 ) 1019} while ( /* CONSTCOND*/ 0 )
1008 1020
1009 1021 if (!statistics) {
1010 if (sensor->percentage) { 1022 if (sensor->percentage) {
1011 PRINTPCT(critmax_value); 1023 PRINTPCT(sensor->critmax_value);
1012 PRINTPCT(warnmax_value); 1024 PRINTPCT(sensor->warnmax_value);
1013 PRINTPCT(warnmin_value); 1025 PRINTPCT(sensor->warnmin_value);
1014 PRINTPCT(critmin_value); 1026 PRINTPCT(sensor->critmin_value);
1015 } else { 1027 } else {
1016 1028
1017 PRINTVAL(critmax_value); 1029 PRINTVAL(sensor->critmax_value);
1018 PRINTVAL(warnmax_value); 1030 PRINTVAL(sensor->warnmax_value);
1019 PRINTVAL(warnmin_value); 1031 PRINTVAL(sensor->warnmin_value);
1020 PRINTVAL(critmin_value); 1032 PRINTVAL(sensor->critmin_value);
1021#undef PRINTPCT 1033 }
1022#undef PRINTVAL 1034 } else {
 1035 if (sensor->percentage) {
 1036 PRINTPCT(stats->max);
 1037 PRINTPCT(stats->min);
 1038 PRINTPCT(stats->avg);
 1039 } else {
 1040 PRINTVAL(stats->max);
 1041 PRINTVAL(stats->min);
 1042 PRINTVAL(stats->avg);
1023 } 1043 }
1024 } 
1025 
1026 if (statistics && !sensor->percentage) { 
1027 /* show statistics if flag set */ 
1028 (void)printf("%8.3f %8.3f %8.3f ", 
1029 stats->max / 1000000.0, 
1030 stats->min / 1000000.0, 
1031 stats->avg / 1000000.0); 
1032 ilen += 2; 1044 ilen += 2;
1033 } 1045 }
 1046#undef PRINTPCT
 1047#undef PRINTVAL
1034 1048
1035 (void)printf("%*s", (int)ilen - 4, stype); 1049 (void)printf("%*s", (int)ilen - 3, stype);
1036 1050
1037 if (sensor->percentage && sensor->max_value) { 1051 if (sensor->percentage && sensor->max_value) {
1038 (void)printf(" (%5.2f%%)", 1052 (void)printf(" (%5.2f%%)",
1039 (sensor->cur_value * 100.0) / 1053 (sensor->cur_value * 100.0) /
1040 sensor->max_value); 1054 sensor->max_value);
1041 } 1055 }
1042 } 1056 }
1043 (void)printf("\n"); 1057 (void)printf("\n");
1044 } 1058 }
1045} 1059}
1046 1060
1047static int 1061static int
1048usage(void) 1062usage(void)
1049{ 1063{
1050 (void)fprintf(stderr, "Usage: %s [-DfIklrSTx] ", getprogname()); 1064 (void)fprintf(stderr, "Usage: %s [-DfIklrSTx] ", getprogname());
1051 (void)fprintf(stderr, "[-c file] [-d device] [-i interval] "); 1065 (void)fprintf(stderr, "[-c file] [-d device] [-i interval] ");
1052 (void)fprintf(stderr, "[-s device:sensor,...] [-w width]\n"); 1066 (void)fprintf(stderr, "[-s device:sensor,...] [-w width]\n");
1053 exit(EXIT_FAILURE); 1067 exit(EXIT_FAILURE);
1054 /* NOTREACHED */ 1068 /* NOTREACHED */
1055} 1069}