Kaynağa Gözat

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

Wictor Lund 3 yıl önce
ebeveyn
işleme
9a1f7a104d

+ 23 - 0
symon/CHANGELOG

@@ -1,3 +1,26 @@
+31/05/2010 - 2.81
+
+   - symon: Allow multiple monitor statements with different intervals to the
+     same mux. Retrieving smart info every 5 secs confuses some disks.
+
+   - platform/Linux/sm_df.c now uses statvfs (Harm Schotanus)
+
+   - Added load average probe (Lars Kotthoff)
+
+   - Smart probe assumed that its ioctl cmd structure was not overwritten and
+     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.
+
+   - c_smrrds.sh: Allow more than 10 cpus.
+
+   - platform/OpenBSD/sm_proc.c now uses PROC2 sysctl (Stuart Henderson /
+     Tasmanian Devil)
+
+   - platform/OpenBSD/sm_sensor.c now uses the updated sensors api (Stuart
+     Henderson / Tasmanian Devil).
+
 23/11/2009 - 2.80
 23/11/2009 - 2.80
 
 
    - Removed all cvs ids, moved src control to git
    - Removed all cvs ids, moved src control to git

+ 1 - 1
symon/INSTALL

@@ -78,7 +78,7 @@ Less quick, but all OSes
        overwriting the defaults.
        overwriting the defaults.
 
 
    BSDs: Run make && make install
    BSDs: Run make && make install
-  Linux: Run pmake && pmake install
+  Linux: Run pmake && pmake install || bmake && bmake install
 
 
 - Create an '/etc/symon.conf' for each monitored host and one symux.conf for
 - Create an '/etc/symon.conf' for each monitored host and one symux.conf for
   the gatherer host. See the manual pages on how to specify alternative
   the gatherer host. See the manual pages on how to specify alternative

+ 1 - 1
symon/Makefile.inc

@@ -1,4 +1,4 @@
-V=2.80
+V=2.81
 
 
 AR?=	ar
 AR?=	ar
 CC?=	cc
 CC?=	cc

+ 3 - 2
symon/client/SymuxClient.pm

@@ -1,5 +1,5 @@
 #
 #
-# Copyright (c) 2001-2008 Willem Dijkstra
+# Copyright (c) 2001-2010 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
@@ -74,7 +74,8 @@ my $streamitem =
                 air_flow_temp => 4, temperature => 5, reallocations => 6,
                 air_flow_temp => 4, temperature => 5, reallocations => 6,
                 current_pending => 7, uncorrectables => 8,
                 current_pending => 7, uncorrectables => 8,
                 soft_read_error_rate => 9, g_sense_error_rate => 10,
                 soft_read_error_rate => 9, g_sense_error_rate => 10,
-                temperature2 => 10, free_fall_protection => 11}
+                temperature2 => 10, free_fall_protection => 11},
+     load   => {load1 => 1, load5 => 2, load15 => 3}
 };
 };
 
 
 sub new {
 sub new {

+ 15 - 1
symon/lib/data.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 Willem Dijkstra
  * All rights reserved.
  * All rights reserved.
  *
  *
  * The crc routine is by Rob Warnock <rpw3@sgi.com>, from the
  * The crc routine is by Rob Warnock <rpw3@sgi.com>, from the
@@ -111,6 +111,7 @@ struct {
     { MT_IF2, "LLLLLLLLLL" },
     { MT_IF2, "LLLLLLLLLL" },
     { MT_CPUIOW, "cccccc" },
     { MT_CPUIOW, "cccccc" },
     { MT_SMART, "bbbbbbbbbbbb" },
     { MT_SMART, "bbbbbbbbbbbb" },
+    { MT_LOAD, "ccc" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_EOT, "" }
     { MT_EOT, "" }
 };
 };
@@ -135,6 +136,7 @@ struct {
     { MT_IF2, LXT_IF },
     { MT_IF2, LXT_IF },
     { MT_CPUIOW, LXT_CPUIOW },
     { MT_CPUIOW, LXT_CPUIOW },
     { MT_SMART, LXT_SMART },
     { MT_SMART, LXT_SMART },
+    { MT_LOAD, LXT_LOAD },
     { MT_EOT, LXT_BADTOKEN }
     { MT_EOT, LXT_BADTOKEN }
 };
 };
 /* parallel crc32 table */
 /* parallel crc32 table */
@@ -1070,3 +1072,15 @@ init_crc32()
         crc32_table[i] = c;
         crc32_table[i] = c;
     }
     }
 }
 }
+int
+gcd(int a, int b)
+{
+    for(;;) {
+        if (a == 0)
+            return b;
+        b %= a;
+        if (b == 0)
+            return a;
+        a %= b;
+    }
+}

+ 12 - 3
symon/lib/data.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -127,6 +127,8 @@ struct mux {
     int clientsocket;           /* symux; incoming tcp connections */
     int clientsocket;           /* symux; incoming tcp connections */
     int symonsocket[AF_MAX];    /* symux; incoming symon data */
     int symonsocket[AF_MAX];    /* symux; incoming symon data */
     int symuxsocket;            /* symon; outgoing data to mux */
     int symuxsocket;            /* symon; outgoing data to mux */
+    int last;
+    int interval;
     struct symonpacket packet;
     struct symonpacket packet;
     struct sockaddr_storage sockaddr;
     struct sockaddr_storage sockaddr;
     struct streamlist sl;
     struct streamlist sl;
@@ -160,8 +162,9 @@ SLIST_HEAD(muxlist, mux);
 #define MT_IF2    13
 #define MT_IF2    13
 #define MT_CPUIOW 14
 #define MT_CPUIOW 14
 #define MT_SMART  15
 #define MT_SMART  15
-#define MT_TEST   16
-#define MT_EOT    17
+#define MT_LOAD   16
+#define MT_TEST   17
+#define MT_EOT    18
 
 
 /*
 /*
  * Unpacking of incoming packets is done via a packedstream structure. This
  * Unpacking of incoming packets is done via a packedstream structure. This
@@ -342,6 +345,11 @@ struct packedstream {
             u_int8_t temperature2;
             u_int8_t temperature2;
             u_int8_t free_fall_protection;
             u_int8_t free_fall_protection;
         }      ps_smart;
         }      ps_smart;
+        struct {
+            u_int16_t mload1;
+            u_int16_t mload2;
+            u_int16_t mload3;
+        }      ps_load;
     }     data;
     }     data;
 };
 };
 
 
@@ -350,6 +358,7 @@ __BEGIN_DECLS
 char *type2str(const int);
 char *type2str(const int);
 int bytelen_sourcelist(struct sourcelist *);
 int bytelen_sourcelist(struct sourcelist *);
 int bytelen_streamlist(struct streamlist *);
 int bytelen_streamlist(struct streamlist *);
+int gcd(int a, int b);
 int getheader(char *, struct symonpacketheader *);
 int getheader(char *, struct symonpacketheader *);
 int ps2strn(struct packedstream *, char *, int, int);
 int ps2strn(struct packedstream *, char *, int, int);
 int setheader(char *, struct symonpacketheader *);
 int setheader(char *, struct symonpacketheader *);

+ 6 - 1
symon/lib/lex.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -56,6 +56,7 @@
 #include "xmalloc.h"
 #include "xmalloc.h"
 #include "lex.h"
 #include "lex.h"
 #include "error.h"
 #include "error.h"
+#include "sylimits.h"
 
 
 static struct {
 static struct {
     const char *name;
     const char *name;
@@ -81,6 +82,7 @@ static struct {
     { "io", LXT_IO },
     { "io", LXT_IO },
     { "io1", LXT_IO1 },
     { "io1", LXT_IO1 },
     { "io2", LXT_IO },
     { "io2", LXT_IO },
+    { "load", LXT_LOAD },
     { "mbuf", LXT_MBUF },
     { "mbuf", LXT_MBUF },
     { "mem", LXT_MEM },
     { "mem", LXT_MEM },
     { "mem1", LXT_MEM1 },
     { "mem1", LXT_MEM1 },
@@ -305,6 +307,9 @@ lex_nexttoken(struct lex *l)
         if (strlen(l->token) == strspn(l->token, "0123456789")) {
         if (strlen(l->token) == strspn(l->token, "0123456789")) {
             l->type = LXY_NUMBER;
             l->type = LXY_NUMBER;
             l->value = strtol(l->token, NULL, 10);
             l->value = strtol(l->token, NULL, 10);
+            if (l->value > SYMON_MAXLEXNUM) {
+                fatal("%.200s:%d: parse error at '%.200s': number too large", l->filename, l->cline, l->token);
+            }
         }
         }
     }
     }
     return 1;
     return 1;

+ 21 - 20
symon/lib/lex.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -41,8 +41,8 @@
 #include <stdio.h>
 #include <stdio.h>
 
 
 /* Tokens known to lex */
 /* Tokens known to lex */
-#define LXT_BADTOKEN   0
 #define LXT_ACCEPT     1
 #define LXT_ACCEPT     1
+#define LXT_BADTOKEN   0
 #define LXT_BEGIN      2
 #define LXT_BEGIN      2
 #define LXT_CLOSE      3
 #define LXT_CLOSE      3
 #define LXT_COMMA      4
 #define LXT_COMMA      4
@@ -59,24 +59,25 @@
 #define LXT_IN        15
 #define LXT_IN        15
 #define LXT_IO        16
 #define LXT_IO        16
 #define LXT_IO1       17
 #define LXT_IO1       17
-#define LXT_MBUF      18
-#define LXT_MEM       19
-#define LXT_MEM1      20
-#define LXT_MONITOR   21
-#define LXT_MUX       22
-#define LXT_OPEN      23
-#define LXT_PF        24
-#define LXT_PFQ       25
-#define LXT_PORT      26
-#define LXT_PROC      27
-#define LXT_SECOND    28
-#define LXT_SECONDS   29
-#define LXT_SENSOR    30
-#define LXT_SMART     31
-#define LXT_SOURCE    32
-#define LXT_STREAM    33
-#define LXT_TO        34
-#define LXT_WRITE     35
+#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
 
 
 struct lex {
 struct lex {
     char *buffer;               /* current line(s) */
     char *buffer;               /* current line(s) */

+ 25 - 1
symon/lib/smart.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2009 Willem Dijkstra
+ * Copyright (c) 2010 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
@@ -102,3 +102,27 @@ smart_parse(struct smart_values *ds, struct smart_report *sr)
         }
         }
     }
     }
 }
 }
