Browse Source

Add ./tarball_archive/symon-2.83.tar.gz

Wictor Lund 3 years ago
parent
commit
5c0c6e87b4

+ 13 - 2
symon/CHANGELOG

@@ -1,3 +1,14 @@
+01/05/2011 - 2.83
+
+   - Added flukso probe
+
+   - platform/OpenBSD/sm_io.c updated to support uids (Stuart Henderson)
+
+   - platform/Linux/sm_df.c checks if /etc/mtab could be openend (Lars Kotthoff)
+
+   - platform/Linux: Support diskname by id, label, path or uuid for smart, io
+     and df probes.
+
 15/06/2010 - 2.82
 15/06/2010 - 2.82
 
 
    - platform/OpenBSD/sm_sensor.c define MAXSENSORSDEVICES (Stuart Henderson)
    - platform/OpenBSD/sm_sensor.c define MAXSENSORSDEVICES (Stuart Henderson)
@@ -14,8 +25,8 @@
    - Smart probe assumed that its ioctl cmd structure was not overwritten and
    - Smart probe assumed that its ioctl cmd structure was not overwritten and
      did not check the return code correctly on NetBSD. (Tito Dal Canton)
      did not check the return code correctly on NetBSD. (Tito Dal Canton)
 
 
-   - sm_smart.c: support for kernels 2.6.9 and friends that miss the required
-     hdio structure.
+   - platform/Linux/sm_smart.c: support for kernels 2.6.9 and friends that miss
+     the required hdio structure.
 
 
    - c_smrrds.sh: Allow more than 10 cpus.
    - c_smrrds.sh: Allow more than 10 cpus.
 
 

+ 1 - 5
symon/Makefile.inc

@@ -1,12 +1,8 @@
-V=2.82
+V=2.83
 
 
 AR?=	ar
 AR?=	ar
 CC?=	cc
 CC?=	cc
-.ifdef DEBUG
-CFLAGS=-g -Wall
-.else
 CFLAGS+=-Wall
 CFLAGS+=-Wall
-.endif
 INSTALL?=install
 INSTALL?=install
 LORDER?=lorder
 LORDER?=lorder
 TSORT?=tsort
 TSORT?=tsort

+ 2 - 0
symon/lib/data.c

@@ -112,6 +112,7 @@ struct {
     { MT_CPUIOW, "cccccc" },
     { MT_CPUIOW, "cccccc" },
     { MT_SMART, "bbbbbbbbbbbb" },
     { MT_SMART, "bbbbbbbbbbbb" },
     { MT_LOAD, "ccc" },
     { MT_LOAD, "ccc" },
+    { MT_FLUKSO, "D" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_EOT, "" }
     { MT_EOT, "" }
 };
 };
@@ -137,6 +138,7 @@ struct {
     { MT_CPUIOW, LXT_CPUIOW },
     { MT_CPUIOW, LXT_CPUIOW },
     { MT_SMART, LXT_SMART },
     { MT_SMART, LXT_SMART },
     { MT_LOAD, LXT_LOAD },
     { MT_LOAD, LXT_LOAD },
+    { MT_FLUKSO, LXT_FLUKSO },
     { MT_EOT, LXT_BADTOKEN }
     { MT_EOT, LXT_BADTOKEN }
 };
 };
 /* parallel crc32 table */
 /* parallel crc32 table */

+ 6 - 2
symon/lib/data.h

@@ -163,8 +163,9 @@ SLIST_HEAD(muxlist, mux);
 #define MT_CPUIOW 14
 #define MT_CPUIOW 14
 #define MT_SMART  15
 #define MT_SMART  15
 #define MT_LOAD   16
 #define MT_LOAD   16
-#define MT_TEST   17
-#define MT_EOT    18
+#define MT_FLUKSO 17
+#define MT_TEST   18
+#define MT_EOT    19
 
 
 /*
 /*
  * Unpacking of incoming packets is done via a packedstream structure. This
  * Unpacking of incoming packets is done via a packedstream structure. This
@@ -350,6 +351,9 @@ struct packedstream {
             u_int16_t mload2;
             u_int16_t mload2;
             u_int16_t mload3;
             u_int16_t mload3;
         }      ps_load;
         }      ps_load;
+        struct {
+            int64_t value;
+        }      ps_flukso;
     }     data;
     }     data;
 };
 };
 
 

+ 1 - 0
symon/lib/lex.c

@@ -74,6 +74,7 @@ static struct {
     { "debug", LXT_DEBUG },
     { "debug", LXT_DEBUG },
     { "df", LXT_DF },
     { "df", LXT_DF },
     { "every", LXT_EVERY },
     { "every", LXT_EVERY },
+    { "flukso", LXT_FLUKSO },
     { "from", LXT_FROM },
     { "from", LXT_FROM },
     { "if", LXT_IF },
     { "if", LXT_IF },
     { "if1", LXT_IF1 },
     { "if1", LXT_IF1 },

+ 26 - 25
symon/lib/lex.h

@@ -53,31 +53,32 @@
 #define LXT_DF         9
 #define LXT_DF         9
 #define LXT_END       10
 #define LXT_END       10
 #define LXT_EVERY     11
 #define LXT_EVERY     11
-#define LXT_FROM      12
-#define LXT_IF        13
-#define LXT_IF1       14
-#define LXT_IN        15
-#define LXT_IO        16
-#define LXT_IO1       17
-#define LXT_LOAD      18
-#define LXT_MBUF      19
-#define LXT_MEM       20
-#define LXT_MEM1      21
-#define LXT_MONITOR   22
-#define LXT_MUX       23
-#define LXT_OPEN      24
-#define LXT_PF        25
-#define LXT_PFQ       26
-#define LXT_PORT      27
-#define LXT_PROC      28
-#define LXT_SECOND    29
-#define LXT_SECONDS   30
-#define LXT_SENSOR    31
-#define LXT_SMART     32
-#define LXT_SOURCE    33
-#define LXT_STREAM    34
-#define LXT_TO        35
-#define LXT_WRITE     36
+#define LXT_FLUKSO    12
+#define LXT_FROM      13
+#define LXT_IF        14
+#define LXT_IF1       15
+#define LXT_IN        16
+#define LXT_IO        17
+#define LXT_IO1       18
+#define LXT_LOAD      19
+#define LXT_MBUF      20
+#define LXT_MEM       21
+#define LXT_MEM1      22
+#define LXT_MONITOR   23
+#define LXT_MUX       24
+#define LXT_OPEN      25
+#define LXT_PF        26
+#define LXT_PFQ       27
+#define LXT_PORT      28
+#define LXT_PROC      29
+#define LXT_SECOND    30
+#define LXT_SECONDS   31
+#define LXT_SENSOR    32
+#define LXT_SMART     33
+#define LXT_SOURCE    34
+#define LXT_STREAM    35
+#define LXT_TO        36
+#define LXT_WRITE     37
 
 
 struct lex {
 struct lex {
     char *buffer;               /* current line(s) */
     char *buffer;               /* current line(s) */

