Browse Source

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

Wictor Lund 3 years ago
parent
commit
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
 
    - 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.
 
    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
   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
 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.
 #
 # 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,
                 current_pending => 7, uncorrectables => 8,
                 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 {

+ 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.
  *
  * The crc routine is by Rob Warnock <rpw3@sgi.com>, from the
@@ -111,6 +111,7 @@ struct {
     { MT_IF2, "LLLLLLLLLL" },
     { MT_CPUIOW, "cccccc" },
     { MT_SMART, "bbbbbbbbbbbb" },
+    { MT_LOAD, "ccc" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_EOT, "" }
 };
@@ -135,6 +136,7 @@ struct {
     { MT_IF2, LXT_IF },
     { MT_CPUIOW, LXT_CPUIOW },
     { MT_SMART, LXT_SMART },
+    { MT_LOAD, LXT_LOAD },
     { MT_EOT, LXT_BADTOKEN }
 };
 /* parallel crc32 table */
@@ -1070,3 +1072,15 @@ init_crc32()
         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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -127,6 +127,8 @@ struct mux {
     int clientsocket;           /* symux; incoming tcp connections */
     int symonsocket[AF_MAX];    /* symux; incoming symon data */
     int symuxsocket;            /* symon; outgoing data to mux */
+    int last;
+    int interval;
     struct symonpacket packet;
     struct sockaddr_storage sockaddr;
     struct streamlist sl;
@@ -160,8 +162,9 @@ SLIST_HEAD(muxlist, mux);
 #define MT_IF2    13
 #define MT_CPUIOW 14
 #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
@@ -342,6 +345,11 @@ struct packedstream {
             u_int8_t temperature2;
             u_int8_t free_fall_protection;
         }      ps_smart;
+        struct {
+            u_int16_t mload1;
+            u_int16_t mload2;
+            u_int16_t mload3;
+        }      ps_load;
     }     data;
 };
 
@@ -350,6 +358,7 @@ __BEGIN_DECLS
 char *type2str(const int);
 int bytelen_sourcelist(struct sourcelist *);
 int bytelen_streamlist(struct streamlist *);
+int gcd(int a, int b);
 int getheader(char *, struct symonpacketheader *);
 int ps2strn(struct packedstream *, char *, int, int);
 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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -56,6 +56,7 @@
 #include "xmalloc.h"
 #include "lex.h"
 #include "error.h"
+#include "sylimits.h"
 
 static struct {
     const char *name;
@@ -81,6 +82,7 @@ static struct {
     { "io", LXT_IO },
     { "io1", LXT_IO1 },
     { "io2", LXT_IO },
+    { "load", LXT_LOAD },
     { "mbuf", LXT_MBUF },
     { "mem", LXT_MEM },
     { "mem1", LXT_MEM1 },
@@ -305,6 +307,9 @@ lex_nexttoken(struct lex *l)
         if (strlen(l->token) == strspn(l->token, "0123456789")) {
             l->type = LXY_NUMBER;
             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;

+ 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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -41,8 +41,8 @@
 #include <stdio.h>
 
 /* Tokens known to lex */
-#define LXT_BADTOKEN   0
 #define LXT_ACCEPT     1
+#define LXT_BADTOKEN   0
 #define LXT_BEGIN      2
 #define LXT_CLOSE      3
 #define LXT_COMMA      4
@@ -59,24 +59,25 @@
 #define LXT_IN        15
 #define LXT_IO        16
 #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 {
     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.
  *
  * 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
 
 #define SMART_CYLINDER                             0xc24f
-#define SMART_TIMEOUT                              600
+#define SMART_TIMEOUT                              1000
 
 #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 int smart_status(unsigned char low, unsigned char high);
 
 #endif /* _SYMON_LIB_SMART_H */

+ 1 - 0
symon/lib/sylimits.h

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

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

@@ -10,4 +10,10 @@ if [ -f /proc/partitions ]; then
     else
 	echo "#undef HAS_PROC_PARTITIONS"
     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 <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
@@ -125,7 +126,7 @@ get_cpu(char *symon_buf, int maxlen, struct stream *st)
     }
 
     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_NICE],
                            &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])) {
       /* /proc/stat might not support steal */
       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_NICE],
 				   &st->parg.cp.time[CP_SYS],

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

@@ -41,6 +41,7 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <strings.h>
@@ -125,28 +126,28 @@ get_cpuiow(char *symon_buf, int maxlen, struct stream *st)
     }
 
     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,

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

@@ -40,7 +40,7 @@
 #include <stdio.h>
 #include <mntent.h>
 #include <string.h>
-#include <sys/vfs.h>
+#include <sys/statvfs.h>
 
 #include "conf.h"
 #include "error.h"