+/*
+ * The return value of the smart read values is encoded in the ata
+ * cylinder register. This function hides that magic and is used by
+ * those operating systems that do not decode this data for us.
+ */
+int
+smart_status(unsigned char low, unsigned char high)
+{
+    unsigned const char nlow = 0x4f;
+    unsigned const char nhigh = 0xc2;
+    unsigned const char flow = 0xf4;
+    unsigned const char fhigh = 0x2c;
+
+    /* Check for good values */
+    if ((low == nlow) && (high == nhigh))
+        return 0;
+
+    /* Check for bad values */
+    if ((low == flow) && (high == fhigh))
+        return 1;
+
+    /* Values do not make sense - signal to caller */
+    return 2;
+}

+ 2 - 1
symon/lib/smart.h

@@ -42,7 +42,7 @@ struct smart_values {
 #endif
 #endif
 
 
 #define SMART_CYLINDER                             0xc24f
 #define SMART_CYLINDER                             0xc24f
-#define SMART_TIMEOUT                              600
+#define SMART_TIMEOUT                              1000
 
 
 #define ATA_SMART_READ_VALUES                      0xd0
 #define ATA_SMART_READ_VALUES                      0xd0
 
 
@@ -76,5 +76,6 @@ struct smart_report {
 };
 };
 
 
 extern void smart_parse(struct smart_values *ds, struct smart_report *sr);
 extern void smart_parse(struct smart_values *ds, struct smart_report *sr);
+extern int smart_status(unsigned char low, unsigned char high);
 
 
 #endif /* _SYMON_LIB_SMART_H */
 #endif /* _SYMON_LIB_SMART_H */

+ 1 - 0
symon/lib/sylimits.h

@@ -15,4 +15,5 @@
 #define SYMON_DFNAMESIZE       64
 #define SYMON_DFNAMESIZE       64
 #define SYMON_MAXPACKET        65515    /* udp packet max payload 65Kb - 20 byte header */
 #define SYMON_MAXPACKET        65515    /* udp packet max payload 65Kb - 20 byte header */
 
 
+#define SYMON_MAXLEXNUM        65535    /* maximum numeric argument while lexing */
 #endif
 #endif

+ 7 - 1
symon/platform/Linux/conf.sh

@@ -10,4 +10,10 @@ if [ -f /proc/partitions ]; then
     else
     else
 	echo "#undef HAS_PROC_PARTITIONS"
 	echo "#undef HAS_PROC_PARTITIONS"
     fi
     fi
-fi
+fi
+if grep -q "hd_drive_cmd_hdr" /usr/include/linux/hdreg.h; then
+    echo "#define HAS_HDDRIVECMDHDR 1"
+else
+    echo "#undef HAS_HDDRIVECMDHDR"
+fi
+

+ 3 - 2
symon/platform/Linux/sm_cpu.c

@@ -41,6 +41,7 @@
 
 
 #include <ctype.h>
 #include <ctype.h>
 #include <errno.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 #include <strings.h>
 #include <strings.h>
@@ -125,7 +126,7 @@ get_cpu(char *symon_buf, int maxlen, struct stream *st)
     }
     }
 
 
     line += strlen(st->parg.cp.name);
     line += strlen(st->parg.cp.name);