+ 2 - 0
symon/platform/Linux/Makefile.inc

@@ -8,3 +8,5 @@ BINDIR?=bin
 INSTALLUSER?=root
 INSTALLUSER?=root
 INSTALLGROUPFILE?=bin
 INSTALLGROUPFILE?=bin
 INSTALLGROUPDIR?=bin
 INSTALLGROUPDIR?=bin
+
+PLATFORM_SRC=diskbyname.c

+ 120 - 0
symon/platform/Linux/diskbyname.c

@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2011 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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/stat.h>
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+
+#include "error.h"
+#include "platform.h"
+
+/*
+ * checkdisk(spath, dpath, maxlen)
+ *
+ * Determine that <spath> exists, and return the device name that was referenced
+ * (/dev/sdx) when <spath> is a link in <dpath>, observing <dpath>'s <maxlen>.
+ */
+static size_t
+checkdisk(const char *spath, char *dpath, size_t maxlen)
+{
+    char diskname[MAX_PATH_LEN];
+    char *r;
+    struct stat buffer;
+    size_t result;
+
+    bzero(diskname, MAX_PATH_LEN);
+    bzero(&buffer, sizeof(struct stat));
+
+    if (lstat(spath, &buffer)) {
+        return 0;
+    }
+
+    if (S_ISLNK(buffer.st_mode)) {
+        if ((r = realpath(spath, NULL))) {
+            strlcpy(diskname, r, sizeof(diskname));
+            free(r);
+        }
+        bzero(&buffer, sizeof(struct stat));
+        if (lstat(diskname, &buffer)) {
+            fatal("diskbyname: '%.200s' = '%.200s' cannot be examined: %.200s", spath, diskname, strerror(errno));
+        }
+    } else
+        strlcpy(diskname, spath, sizeof(diskname));
+
+    if (S_ISBLK(buffer.st_mode) && !S_ISLNK(buffer.st_mode)) {
+        result = strlcpy(dpath, diskname, maxlen);
+        return result;
+    }
+
+    return 0;
+}
+
+/*
+ * diskbyname(spath, dpath, maxlen)
+ *
+ * Resolve a logical disk name <spath> to it's block device name
+ * <dpath>. <dpath> is preallocated and can hold <maxlen> characters. <spath>
+ * can refer to a disk via 1) an absolute path or 2) a diskname relative to
+ * /dev, or 3) a diskname relative to the /dev/disk/by-* directories.
+ */
+size_t
+diskbyname(const char *spath, char *dpath, size_t maxlen)
+{
+    char diskname[MAX_PATH_LEN];
+    size_t size;
+    char *l[] = {
+        "/dev/%s",
+        "/dev/disk/by-id/%s",
+        "/dev/disk/by-label/%s",
+        "/dev/disk/by-uuid/%s",
+        "/dev/disk/by-path/%s",
+        NULL
+    };
+    int i;
+
+    if (spath == NULL)
+        return 0;
+
+    if (strchr(spath, '/'))
+        return checkdisk(spath, dpath, maxlen);
+
+    for (i = 0; l[i] != NULL; i++) {
+        bzero(diskname, sizeof(diskname));
+        snprintf(diskname, sizeof(diskname), l[i], spath);
+        if ((size = checkdisk(diskname, dpath, maxlen)))
+            return size;
+    }
+
+    return 0;
+}

+ 11 - 0
symon/platform/Linux/platform.h

@@ -5,6 +5,12 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <grp.h>
 #include <grp.h>
 
 
+/* uclibc snprintf is redefined between stdio.h and string.h */
+#include <features.h>
+#ifdef __UCLIBC_MAJOR__
+#undef __USE_BSD
+#endif
+
 #include "queue.h"
 #include "queue.h"
 #include "sylimits.h"
 #include "sylimits.h"
 
 
@@ -65,6 +71,11 @@ union stream_parg {
         char path[MAX_PATH_LEN];
         char path[MAX_PATH_LEN];
     } sn;
     } sn;
     int smart;
     int smart;
+    char flukso[MAX_PATH_LEN];
+    char io[MAX_PATH_LEN];
 };
 };
 
 
+extern size_t
+diskbyname(const char *spath, char *dpath, size_t maxlen);
+
 #endif
 #endif

+ 19 - 11
symon/platform/Linux/sm_df.c