@@ -91,9 +91,9 @@ fsbtoblk(u_int64_t num, u_int64_t fsbs, u_int64_t bs)
 int
 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,
                       (u_int64_t)fsbtoblk(buf.f_blocks, 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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -139,7 +140,10 @@ get_if(char *symon_buf, int maxlen, struct stream *st)
     /* Inter-|   Receive                                                |  Transmit
      *  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_frame_errors, &stats.rx_compressed, &stats.multicast,
                     &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 <fcntl.h>
+#include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
 
@@ -135,7 +136,12 @@ get_io(char *symon_buf, int maxlen, struct stream *st)
     line += strlen(st->arg);
     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_sectors, &stats.read_milliseconds,
                     &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_weight)) {
 #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.write_issued, &stats.write_sectors)) {
             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]
  */
 
-#include <stdlib.h>
-#include <string.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
 #include <unistd.h>
+
 #include "error.h"
 #include "conf.h"
 #include "symon.h"
@@ -108,7 +110,7 @@ mem_getitem(char *name)
     }
 
     line += strlen(name);
-    if (1 < sscanf(line, ": %llu Kb", &stat)) {
+    if (1 < sscanf(line, ": %" SCNu64 " Kb", &stat)) {
         warning("could not parse memory statistics");
         return 0;
     } else {

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

@@ -40,11 +40,12 @@
 #include <sys/types.h>
 #include <sys/stat.h>
 
+#include <ctype.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 
 #include "error.h"
 #include "symon.h"
@@ -62,7 +63,7 @@ init_sensor(struct stream *st)
     char buf[SYMON_MAX_OBJSIZE];
     struct stat pathinfo;
     char *name, *p;
-    int n;
+    int32_t n;
 
     /* sensors can be identified as using
      *
@@ -88,11 +89,11 @@ init_sensor(struct stream *st)
     else
         name = st->arg;
 
-    if (sscanf(name, "fan%d", &n) == 1)
+    if (sscanf(name, "fan%" SCNd32, &n) == 1)
         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;
-    else if (sscanf(name, "temp%d", &n) == 1)
+    else if (sscanf(name, "temp%" SCNd32, &n) == 1)
         st->parg.sn.type = SENSOR_TEMP;
     else
         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 "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 */
 static struct hd_drive_cmd_hdr smart_cmd = {
     WIN_SMART, /* command code */
@@ -53,15 +64,20 @@ static struct hd_drive_cmd_hdr smart_cmd = {
     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 hd_drive_cmd_hdr cmd;
+    struct smart_values data;
     char name[MAX_PATH_LEN];
     int fd;
     int type;
     int failed;
-    struct hd_drive_cmd_hdr cmd;
-    struct smart_values data;
 };
+#pragma pack()
 
 static struct smart_device *smart_devs = NULL;
 static int smart_cur = 0;
@@ -104,9 +120,6 @@ init_smart(struct stream *st)
     /* store drivename in new block */
     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 */
     smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
 
@@ -125,21 +138,25 @@ init_smart(struct stream *st)
 void
 gets_smart()
 {
-    int i;
+  int 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)) {
             warning("smart: ioctl for drive '%s' failed: %d",
                     &smart_devs[i].name, errno);
             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;
          * additional code that identifies these drives would increase our
          * footprint and the amount of datajuggling we need to do; we would
          * rather ignore the checksums.
          */
-
         smart_devs[i].failed = 0;
     }
     return;

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

@@ -46,14 +46,28 @@
 #include "error.h"
 #include "xmalloc.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 */
-struct smart_device {
+static struct smart_device {
     char name[MAX_PATH_LEN];
     int fd;
     int type;
     int failed;
-    struct atareq cmd;
     struct smart_values data;
 };
 
@@ -99,14 +113,6 @@ init_smart(struct stream *st)
     /* store drivename in new block */
     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 */
     if ((sd->fd = opendisk(drivename, O_RDONLY | O_NONBLOCK, sd->name, sizeof(sd->name), 0)) == -1) {
         if (errno == ENOENT) {
@@ -129,14 +135,44 @@ void
 gets_smart()
 {
     int i;
+    struct atareq cmd;
 
     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)) {
             warning("smart: ioctl for drive '%s' failed: %d",
                     &smart_devs[i].name, errno);
             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;
          * additional code that identifies these drives would increase our
          * 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" ;;
 0)	echo "#undef HAS_KERN_CPTIME2" ;;
 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
 1)	echo "#define HAS_SENSORDEV	1" ;;
 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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,8 @@
  *
  */
 
+#include "conf.h"
+
 #include <sys/param.h>
 #include <sys/sysctl.h>
 
@@ -50,7 +52,11 @@
 #define pagetob(size) (((u_int32_t)size) << proc_pageshift)
 
 /* 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;
+#endif
 static int proc_max = 0;
 static int proc_cur = 0;
 static int proc_stathz = 0;
@@ -65,7 +71,7 @@ typedef long pctcpu;
 void
 gets_proc()
 {
-    int mib[3];
+    int mib[6];
     int procs;
     size_t size;
 
@@ -78,6 +84,41 @@ gets_proc()
               __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 */
     if (procs > proc_max) {
         proc_max = (procs * 5) / 4;
@@ -108,6 +149,7 @@ gets_proc()
     } else {
         proc_cur = size / sizeof(struct kinfo_proc);
     }
+#endif
 }
 
 void
@@ -145,7 +187,11 @@ int
 get_proc(char *symon_buf, int maxlen, struct stream *st)
 {
     int i;
+#ifdef HAS_KERN_PROC2
+    struct kinfo_proc2 *pp;
+#else
     struct kinfo_proc *pp;
+#endif
     u_quad_t  cpu_ticks = 0;
     u_quad_t  cpu_uticks = 0;
     u_quad_t  cpu_iticks = 0;
@@ -158,6 +204,21 @@ get_proc(char *symon_buf, int maxlen, struct stream *st)
     int n = 0;
 
     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) {
              /* cpu time - accumulated */
              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_ssize); /* stack */
              mem_rss += pagetob(pp->kp_eproc.e_vm.vm_rssize);     /* rss  */
+#endif
              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 */
     for (dev = 0; dev < MAXSENSORDEVICES; 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)
             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"
 
 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 )
 SRCS=	symon.c readconf.c symonnet.c ${MODS}
 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.
  *
  * 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));
