summaryrefslogtreecommitdiff
path: root/usr.sbin/envstat
diff options
context:
space:
mode:
authorgroo <groo@NetBSD.org>2000-03-10 05:51:56 +0000
committergroo <groo@NetBSD.org>2000-03-10 05:51:56 +0000
commit38cfdfd8fc82fe3e90cea77f719de8fd7b005755 (patch)
tree416c05a24b8896adbc3bc984657cc44a598d06b5 /usr.sbin/envstat
parentcf32e2713c5a19d6b82c2c3e11f612352ecddb2f (diff)
Add envstat(8) for displaying sensor readings from any envsys(4)
compatible device.
Diffstat (limited to 'usr.sbin/envstat')
-rw-r--r--usr.sbin/envstat/Makefile7
-rw-r--r--usr.sbin/envstat/envstat.8101
-rw-r--r--usr.sbin/envstat/envstat.c462
3 files changed, 570 insertions, 0 deletions
diff --git a/usr.sbin/envstat/Makefile b/usr.sbin/envstat/Makefile
new file mode 100644
index 00000000000..7bba8ba5498
--- /dev/null
+++ b/usr.sbin/envstat/Makefile
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile,v 1.1 2000/03/10 05:51:57 groo Exp $
+# @(#)Makefile 8.1 (Berkeley) 6/6/93
+
+PROG= envstat
+MAN= envstat.8
+
+.include <bsd.prog.mk>
diff --git a/usr.sbin/envstat/envstat.8 b/usr.sbin/envstat/envstat.8
new file mode 100644
index 00000000000..e076bacf227
--- /dev/null
+++ b/usr.sbin/envstat/envstat.8
@@ -0,0 +1,101 @@
+.\" $NetBSD: envstat.8,v 1.1 2000/03/10 05:51:58 groo Exp $
+.\"
+.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Bill Squier.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the NetBSD
+.\" Foundation, Inc. and its contributors.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.Dd March 8, 2000
+.Dt ENVSTAT 8
+.Os
+.Sh NAME
+.Nm envstat
+.Nd display environmental sensor readings
+.Sh SYNOPSIS
+.Nm
+.Op Fl fl
+.Op Fl i Ar interval
+.Op Fl n Ar headrep
+.Op Fl s Ar sensor1,sensor2,...
+.Op Fl w Ar width
+.Ar device
+.Sh DESCRIPTION
+.Nm
+displays sensor readings from any device which supports the
+.Xr envsys 4
+API. Readings are displayed in columns, one column per sensor. Column
+widths as well as displayed sensors are fully customizable. The column
+headers display the name (stored in the device driver) as well as
+the units of each sensor.
+.Pp
+The options are as follows:
+.Bl -tag -width flag
+.It Fl f
+Display any temperature values in degrees Fahrenheit. The default is to
+display temperature values in degrees Celsius.
+.It Fl l
+List the names of all supported sensors, one per line. Use of this
+flag causes
+.Nm
+to ignore all other option flags.
+.It Fl i
+Repeat the display every
+.Ar interval
+seconds. Note that some devices do not provide fresh values on demand.
+See the individual device's manual page for meaningful values for
+.Ar interval .
+If not specified, or specified as 0,
+.Nm
+produces one line of values and exits.
+.It Fl n
+Display a new header every
+.Ar headrep
+lines. An argument of 0 disables header line printing completely.
+The default is every 22 lines.
+.It Fl s
+Restrict the display to the named sensors. The sensor names must be
+supplied as a comma separated list. Sensor names are case sensitive.
+.It Fl w
+Use
+.Ar width
+as the column width for the output. Each column is additionally separated
+by a single space. The default is either the length of the longest sensor
+name or spread evenly to fill 80 columns, whichever is greater.
+.El
+.Sh SEE ALSO
+.Xr envsys 4 ,
+.Xr lm 4
+.Sh HISTORY
+.Nm
+appeared in
+.Nx 1.5 .
+
diff --git a/usr.sbin/envstat/envstat.c b/usr.sbin/envstat/envstat.c
new file mode 100644
index 00000000000..9805ae997b8
--- /dev/null
+++ b/usr.sbin/envstat/envstat.c
@@ -0,0 +1,462 @@
+/* $NetBSD: envstat.c,v 1.1 2000/03/10 05:51:58 groo Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Bill Squier.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__RCSID("$NetBSD: envstat.c,v 1.1 2000/03/10 05:51:58 groo Exp $");
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/envsys.h>
+#include <sys/ioctl.h>
+
+extern char *__progname;
+const char E_CANTENUM[] = "envsys: cannot enumerate sensors\n";
+
+int main __P((int, char **));
+void listsensors __P((envsys_basic_info_t *, int));
+int numsensors __P((int));
+int fillsensors __P((int, envsys_tre_data_t *, envsys_basic_info_t *, int));
+int longestname __P((envsys_basic_info_t *, int));
+int marksensors __P((envsys_basic_info_t *, int *, char *, int));
+int strtosnum __P((envsys_basic_info_t *, const char *, int));
+void header __P((unsigned, int, envsys_basic_info_t *, const int * const,
+ int));
+void values __P((unsigned, int, envsys_tre_data_t *, const int * const, int));
+void usage __P((void));
+
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ extern int optind;
+ extern char *optarg;
+ int c, fd, ns, ls, celsius;
+ unsigned int interval, width, headrep, headcnt;
+ envsys_tre_data_t *etds;
+ envsys_basic_info_t *ebis;
+ int *cetds;
+ char *sensors;
+
+ fd = -1;
+ ls = 0;
+ celsius = 1;
+ interval = 0;
+ width = 0;
+ sensors = NULL;
+ headrep = 22;
+
+ while ((c = getopt(argc, argv, "cfi:ln:s:w:")) != -1) {
+ switch(c) {
+ case 'i': /* wait time between displays */
+ interval = atoi(optarg);
+ break;
+ case 'w': /* minimum column width */
+ width = atoi(optarg);
+ break;
+ case 'l': /* list sensor names */
+ ls = 1;
+ break;
+ case 'n': /* repeat header every headrep lines */
+ headrep = atoi(optarg);
+ break;
+ case 's': /* restrict display to named sensors */
+ sensors = (char *)malloc(strlen(optarg) + 1);
+ if (sensors == NULL)
+ exit(1);
+ strcpy(sensors, optarg);
+ break;
+ case 'f': /* display temp in degF */
+ celsius = 0;
+ break;
+ case '?':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (optind < argc) {
+ if ((fd = open(argv[optind], O_RDONLY)) == -1) {
+ perror("envstat");
+ exit(1);
+ }
+ } else {
+ fprintf(stderr, "envstat: no device specified\n");
+ usage();
+ }
+
+
+ /*
+ * Determine number of sensors, allocate and fill arrays with
+ * initial information. Determine column width
+ */
+ if ((ns = numsensors(fd)) <= 0) {
+ fprintf(stderr, E_CANTENUM);
+ exit(1);
+ }
+
+ cetds = (int *)malloc(ns * sizeof(int));
+ etds = (envsys_tre_data_t *)malloc(ns * sizeof(envsys_tre_data_t));
+ ebis = (envsys_basic_info_t *)malloc(ns * sizeof(envsys_basic_info_t));
+
+ if ((cetds == NULL) || (etds == NULL) || (ebis == NULL)) {
+ fprintf(stderr, "envstat: cannot allocate memory\n");
+ exit(1);
+ }
+
+ if (fillsensors(fd, etds, ebis, ns) == -1) {
+ fprintf(stderr, E_CANTENUM);
+ exit(1);
+ }
+
+
+ if (ls) {
+ listsensors(ebis, ns);
+ exit(0);
+ }
+
+
+#define MAX(x, y) (((x) > (y)) ? (x) : (y))
+ if (!width) {
+ width = longestname(ebis, ns);
+ width = MAX(((79 - ns) / ns), width);
+ }
+
+ /* Mark which sensor numbers are to be displayed */
+ if (marksensors(ebis, cetds, sensors, ns) == -1)
+ exit(1);
+
+ /* If we didn't specify an interval value, print the sensors once */
+ if (!interval) {
+ if (headrep)
+ header(width, celsius, ebis, cetds, ns);
+ values(width, celsius, etds, cetds, ns);
+
+ exit (0);
+ }
+
+ headcnt = 0;
+ if (headrep)
+ header(width, celsius, ebis, cetds, ns);
+
+ for (;;) {
+ values(width, celsius, etds, cetds, ns);
+ if (headrep && (++headcnt == headrep)) {
+ headcnt = 0;
+ header(width, celsius, ebis, cetds, ns);
+ }
+
+ sleep(interval);
+
+ if (fillsensors(fd, etds, ebis, ns) == -1) {
+ fprintf(stderr, E_CANTENUM);
+ exit(1);
+ }
+ }
+
+ /* NOTREACHED */
+ return (0);
+}
+
+
+static const char *unit_str[] = {"degC", "RPM", "VAC", "Vcc", "Ohms", "Watts",
+ "Amps", "Ukn"};
+
+/*
+ * pre: cetds[i] != 0 iff sensor i should appear in the output
+ * post: a column header line is displayed on stdout
+ */
+void
+header(width, celsius, ebis, cetds, ns)
+ unsigned width;
+ int celsius;
+ envsys_basic_info_t *ebis;
+ const int * const cetds;
+ int ns;
+{
+ int i;
+ const char *s;
+
+ /* sensor names */
+ for (i = 0; i < ns; ++i)
+ if (cetds[i])
+ printf(" %*.*s", (int)width, (int)width, ebis[i].desc);
+
+ printf("\n");
+
+ /* units */
+ for (i = 0; i < ns; ++i)
+ if (cetds[i]) {
+ if ((ebis[i].units == ENVSYS_STEMP) &&
+ !celsius)
+ s = "degF";
+ else if (ebis[i].units > 6)
+ s = unit_str[7];
+ else
+ s = unit_str[ebis[i].units];
+
+ printf(" %*.*s", (int)width, (int)width, s);
+ }
+ printf("\n");
+}
+
+void
+values(width, celsius, etds, cetds, ns)
+ unsigned width;
+ int celsius;
+ envsys_tre_data_t *etds;
+ const int * const cetds;
+ int ns;
+{
+ int i;
+ double temp;
+
+ for (i = 0; i < ns; ++i)
+ if (cetds[i]) {
+
+ /* * sensors without valid data */
+ if ((etds[i].validflags & ENVSYS_FCURVALID) == 0) {
+ printf(" %*.*s", (int)width, (int)width, "*");
+ continue;
+ }
+
+ switch(etds[i].units) {
+ case ENVSYS_STEMP:
+ temp = (etds[i].cur.data_us / 1000000.0) -
+ 273.15;
+ if (!celsius)
+ temp = (9.0 / 5.0) * temp + 32.0;
+ printf(" %*.2f", width, temp);
+ break;
+ case ENVSYS_SFANRPM:
+ printf(" %*u", width, etds[i].cur.data_us);
+ break;
+ default:
+ printf(" %*.2f", width, etds[i].cur.data_s /
+ 1000000.0);
+ break;
+ }
+ }
+ printf("\n");
+}
+
+
+/*
+ * post: displays usage on stderr
+ */
+void
+usage()
+{
+ fprintf(stderr, "usage: %s [-c] [-s s1,s2,...]", __progname);
+ fprintf(stderr, " [-i interval] [-n headrep] [-w width] device\n");
+ fprintf(stderr, " envstat -l device\n");
+ exit(1);
+}
+
+
+/*
+ * post: a list of sensor names supported by the device is displayed on stdout
+ */
+void
+listsensors(ebis, ns)
+ envsys_basic_info_t *ebis;
+ int ns;
+{
+ int i;
+
+ for (i = 0; i < ns; ++i)
+ if (ebis[i].validflags & ENVSYS_FVALID)
+ printf("%s\n", ebis[i].desc);
+}
+
+
+/*
+ * pre: fd contains a valid file descriptor of an envsys(4) supporting device
+ * post: returns the number of valid sensors provided by the device
+ * or -1 on error
+ */
+int
+numsensors(fd)
+ int fd;
+{
+ int count = 0, valid = 1;
+ envsys_tre_data_t etd;
+ etd.sensor = 0;
+
+ while (valid) {
+ if (ioctl(fd, ENVSYS_GTREDATA, &etd) == -1) {
+ fprintf(stderr, E_CANTENUM);
+ exit(1);
+ }
+
+ valid = etd.validflags & ENVSYS_FVALID;
+ if (valid)
+ ++count;
+
+ ++etd.sensor;
+ }
+
+ return count;
+}
+
+/*
+ * pre: fd contains a valid file descriptor of an envsys(4) supporting device
+ * && ns is the number of sensors
+ * && etds and ebis are arrays of sufficient size
+ * post: returns 0 and etds and ebis arrays are filled with sensor info
+ * or returns -1 on failure
+ */
+int
+fillsensors(fd, etds, ebis, ns)
+ int fd;
+ envsys_tre_data_t *etds;
+ envsys_basic_info_t *ebis;
+ int ns;
+{
+ int i;
+
+ for (i = 0; i < ns; ++i) {
+ ebis[i].sensor = i;
+ if (ioctl(fd, ENVSYS_GTREINFO, &ebis[i]) == -1)
+ return -1;
+
+ etds[i].sensor = i;
+ if (ioctl(fd, ENVSYS_GTREDATA, &etds[i]) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*
+ * post: returns the strlen() of the longest sensor name
+ */
+int
+longestname(ebis, ns)
+ envsys_basic_info_t *ebis;
+ int ns;
+{
+ int i, maxlen, cur;
+
+ maxlen = 0;
+
+ for (i = 0; i < ns; ++i) {
+ cur = strlen(ebis[i].desc);
+ if (cur > maxlen)
+ maxlen = cur;
+ }
+
+ return maxlen;
+}
+
+/*
+ * post: returns 0 and cetds[i] != 0 iff sensor i should appear in the output
+ * or returns -1
+ */
+int
+marksensors(ebis, cetds, sensors, ns)
+ envsys_basic_info_t *ebis;
+ int *cetds;
+ char *sensors;
+ int ns;
+{
+ int i;
+ char *s;
+
+ if (sensors == NULL) {
+ /* No sensors specified, include them all */
+ for (i = 0; i < ns; ++i)
+ cetds[i] = 1;
+
+ return 0;
+ }
+
+ /* Assume no sensors in display */
+ memset(cetds, 0, ns * sizeof(int));
+
+ s = strtok(sensors, ",");
+ while (s != NULL) {
+ if ((i = strtosnum(ebis, s, ns)) != -1)
+ cetds[i] = 1;
+ else {
+ fprintf(stderr, "envstat: unknown sensor %s\n", s);
+ return (-1);
+ }
+
+ s = strtok(NULL, ",");
+ }
+
+ /* Check if we have at least one sensor selected for output */
+ for (i = 0; i < ns; ++i)
+ if (cetds[i] == 1)
+ return (0);
+
+ fprintf(stderr, "envstat: no sensors selected for display\n");
+ return (-1);
+}
+
+
+/*
+ * returns -1 if s is not a valid sensor name for the device
+ * or the sensor number of a sensor which has that name
+ */
+int
+strtosnum(ebis, s, ns)
+ envsys_basic_info_t *ebis;
+ const char *s;
+ int ns;
+{
+ int i;
+
+ for (i = 0; i < ns; ++i) {
+ if((ebis[i].validflags & ENVSYS_FVALID) &&
+ !strcmp(s, ebis[i].desc))
+ return ebis[i].sensor;
+ }
+
+ return -1;
+}