@@ -1,4 +1,5 @@
 /*
 /*
+ * Copyright (c) 2011 Willem Dijkstra
  * Copyright (c) 2007 Martin van der Werff
  * Copyright (c) 2007 Martin van der Werff
  * All rights reserved.
  * All rights reserved.
  *
  *
@@ -37,6 +38,7 @@
 
 
 
 
 #include <sys/types.h>
 #include <sys/types.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <mntent.h>
 #include <mntent.h>
 #include <string.h>
 #include <string.h>
@@ -49,25 +51,31 @@
 void
 void
 init_df(struct stream *st)
 init_df(struct stream *st)
 {
 {
+    char drivename[MAX_PATH_LEN];
     FILE * fp = setmntent("/etc/mtab", "r");
     FILE * fp = setmntent("/etc/mtab", "r");
     struct mntent *mount;
     struct mntent *mount;
 
 
+    if (fp == NULL)
+        fatal("df: cannot access /etc/mtab: %.200s", strerror(errno));
+
+    if (st->arg == NULL)
+        fatal("df: need a <disk device|name> argument");
+
+    if ((diskbyname(st->arg, drivename, sizeof(drivename)) == 0))
+        fatal("df: '%.200s' is not a disk device", st->arg);
+
     while ((mount = getmntent(fp))) {
     while ((mount = getmntent(fp))) {
-	if (strncmp(mount->mnt_fsname, "/dev/", 5) == 0) {
-            if (strcmp(mount->mnt_fsname + 5, st->arg) == 0) {
-                strlcpy(st->parg.df.mountpath, mount->mnt_dir, sizeof(st->parg.df.mountpath));
-                info("started module df(%.200s) --> %.200s", st->arg, st->parg.df.mountpath);
-                endmntent(fp);
-		return;
-            }
-	}
+	if (strncmp(mount->mnt_fsname, drivename, sizeof(drivename)) == 0) {
+            strlcpy(st->parg.df.mountpath, mount->mnt_dir, sizeof(st->parg.df.mountpath));
+            info("started module df(%.200s = %.200s)", st->arg, st->parg.df.mountpath);
+            endmntent(fp);
+            return;
+        }
     }
     }
 
 
     endmntent(fp);
     endmntent(fp);
 
 
-    strlcpy(st->parg.df.mountpath, "/", sizeof(st->parg.df.mountpath));
-
-    info("failed to find (%.200s) - started module df for /", st->arg);
+    fatal("df(.200s): not mounted", st->arg);
 }
 }
 
 
 void
 void

+ 179 - 0
symon/platform/Linux/sm_flukso.c

@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2010 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT HOLDERS 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.
+ *
+ */
+
+/*
+ * Get measurement data from a flukso (arduino) board tied to the serial port.
+ *
+ * num : value
+ *
+ */
+
+#include "conf.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <string.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <strings.h>
+
+#include "error.h"
+#include "symon.h"
+#include "xmalloc.h"
+
+#define FLUKSO_MAXSENSORS 3
+#define FLUKSO_IDLEN 32
+#define SCN(x) #x
+
+static int flukso_fd = -1;
+static void *flukso_buf = NULL;
+static int flukso_size = 0;
+static int flukso_maxsize = 0;
+static int flukso_nrsensors = 0;
+
+struct flukso_sensor {
+    char id[FLUKSO_IDLEN];
+    uint64_t value;
+    uint64_t n;
+};
+struct flukso_sensor flukso_sensor[FLUKSO_MAXSENSORS];
+
+void
+init_flukso(struct stream *st)
+{
+    struct termios tio;
+
+    bzero(flukso_sensor, sizeof(struct flukso_sensor) * FLUKSO_MAXSENSORS);
+
+    if (flukso_buf == NULL) {
+        flukso_maxsize = SYMON_MAX_OBJSIZE;
+        flukso_buf = xmalloc(flukso_maxsize);
+    }
+
+    if (flukso_fd == -1) {
+        bzero(&tio, sizeof(tio));
+        tio.c_iflag = tio.c_oflag = tio.c_lflag = 0;
+        tio.c_cflag = CS8 | CREAD | CLOCAL;
+        tio.c_cc[VMIN] = 1;
+        tio.c_cc[VTIME] = 5;
+        if ((flukso_fd = open("/dev/ttyS0", O_RDONLY | O_NONBLOCK)) < 0)
+            fatal("flukso: could not open '%s' for read", "/dev/ttyS0");
+        cfsetispeed(&tio, B4800);
+        tcsetattr(flukso_fd, TCSANOW, &tio);
+    }
+
+    if (flukso_size == 0)
+        gets_flukso();
+
+    if (st->arg != NULL &&
+        FLUKSO_IDLEN == strspn(st->arg, "0123456789abcdef")) {
+        bcopy(st->arg, st->parg.flukso, FLUKSO_IDLEN);
+        info("started module flukso(%.200s)", st->arg);
+    } else {
+        fatal("flukso: could not parse sensor name %.200s", st->arg);
+    }
+}
+
+void
+gets_flukso()
+{
+    int len = 0;
+    int p = 0;
+    int i;
+    void *nl;
+    uint32_t value;
+    char id[FLUKSO_IDLEN];
+
+    if ((len = read(flukso_fd, flukso_buf + flukso_size, flukso_maxsize - flukso_size)) < 0) {
+        warning("flukso: cannot read data");
+        return;
+    }
+
+    flukso_size += len;
+
+    /* We read the pwr messages rather than the pls pulse messages as we are
+     * interested in the current load only */
+    while ((p < flukso_size) &&
+           ((nl = memchr(flukso_buf + p, '\n', flukso_size - p)) != NULL)) {
+        len = nl - (flukso_buf + p) + 1;
+
+        if (2 > sscanf(flukso_buf + p, "pwr %32s:%" SCNu32 "\n", &id[0], &value)) {
+            p += len;
+            continue;
+        }
+
+        for (i = 0; i < flukso_nrsensors; i++) {
+            if (strncmp(flukso_sensor[i].id, id, FLUKSO_IDLEN) == 0) {
+                flukso_sensor[i].value += value;
+                flukso_sensor[i].n++;
+                break;
+            }
+        }
+
+        if ((i == flukso_nrsensors) && (flukso_nrsensors < FLUKSO_MAXSENSORS)) {
+            bcopy(id, flukso_sensor[i].id, FLUKSO_IDLEN);
+            flukso_sensor[i].value = value;
+            flukso_sensor[i].n = 1;
+            flukso_nrsensors++;
+        }
+
+        p += len;
+    }
+
+    if (p < flukso_size) {
+        bcopy(flukso_buf + p, flukso_buf, flukso_size - p);
+        flukso_size -= p;
+    } else {
+        flukso_size = 0;
+    }
+}
+
+int
+get_flukso(char *symon_buf, int maxlen, struct stream *st)
+{
+    int i;
+    double avgwatts;
+
+    for (i = 0; i < flukso_nrsensors; i++) {
+        if (strncmp(st->parg.flukso, flukso_sensor[i].id, FLUKSO_IDLEN) == 0) {
+            avgwatts = (double) flukso_sensor[i].value / (double) flukso_sensor[i].n;
+            flukso_sensor[i].value = 0;
+            flukso_sensor[i].n = 0;
+
+            return snpack(symon_buf, maxlen, st->arg, MT_FLUKSO, avgwatts);
+        }
+    }
+
+    return 0;
+}