-    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) {
         warning("%.200s:%d: monitored data for host '%.200s' has already been specified",
                 l->filename, l->cline, muxname);
@@ -115,6 +115,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_PROC:
         case LXT_SENSOR:
         case LXT_SMART:
+        case LXT_LOAD:
             st = token2type(l->op);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
@@ -153,7 +154,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_COMMA:
             break;
         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;
             break;
         }
@@ -182,9 +183,9 @@ read_monitor(struct muxlist * mul, struct lex * l)
         lex_nexttoken(l);
 
         if (l->op == LXT_SECOND) {
-            symon_interval = 1;
+            mux->interval = 1;
         } else if (l->type == LXY_NUMBER) {
-            symon_interval = l->value;
+            mux->interval = l->value;
             lex_nexttoken(l);
             if (l->op != LXT_SECONDS) {
                 parse_error(l, "seconds");
@@ -195,7 +196,8 @@ read_monitor(struct muxlist * mul, struct lex * l)
         }
 
         lex_nexttoken(l);
-    }
+    } else
+        mux->interval = SYMON_DEFAULT_INTERVAL;
 
     /* parse [stream [from <host>] to] */
     if (l->op != LXT_STREAM) {
@@ -260,10 +262,9 @@ read_config_file(struct muxlist *muxlist, char *filename)
                     l->filename, mux->name);
             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);

+ 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 -*-
 .\"
-.\" Copyright (c) 2001-2009 Willem Dijkstra
+.\" Copyright (c) 2001-2010 Willem Dijkstra
 .\" All rights reserved.
 .\"
 .\" Redistribution and use in source and binary forms, with or without
@@ -40,7 +40,7 @@
 .Pp
 .Sh DESCRIPTION
 .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
 information is then spooled to
 .Xr symux 8
@@ -107,8 +107,8 @@ monitor-rule = "monitor" "{" resources "}" [every]
                "stream" ["from" host] ["to"] host [ port ]
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " 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"
 version      = number
 argument     = number | name
@@ -179,8 +179,9 @@ exist.
 Willem Dijkstra <wpd@xs4all.nl>. \%Daniel \%Hartmeier helped to port to big-endian
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 .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
 .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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -58,13 +58,14 @@ void alarmhandler(int);
 void drop_privileges();
 void exithandler(int);
 void huphandler(int);
-void set_stream_use(struct muxlist *);
+void init_streams(struct muxlist *mul);
+void drop_privileges(int unsecure);
 __END_DECLS
 
 int flag_unsecure = 0;
 int flag_hup = 0;
 int flag_testconf = 0;
