1 /* $NetBSD: envstat.c,v 1.71 2009/02/14 16:08:22 ahoka Exp $ */
4 * Copyright (c) 2007, 2008 Juan Romero Pardines.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
30 __RCSID("$NetBSD: envstat.c,v 1.71 2009/02/14 16:08:22 ahoka Exp $");
42 #include <sys/envsys.h>
43 #include <sys/types.h>
44 #include <sys/queue.h>
45 #include <prop/proplib.h>
49 #define _PATH_DEV_SYSMON "/dev/sysmon"
51 #define ENVSYS_DFLAG 0x00000001 /* list registered devices */
52 #define ENVSYS_FFLAG 0x00000002 /* show temp in farenheit */
53 #define ENVSYS_LFLAG 0x00000004 /* list sensors */
54 #define ENVSYS_XFLAG 0x00000008 /* externalize dictionary */
55 #define ENVSYS_IFLAG 0x00000010 /* skip invalid sensors */
56 #define ENVSYS_SFLAG 0x00000020 /* remove all properties set */
57 #define ENVSYS_TFLAG 0x00000040 /* make statistics */
58 #define ENVSYS_WFLAG 0x00000080 /* print warn{min,max} values */
59 #define ENVSYS_KFLAG 0x00000100 /* show temp in kelvin */
62 typedef struct envsys_sensor
{
63 SIMPLEQ_ENTRY(envsys_sensor
) entries
;
68 int32_t critcap_value
;
69 int32_t critmin_value
;
70 int32_t critmax_value
;
71 int32_t warncap_value
;
72 int32_t warnmin_value
;
73 int32_t warnmax_value
;
74 char desc
[ENVSYS_DESCLEN
];
75 char type
[ENVSYS_DESCLEN
];
76 char drvstate
[ENVSYS_DESCLEN
];
77 char battcap
[ENVSYS_DESCLEN
];
78 char dvname
[ENVSYS_DESCLEN
];
84 /* Sensor statistics */
85 typedef struct envsys_sensor_stats
{
86 SIMPLEQ_ENTRY(envsys_sensor_stats
) entries
;
90 char desc
[ENVSYS_DESCLEN
];
93 /* Device properties */
94 typedef struct envsys_dvprops
{
95 uint64_t refresh_timo
;
96 /* more members could be added in the future */
99 /* A simple queue to manage all sensors */
100 static SIMPLEQ_HEAD(, envsys_sensor
) sensors_list
=
101 SIMPLEQ_HEAD_INITIALIZER(sensors_list
);
103 /* A simple queue to manage statistics for all sensors */
104 static SIMPLEQ_HEAD(, envsys_sensor_stats
) sensor_stats_list
=
105 SIMPLEQ_HEAD_INITIALIZER(sensor_stats_list
);
107 static unsigned int interval
, flags
, width
;
108 static char *mydevname
, *sensors
;
109 static bool statistics
;
110 static u_int header_passes
;
112 static int parse_dictionary(int);
113 static int send_dictionary(FILE *, int);
114 static int find_sensors(prop_array_t
, const char *, dvprops_t
);
115 static void print_sensors(void);
116 static int check_sensors(char *);
117 static int usage(void);
120 int main(int argc
, char **argv
)
122 prop_dictionary_t dict
;
124 char *endptr
, *configfile
= NULL
;
127 setprogname(argv
[0]);
129 while ((c
= getopt(argc
, argv
, "c:Dd:fIi:klrSs:Tw:Wx")) != -1) {
131 case 'c': /* configuration file */
132 configfile
= strdup(optarg
);
133 if (configfile
== NULL
)
134 err(EXIT_FAILURE
, "strdup");
136 case 'D': /* list registered devices */
137 flags
|= ENVSYS_DFLAG
;
139 case 'd': /* show sensors of a specific device */
140 mydevname
= strdup(optarg
);
141 if (mydevname
== NULL
)
142 err(EXIT_FAILURE
, "strdup");
144 case 'f': /* display temperature in Farenheit */
145 flags
|= ENVSYS_FFLAG
;
147 case 'I': /* Skips invalid sensors */
148 flags
|= ENVSYS_IFLAG
;
150 case 'i': /* wait time between intervals */
151 interval
= (unsigned int)strtoul(optarg
, &endptr
, 10);
153 errx(EXIT_FAILURE
, "bad interval '%s'", optarg
);
155 case 'k': /* display temperature in Kelvin */
156 flags
|= ENVSYS_KFLAG
;
158 case 'l': /* list sensors */
159 flags
|= ENVSYS_LFLAG
;
163 * This flag is noop.. it's only here for
164 * compatibility with the old implementation.
168 flags
|= ENVSYS_SFLAG
;
170 case 's': /* only show specified sensors */
171 sensors
= strdup(optarg
);
173 err(EXIT_FAILURE
, "strdup");
175 case 'T': /* make statistics */
176 flags
|= ENVSYS_TFLAG
;
178 case 'W': /* print warn{max,min} vs crit{max,min} */
179 flags
|= ENVSYS_WFLAG
;
181 case 'w': /* width value for the lines */
182 width
= (unsigned int)strtoul(optarg
, &endptr
, 10);
184 errx(EXIT_FAILURE
, "bad width '%s'", optarg
);
186 case 'x': /* print the dictionary in raw format */
187 flags
|= ENVSYS_XFLAG
;
202 /* Check if we want to make statistics */
203 if (flags
& ENVSYS_TFLAG
) {
206 "-T cannot be used without an interval (-i)");
207 if (flags
& ENVSYS_WFLAG
)
209 "-T cannot be used with -W");
214 if (mydevname
&& sensors
)
215 errx(EXIT_FAILURE
, "-d flag cannot be used with -s");
217 /* Open the device in ro mode */
218 if ((fd
= open(_PATH_DEV_SYSMON
, O_RDONLY
)) == -1)
219 err(EXIT_FAILURE
, "%s", _PATH_DEV_SYSMON
);
221 /* Print dictionary in raw mode */
222 if (flags
& ENVSYS_XFLAG
) {
223 rval
= prop_dictionary_recv_ioctl(fd
,
224 ENVSYS_GETDICTIONARY
,
227 errx(EXIT_FAILURE
, "%s", strerror(rval
));
229 config_dict_dump(dict
);
231 /* Remove all properties set in dictionary */
232 } else if (flags
& ENVSYS_SFLAG
) {
233 /* Close the ro descriptor */
236 /* open the fd in rw mode */
237 if ((fd
= open(_PATH_DEV_SYSMON
, O_RDWR
)) == -1)
238 err(EXIT_FAILURE
, "%s", _PATH_DEV_SYSMON
);
240 dict
= prop_dictionary_create();
242 err(EXIT_FAILURE
, "prop_dictionary_create");
244 rval
= prop_dictionary_set_bool(dict
,
245 "envsys-remove-props",
248 err(EXIT_FAILURE
, "prop_dict_set_bool");
250 /* send the dictionary to the kernel now */
251 rval
= prop_dictionary_send_ioctl(dict
, fd
, ENVSYS_REMOVEPROPS
);
253 warnx("%s", strerror(rval
));
255 /* Set properties in dictionary */
256 } else if (configfile
) {
258 * Parse the configuration file.
260 if ((cf
= fopen(configfile
, "r")) == NULL
) {
261 syslog(LOG_ERR
, "fopen failed: %s", strerror(errno
));
262 errx(EXIT_FAILURE
, "%s", strerror(errno
));
265 rval
= send_dictionary(cf
, fd
);
268 /* Show sensors with interval */
269 } else if (interval
) {
271 rval
= parse_dictionary(fd
);
275 (void)fflush(stdout
);
276 (void)sleep(interval
);
278 /* Show sensors without interval */
280 rval
= parse_dictionary(fd
);
289 return rval
? EXIT_FAILURE
: EXIT_SUCCESS
;
293 send_dictionary(FILE *cf
, int fd
)
295 prop_dictionary_t kdict
, udict
;
298 /* Retrieve dictionary from kernel */
299 error
= prop_dictionary_recv_ioctl(fd
, ENVSYS_GETDICTIONARY
, &kdict
);
303 config_parse(cf
, kdict
);
306 * Dictionary built by the parser from the configuration file.
308 udict
= config_dict_parsed();
311 * Close the read only descriptor and open a new one read write.
314 if ((fd
= open(_PATH_DEV_SYSMON
, O_RDWR
)) == -1) {
316 warn("%s", _PATH_DEV_SYSMON
);
321 * Send our sensor properties dictionary to the kernel then.
323 error
= prop_dictionary_send_ioctl(udict
, fd
, ENVSYS_SETDICTIONARY
);
325 warnx("%s", strerror(error
));
327 prop_object_release(udict
);
331 static sensor_stats_t
332 find_stats_sensor(const char *desc
)
334 sensor_stats_t stats
;
337 * If we matched a sensor by its description return it, otherwise
338 * allocate a new one.
340 SIMPLEQ_FOREACH(stats
, &sensor_stats_list
, entries
)
341 if (strcmp(stats
->desc
, desc
) == 0)
344 stats
= calloc(1, sizeof(*stats
));
348 (void)strlcpy(stats
->desc
, desc
, sizeof(stats
->desc
));
349 SIMPLEQ_INSERT_TAIL(&sensor_stats_list
, stats
, entries
);
355 parse_dictionary(int fd
)
357 sensor_t sensor
= NULL
;
358 dvprops_t edp
= NULL
;
360 prop_dictionary_t dict
;
361 prop_object_iterator_t iter
;
363 const char *dnp
= NULL
;
366 /* receive dictionary from kernel */
367 rval
= prop_dictionary_recv_ioctl(fd
, ENVSYS_GETDICTIONARY
, &dict
);
371 /* No drivers registered? */
372 if (prop_dictionary_count(dict
) == 0) {
373 warnx("no drivers registered");
378 /* -d flag specified, print sensors only for this device */
379 obj
= prop_dictionary_get(dict
, mydevname
);
380 if (prop_object_type(obj
) != PROP_TYPE_ARRAY
) {
381 warnx("unknown device `%s'", mydevname
);
386 rval
= find_sensors(obj
, mydevname
, NULL
);
391 /* print sensors for all devices registered */
392 iter
= prop_dictionary_iterator(dict
);
398 /* iterate over the dictionary returned by the kernel */
399 while ((obj
= prop_object_iterator_next(iter
)) != NULL
) {
400 array
= prop_dictionary_get_keysym(dict
, obj
);
401 if (prop_object_type(array
) != PROP_TYPE_ARRAY
) {
402 warnx("no sensors found");
407 edp
= calloc(1, sizeof(*edp
));
413 dnp
= prop_dictionary_keysym_cstring_nocopy(obj
);
414 rval
= find_sensors(array
, dnp
, edp
);
418 if (((flags
& ENVSYS_LFLAG
) == 0) &&
419 (flags
& ENVSYS_DFLAG
)) {
420 (void)printf("%s (checking events every ",
422 if (edp
->refresh_timo
== 1)
423 (void)printf("second)\n");
425 (void)printf("%d seconds)\n",
426 (int)edp
->refresh_timo
);
432 prop_object_iterator_release(iter
);
435 /* print sensors now */
437 char *str
= strdup(sensors
);
442 rval
= check_sensors(str
);
449 if ((flags
& ENVSYS_LFLAG
) == 0 && (flags
& ENVSYS_DFLAG
) == 0)
455 while ((sensor
= SIMPLEQ_FIRST(&sensors_list
))) {
456 SIMPLEQ_REMOVE_HEAD(&sensors_list
, entries
);
461 prop_object_release(dict
);
466 find_sensors(prop_array_t array
, const char *dvname
, dvprops_t edp
)
468 prop_object_iterator_t iter
;
469 prop_object_t obj
, obj1
, obj2
;
470 prop_string_t state
, desc
= NULL
;
471 sensor_t sensor
= NULL
;
472 sensor_stats_t stats
= NULL
;
474 iter
= prop_array_iterator(array
);
478 /* iterate over the array of dictionaries */
479 while ((obj
= prop_object_iterator_next(iter
)) != NULL
) {
480 /* get the refresh-timeout property */
481 obj2
= prop_dictionary_get(obj
, "device-properties");
485 if (!prop_dictionary_get_uint64(obj2
,
491 /* new sensor coming */
492 sensor
= calloc(1, sizeof(*sensor
));
493 if (sensor
== NULL
) {
494 prop_object_iterator_release(iter
);
498 /* copy device name */
499 (void)strlcpy(sensor
->dvname
, dvname
, sizeof(sensor
->dvname
));
501 /* description string */
502 desc
= prop_dictionary_get(obj
, "description");
504 /* copy description */
505 (void)strlcpy(sensor
->desc
,
506 prop_string_cstring_nocopy(desc
),
507 sizeof(sensor
->desc
));
514 obj1
= prop_dictionary_get(obj
, "type");
517 (void)strlcpy(sensor
->type
,
518 prop_string_cstring_nocopy(obj1
),
519 sizeof(sensor
->type
));
525 /* check sensor's state */
526 state
= prop_dictionary_get(obj
, "state");
528 /* mark sensors with invalid/unknown state */
529 if ((prop_string_equals_cstring(state
, "invalid") ||
530 prop_string_equals_cstring(state
, "unknown")))
531 sensor
->invalid
= true;
533 /* get current drive state string */
534 obj1
= prop_dictionary_get(obj
, "drive-state");
536 (void)strlcpy(sensor
->drvstate
,
537 prop_string_cstring_nocopy(obj1
),
538 sizeof(sensor
->drvstate
));
541 /* get current battery capacity string */
542 obj1
= prop_dictionary_get(obj
, "battery-capacity");
544 (void)strlcpy(sensor
->battcap
,
545 prop_string_cstring_nocopy(obj1
),
546 sizeof(sensor
->battcap
));
549 /* get current value */
550 obj1
= prop_dictionary_get(obj
, "cur-value");
552 sensor
->cur_value
= prop_number_integer_value(obj1
);
555 obj1
= prop_dictionary_get(obj
, "max-value");
557 sensor
->max_value
= prop_number_integer_value(obj1
);
560 obj1
= prop_dictionary_get(obj
, "min-value");
562 sensor
->min_value
= prop_number_integer_value(obj1
);
565 obj1
= prop_dictionary_get(obj
, "avg-value");
567 sensor
->avg_value
= prop_number_integer_value(obj1
);
569 /* get percentage flag */
570 obj1
= prop_dictionary_get(obj
, "want-percentage");
572 sensor
->percentage
= prop_bool_true(obj1
);
574 /* get critical max value if available */
575 obj1
= prop_dictionary_get(obj
, "critical-max");
577 sensor
->critmax_value
= prop_number_integer_value(obj1
);
579 /* get critical min value if available */
580 obj1
= prop_dictionary_get(obj
, "critical-min");
582 sensor
->critmin_value
= prop_number_integer_value(obj1
);
584 /* get critical capacity value if available */
585 obj1
= prop_dictionary_get(obj
, "critical-capacity");
587 sensor
->critcap_value
= prop_number_integer_value(obj1
);
589 /* get warning max value if available */
590 obj1
= prop_dictionary_get(obj
, "warning-max");
592 sensor
->warnmax_value
= prop_number_integer_value(obj1
);
594 /* get warning min value if available */
595 obj1
= prop_dictionary_get(obj
, "warning-min");
597 sensor
->warnmin_value
= prop_number_integer_value(obj1
);
599 /* get warning capacity value if available */
600 obj1
= prop_dictionary_get(obj
, "warning-capacity");
602 sensor
->warncap_value
= prop_number_integer_value(obj1
);
604 /* print sensor names if -l was given */
605 if (flags
& ENVSYS_LFLAG
) {
607 (void)printf("%*s\n", width
,
608 prop_string_cstring_nocopy(desc
));
611 prop_string_cstring_nocopy(desc
));
614 /* Add the sensor into the list */
615 SIMPLEQ_INSERT_TAIL(&sensors_list
, sensor
, entries
);
617 /* Collect statistics if flag enabled */
619 /* ignore sensors not relevant for statistics */
620 if ((strcmp(sensor
->type
, "Indicator") == 0) ||
621 (strcmp(sensor
->type
, "Battery charge") == 0) ||
622 (strcmp(sensor
->type
, "Drive") == 0))
625 /* ignore invalid data */
626 if (sensor
->invalid
|| !sensor
->cur_value
)
629 /* find or allocate a new statistics sensor */
630 stats
= find_stats_sensor(sensor
->desc
);
633 prop_object_iterator_release(iter
);
639 stats
->max
= sensor
->cur_value
;
641 stats
->min
= sensor
->cur_value
;
643 if (sensor
->cur_value
> stats
->max
)
644 stats
->max
= sensor
->cur_value
;
646 if (sensor
->cur_value
< stats
->min
)
647 stats
->min
= sensor
->cur_value
;
649 /* compute avg value */
650 if (stats
->max
&& stats
->min
)
652 (sensor
->cur_value
+ stats
->max
+
658 prop_object_iterator_release(iter
);
663 check_sensors(char *str
)
665 sensor_t sensor
= NULL
;
666 char *dvstring
, *sstring
, *p
, *last
;
667 bool sensor_found
= false;
670 * Parse device name and sensor description and find out
671 * if the sensor is valid.
673 for ((p
= strtok_r(str
, ",", &last
)); p
;
674 (p
= strtok_r(NULL
, ",", &last
))) {
675 /* get device name */
676 dvstring
= strtok(p
, ":");
677 if (dvstring
== NULL
) {
678 warnx("missing device name");
682 /* get sensor description */
683 sstring
= strtok(NULL
, ":");
684 if (sstring
== NULL
) {
685 warnx("missing sensor description");
689 SIMPLEQ_FOREACH(sensor
, &sensors_list
, entries
) {
690 /* skip until we match device */
691 if (strcmp(dvstring
, sensor
->dvname
))
693 if (strcmp(sstring
, sensor
->desc
) == 0) {
694 sensor
->visible
= true;
699 if (sensor_found
== false) {
700 warnx("unknown sensor `%s' for device `%s'",
704 sensor_found
= false;
707 /* check if all sensors were ok, and error out if not */
708 SIMPLEQ_FOREACH(sensor
, &sensors_list
, entries
)
712 warnx("no sensors selected to display");
720 sensor_stats_t stats
= NULL
;
721 size_t maxlen
= 0, ilen
= 32 + 3;
723 const char *invalid
= "N/A", *degrees
, *tmpstr
, *stype
;
724 const char *a
, *b
, *c
, *d
, *units
;
726 tmpstr
= stype
= d
= NULL
;
728 /* find the longest description */
729 SIMPLEQ_FOREACH(sensor
, &sensors_list
, entries
)
730 if (strlen(sensor
->desc
) > maxlen
)
731 maxlen
= strlen(sensor
->desc
);
737 * Print a header at the bottom only once showing different
738 * members if the statistics flag is set or not.
740 * As bonus if -s is set, only print this header every 10 iterations
741 * to avoid redundancy... like vmstat(1).
750 } else if (flags
& ENVSYS_WFLAG
) {
760 if (!sensors
|| (!header_passes
&& sensors
) ||
761 (header_passes
== 10 && sensors
)) {
762 (void)printf("%s%*s %10s %8s %8s %8s %8s\n",
763 mydevname
? "" : " ", (int)maxlen
,
764 "", a
, b
, c
, d
, units
);
765 if (sensors
&& header_passes
== 10)
771 /* print the sensors */
772 SIMPLEQ_FOREACH(sensor
, &sensors_list
, entries
) {
773 /* skip sensors that were not marked as visible */
774 if (sensors
&& !sensor
->visible
)
777 /* skip invalid sensors if -I is set */
778 if ((flags
& ENVSYS_IFLAG
) && sensor
->invalid
)
781 /* print device name */
783 if (tmpstr
== NULL
|| strcmp(tmpstr
, sensor
->dvname
))
784 printf("[%s]\n", sensor
->dvname
);
786 tmpstr
= sensor
->dvname
;
789 /* find out the statistics sensor */
791 stats
= find_stats_sensor(sensor
->desc
);
793 /* No statistics for this sensor */
798 /* print sensor description */
799 (void)printf("%s%*.*s", mydevname
? "" : " ", (int)maxlen
,
800 (int)maxlen
, sensor
->desc
);
802 /* print invalid string */
803 if (sensor
->invalid
) {
804 (void)printf(": %10s\n", invalid
);
809 * Indicator and Battery charge sensors.
811 if ((strcmp(sensor
->type
, "Indicator") == 0) ||
812 (strcmp(sensor
->type
, "Battery charge") == 0)) {
814 (void)printf(": %10s", sensor
->cur_value
? "ON" : "OFF");
816 /* converts the value to degC or degF or keep in Kelvin */
817 #define CONVERTTEMP(a, b, c) \
820 (a) = ((b) / 1000000.0); \
821 if (flags & ENVSYS_FFLAG) { \
823 (a) = (a) * (9.0 / 5.0) - 459.67; \
825 } else if (flags & ENVSYS_KFLAG) { \
829 (a) = (a) - 273.15; \
832 } while (/* CONSTCOND */ 0)
836 } else if (strcmp(sensor
->type
, "Temperature") == 0) {
838 CONVERTTEMP(temp
, sensor
->cur_value
, degrees
);
840 (void)printf(": %10.3f ", temp
);
843 /* show statistics if flag set */
844 CONVERTTEMP(temp
, stats
->max
, degrees
);
845 (void)printf("%8.3f ", temp
);
846 CONVERTTEMP(temp
, stats
->min
, degrees
);
847 (void)printf("%8.3f ", temp
);
848 CONVERTTEMP(temp
, stats
->avg
, degrees
);
849 (void)printf("%8.3f ", temp
);
851 } else if (flags
& ENVSYS_WFLAG
) {
852 if (sensor
->warnmax_value
) {
854 sensor
->warnmax_value
, degrees
);
855 (void)printf( "%8.3f ", temp
);
859 if (sensor
->warnmin_value
) {
861 sensor
->warnmin_value
, degrees
);
862 if (sensor
->warnmax_value
)
867 (void)printf("%*.3f ", (int)ilen
, temp
);
871 if (sensor
->critmax_value
) {
873 sensor
->critmax_value
, degrees
);
874 (void)printf( "%8.3f ", temp
);
878 if (sensor
->critmin_value
) {
880 sensor
->critmin_value
, degrees
);
881 if (sensor
->critmax_value
)
886 (void)printf("%*.3f ", (int)ilen
, temp
);
891 (void)printf("%*s", (int)ilen
, stype
);
895 } else if (strcmp(sensor
->type
, "Fan") == 0) {
898 (void)printf(": %10u ", sensor
->cur_value
);
900 /* show statistics if flag set */
901 (void)printf("%8u %8u %8u ",
902 stats
->max
, stats
->min
, stats
->avg
);
904 } else if (flags
& ENVSYS_WFLAG
) {
905 if (sensor
->warnmax_value
) {
907 sensor
->warnmax_value
);
911 if (sensor
->warnmin_value
) {
912 if (sensor
->warnmax_value
)
916 (void)printf("%*u ", (int)ilen
,
917 sensor
->warnmin_value
);
921 if (sensor
->critmax_value
) {
923 sensor
->critmax_value
);
927 if (sensor
->critmin_value
) {
928 if (sensor
->critmax_value
)
932 (void)printf("%*u ", (int)ilen
,
933 sensor
->critmin_value
);
938 (void)printf("%*s", (int)ilen
, stype
);
941 } else if (strcmp(sensor
->type
, "Integer") == 0) {
943 (void)printf(": %10d", sensor
->cur_value
);
946 } else if (strcmp(sensor
->type
, "Drive") == 0) {
948 (void)printf(": %10s", sensor
->drvstate
);
950 /* Battery capacity */
951 } else if (strcmp(sensor
->type
, "Battery capacity") == 0) {
953 (void)printf(": %10s", sensor
->battcap
);
955 /* everything else */
957 if (strcmp(sensor
->type
, "Voltage DC") == 0)
959 else if (strcmp(sensor
->type
, "Voltage AC") == 0)
961 else if (strcmp(sensor
->type
, "Ampere") == 0)
963 else if (strcmp(sensor
->type
, "Watts") == 0)
965 else if (strcmp(sensor
->type
, "Ohms") == 0)
967 else if (strcmp(sensor
->type
, "Watt hour") == 0)
969 else if (strcmp(sensor
->type
, "Ampere hour") == 0)
972 (void)printf(": %10.3f ",
973 sensor
->cur_value
/ 1000000.0);
976 if (flags
& ENVSYS_WFLAG
) {
977 if (sensor
->warnmax_value
) {
978 (void)printf("%8.3f ",
979 sensor
->warnmax_value
/ 1000000.0);
983 if (sensor
->warnmin_value
) {
984 if (sensor
->warnmax_value
)
988 (void)printf("%*.3f ", (int)ilen
,
989 sensor
->warnmin_value
/ 1000000.0);
992 if (sensor
->warncap_value
) {
994 (void)printf("%*.2f%% ", (int)ilen
,
995 (sensor
->warncap_value
* 100.0) /
1000 if (sensor
->critmax_value
) {
1001 (void)printf("%8.3f ",
1002 sensor
->critmax_value
/ 1000000.0);
1006 if (sensor
->critmin_value
) {
1007 if (sensor
->critmax_value
)
1011 (void)printf("%*.3f ", (int)ilen
,
1012 sensor
->critmin_value
/ 1000000.0);
1017 if (sensor
->critcap_value
) {
1019 (void)printf("%*.2f%% ", (int)ilen
,
1020 (sensor
->critcap_value
* 100.0) /
1027 if (statistics
&& !sensor
->percentage
) {
1028 /* show statistics if flag set */
1029 (void)printf("%8.3f %8.3f %8.3f ",
1030 stats
->max
/ 1000000.0,
1031 stats
->min
/ 1000000.0,
1032 stats
->avg
/ 1000000.0);
1036 (void)printf("%*s", (int)ilen
, stype
);
1037 if (sensor
->percentage
&& sensor
->max_value
) {
1038 (void)printf(" (%5.2f%%)",
1039 (sensor
->cur_value
* 100.0) /
1051 (void)fprintf(stderr
, "Usage: %s [-DfIklrSTx] ", getprogname());
1052 (void)fprintf(stderr
, "[-c file] [-d device] [-i interval] ");
1053 (void)fprintf(stderr
, "[-s device:sensor,...] [-w width]\n");