+ 21 - 5
symon/platform/Linux/sm_io.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2006 Willem Dijkstra
+ * Copyright (c) 2001-2011 Willem Dijkstra
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -80,12 +80,28 @@ char *io_filename = "/proc/partitions";
 void
 void
 init_io(struct stream *st)
 init_io(struct stream *st)
 {
 {
+    size_t lead;
+
     if (io_buf == NULL) {
     if (io_buf == NULL) {
         io_maxsize = SYMON_MAX_OBJSIZE;
         io_maxsize = SYMON_MAX_OBJSIZE;
         io_buf = xmalloc(io_maxsize);
         io_buf = xmalloc(io_maxsize);
     }
     }
 
 
-    info("started module io(%.200s)", st->arg);
+    if (st->arg == NULL)
+        fatal("io: need a <device>|<devicename> argument");
+
+    if ((diskbyname(st->arg, &st->parg.io[0], MAX_PATH_LEN) == 0))
+        fatal("io: '%.200s' is not a <device>|<devicename>", st->arg);
+
+    /* devices are named sdX, not /dev/sdX */
+    lead = sizeof("/dev/") - 1;
+    if (strncmp(st->parg.io, "/dev/", lead) == 0)
+        memmove(&st->parg.io[0], &st->parg.io[0] + lead, sizeof(st->parg.io) - lead);
+
+    if (strcmp(st->arg, st->parg.io) == 0)
+        info("started module io(%.200s)", st->parg.io);
+    else
+        info("started module io(%.200s = %.200s)", st->arg, st->parg.io);
 }
 }
 
 
 void
 void
@@ -128,12 +144,12 @@ get_io(char *symon_buf, int maxlen, struct stream *st)
         return 0;
         return 0;
     }
     }
 
 
-    if ((line = strstr(io_buf, st->arg)) == NULL) {
-        warning("could not find disk %s", st->arg);
+    if ((line = strstr(io_buf, st->parg.io)) == NULL) {
+        warning("could not find disk %.200s = %.200s", st->arg, st->parg.io);
         return 0;
         return 0;
     }
     }
 
 
-    line += strlen(st->arg);
+    line += strlen(st->parg.io);
     bzero(&stats, sizeof(struct io_device_stats));
     bzero(&stats, sizeof(struct io_device_stats));
 
 
     if (11 > sscanf(line, " %" SCNu64 " %" SCNu64
     if (11 > sscanf(line, " %" SCNu64 " %" SCNu64

+ 10 - 14
symon/platform/Linux/sm_smart.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2008-2009 Willem Dijkstra
+ * Copyright (c) 2008-2011 Willem Dijkstra
  * All rights reserved.
  * All rights reserved.
  *
  *
  * Redistribution and use in source and binary forms, with or without
  * Redistribution and use in source and binary forms, with or without
@@ -92,16 +92,15 @@ init_smart(struct stream *st)
         fatal("smart: internal error: smart values structure is broken");
         fatal("smart: internal error: smart values structure is broken");
     }
     }
 
 
-    if (st->arg == NULL) {
-        fatal("smart: need a <device> argument");
-    }
+    if (st->arg == NULL)
+        fatal("smart: need a <disk device|name> argument");
 
 
-    bzero(drivename, MAX_PATH_LEN);
-    snprintf(drivename, MAX_PATH_LEN, "/dev/%s", st->arg);
+    if ((diskbyname(st->arg, drivename, sizeof(drivename)) == 0))
+        fatal("smart: '%.200s' is not a disk device", st->arg);
 
 
     /* look for drive in our global table */
     /* look for drive in our global table */
     for (i = 0; i < smart_cur; i++) {
     for (i = 0; i < smart_cur; i++) {
-        if (strncmp(smart_devs[i].name, drivename, MAX_PATH_LEN) == 0) {
+        if (strncmp(smart_devs[i].name, drivename, sizeof(drivename)) == 0) {
             st->parg.smart = i;
             st->parg.smart = i;
             return;
             return;
         }
         }
@@ -118,21 +117,18 @@ init_smart(struct stream *st)
     bzero(&smart_devs[smart_cur], sizeof(struct smart_device));
     bzero(&smart_devs[smart_cur], sizeof(struct smart_device));
 
 
     /* store drivename in new block */
     /* store drivename in new block */
-    snprintf(smart_devs[smart_cur].name, MAX_PATH_LEN, "%s", drivename);
+    strlcpy(smart_devs[smart_cur].name, drivename, sizeof(smart_devs[0].name));
 
 
     /* store filedescriptor to device */
     /* store filedescriptor to device */
-    smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
-
-    if (errno) {
-        fatal("smart: could not open '%s' for read", drivename);
-    }
+    if ((smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK)) < 0)
+        fatal("smart: could not open '%.200s' for read: %.200s", drivename, strerror(errno));
 
 
     /* store smart dev entry in stream to facilitate quick get */
     /* store smart dev entry in stream to facilitate quick get */
     st->parg.smart = smart_cur;
     st->parg.smart = smart_cur;
 
 
     smart_cur++;
     smart_cur++;
 
 
-    info("started module smart(%.200s)", st->arg);
+    info("started module smart(%.200s = %.200s)", st->arg, smart_devs[st->parg.smart].name);
 }
 }
 
 
 void
 void

+ 1 - 0
symon/platform/OpenBSD/Makefile.inc

@@ -1,2 +1,3 @@
 SYMUX_LIBS?=-L/usr/X11R6/lib -lfontconfig
 SYMUX_LIBS?=-L/usr/X11R6/lib -lfontconfig
 MANDIR?=man
 MANDIR?=man
+NROFF!= (if [ -x /usr/bin/mandoc ]; then echo mandoc; else echo nroff; fi)

+ 11 - 1
symon/platform/OpenBSD/sm_io.c

@@ -51,6 +51,7 @@
 static char *io_dkstr = NULL;
 static char *io_dkstr = NULL;
 static struct diskstats *io_dkstats = NULL;
 static struct diskstats *io_dkstats = NULL;
 static char **io_dknames = NULL;
 static char **io_dknames = NULL;
+static char **io_dkuids = NULL;
 static int io_dks = 0;
 static int io_dks = 0;
 static int io_maxdks = 0;
 static int io_maxdks = 0;
 static size_t io_maxstr = 0;
 static size_t io_maxstr = 0;
@@ -98,6 +99,7 @@ gets_io()
 
 
         io_dkstats = xrealloc(io_dkstats, io_maxdks * sizeof(struct diskstats));
         io_dkstats = xrealloc(io_dkstats, io_maxdks * sizeof(struct diskstats));
         io_dknames = xrealloc(io_dknames, io_maxdks * sizeof(char *));
         io_dknames = xrealloc(io_dknames, io_maxdks * sizeof(char *));
+        io_dkuids = xrealloc(io_dkuids, io_maxdks * sizeof(char *));
         io_dkstr = xrealloc(io_dkstr, io_maxstr + 1);
         io_dkstr = xrealloc(io_dkstr, io_maxstr + 1);
     }
     }
 
 