-int symon_interval = SYMON_DEFAULT_INTERVAL;
+int symon_interval = 0;
 
 /* map stream types to inits and getters */
 struct funcmap streamfunc[] = {
@@ -84,23 +85,46 @@ struct funcmap streamfunc[] = {
     {MT_IF2, 0, NULL, init_if, gets_if, get_if},
     {MT_CPUIOW, 0, NULL, init_cpuiow, gets_cpuiow, get_cpuiow},
     {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}
 };
 
 void
-set_stream_use(struct muxlist *mul)
+init_streams(struct muxlist *mul)
 {
-    struct mux *mux;
+    struct itimerval alarminterval;
     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(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
@@ -172,7 +196,6 @@ int
 main(int argc, char *argv[])
 {
     struct muxlist mul, newmul;
-    struct itimerval alarminterval;
     struct stream *stream;
     struct mux *mux;
     time_t now, last_update;
@@ -224,7 +247,11 @@ main(int argc, char *argv[])
         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 */
     for (i = 0; i < MT_EOT; i++)
@@ -267,24 +294,7 @@ main(int argc, char *argv[])
     /* prepare 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);
     for (;;) {                  /* FOREVER */
@@ -306,14 +316,7 @@ main(int argc, char *argv[])
                     info("read configuration file '%.200s' successfully", cfgpath);
 
                     /* 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 {
                 info("configuration unreachable because of privsep; keeping old configuration");
@@ -330,20 +333,36 @@ main(int argc, char *argv[])
             }
             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++)
-                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) {
-                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),
 #	  pf,
 #         mbuf,
-#         sensor(0),
+#         sensor(cpu0.temp0),
 #         proc(httpd),
 #         if(xl0), if(de0), if(wi0),
 #	  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.
  *
  * 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 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
 
 #endif                          /* _SYMON_SYMON_H */

+ 1 - 3
symon/symon/symonnet.c

@@ -85,10 +85,8 @@ send_packet(struct mux * mux)
 }
 /* Prepare a packet for data */
 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);
     mux->packet.header.symon_version = SYMON_PACKET_VER;
     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.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -37,7 +37,7 @@
 __BEGIN_DECLS
 void connect2mux(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 finish_packet(struct mux *);
 __END_DECLS

+ 11 - 3
symon/symux/c_smrrds.sh

@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# Copyright (c) 2001-2009 Willem Dijkstra
+# Copyright (c) 2001-2010 Willem Dijkstra
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -152,7 +152,7 @@ all)
     sh $this interval $INTERVAL child $config `$SYMUX -l`
     ;;
 
-cpu[0-9].rrd)
+cpu[0-9]*.rrd)
     # Build cpu file
     create_rrd $i \
 	DS:user:GAUGE:$INTERVAL:0:100 \
@@ -162,7 +162,7 @@ cpu[0-9].rrd)
 	DS:idle:GAUGE:$INTERVAL:0:100
     ;;
 
-cpuiow[0-9].rrd)
+cpuiow[0-9]*.rrd)
     # Build cpuiow file
     create_rrd $i \
 	DS:user:GAUGE:$INTERVAL:0:100 \
@@ -312,6 +312,14 @@ smart_*.rrd)
         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")
     # 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.
  *
  * 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_";
         ta = args;
         break;
+    case MT_LOAD:
+        ts = "load";
+        ta = "";
+        break;
 
     default:
         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_SENSOR:
                 case LXT_SMART:
+                case LXT_LOAD:
                     st = token2type(l->op);
                     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:
                     break;
                 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;
 
                     break;
@@ -378,6 +383,7 @@ read_source(struct sourcelist * sol, struct lex * l, int filecheck)
             case LXT_PROC:
             case LXT_SENSOR:
             case LXT_SMART:
+            case LXT_LOAD:
                 st = token2type(l->op);
                 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 */
             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;
                 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 -*-
 .\"
-.\" Copyright (c) 2001-2009 Willem Dijkstra
+.\" Copyright (c) 2001-2010 Willem Dijkstra
 .\" All rights reserved.
 .\"
 .\" 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
 .\" POSSIBILITY OF SUCH DAMAGE.
 .\"
-.Dd November 23, 2009
+.Dd January 20, 2010
 .Dt SYMUX 8
 .Os
 .Sh NAME
@@ -40,7 +40,7 @@
 .Pp
 .Sh DESCRIPTION
 .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
 information is then spooled to
 .Nm
@@ -118,7 +118,7 @@ accept-stmt  = "accept" "{" resources "}"
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " resources ]
 resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io"
-               "mbuf" | "mem" | "pf" | "pfq" | "proc" |
+               "load" | "mbuf" | "mem" | "pf" | "pfq" | "proc" |
                "sensor" | "smart"
 version      = number
 argument     = number | interfacename | diskname
@@ -228,6 +228,9 @@ bit unsigned integers.
 .It df
 Disk free statistics ( blocks : bfree : bavail : files :
 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
 Alias for if2. See below.
 .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
 architectures. \%Matthew \%Gream helped to port symon to other BSD platforms.
 .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
 .Xr symon 8

+ 1 - 1
symon/symux/symux.conf

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