-    if (CPUSTATES > sscanf(line, "%llu %llu %llu %llu %llu %llu %llu %llu\n",
+    if (CPUSTATES > sscanf(line, "%" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 "\n",
                            &st->parg.cp.time[CP_USER],
                            &st->parg.cp.time[CP_USER],
                            &st->parg.cp.time[CP_NICE],
                            &st->parg.cp.time[CP_NICE],
                            &st->parg.cp.time[CP_SYS],
                            &st->parg.cp.time[CP_SYS],
@@ -136,7 +137,7 @@ get_cpu(char *symon_buf, int maxlen, struct stream *st)
                            &st->parg.cp.time[CP_STEAL])) {
                            &st->parg.cp.time[CP_STEAL])) {
       /* /proc/stat might not support steal */
       /* /proc/stat might not support steal */
       st->parg.cp.time[CP_STEAL] = 0;
       st->parg.cp.time[CP_STEAL] = 0;
-      if ((CPUSTATES - 1) > sscanf(line, "%llu %llu %llu %llu %llu %llu %llu\n",
+      if ((CPUSTATES - 1) > sscanf(line, "%" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 "\n",
 				   &st->parg.cp.time[CP_USER],
 				   &st->parg.cp.time[CP_USER],
 				   &st->parg.cp.time[CP_NICE],
 				   &st->parg.cp.time[CP_NICE],
 				   &st->parg.cp.time[CP_SYS],
 				   &st->parg.cp.time[CP_SYS],

+ 23 - 22
symon/platform/Linux/sm_cpuiow.c

@@ -41,6 +41,7 @@
 
 
 #include <ctype.h>
 #include <ctype.h>
 #include <errno.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 #include <strings.h>
 #include <strings.h>
@@ -125,28 +126,28 @@ get_cpuiow(char *symon_buf, int maxlen, struct stream *st)
     }
     }
 
 
     line += strlen(st->parg.cpw.name);
     line += strlen(st->parg.cpw.name);
-    if (CPUSTATES > sscanf(line, "%llu %llu %llu %llu %llu %llu %llu %llu\n",
-                           &st->parg.cpw.time[CP_USER],
-                           &st->parg.cpw.time[CP_NICE],
-                           &st->parg.cpw.time[CP_SYS],
-                           &st->parg.cpw.time[CP_IDLE],
-                           &st->parg.cpw.time[CP_IOWAIT],
-                           &st->parg.cpw.time[CP_HARDIRQ],
-                           &st->parg.cpw.time[CP_SOFTIRQ],
-                           &st->parg.cpw.time[CP_STEAL])) {
-        /* /proc/stat might not support steal */
-        st->parg.cpw.time[CP_STEAL] = 0;
-        if ((CPUSTATES - 1) > sscanf(line, "%llu %llu %llu %llu %llu %llu %llu\n",
-                                     &st->parg.cpw.time[CP_USER],
-                                     &st->parg.cpw.time[CP_NICE],
-                                     &st->parg.cpw.time[CP_SYS],
-                                     &st->parg.cpw.time[CP_IDLE],
-                                     &st->parg.cpw.time[CP_IOWAIT],
-                                     &st->parg.cpw.time[CP_HARDIRQ],
-                                     &st->parg.cpw.time[CP_SOFTIRQ])) {
-            warning("could not parse cpu statistics for %.200s", &st->parg.cpw.name);
-            return 0;
-        }
+    if (CPUSTATES > sscanf(line, "%" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 "\n",
+                           &st->parg.cp.time[CP_USER],
+                           &st->parg.cp.time[CP_NICE],
+                           &st->parg.cp.time[CP_SYS],
+                           &st->parg.cp.time[CP_IDLE],
+                           &st->parg.cp.time[CP_IOWAIT],
+                           &st->parg.cp.time[CP_HARDIRQ],
+                           &st->parg.cp.time[CP_SOFTIRQ],
+                           &st->parg.cp.time[CP_STEAL])) {
+      /* /proc/stat might not support steal */
+      st->parg.cp.time[CP_STEAL] = 0;
+      if ((CPUSTATES - 1) > sscanf(line, "%" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 " %" SCNd64 "\n",
+				   &st->parg.cp.time[CP_USER],
+				   &st->parg.cp.time[CP_NICE],
+				   &st->parg.cp.time[CP_SYS],
+				   &st->parg.cp.time[CP_IDLE],
+				   &st->parg.cp.time[CP_IOWAIT],
+				   &st->parg.cp.time[CP_HARDIRQ],
+				   &st->parg.cp.time[CP_SOFTIRQ])) {
+        warning("could not parse cpu statistics for %.200s", &st->parg.cp.name);
+        return 0;
+      }
     }
     }
 
 
     percentages(CPUSTATES, st->parg.cpw.states, st->parg.cpw.time,
     percentages(CPUSTATES, st->parg.cpw.states, st->parg.cpw.time,

+ 3 - 3
symon/platform/Linux/sm_df.c

@@ -40,7 +40,7 @@
 #include <stdio.h>
 #include <stdio.h>
 #include <mntent.h>
 #include <mntent.h>
 #include <string.h>
 #include <string.h>
-#include <sys/vfs.h>
+#include <sys/statvfs.h>
 
 
 #include "conf.h"
 #include "conf.h"
 #include "error.h"
 #include "error.h"
@@ -91,9 +91,9 @@ fsbtoblk(u_int64_t num, u_int64_t fsbs, u_int64_t bs)
 int
 int
 get_df(char *symon_buf, int maxlen, struct stream *st)
 get_df(char *symon_buf, int maxlen, struct stream *st)
 {
 {
-    struct statfs buf;
+    struct statvfs buf;
 
 
-    if (statfs(st->parg.df.mountpath, &buf) == 0 ) {
+    if (statvfs(st->parg.df.mountpath, &buf) == 0 ) {
         return snpack(symon_buf, maxlen, st->arg, MT_DF,
         return snpack(symon_buf, maxlen, st->arg, MT_DF,
                       (u_int64_t)fsbtoblk(buf.f_blocks, buf.f_bsize, SYMON_DFBLOCKSIZE),
                       (u_int64_t)fsbtoblk(buf.f_blocks, buf.f_bsize, SYMON_DFBLOCKSIZE),
                       (u_int64_t)fsbtoblk(buf.f_bfree, buf.f_bsize, SYMON_DFBLOCKSIZE),
                       (u_int64_t)fsbtoblk(buf.f_bfree, buf.f_bsize, SYMON_DFBLOCKSIZE),

+ 6 - 2
symon/platform/Linux/sm_if.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2007 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -40,6 +40,7 @@
 
 
 #include <errno.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <string.h>
 #include <string.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
@@ -139,7 +140,10 @@ get_if(char *symon_buf, int maxlen, struct stream *st)
     /* Inter-|   Receive                                                |  Transmit
     /* Inter-|   Receive                                                |  Transmit
      *  face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
      *  face |bytes    packets errs drop fifo frame compressed multicast|bytes    packets errs drop fifo colls carrier compressed
      */
      */
-    if (16 > sscanf(line, ":%Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu %Lu\n",
+    if (16 > sscanf(line, ":%" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %"
+                               SCNu64 " %" SCNu64 " %" SCNu64 " %"
+                               SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %" SCNu64 " %"
+                               SCNu64 " %" SCNu64 " %" SCNu64 "\n",
                     &stats.rx_bytes, &stats.rx_packets, &stats.rx_errors, &stats.rx_dropped, &stats.rx_fifo_errors,
                     &stats.rx_bytes, &stats.rx_packets, &stats.rx_errors, &stats.rx_dropped, &stats.rx_fifo_errors,
                     &stats.rx_frame_errors, &stats.rx_compressed, &stats.multicast,
                     &stats.rx_frame_errors, &stats.rx_compressed, &stats.multicast,
                     &stats.tx_bytes, &stats.tx_packets, &stats.tx_errors, &stats.tx_dropped, &stats.tx_fifo_errors,
                     &stats.tx_bytes, &stats.tx_packets, &stats.tx_errors, &stats.tx_dropped, &stats.tx_fifo_errors,

+ 9 - 2
symon/platform/Linux/sm_io.c

@@ -41,6 +41,7 @@
 
 
 #include <errno.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <string.h>
 #include <string.h>
 #include <unistd.h>
 #include <unistd.h>
 
 
@@ -135,7 +136,12 @@ get_io(char *symon_buf, int maxlen, struct stream *st)
     line += strlen(st->arg);
     line += strlen(st->arg);
     bzero(&stats, sizeof(struct io_device_stats));
     bzero(&stats, sizeof(struct io_device_stats));
 
 
-    if (11 > sscanf(line, " %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
+    if (11 > sscanf(line, " %" SCNu64 " %" SCNu64
+                          " %" SCNu64 " %" SCNu64
+                          " %" SCNu64 " %" SCNu64
+                          " %" SCNu64 " %" SCNu64
+                          " %" SCNu64 " %" SCNu64
+                          " %" SCNu64 "\n",
                     &stats.read_issued, &stats.read_merged,
                     &stats.read_issued, &stats.read_merged,
                     &stats.read_sectors, &stats.read_milliseconds,
                     &stats.read_sectors, &stats.read_milliseconds,
                     &stats.write_issued, &stats.write_merged,
                     &stats.write_issued, &stats.write_merged,
@@ -143,7 +149,8 @@ get_io(char *symon_buf, int maxlen, struct stream *st)
                     &stats.progress_ios, &stats.progress_milliseconds,
                     &stats.progress_ios, &stats.progress_milliseconds,
                     &stats.progress_weight)) {
                     &stats.progress_weight)) {
 #ifdef HAS_PROC_DISKSTATS
 #ifdef HAS_PROC_DISKSTATS
-        if (4 > sscanf(line, " %llu %llu %llu %llu\n",
+        if (4 > sscanf(line, " %" SCNu64 " %" SCNu64
+                             " %" SCNu64 " %" SCNu64 "\n",
                        &stats.read_issued, &stats.read_sectors,
                        &stats.read_issued, &stats.read_sectors,
                        &stats.write_issued, &stats.write_sectors)) {
                        &stats.write_issued, &stats.write_sectors)) {
             warning("could not parse disk statistics for %.200s", st->arg);
             warning("could not parse disk statistics for %.200s", st->arg);

+ 5 - 3
symon/platform/Linux/sm_mem.c

@@ -34,11 +34,13 @@
  * real active : real total : free : [swap used : swap total]
  * real active : real total : free : [swap used : swap total]
  */
  */
 
 
-#include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
 #include <unistd.h>
+
 #include "error.h"
 #include "error.h"
 #include "conf.h"
 #include "conf.h"
 #include "symon.h"
 #include "symon.h"
@@ -108,7 +110,7 @@ mem_getitem(char *name)
     }
     }
 
 
     line += strlen(name);
     line += strlen(name);
-    if (1 < sscanf(line, ": %llu Kb", &stat)) {
+    if (1 < sscanf(line, ": %" SCNu64 " Kb", &stat)) {
         warning("could not parse memory statistics");
         warning("could not parse memory statistics");
         return 0;
         return 0;
     } else {
     } else {

+ 6 - 5
symon/platform/Linux/sm_sensor.c

@@ -40,11 +40,12 @@
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
 
 
+#include <ctype.h>
 #include <errno.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
-#include <ctype.h>
 
 
 #include "error.h"
 #include "error.h"
 #include "symon.h"
 #include "symon.h"
@@ -62,7 +63,7 @@ init_sensor(struct stream *st)
     char buf[SYMON_MAX_OBJSIZE];
     char buf[SYMON_MAX_OBJSIZE];
     struct stat pathinfo;
     struct stat pathinfo;
     char *name, *p;
     char *name, *p;
-    int n;
+    int32_t n;
 
 
     /* sensors can be identified as using
     /* sensors can be identified as using
      *
      *
@@ -88,11 +89,11 @@ init_sensor(struct stream *st)
     else
     else
         name = st->arg;
         name = st->arg;
 
 
-    if (sscanf(name, "fan%d", &n) == 1)
+    if (sscanf(name, "fan%" SCNd32, &n) == 1)
         st->parg.sn.type = SENSOR_FAN;
         st->parg.sn.type = SENSOR_FAN;
-    else if (sscanf(name, "in%d", &n) == 1)
+    else if (sscanf(name, "in%" SCNd32, &n) == 1)
         st->parg.sn.type = SENSOR_IN;
         st->parg.sn.type = SENSOR_IN;
-    else if (sscanf(name, "temp%d", &n) == 1)
+    else if (sscanf(name, "temp%" SCNd32, &n) == 1)
         st->parg.sn.type = SENSOR_TEMP;
         st->parg.sn.type = SENSOR_TEMP;
     else
     else
         fatal("sensor(%.200s): '%s' is a unknown sensor type; expected fan/in/temp",
         fatal("sensor(%.200s): '%s' is a unknown sensor type; expected fan/in/temp",

+ 25 - 8
symon/platform/Linux/sm_smart.c

@@ -45,6 +45,17 @@
 #include "xmalloc.h"
 #include "xmalloc.h"
 #include "smart.h"
 #include "smart.h"
 
 
+#ifndef HAS_HDDRIVECMDHDR
+typedef unsigned char task_ioreg_t;
+
+struct hd_drive_cmd_hdr {
+    task_ioreg_t command;
+    task_ioreg_t sector_number;
+    task_ioreg_t feature;
+    task_ioreg_t sector_count;
+};
+#endif
+
 /* Ata command register set for requesting smart values */
 /* Ata command register set for requesting smart values */
 static struct hd_drive_cmd_hdr smart_cmd = {
 static struct hd_drive_cmd_hdr smart_cmd = {
     WIN_SMART, /* command code */
     WIN_SMART, /* command code */
@@ -53,15 +64,20 @@ static struct hd_drive_cmd_hdr smart_cmd = {
     1 /* sector count */
     1 /* sector count */
 };
 };
 
 
-/* per drive storage structure */
+/* Per drive storage structure; the ata cmd is followed by the data buffer that
+ * is filled by the ioctl. There can be no room between the two; hence the
+ * pragma for byte alignment.
+ */
+#pragma pack(1)
 struct smart_device {
 struct smart_device {
+    struct hd_drive_cmd_hdr cmd;
+    struct smart_values data;
     char name[MAX_PATH_LEN];
     char name[MAX_PATH_LEN];
     int fd;
     int fd;
     int type;
     int type;
     int failed;
     int failed;
-    struct hd_drive_cmd_hdr cmd;
-    struct smart_values data;
 };
 };
+#pragma pack()
 
 
 static struct smart_device *smart_devs = NULL;
 static struct smart_device *smart_devs = NULL;
 static int smart_cur = 0;
 static int smart_cur = 0;
@@ -104,9 +120,6 @@ init_smart(struct stream *st)
     /* store drivename in new block */
     /* store drivename in new block */
     snprintf(smart_devs[smart_cur].name, MAX_PATH_LEN, "%s", drivename);
     snprintf(smart_devs[smart_cur].name, MAX_PATH_LEN, "%s", drivename);
 
 
-    /* populate ata command header */
-    memcpy(&smart_devs[smart_cur].cmd, (void *) &smart_cmd, sizeof(struct hd_drive_cmd_hdr));
-
     /* store filedescriptor to device */
     /* store filedescriptor to device */
     smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
     smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
 
 
@@ -125,21 +138,25 @@ init_smart(struct stream *st)
 void
 void
 gets_smart()
 gets_smart()
 {
 {
-    int i;
+  int i;
 
 
     for (i = 0; i < smart_cur; i++) {
     for (i = 0; i < smart_cur; i++) {
+        /* populate ata command header */
+        memcpy(&smart_devs[i].cmd, (void *) &smart_cmd, sizeof(struct hd_drive_cmd_hdr));
         if (ioctl(smart_devs[i].fd, HDIO_DRIVE_CMD, &smart_devs[i].cmd)) {
         if (ioctl(smart_devs[i].fd, HDIO_DRIVE_CMD, &smart_devs[i].cmd)) {
             warning("smart: ioctl for drive '%s' failed: %d",
             warning("smart: ioctl for drive '%s' failed: %d",
                     &smart_devs[i].name, errno);
                     &smart_devs[i].name, errno);
             smart_devs[i].failed = 1;
             smart_devs[i].failed = 1;
         }
         }
 
 
+        /* Linux does not allow checking the smart return code using the
+         * HDIO_DRIVE_CMD */
+
         /* Some drives do not calculate the smart checksum correctly;
         /* Some drives do not calculate the smart checksum correctly;
          * additional code that identifies these drives would increase our
          * additional code that identifies these drives would increase our
          * footprint and the amount of datajuggling we need to do; we would
          * footprint and the amount of datajuggling we need to do; we would
          * rather ignore the checksums.
          * rather ignore the checksums.
          */
          */
-
         smart_devs[i].failed = 0;
         smart_devs[i].failed = 0;
     }
     }
     return;
     return;

+ 46 - 10
symon/platform/NetBSD/sm_smart.c

@@ -46,14 +46,28 @@
 #include "error.h"
 #include "error.h"
 #include "xmalloc.h"
 #include "xmalloc.h"
 #include "smart.h"
 #include "smart.h"
+/* ata command register set for requesting smart values */
+static struct atareq smart_cmd = {
+  ATACMD_READ, /* flags */
+  WDCC_SMART,  /* command */
+  WDSM_RD_DATA, /* features */
+  1, /* sector count */
+  0, /* sector number */
+  0, /* head */
+  WDSMART_CYL, /* cylinder */
+  NULL, /* data buffer */
+  sizeof(struct smart_values), /* sizeof data buffer */
+  SMART_TIMEOUT, /* timeout */
+  0, /* retsts */
+  0 /* error bits */
+};
 
 
 /* per drive storage structure */
 /* per drive storage structure */
-struct smart_device {
+static struct smart_device {
     char name[MAX_PATH_LEN];
     char name[MAX_PATH_LEN];
     int fd;
     int fd;
     int type;
     int type;
     int failed;
     int failed;
-    struct atareq cmd;
     struct smart_values data;
     struct smart_values data;
 };
 };
 
 
@@ -99,14 +113,6 @@ init_smart(struct stream *st)
     /* store drivename in new block */
     /* store drivename in new block */
     snprintf(sd->name, MAX_PATH_LEN, "%s", drivename);
     snprintf(sd->name, MAX_PATH_LEN, "%s", drivename);
 
 
-    /* populate ata command header */
-    sd->cmd.flags = ATACMD_READ;
-    sd->cmd.features = WDSM_RD_DATA;
-    sd->cmd.command = WDCC_SMART;
-    sd->cmd.datalen = sizeof(struct smart_values);
-    sd->cmd.cylinder = WDSMART_CYL;
-    sd->cmd.timeout = SMART_TIMEOUT;
-
     /* store filedescriptor to device */
     /* store filedescriptor to device */
     if ((sd->fd = opendisk(drivename, O_RDONLY | O_NONBLOCK, sd->name, sizeof(sd->name), 0)) == -1) {
     if ((sd->fd = opendisk(drivename, O_RDONLY | O_NONBLOCK, sd->name, sizeof(sd->name), 0)) == -1) {
         if (errno == ENOENT) {
         if (errno == ENOENT) {
@@ -129,14 +135,44 @@ void
 gets_smart()
 gets_smart()
 {
 {
     int i;
     int i;
+    struct atareq cmd;
 
 
     for (i = 0; i < smart_size; i++) {
     for (i = 0; i < smart_size; i++) {
+        /* populate ata command header */
+        memcpy(&cmd, (void *) &smart_cmd, sizeof(struct atareq));
+        cmd.databuf = (caddr_t)&smart_devs[i].data;
+        
         if (ioctl(smart_devs[i].fd, ATAIOCCOMMAND, &smart_devs[i].cmd)) {
         if (ioctl(smart_devs[i].fd, ATAIOCCOMMAND, &smart_devs[i].cmd)) {
             warning("smart: ioctl for drive '%s' failed: %d",
             warning("smart: ioctl for drive '%s' failed: %d",
                     &smart_devs[i].name, errno);
                     &smart_devs[i].name, errno);
             smart_devs[i].failed = 1;
             smart_devs[i].failed = 1;
         }
         }
 
 
+        /* check ATA command completion status */
+        switch (smart_devs[i].cmd.retsts) {
+            case ATACMD_OK:
+                break;
+            case ATACMD_TIMEOUT:
+                warning("smart: ATA command timed out for drive '%s'", &smart_devs[i].name);
+                smart_devs[i].failed = 1;
+                break;
+            case ATACMD_DF:
+                warning("smart: ATA device '%s' returned a Device Fault", &smart_devs[i].name);
+                smart_devs[i].failed = 1;
+                break;
+            case ATACMD_ERROR:
+                if (smart_devs[i].cmd.error & WDCE_ABRT)
+                    warning("smart: ATA device '%s' returned Aborted Command", &smart_devs[i].name);
+                else
+                    warning("smart: ATA device '%s' returned error register %0x", &smart_devs[i].name, smart_devs[i].cmd.error);
+                smart_devs[i].failed = 1;
+                break;
+            default:
+                warning("smart: ATAIOCCOMMAND returned unknown result code %d for drive '%s'", smart_devs[i].cmd.retsts, &smart_devs[i].name);
+                smart_devs[i].failed = 1;
+                break;
+        }
+
         /* Some drives do not calculate the smart checksum correctly;
         /* Some drives do not calculate the smart checksum correctly;
          * additional code that identifies these drives would increase our
          * additional code that identifies these drives would increase our
          * footprint and the amount of datajuggling we need to do; we would
          * footprint and the amount of datajuggling we need to do; we would

+ 4 - 0
symon/platform/OpenBSD/conf.sh

@@ -6,6 +6,10 @@ case `grep -csq KERN_CPTIME2 /usr/include/sys/sysctl.h` in
 1)	echo "#define HAS_KERN_CPTIME2	1" ;;
 1)	echo "#define HAS_KERN_CPTIME2	1" ;;
 0)	echo "#undef HAS_KERN_CPTIME2" ;;
 0)	echo "#undef HAS_KERN_CPTIME2" ;;
 esac;
 esac;
+case `grep -csq KERN_PROC2 /usr/include/sys/sysctl.h` in
+1)	echo "#define HAS_KERN_PROC2	1" ;;
+0)	echo "#undef HAS_KERN_PROC2" ;;
+esac;
 case `grep -csq "struct sensordev" /usr/include/sys/sensors.h` in
 case `grep -csq "struct sensordev" /usr/include/sys/sensors.h` in
 1)	echo "#define HAS_SENSORDEV	1" ;;
 1)	echo "#define HAS_SENSORDEV	1" ;;
 0)	echo "#undef HAS_SENSORDEV" ;;
 0)	echo "#undef HAS_SENSORDEV" ;;

+ 64 - 2
symon/platform/OpenBSD/sm_proc.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -36,6 +36,8 @@
  *
  *
  */
  */
 
 
+#include "conf.h"
+
 #include <sys/param.h>
 #include <sys/param.h>
 #include <sys/sysctl.h>
 #include <sys/sysctl.h>
 
 
@@ -50,7 +52,11 @@
 #define pagetob(size) (((u_int32_t)size) << proc_pageshift)
 #define pagetob(size) (((u_int32_t)size) << proc_pageshift)
 
 
 /* Globals for this module start with proc_ */
 /* Globals for this module start with proc_ */
+#ifdef HAS_KERN_PROC2
+static struct kinfo_proc2 *proc_ps = NULL;
+#else
 static struct kinfo_proc *proc_ps = NULL;
 static struct kinfo_proc *proc_ps = NULL;
+#endif
 static int proc_max = 0;
 static int proc_max = 0;
 static int proc_cur = 0;
 static int proc_cur = 0;
 static int proc_stathz = 0;
 static int proc_stathz = 0;
@@ -65,7 +71,7 @@ typedef long pctcpu;
 void
 void
 gets_proc()
 gets_proc()
 {
 {
-    int mib[3];
+    int mib[6];
     int procs;
     int procs;
     size_t size;
     size_t size;
 
 
@@ -78,6 +84,41 @@ gets_proc()
               __FILE__, __LINE__);
               __FILE__, __LINE__);
     }
     }
 
 
+#ifdef HAS_KERN_PROC2
+    /* increase buffers if necessary */
+    if (procs > proc_max) {
+        proc_max = (procs * 5) / 4;
+
+        if (proc_max > SYMON_MAX_DOBJECTS) {
+            fatal("%s:%d: dynamic object limit (%d) exceeded for kinfo_proc2 structures",
+                  __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
+        }
+
+        proc_ps = xrealloc(proc_ps, proc_max * sizeof(struct kinfo_proc2));
+    }
+
+    /* read data in anger */
+    mib[0] = CTL_KERN;
+    mib[1] = KERN_PROC2;
+    mib[2] = KERN_PROC_KTHREAD;
+    mib[3] = 0;
+    mib[4] = sizeof(struct kinfo_proc2);
+    mib[5] = proc_max;
+    size = proc_max * sizeof(struct kinfo_proc2);
+    if (sysctl(mib, 6, proc_ps, &size, NULL, 0) < 0) {
+        warning("proc probe cannot get processes");
+        proc_cur = 0;
+        return;
+    }
+
+    if (size % sizeof(struct kinfo_proc2) != 0) {
+        warning("proc size mismatch: got %d bytes, not dividable by sizeof(kinfo_proc2) %d",
+                size, sizeof(struct kinfo_proc2));
+        proc_cur = 0;
+    } else {
+        proc_cur = size / sizeof(struct kinfo_proc2);
+    }
+#else
     /* increase buffers if necessary */
     /* increase buffers if necessary */
     if (procs > proc_max) {
     if (procs > proc_max) {
         proc_max = (procs * 5) / 4;
         proc_max = (procs * 5) / 4;
@@ -108,6 +149,7 @@ gets_proc()
     } else {
     } else {
         proc_cur = size / sizeof(struct kinfo_proc);
         proc_cur = size / sizeof(struct kinfo_proc);
     }
     }
+#endif
 }
 }
 
 
 void
 void
@@ -145,7 +187,11 @@ int
 get_proc(char *symon_buf, int maxlen, struct stream *st)
 get_proc(char *symon_buf, int maxlen, struct stream *st)
 {
 {
     int i;
     int i;
+#ifdef HAS_KERN_PROC2
+    struct kinfo_proc2 *pp;
+#else
     struct kinfo_proc *pp;
     struct kinfo_proc *pp;
+#endif
     u_quad_t  cpu_ticks = 0;
     u_quad_t  cpu_ticks = 0;
     u_quad_t  cpu_uticks = 0;
     u_quad_t  cpu_uticks = 0;
     u_quad_t  cpu_iticks = 0;
     u_quad_t  cpu_iticks = 0;
@@ -158,6 +204,21 @@ get_proc(char *symon_buf, int maxlen, struct stream *st)
     int n = 0;
     int n = 0;
 
 
     for (pp = proc_ps, i = 0; i < proc_cur; pp++, i++) {
     for (pp = proc_ps, i = 0; i < proc_cur; pp++, i++) {
+#ifdef HAS_KERN_PROC2
+         if (strncmp(st->arg, pp->p_comm, strlen(st->arg)) == 0) {
+             /* cpu time - accumulated */
+             cpu_uticks += pp->p_uticks;  /* user */
+             cpu_sticks += pp->p_sticks;  /* sys  */
+             cpu_iticks += pp->p_iticks;  /* int  */
+             /* cpu time - percentage since last measurement */
+             cpu_pct = pctdouble(pp->p_pctcpu) * 100.0;
+             cpu_pcti += cpu_pct;
+             /* memory size - shared pages are counted multiple times */
+             mem_procsize += pagetob(pp->p_vm_tsize + /* text pages */
+                                     pp->p_vm_dsize + /* data */
+                                     pp->p_vm_ssize); /* stack */
+             mem_rss += pagetob(pp->p_vm_rssize);     /* rss  */
+#else
          if (strncmp(st->arg, pp->kp_proc.p_comm, strlen(st->arg)) == 0) {
          if (strncmp(st->arg, pp->kp_proc.p_comm, strlen(st->arg)) == 0) {
              /* cpu time - accumulated */
              /* cpu time - accumulated */
              cpu_uticks += pp->kp_proc.p_uticks;  /* user */
              cpu_uticks += pp->kp_proc.p_uticks;  /* user */
@@ -171,6 +232,7 @@ get_proc(char *symon_buf, int maxlen, struct stream *st)
                                      pp->kp_eproc.e_vm.vm_dsize + /* data */
                                      pp->kp_eproc.e_vm.vm_dsize + /* data */
                                      pp->kp_eproc.e_vm.vm_ssize); /* stack */
                                      pp->kp_eproc.e_vm.vm_ssize); /* stack */
              mem_rss += pagetob(pp->kp_eproc.e_vm.vm_rssize);     /* rss  */
              mem_rss += pagetob(pp->kp_eproc.e_vm.vm_rssize);     /* rss  */
+#endif
              n++;
              n++;
          }
          }
     }
     }

+ 8 - 2
symon/platform/OpenBSD/sm_sensor.c

@@ -93,8 +93,14 @@ init_sensor(struct stream *st)
     /* convert sensor device string to an integer */
     /* convert sensor device string to an integer */
     for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
     for (dev = 0; dev < MAXSENSORDEVICES; dev++) {
         st->parg.sn.mib[2] = dev;
         st->parg.sn.mib[2] = dev;
-        if (sysctl(st->parg.sn.mib, 3, &sensordev, &sdlen, NULL, 0) == -1)
-            continue;
+        if (sysctl(st->parg.sn.mib, 3, &sensordev, &sdlen, NULL, 0) == -1) {
+            if (errno == ENOENT)
+                break;
+            if (errno == ENXIO)
+                continue;
+            fatal("%s:%d: sensor(%.200s): sensor %d unknown errno %d",
+                  __FILE__, __LINE__, st->arg, dev, errno);
+        }
         if (strcmp(devname, sensordev.xname) == 0)
         if (strcmp(devname, sensordev.xname) == 0)
             break;
             break;
     }
     }

+ 60 - 0
symon/platform/generic/sm_load.c

@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2009 Lars Kotthoff <lars@larsko.org>
+ * 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 <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "conf.h"
+#include "error.h"
+#include "symon.h"
+
+static double load_stats[3];
+
+void
+init_load(struct stream *st)
+{
+    info("started module load(%.200s)", st->arg);
+}
+
+void
+gets_load()
+{
+    if (getloadavg(load_stats, 3) != 3) {
+            warning("could not get load average: %.200s", strerror(errno));
+    }
+}
+
+int
+get_load(char *symon_buf, int maxlen, struct stream *st)
+{
+    return snpack(symon_buf, maxlen, st->arg, MT_LOAD,
+                  load_stats[0], load_stats[1], load_stats[2]);
+}

+ 24 - 0
symon/platform/stub/sm_load.c

@@ -0,0 +1,24 @@
+#include <stdlib.h>
+
+#include "sylimits.h"
+#include "data.h"
+#include "error.h"
+
+void
+init_load(struct stream *st)
+{
+    fatal("load module not available");
+}
+void
+gets_load()
+{
+    fatal("load module not available");
+}
+int
+get_load(char *symon_buf, int maxlen, struct stream *st)
+{
+    fatal("load module not available");
+
+    /* NOT REACHED */
+    return 0;
+}

+ 7 - 5
symon/symon/Makefile

@@ -3,11 +3,13 @@ OS!=uname -s
 .include "../Makefile.inc"
 .include "../Makefile.inc"
 
 
 LIBS+=	${SYMON_LIBS} -L../lib -lsym -lprobe
 LIBS+=	${SYMON_LIBS} -L../lib -lsym -lprobe
-MODS!=	( for g in ../platform/stub/sm_*.c; do \
-		f=../platform/${OS}/`basename $$g`; \
-		if [ -f $$f ]; then echo $$f; \
-		else		    echo $$g; \
-		fi; \
+MODS!=	( for s in ../platform/stub/sm_*.c; do \
+		f=../platform/${OS}/`basename $$s`; \
+		g=../platform/generic/`basename $$s`; \
+		if [ -f $$f ]; then      echo $$f; \
+		else if [ -f $$g ]; then echo $$g; \
+		else                     echo $$s; \
+		fi; fi; \
 	  done )
 	  done )
 SRCS=	symon.c readconf.c symonnet.c ${MODS}
 SRCS=	symon.c readconf.c symonnet.c ${MODS}
 OBJS+=	${SRCS:R:S/$/.o/g}
 OBJS+=	${SRCS:R:S/$/.o/g}

+ 11 - 10
symon/symon/readconf.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -79,7 +79,7 @@ read_host_port(struct muxlist * mul, struct mux * mux, struct lex * l)
     }
     }
 
 
     bzero(&muxname, sizeof(muxname));
     bzero(&muxname, sizeof(muxname));
-    snprintf(&muxname[0], sizeof(muxname), "%s %s", mux->addr, mux->port);
+    snprintf(&muxname[0], sizeof(muxname), "%s %s (%ds)", mux->addr, mux->port, mux->interval);
     if (rename_mux(mul, mux, muxname) == NULL) {
     if (rename_mux(mul, mux, muxname) == NULL) {
         warning("%.200s:%d: monitored data for host '%.200s' has already been specified",
         warning("%.200s:%d: monitored data for host '%.200s' has already been specified",
                 l->filename, l->cline, muxname);
                 l->filename, l->cline, muxname);
@@ -115,6 +115,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_PROC:
         case LXT_PROC:
         case LXT_SENSOR:
         case LXT_SENSOR:
         case LXT_SMART:
         case LXT_SMART:
+        case LXT_LOAD:
             st = token2type(l->op);
             st = token2type(l->op);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -153,7 +154,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|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}");
             return 0;
             return 0;
             break;
             break;
         }
         }
@@ -182,9 +183,9 @@ read_monitor(struct muxlist * mul, struct lex * l)
         lex_nexttoken(l);
         lex_nexttoken(l);
 
 
         if (l->op == LXT_SECOND) {
         if (l->op == LXT_SECOND) {
-            symon_interval = 1;
+            mux->interval = 1;
         } else if (l->type == LXY_NUMBER) {
         } else if (l->type == LXY_NUMBER) {
-            symon_interval = l->value;
+            mux->interval = l->value;
             lex_nexttoken(l);
             lex_nexttoken(l);
             if (l->op != LXT_SECONDS) {
             if (l->op != LXT_SECONDS) {
                 parse_error(l, "seconds");
                 parse_error(l, "seconds");
@@ -195,7 +196,8 @@ read_monitor(struct muxlist * mul, struct lex * l)
         }
         }
 
 
         lex_nexttoken(l);
         lex_nexttoken(l);
-    }
+    } else
+        mux->interval = SYMON_DEFAULT_INTERVAL;
 
 
     /* parse [stream [from <host>] to] */
     /* parse [stream [from <host>] to] */
     if (l->op != LXT_STREAM) {
     if (l->op != LXT_STREAM) {
@@ -260,10 +262,9 @@ read_config_file(struct muxlist *muxlist, char *filename)
                     l->filename, mux->name);
                     l->filename, mux->name);
             return 0;
             return 0;
         }
         }
-    }
-
-    if (symon_interval < SYMON_DEFAULT_INTERVAL) {
-        warning("%.200s: monitoring set to every %d s", l->filename, symon_interval);
+        if (mux->interval < SYMON_DEFAULT_INTERVAL) {
+            warning("%.200s: monitoring set to every %d s", l->filename, mux->interval);
+        }
     }
     }
 
 
     close_lex(l);
     close_lex(l);

+ 0 - 6
symon/symon/smart.conf

@@ -1,6 +0,0 @@
-#
-# Demo configuration for symon. See symon(8) for BNF.
-#
-monitor { cpu(0),  mem,
-	  smart(sda)
-} stream to 127.0.0.1 2100

+ 8 - 7
symon/symon/symon.8

@@ -1,6 +1,6 @@
 .\"  -*- nroff -*-
 .\"  -*- nroff -*-
 .\"
 .\"
-.\" Copyright (c) 2001-2009 Willem Dijkstra
+.\" Copyright (c) 2001-2010 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
@@ -40,7 +40,7 @@
 .Pp
 .Pp
 .Sh DESCRIPTION
 .Sh DESCRIPTION
 .Nm
 .Nm
-is a lightweight system monitor that measures cpu, filesystem, interface, disk,
+is a lightweight system monitor that measures cpu, load, filesystem, interface, disk,
 memory, pf, pf queues, mbuf, proc and sensor statistics every 5 seconds. This
 memory, pf, pf queues, mbuf, proc and sensor statistics every 5 seconds. This
 information is then spooled to
 information is then spooled to
 .Xr symux 8
 .Xr symux 8
@@ -107,8 +107,8 @@ 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"
-               "mbuf" | "mem" | "pf" | "pfq" | "proc" |
+resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io" |
+               "load" | "mbuf" | "mem" | "pf" | "pfq" | "proc" |
                "sensor" | "smart"
                "sensor" | "smart"
 version      = number
 version      = number
 argument     = number | name
 argument     = number | name
@@ -179,8 +179,9 @@ exist.
 Willem Dijkstra <wpd@xs4all.nl>. \%Daniel \%Hartmeier helped to port to big-endian
 Willem Dijkstra <wpd@xs4all.nl>. \%Daniel \%Hartmeier helped to port to big-endian
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 .Pp
 .Pp
-Port contributors: \%Marc \%Balmer, \%Tito \%Dal \%Canton, \%Matthew \%Gream,
-\%Daniel \%Hartmeier, \%Constantine A. \%Murenin, J. \%Martin \%Petersen,
-\%Fredrik \%Soderblom, \%Harm \%Schotanus and \%Martin van der \%Werff.
+Port contributors: \%Marc \%Balmer, \%Tito \%Dal \%Canton, \%Matthew
+\%Gream, \%Daniel \%Hartmeier, \%Lars \%Kotthoff, \%Constantine
+A. \%Murenin, J. \%Martin \%Petersen, \%Fredrik \%Soderblom, \%Harm
+\%Schotanus and \%Martin van der \%Werff.
 .Sh SEE ALSO
 .Sh SEE ALSO
 .Xr symux 8
 .Xr symux 8

+ 65 - 46
symon/symon/symon.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -58,13 +58,14 @@ void alarmhandler(int);
 void drop_privileges();
 void drop_privileges();
 void exithandler(int);
 void exithandler(int);
 void huphandler(int);
 void huphandler(int);
-void set_stream_use(struct muxlist *);
+void init_streams(struct muxlist *mul);
+void drop_privileges(int unsecure);
 __END_DECLS
 __END_DECLS
 
 
 int flag_unsecure = 0;
 int flag_unsecure = 0;
 int flag_hup = 0;
 int flag_hup = 0;
 int flag_testconf = 0;
 int flag_testconf = 0;
-int symon_interval = SYMON_DEFAULT_INTERVAL;
+int symon_interval = 0;
 
 
 /* map stream types to inits and getters */
 /* map stream types to inits and getters */
 struct funcmap streamfunc[] = {
 struct funcmap streamfunc[] = {
@@ -84,23 +85,46 @@ struct funcmap streamfunc[] = {
     {MT_IF2, 0, NULL, init_if, gets_if, get_if},
     {MT_IF2, 0, NULL, init_if, gets_if, get_if},
     {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_EOT, 0, NULL, NULL, NULL}
     {MT_EOT, 0, NULL, NULL, NULL}
 };
 };
 
 
 void
 void
-set_stream_use(struct muxlist *mul)
+init_streams(struct muxlist *mul)
 {
 {
-    struct mux *mux;
+    struct itimerval alarminterval;
     struct stream *stream;
     struct stream *stream;
-    int i;
+    struct mux *mux;
 
 
-    for (i = 0; i < MT_EOT; i++)
-        streamfunc[i].used = 0;
+    mux = NULL;
+
+    if ((mul == NULL) || ((mux = SLIST_FIRST(mul)) == NULL))
+        fatal("empty mux list");
 
 
+    symon_interval = mux->interval;
 
 
     SLIST_FOREACH(mux, mul, muxes) {
     SLIST_FOREACH(mux, mul, muxes) {
-        SLIST_FOREACH(stream, &mux->sl, streams)
-            streamfunc[stream->type].used = 1;
+        /* determine gcd of alarm times */
+        symon_interval = gcd(symon_interval, mux->interval);
+
+        /* init network */
+        init_symon_packet(mux);
+        connect2mux(mux);
+
+        /* init modules */
+        SLIST_FOREACH(stream, &mux->sl, streams) {
+            (streamfunc[stream->type].init) (stream);
+        }
+    }
+
+    /* setup alarm */
+    timerclear(&alarminterval.it_interval);
+    timerclear(&alarminterval.it_value);
+    alarminterval.it_interval.tv_sec =
+        alarminterval.it_value.tv_sec = symon_interval;
+
+    if (setitimer(ITIMER_REAL, &alarminterval, NULL) != 0) {
+        fatal("alarm setup failed: %.200s", strerror(errno));
     }
     }
 }
 }
 void
 void
@@ -172,7 +196,6 @@ int
 main(int argc, char *argv[])
 main(int argc, char *argv[])
 {
 {
     struct muxlist mul, newmul;
     struct muxlist mul, newmul;
-    struct itimerval alarminterval;
     struct stream *stream;
     struct stream *stream;
     struct mux *mux;
     struct mux *mux;
     time_t now, last_update;
     time_t now, last_update;
@@ -224,7 +247,11 @@ main(int argc, char *argv[])
         exit(EX_OK);
         exit(EX_OK);
     }
     }
 
 
-    set_stream_use(&mul);
+    SLIST_FOREACH(mux, &mul, muxes) {
+        SLIST_FOREACH(stream, &mux->sl, streams) {
+            streamfunc[stream->type].used = 1;
+        }
+    }
 
 
     /* open resources that might not be available after privilege drop */
     /* open resources that might not be available after privilege drop */
     for (i = 0; i < MT_EOT; i++)
     for (i = 0; i < MT_EOT; i++)
@@ -267,24 +294,7 @@ main(int argc, char *argv[])
     /* prepare crc32 */
     /* prepare crc32 */
     init_crc32();
     init_crc32();
 
 
-    /* init modules */
-    SLIST_FOREACH(mux, &mul, muxes) {
-        init_symon_packet(mux);
-        connect2mux(mux);
-        SLIST_FOREACH(stream, &mux->sl, streams) {
-            (streamfunc[stream->type].init) (stream);
-        }
-    }
-
-    /* setup alarm */
-    timerclear(&alarminterval.it_interval);
-    timerclear(&alarminterval.it_value);
-    alarminterval.it_interval.tv_sec =
-        alarminterval.it_value.tv_sec = symon_interval;
-
-    if (setitimer(ITIMER_REAL, &alarminterval, NULL) != 0) {
-        fatal("alarm setup failed: %.200s", strerror(errno));
-    }
+    init_streams(&mul);
 
 
     last_update = time(NULL);
     last_update = time(NULL);
     for (;;) {                  /* FOREVER */
     for (;;) {                  /* FOREVER */
@@ -306,14 +316,7 @@ main(int argc, char *argv[])
                     info("read configuration file '%.200s' successfully", cfgpath);
                     info("read configuration file '%.200s' successfully", cfgpath);
 
 
                     /* init modules */
                     /* init modules */
-                    SLIST_FOREACH(mux, &mul, muxes) {
-                        init_symon_packet(mux);
-                        connect2mux(mux);
-                        SLIST_FOREACH(stream, &mux->sl, streams) {
-                            (streamfunc[stream->type].init) (stream);
-                        }
-                    }
-                    set_stream_use(&mul);
+                    init_streams(&mul);
                 }
                 }
             } else {
             } else {
                 info("configuration unreachable because of privsep; keeping old configuration");
                 info("configuration unreachable because of privsep; keeping old configuration");
@@ -330,20 +333,36 @@ main(int argc, char *argv[])
             }
             }
             last_update = now;
             last_update = now;
 
 
-            /* populate for modules that get all their measurements in one go */
+            /* populate for modules that get all their measurements in one
+             * go. we bunch up calls together to ensure that the measurements
+             * happen "at the same time" */
             for (i = 0; i < MT_EOT; i++)
             for (i = 0; i < MT_EOT; i++)
-                if (streamfunc[i].used && (streamfunc[i].gets != NULL))
-                    (streamfunc[i].gets) ();
+                streamfunc[i].used = 0;
+            SLIST_FOREACH(mux, &mul, muxes) {
+                mux->last += symon_interval;
+                if (mux->last >= mux->interval) {
+                    SLIST_FOREACH(stream, &mux->sl, streams) {
+                        if (streamfunc[stream->type].used == 0) {
+                            streamfunc[stream->type].used = 1;
+                            if (streamfunc[stream->type].gets != NULL)
+                                (streamfunc[stream->type].gets)();
+                        }
+                    }
+                }
+            }
 
 
             SLIST_FOREACH(mux, &mul, muxes) {
             SLIST_FOREACH(mux, &mul, muxes) {
-                prepare_packet(mux);
+                if (mux->last >= mux->interval) {
+                    mux->last = 0;
+                    prepare_packet(mux, now);
 
 
-                SLIST_FOREACH(stream, &mux->sl, streams)
-                    stream_in_packet(stream, mux);
+                    SLIST_FOREACH(stream, &mux->sl, streams)
+                        stream_in_packet(stream, mux);
 
 
-                finish_packet(mux);
+                    finish_packet(mux);
 
 
-                send_packet(mux);
+                    send_packet(mux);
+                }
             }
             }
         }
         }
     }
     }

+ 1 - 1
symon/symon/symon.conf

@@ -6,7 +6,7 @@ monitor { cpu(0),  mem,
 	  if(lo0),
 	  if(lo0),
 #	  pf,
 #	  pf,
 #         mbuf,
 #         mbuf,
-#         sensor(0),
+#         sensor(cpu0.temp0),
 #         proc(httpd),
 #         proc(httpd),
 #         if(xl0), if(de0), if(wi0),
 #         if(xl0), if(de0), if(wi0),
 #	  io(wd1), io(wd2), io(wd3), io(cd0)
 #	  io(wd1), io(wd2), io(wd3), io(cd0)

+ 6 - 1
symon/symon/symon.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2005 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -125,6 +125,11 @@ extern void init_smart(struct stream *);
 extern void gets_smart();
 extern void gets_smart();
 extern int get_smart(char *, int, struct stream *);
 extern int get_smart(char *, int, struct stream *);
 
 
+/* sm_load.c */
+extern void init_load(struct stream *);
+extern void gets_load();
+extern int get_load(char *, int, struct stream *);
+
 __END_DECLS
 __END_DECLS
 
 
 #endif                          /* _SYMON_SYMON_H */
 #endif                          /* _SYMON_SYMON_H */

+ 1 - 3
symon/symon/symonnet.c

@@ -85,10 +85,8 @@ send_packet(struct mux * mux)
 }
 }
 /* Prepare a packet for data */
 /* Prepare a packet for data */
 void
 void
-prepare_packet(struct mux * mux)
+prepare_packet(struct mux * mux, time_t t)
 {
 {
-    time_t t = time(NULL);
-
     bzero(mux->packet.data, mux->packet.size);
     bzero(mux->packet.data, mux->packet.size);
     mux->packet.header.symon_version = SYMON_PACKET_VER;
     mux->packet.header.symon_version = SYMON_PACKET_VER;
     mux->packet.header.timestamp = t;
     mux->packet.header.timestamp = t;

+ 2 - 2
symon/symon/symonnet.h

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2004 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -37,7 +37,7 @@
 __BEGIN_DECLS
 __BEGIN_DECLS
 void connect2mux(struct mux *);
 void connect2mux(struct mux *);
 void send_packet(struct mux *);
 void send_packet(struct mux *);
-void prepare_packet(struct mux *);
+void prepare_packet(struct mux *, time_t t);
 void stream_in_packet(struct stream *, struct mux *);
 void stream_in_packet(struct stream *, struct mux *);
 void finish_packet(struct mux *);
 void finish_packet(struct mux *);
 __END_DECLS
 __END_DECLS

+ 11 - 3
symon/symux/c_smrrds.sh

@@ -1,7 +1,7 @@
 #!/bin/sh
 #!/bin/sh
 
 
 #
 #
-# Copyright (c) 2001-2009 Willem Dijkstra
+# Copyright (c) 2001-2010 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
@@ -152,7 +152,7 @@ all)
     sh $this interval $INTERVAL child $config `$SYMUX -l`
     sh $this interval $INTERVAL child $config `$SYMUX -l`
     ;;
     ;;
 
 
-cpu[0-9].rrd)
+cpu[0-9]*.rrd)
     # Build cpu file
     # Build cpu file
     create_rrd $i \
     create_rrd $i \
 	DS:user:GAUGE:$INTERVAL:0:100 \
 	DS:user:GAUGE:$INTERVAL:0:100 \
@@ -162,7 +162,7 @@ cpu[0-9].rrd)
 	DS:idle:GAUGE:$INTERVAL:0:100
 	DS:idle:GAUGE:$INTERVAL:0:100
     ;;
     ;;
 
 
-cpuiow[0-9].rrd)
+cpuiow[0-9]*.rrd)
     # Build cpuiow file
     # Build cpuiow file
     create_rrd $i \
     create_rrd $i \
 	DS:user:GAUGE:$INTERVAL:0:100 \
 	DS:user:GAUGE:$INTERVAL:0:100 \
@@ -312,6 +312,14 @@ smart_*.rrd)
         DS:freefall:GAUGE:$INTERVAL:U:U
         DS:freefall:GAUGE:$INTERVAL:U:U
     ;;
     ;;
 
 
+load.rrd)
+    # Build load file
+    create_rrd $i \
+	DS:load1:GAUGE:$INTERVAL:0:U \
+	DS:load5:GAUGE:$INTERVAL:0:U \
+	DS:load15:GAUGE:$INTERVAL:0:U \
+    ;;
+
 "done")
 "done")
     # ignore
     # ignore
     ;;
     ;;

+ 9 - 3
symon/symux/readconf.c

@@ -1,5 +1,5 @@
 /*
 /*
- * Copyright (c) 2001-2008 Willem Dijkstra
+ * Copyright (c) 2001-2010 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
@@ -119,6 +119,10 @@ insert_filename(char *path, int maxlen, int type, char *args)
         ts = "smart_";
         ts = "smart_";
         ta = args;
         ta = args;
         break;
         break;
+    case MT_LOAD:
+        ts = "load";
+        ta = "";
+        break;
 
 
     default:
     default:
         warning("%.200s:%d: internal error: type (%d) unknown",
         warning("%.200s:%d: internal error: type (%d) unknown",
@@ -234,6 +238,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
                 case LXT_PROC:
                 case LXT_PROC:
                 case LXT_SENSOR:
                 case LXT_SENSOR:
                 case LXT_SMART:
                 case LXT_SMART:
+                case LXT_LOAD:
                     st = token2type(l->op);
                     st = token2type(l->op);
                     strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
                     strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -275,7 +280,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|mem|if|io|pf|debug|mbuf|proc|sensor|smart}");
+                    parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load}");
                     return 0;
                     return 0;
 
 
                     break;
                     break;
@@ -378,6 +383,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
             case LXT_PROC:
             case LXT_PROC:
             case LXT_SENSOR:
             case LXT_SENSOR:
             case LXT_SMART:
             case LXT_SMART:
+            case LXT_LOAD:
                 st = token2type(l->op);
                 st = token2type(l->op);
                 strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
                 strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
 
@@ -439,7 +445,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}");
+                parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart|load}");
                 return 0;
                 return 0;
                 break;
                 break;
             }
             }

+ 0 - 5
symon/symux/smart.conf

@@ -1,5 +0,0 @@
-mux 127.0.0.1 2100
-
-source 127.0.0.1 {
-	accept { cpu(0),  mem, smart(sda) }
-}

+ 11 - 7
symon/symux/symux.8

@@ -1,6 +1,6 @@
 .\"  -*- nroff -*-
 .\"  -*- nroff -*-
 .\"
 .\"
-.\" Copyright (c) 2001-2009 Willem Dijkstra
+.\" Copyright (c) 2001-2010 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
@@ -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 January 20, 2010
 .Dt SYMUX 8
 .Dt SYMUX 8
 .Os
 .Os
 .Sh NAME
 .Sh NAME
@@ -40,7 +40,7 @@
 .Pp
 .Pp
 .Sh DESCRIPTION
 .Sh DESCRIPTION
 .Xr symon 8
 .Xr symon 8
-is a lightweight system monitor that measures cpu, filesystem, interface, disk,
+is a lightweight system monitor that measures cpu, load, filesystem, interface, disk,
 memory, pf, pf queues, mbuf, proc and sensor statistics every 5 seconds. This
 memory, pf, pf queues, mbuf, proc and sensor statistics every 5 seconds. This
 information is then spooled to
 information is then spooled to
 .Nm
 .Nm
@@ -118,7 +118,7 @@ accept-stmt  = "accept" "{" resources "}"
 resources    = resource [ version ] ["(" argument ")"]
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " resources ]
                [ ","|" " resources ]
 resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io"
 resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io"
-               "mbuf" | "mem" | "pf" | "pfq" | "proc" |
+               "load" | "mbuf" | "mem" | "pf" | "pfq" | "proc" |
                "sensor" | "smart"
                "sensor" | "smart"
 version      = number
 version      = number
 argument     = number | interfacename | diskname
 argument     = number | interfacename | diskname
@@ -228,6 +228,9 @@ bit unsigned integers.
 .It df
 .It df
 Disk free statistics ( blocks : bfree : bavail : files :
 Disk free statistics ( blocks : bfree : bavail : files :
 ffree : synwrites : asyncwrites). Values are 64 bit unsigned integers.
 ffree : synwrites : asyncwrites). Values are 64 bit unsigned integers.
+.It load
+Load averages for the last 1, 5, and 15 minutes. Data is offered with precision
+2 and a maximum of 655.
 .It if
 .It if
 Alias for if2. See below.
 Alias for if2. See below.
 .It if1
 .It if1
@@ -343,8 +346,9 @@ will be unresponsive during this process.
 Willem Dijkstra <wpd@xs4all.nl>. \%Daniel \%Hartmeier helped to port to big-endian
 Willem Dijkstra <wpd@xs4all.nl>. \%Daniel \%Hartmeier helped to port to big-endian
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 .Pp
 .Pp
-Port contributors: \%Marc \%Balmer, \%Tito \%Dal \%Canton, \%Matthew \%Gream,
-\%Daniel \%Hartmeier, \%Constantine A. \%Murenin, J. \%Martin \%Petersen,
-\%Fredrik \%Soderblom, \%Harm \%Schotanus and \%Martin van der \%Werff.
+Port contributors: \%Marc \%Balmer, \%Tito \%Dal \%Canton, \%Matthew
+\%Gream, \%Daniel \%Hartmeier, \%Lars \%Kotthoff, \%Constantine
+A. \%Murenin, J. \%Martin \%Petersen, \%Fredrik \%Soderblom, \%Harm
+\%Schotanus and \%Martin van der \%Werff.
 .Sh SEE ALSO
 .Sh SEE ALSO
 .Xr symon 8
 .Xr symon 8

+ 1 - 1
symon/symux/symux.conf

@@ -9,7 +9,7 @@ source 127.0.0.1 {
 	  	 if(lo0),
 	  	 if(lo0),
 #	  	 pf,
 #	  	 pf,
 #         	 mbuf,
 #         	 mbuf,
-#         	 sensor(0),
+#         	 sensor(cpu0.temp0),
 #         	 proc(httpd),
 #         	 proc(httpd),
 #         	 if(xl0), if(de0), if(wi0),
 #         	 if(xl0), if(de0), if(wi0),
 #	  	 io(wd1), io(wd2), io(wd3), io(cd0)
 #	  	 io(wd1), io(wd2), io(wd3), io(cd0)