@@ -128,7 +130,13 @@ gets_io()
             *p = '\0';
             *p = '\0';
             io_dks++; p++;
             io_dks++; p++;
             io_dknames[io_dks] = p;
             io_dknames[io_dks] = p;
+            io_dkuids[io_dks] = NULL;
         }
         }
+        if ((*p == ':') && (*p+1 != '\0')) {
+            *p = '\0';
+            p++;
+            io_dkuids[io_dks] = p;
+	}
         p++;
         p++;
     }
     }
 }
 }
@@ -146,8 +154,10 @@ get_io(char *symon_buf, int maxlen, struct stream *st)
 
 
     /* look for disk */
     /* look for disk */
     for (i = 0; i <= io_dks; i++) {
     for (i = 0; i <= io_dks; i++) {
-        if (strncmp(io_dknames[i], st->arg,
+        if ((strncmp(io_dknames[i], st->arg,
                     (io_dkstr + io_maxstr - io_dknames[i])) == 0)
                     (io_dkstr + io_maxstr - io_dknames[i])) == 0)
+        	    || (io_dkuids[i] && (strncmp(io_dkuids[i], st->arg,
+                    (io_dkstr + io_maxstr - io_dkuids[i])) == 0)))
 #ifdef HAS_IO2
 #ifdef HAS_IO2
             return snpack(symon_buf, maxlen, st->arg, MT_IO2,
             return snpack(symon_buf, maxlen, st->arg, MT_IO2,
                           io_dkstats[i].ds_rxfer,
                           io_dkstats[i].ds_rxfer,

+ 25 - 0
symon/platform/stub/sm_flukso.c

@@ -0,0 +1,25 @@
+#include <stdlib.h>
+
+#include "sylimits.h"
+#include "data.h"
+#include "error.h"
+
+void
+init_flukso(struct stream *st)
+{
+    fatal("flukso module not available");
+}
+
+void
+gets_flukso()
+{
+    fatal("flukso module not available");
+}
+
+int
+get_flukso(char *symon_buf, int maxlen, struct stream *st)
+{
+    fatal("flukso module not available");
+    /* NOT REACHED */
+    return 0;
+}

+ 3 - 1
symon/symon/Makefile

@@ -11,7 +11,9 @@ MODS!=	( for s in ../platform/stub/sm_*.c; do \
 		else                     echo $$s; \
 		else                     echo $$s; \
 		fi; fi; \
 		fi; fi; \
 	  done )
 	  done )
-SRCS=	symon.c readconf.c symonnet.c ${MODS}
+
+EXTRA_SRC=${PLATFORM_SRC:S,^,../platform/${OS}/,g}
+SRCS=	symon.c readconf.c symonnet.c ${MODS} ${EXTRA_SRC}
 OBJS+=	${SRCS:R:S/$/.o/g}
 OBJS+=	${SRCS:R:S/$/.o/g}
 CFLAGS+=-I../lib -I../platform/${OS} -I.
 CFLAGS+=-I../lib -I../platform/${OS} -I.
 
 

+ 2 - 1
symon/symon/readconf.c

@@ -116,6 +116,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_SENSOR:
         case LXT_SENSOR:
         case LXT_SMART:
         case LXT_SMART:
         case LXT_LOAD:
         case LXT_LOAD:
+        case LXT_FLUKSO:
             st = token2type(l->op);
             st = token2type(l->op);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -154,7 +155,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_COMMA:
         case LXT_COMMA:
             break;
             break;
         default:
         default:
-            parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|load|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart}");
+            parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|load|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load|flukso}");
             return 0;
             return 0;
             break;
             break;
         }
         }

+ 42 - 14
symon/symon/symon.8

@@ -27,7 +27,7 @@
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\"
-.Dd November 23, 2009
+.Dd October 20, 2010
 .Dt SYMON 8
 .Dt SYMON 8
 .Os
 .Os
 .Sh NAME
 .Sh NAME
@@ -99,46 +99,74 @@ resources should be monitored and to which
 .Xr symux 8
 .Xr symux 8
 the information should be streamed to.
 the information should be streamed to.
 .Pp
 .Pp
-Multiple monitor statements to different muxes are allowed. Whitespace,
-newlines and text behind '#' are ignored. The format in BNF:
+Multiple monitor statements are allowed. Whitespace, newlines and text
+behind '#' are ignored. The format in BNF:
 .Pp
 .Pp
-.nf
+.Bd -literal -offset indent -compact
 monitor-rule = "monitor" "{" resources "}" [every]
 monitor-rule = "monitor" "{" resources "}" [every]
                "stream" ["from" host] ["to"] host [ port ]
                "stream" ["from" host] ["to"] host [ port ]
 resources    = resource [ version ] ["(" argument ")"]
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " resources ]
                [ ","|" " resources ]
-resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io" |
-               "load" | "mbuf" | "mem" | "pf" | "pfq" | "proc" |
-               "sensor" | "smart"
+resource     = "cpu" | "cpuiow" | "debug" | "df" | "flukso" |
+               "if" | "io" | "load" | "mbuf" | "mem" | "pf" |
+               "pfq" | "proc" | "sensor" | "smart"
 version      = number
 version      = number
 argument     = number | name
 argument     = number | name
 every        = "every" time
 every        = "every" time
 time         = "second" | number "seconds"
 time         = "second" | number "seconds"
 host         = ip4addr | ip6addr | hostname
 host         = ip4addr | ip6addr | hostname
 port         = [ "port" | "," ] portnumber
 port         = [ "port" | "," ] portnumber
-.fi
+.Ed
 .Pp
 .Pp
 Note that symux(8) data files default to receiving data every 5
 Note that symux(8) data files default to receiving data every 5
-seconds. Adjusting the monitoring interval will also require adjusting every
-symux(8) datafile.
+seconds. Adjusting the monitoring interval will also require adjusting the
+associated symux(8) datafile(s).
 .Pp
 .Pp
 The pf probe will return data that is collected for the
 The pf probe will return data that is collected for the
 .Pa loginterface
 .Pa loginterface
 set in /etc/pf.conf(5).
 set in /etc/pf.conf(5).
+.Pp
+The Linux io, df, and smart probes support device names via id, label, path and uuid.
+.Pp
+The OpenBSD io probe supports device uuids.
+.Pp
 .Sh EXAMPLE
 .Sh EXAMPLE
-Here is an example
+Here is an example OpenBSD
 .Ar symon.conf
 .Ar symon.conf
 that monitors cpu, memory, pf, interfaces xl0/de0/lo0/wi0, disks
 that monitors cpu, memory, pf, interfaces xl0/de0/lo0/wi0, disks
 wd[0-3]/cd[0-1], debug variables debug0 to debug19 and streams that
 wd[0-3]/cd[0-1], debug variables debug0 to debug19 and streams that
 information to localhost on port 2100.
 information to localhost on port 2100.
 .Pp
 .Pp
-.nf
+.Bd -literal -offset indent -compact
 monitor { cpu(0),  mem, pf, if(xl0), if(de0),
 monitor { cpu(0),  mem, pf, if(xl0), if(de0),
 	  if(lo0), if(wi0), io(wd0), io(wd1),
 	  if(lo0), if(wi0), io(wd0), io(wd1),
 	  io(wd2), io(wd3), io(cd0), io(cd1),
 	  io(wd2), io(wd3), io(cd0), io(cd1),
 	  io(ccd0), df(sd0a), df(sd0d), df(sd0e),
 	  io(ccd0), df(sd0a), df(sd0d), df(sd0e),
 	  debug, proc(httpd) } stream to 127.0.0.1 2100
 	  debug, proc(httpd) } stream to 127.0.0.1 2100
-.fi
+.Ed
+.Sh EXAMPLE
+Here is an example Linux
+.Ar symon.conf
+that monitors cpu including iowait, memory, load, interface eth0, io and df for
+a set of disks every 5 seconds. Smart data is to be collected every 60 seconds.
+Disks in the smart and io statements are identified using ids, filesystem
+volumes in df using labels.
+.Bd -literal -offset indent -compact
+monitor { smart(ata-Hitachi_HDS722020ALA330_JK1130ABABABAB),
+          smart(ata-Hitachi_HDS722020ALA330_JK1130ACACACAC),
+        } every 60 seconds stream to 192.168.0.2 port 2100
+
+monitor { cpuiow(0), cpuiow(1), mem, if(eth0),
+          io(ata-Hitachi_HDS722020ALA330_JK1130ABABABAB),
+          io(ata-Hitachi_HDS722020ALA330_JK1130ACACACAC),
+          df(data_1),
+          df(data_2),
+          df(data_3),
+          df(home),
+          df(var),
+          load
+        } stream to 192.168.0.2 port 2100
+.Ed
 .Sh SIGNALS
 .Sh SIGNALS
 .Bl -tag -width Ds
 .Bl -tag -width Ds
 .It SIGHUP
 .It SIGHUP
@@ -171,7 +199,7 @@ The proc module is too simple: memory shared between two instances of the same
 process is simply counted twice.
 process is simply counted twice.
 .Pp
 .Pp
 .Nm
 .Nm
-does not check whether resources mentioned in
+does not check whether all resources mentioned in
 .Pa /etc/symon.conf
 .Pa /etc/symon.conf
 exist.
 exist.
 .Pp
 .Pp

+ 5 - 1
symon/symon/symon.c

@@ -67,6 +67,9 @@ int flag_hup = 0;
 int flag_testconf = 0;
 int flag_testconf = 0;
 int symon_interval = 0;
 int symon_interval = 0;
 
 
+/* program wide time_t indicating start of measurement time */
+time_t now;
+
 /* map stream types to inits and getters */
 /* map stream types to inits and getters */
 struct funcmap streamfunc[] = {
 struct funcmap streamfunc[] = {
     {MT_IO1, 0, NULL, init_io, gets_io, get_io},
     {MT_IO1, 0, NULL, init_io, gets_io, get_io},
@@ -86,6 +89,7 @@ struct funcmap streamfunc[] = {
     {MT_CPUIOW, 0, NULL, init_cpuiow, gets_cpuiow, get_cpuiow},
     {MT_CPUIOW, 0, NULL, init_cpuiow, gets_cpuiow, get_cpuiow},
     {MT_SMART, 0, NULL, init_smart, gets_smart, get_smart},
     {MT_SMART, 0, NULL, init_smart, gets_smart, get_smart},
     {MT_LOAD, 0, NULL, init_load, gets_load, get_load},
     {MT_LOAD, 0, NULL, init_load, gets_load, get_load},
+    {MT_FLUKSO, 0, NULL, init_flukso, gets_flukso, get_flukso},
     {MT_EOT, 0, NULL, NULL, NULL}
     {MT_EOT, 0, NULL, NULL, NULL}
 };
 };
 
 
@@ -198,7 +202,7 @@ main(int argc, char *argv[])
     struct muxlist mul, newmul;
     struct muxlist mul, newmul;
     struct stream *stream;
     struct stream *stream;
     struct mux *mux;
     struct mux *mux;
-    time_t now, last_update;
+    time_t last_update;
     FILE *pidfile;
     FILE *pidfile;
     char *cfgpath;
     char *cfgpath;
     int ch;
     int ch;

+ 6 - 0
symon/symon/symon.h

@@ -56,6 +56,7 @@ struct funcmap {
 extern struct funcmap streamfunc[];
 extern struct funcmap streamfunc[];
 
 
 extern int symon_interval;
 extern int symon_interval;
+extern time_t now;
 
 
 /* prototypes */
 /* prototypes */
 __BEGIN_DECLS
 __BEGIN_DECLS
@@ -130,6 +131,11 @@ extern void init_load(struct stream *);
 extern void gets_load();
 extern void gets_load();
 extern int get_load(char *, int, struct stream *);
 extern int get_load(char *, int, struct stream *);
 
 
+/* sm_flukso.c */
+void init_flukso(struct stream *);
+void gets_flukso();
+int get_flukso(char *, int, struct stream *);
+
 __END_DECLS
 __END_DECLS
 
 
 #endif                          /* _SYMON_SYMON_H */
 #endif                          /* _SYMON_SYMON_H */

+ 7 - 1
symon/symux/c_smrrds.sh

@@ -317,7 +317,13 @@ load.rrd)
     create_rrd $i \
     create_rrd $i \
 	DS:load1:GAUGE:$INTERVAL:0:U \
 	DS:load1:GAUGE:$INTERVAL:0:U \
 	DS:load5:GAUGE:$INTERVAL:0:U \
 	DS:load5:GAUGE:$INTERVAL:0:U \
-	DS:load15:GAUGE:$INTERVAL:0:U \
+	DS:load15:GAUGE:$INTERVAL:0:U
+    ;;
+
+flukso_*.rrd)
+    # Build the flukso file
+    create_rrd $i \
+        DS:watts:GAUGE:$INTERVAL:0:U
     ;;
     ;;
 
 
 "done")
 "done")

+ 8 - 2
symon/symux/readconf.c

@@ -123,6 +123,10 @@ insert_filename(char *path, int maxlen, int type, char *args)
         ts = "load";
         ts = "load";
         ta = "";
         ta = "";
         break;
         break;
+    case MT_FLUKSO:
+        ts = "flukso_";
+        ta = args;
+        break;
 
 
     default:
     default:
         warning("%.200s:%d: internal error: type (%d) unknown",
         warning("%.200s:%d: internal error: type (%d) unknown",
@@ -239,6 +243,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
                 case LXT_SENSOR:
                 case LXT_SENSOR:
                 case LXT_SMART:
                 case LXT_SMART:
                 case LXT_LOAD:
                 case LXT_LOAD:
+                case LXT_FLUKSO:
                     st = token2type(l->op);
                     st = token2type(l->op);
                     strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
                     strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -280,7 +285,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
                 case LXT_COMMA:
                 case LXT_COMMA:
                     break;
                     break;
                 default:
                 default:
-                    parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load}");
+                    parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load|flukso}");
                     return 0;
                     return 0;
 
 
                     break;
                     break;
@@ -384,6 +389,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
             case LXT_SENSOR:
             case LXT_SENSOR:
             case LXT_SMART:
             case LXT_SMART:
             case LXT_LOAD:
             case LXT_LOAD:
+            case LXT_FLUKSO:
                 st = token2type(l->op);
                 st = token2type(l->op);
                 strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
                 strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -445,7 +451,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
                 }
                 }
                 break;          /* LXT_resource */
                 break;          /* LXT_resource */
             default:
             default:
-                parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load}");
+                parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load|flukso}");
                 return 0;
                 return 0;
                 break;
                 break;
             }
             }

+ 15 - 11
symon/symux/symux.8

@@ -27,7 +27,7 @@
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
 .\"
-.Dd January 20, 2010
+.Dd October 20, 2010
 .Dt SYMUX 8
 .Dt SYMUX 8
 .Os
 .Os
 .Sh NAME
 .Sh NAME
@@ -104,7 +104,7 @@ ipv6 with mux = ipv4, a listen port of the sources' family is opened
 using the unspecified address. Whitespace, newlines and text behind '#'
 using the unspecified address. Whitespace, newlines and text behind '#'
 are ignored. The format in BNF:
 are ignored. The format in BNF:
 .Pp
 .Pp
-.nf
+.Bd -literal -offset indent -compact
 stmt         = mux-stmt | source-stmt
 stmt         = mux-stmt | source-stmt
 mux-stmt     = "mux" host [ port ]
 mux-stmt     = "mux" host [ port ]
 host         = ip4addr | ip6addr | hostname
 host         = ip4addr | ip6addr | hostname
@@ -117,15 +117,15 @@ accept-stmts = accept-stmt [accept-stmts]
 accept-stmt  = "accept" "{" resources "}"
 accept-stmt  = "accept" "{" resources "}"
 resources    = resource [ version ] ["(" argument ")"]
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " resources ]
                [ ","|" " resources ]
-resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io"
-               "load" | "mbuf" | "mem" | "pf" | "pfq" | "proc" |
-               "sensor" | "smart"
+resource     = "cpu" | "cpuiow" | "debug" | "df" | "flukso" |
+               "if" | "io" | "load" | "mbuf" | "mem" | "pf" |
+               "pfq" | "proc" | "sensor" | "smart"
 version      = number
 version      = number
 argument     = number | interfacename | diskname
 argument     = number | interfacename | diskname
 datadir-stmt = "datadir" dirname
 datadir-stmt = "datadir" dirname
 write-stmts  = write-stmt [write-stmts]
 write-stmts  = write-stmt [write-stmts]
 write-stmt   = "write" resource "in" filename
 write-stmt   = "write" resource "in" filename
-.fi
+.Ed
 .Pp
 .Pp
 Note that
 Note that
 .Bl -tag -width Ds
 .Bl -tag -width Ds
@@ -158,7 +158,7 @@ on localhost.
 .Nm
 .Nm
 will also listen on tcp port 2100 for incoming listeners.
 will also listen on tcp port 2100 for incoming listeners.
 .Pp
 .Pp
-.nf
+.Bd -literal -offset indent -compact
 mux 127.0.0.1 2100
 mux 127.0.0.1 2100
 source 127.0.0.1 {
 source 127.0.0.1 {
     accept { cpu(0), mem, pf,
     accept { cpu(0), mem, pf,
@@ -170,14 +170,14 @@ source 127.0.0.1 {
 .Pp
 .Pp
     datadir "/var/www/symon/rrds/localhost"
     datadir "/var/www/symon/rrds/localhost"
 }
 }
-.fi
+.Ed
 .Sh LISTENERS
 .Sh LISTENERS
 .Nm
 .Nm
 offers received
 offers received
 .Xr symon 8
 .Xr symon 8
 data to other programs via tcp. An example of a listener session:
 data to other programs via tcp. An example of a listener session:
 .Pp
 .Pp
-.nf
+.Bd -literal -offset indent -compact
 nexus:~/project/symon$ telnet 10.0.0.1 2100
 nexus:~/project/symon$ telnet 10.0.0.1 2100
 Trying 10.0.0.1...
 Trying 10.0.0.1...
 Connected to 10.0.0.1.
 Connected to 10.0.0.1.
@@ -190,7 +190,7 @@ Escape character is '^]'.
 0:0;pf::1077658247:700930123:535398451:0:352:1107229:706391:119833
 0:0;pf::1077658247:700930123:535398451:0:352:1107229:706391:119833
 9:4:0:0:2:3:29:4109383:83291:83262:980325:0:1:6:0:0;mem::107765824
 9:4:0:0:2:3:29:4109383:83291:83262:980325:0:1:6:0:0;mem::107765824
 7:79155200:131956736:391430144:0:536739840;cpu:0:1077658247:0.50:0
 7:79155200:131956736:391430144:0:536739840;cpu:0:1077658247:0.50:0
-.00:0.00:0.90:98.60;proc:httpd:1077658247:9:216:172:8:3:0.00:14999
+\.00:0.00:0.90:98.60;proc:httpd:1077658247:9:216:172:8:3:0.00:14999
 552:0;if:lo0:1077658247:147104:147104:45868177:45868177:0:0:0:0:0:
 552:0;if:lo0:1077658247:147104:147104:45868177:45868177:0:0:0:0:0:
 0;if:xl0:1077658247:284267:452077:150620236:273265863:372:89478:0:
 0;if:xl0:1077658247:284267:452077:150620236:273265863:372:89478:0:
 0:0:0;if:de0:1077658247:1813721:1197722:729054136:568900227:101:2:
 0:0:0;if:de0:1077658247:1813721:1197722:729054136:568900227:101:2:
@@ -199,7 +199,7 @@ Escape character is '^]'.
 ^]
 ^]
 telnet> close
 telnet> close
 Connection closed.
 Connection closed.
-.fi
+.Ed
 .Lp
 .Lp
 The format is
 The format is
 .Va symon-version
 .Va symon-version
@@ -284,6 +284,10 @@ SMART attributes ( read_error_rate: reallocated_sectors: spin_retries:
 air_flow_temp: temperature: reallocations: current_pending: uncorrectables:
 air_flow_temp: temperature: reallocations: current_pending: uncorrectables:
 soft_read_error_rate: g_sense_error_rate: temperature2: free_fall_protection
 soft_read_error_rate: g_sense_error_rate: temperature2: free_fall_protection
 ). Values depend on drive model and may change between models.
 ). Values depend on drive model and may change between models.
+.It flukso
+Average pwr sensor value offered with 7.6 precision. Value is a moving average
+and will depend on the number of measurements seen in a particular symon
+interval.
 .El
 .El
 .Sh SIGNALS
 .Sh SIGNALS
 .Bl -tag -width Ds
 .Bl -tag -width Ds