Browse Source

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

Wictor Lund 3 years ago
parent
commit
74e4293533
100 changed files with 1408 additions and 550 deletions
  1. 27 2
      symon/CHANGELOG
  2. 0 2
      symon/HACKERS
  3. 3 5
      symon/INSTALL
  4. 0 2
      symon/Makefile
  5. 1 3
      symon/Makefile.inc
  6. 1 4
      symon/TODO
  7. 0 1
      symon/client/Makefile
  8. 9 3
      symon/client/SymuxClient.pm
  9. 1 2
      symon/client/getsymonitem.pl
  10. 21 12
      symon/lib/Makefile
  11. 4 3
      symon/lib/data.c
  12. 19 6
      symon/lib/data.h
  13. 0 2
      symon/lib/error.c
  14. 0 2
      symon/lib/error.h
  15. 7 5
      symon/lib/lex.c
  16. 6 6
      symon/lib/lex.h
  17. 0 2
      symon/lib/net.c
  18. 0 2
      symon/lib/net.h
  19. 61 0
      symon/lib/percentages.c
  20. 4 0
      symon/lib/percentages.h
  21. 104 0
      symon/lib/smart.c
  22. 80 0
      symon/lib/smart.h
  23. 0 2
      symon/lib/sylimits.h
  24. 0 2
      symon/lib/xmalloc.c
  25. 0 2
      symon/lib/xmalloc.h
  26. 0 1
      symon/platform/FreeBSD/Makefile.inc
  27. 10 1
      symon/platform/FreeBSD/conf.sh
  28. 6 6
      symon/platform/FreeBSD/platform.h
  29. 10 68
      symon/platform/FreeBSD/sm_cpu.c
  30. 0 2
      symon/platform/FreeBSD/sm_debug.c
  31. 0 2
      symon/platform/FreeBSD/sm_df.c
  32. 0 2
      symon/platform/FreeBSD/sm_if.c
  33. 0 2
      symon/platform/FreeBSD/sm_io.c
  34. 0 2
      symon/platform/FreeBSD/sm_mbuf.c
  35. 0 2
      symon/platform/FreeBSD/sm_mem.c
  36. 0 2
      symon/platform/FreeBSD/sm_pf.c
  37. 0 2
      symon/platform/FreeBSD/sm_pfq.c
  38. 0 2
      symon/platform/FreeBSD/sm_proc.c
  39. 201 0
      symon/platform/FreeBSD/sm_smart.c
  40. 0 2
      symon/platform/Linux/Makefile.inc
  41. 19 11
      symon/platform/Linux/platform.h
  42. 2 62
      symon/platform/Linux/sm_cpu.c
  43. 2 62
      symon/platform/Linux/sm_cpuiow.c
  44. 2 4
      symon/platform/Linux/sm_df.c
  45. 0 2
      symon/platform/Linux/sm_if.c
  46. 0 2
      symon/platform/Linux/sm_io.c
  47. 0 2
      symon/platform/Linux/sm_mem.c
  48. 157 0
      symon/platform/Linux/sm_sensor.c
  49. 173 0
      symon/platform/Linux/sm_smart.c
  50. 1 1
      symon/platform/NetBSD/Makefile.inc
  51. 8 6
      symon/platform/NetBSD/platform.h
  52. 2 66
      symon/platform/NetBSD/sm_cpu.c
  53. 0 2
      symon/platform/NetBSD/sm_debug.c
  54. 0 2
      symon/platform/NetBSD/sm_df.c
  55. 0 2
      symon/platform/NetBSD/sm_if.c
  56. 0 2
      symon/platform/NetBSD/sm_io.c
  57. 0 2
      symon/platform/NetBSD/sm_mbuf.c
  58. 0 2
      symon/platform/NetBSD/sm_mem.c
  59. 0 2
      symon/platform/NetBSD/sm_pf.c
  60. 0 2
      symon/platform/NetBSD/sm_pfq.c
  61. 0 2
      symon/platform/NetBSD/sm_proc.c
  62. 0 2
      symon/platform/NetBSD/sm_sensor.c
  63. 176 0
      symon/platform/NetBSD/sm_smart.c
  64. 0 1
      symon/platform/OpenBSD/Makefile.inc
  65. 1 2
      symon/platform/OpenBSD/platform.h
  66. 2 58
      symon/platform/OpenBSD/sm_cpu.c
  67. 0 2
      symon/platform/OpenBSD/sm_debug.c
  68. 0 2
      symon/platform/OpenBSD/sm_df.c
  69. 0 2
      symon/platform/OpenBSD/sm_if.c
  70. 0 2
      symon/platform/OpenBSD/sm_io.c
  71. 48 10
      symon/platform/OpenBSD/sm_mbuf.c
  72. 2 4
      symon/platform/OpenBSD/sm_mem.c
  73. 0 2
      symon/platform/OpenBSD/sm_pf.c
  74. 0 2
      symon/platform/OpenBSD/sm_pfq.c
  75. 0 2
      symon/platform/OpenBSD/sm_proc.c
  76. 0 2
      symon/platform/OpenBSD/sm_sensor.c
  77. 180 0
      symon/platform/OpenBSD/sm_smart.c
  78. 0 2
      symon/platform/stub/sm_cpu.c
  79. 0 2
      symon/platform/stub/sm_cpuiow.c
  80. 0 2
      symon/platform/stub/sm_debug.c
  81. 0 2
      symon/platform/stub/sm_df.c
  82. 0 2
      symon/platform/stub/sm_if.c
  83. 0 2
      symon/platform/stub/sm_io.c
  84. 0 2
      symon/platform/stub/sm_mbuf.c
  85. 0 2
      symon/platform/stub/sm_mem.c
  86. 0 2
      symon/platform/stub/sm_pf.c
  87. 0 2
      symon/platform/stub/sm_pfq.c
  88. 0 2
      symon/platform/stub/sm_proc.c
  89. 0 2
      symon/platform/stub/sm_sensor.c
  90. 24 0
      symon/platform/stub/sm_smart.c
  91. 1 2
      symon/symon/Makefile
  92. 0 1
      symon/symon/c_config.sh
  93. 12 12
      symon/symon/readconf.c
  94. 0 2
      symon/symon/readconf.h
  95. 6 0
      symon/symon/smart.conf
  96. 7 6
      symon/symon/symon.8
  97. 1 2
      symon/symon/symon.c
  98. 1 2
      symon/symon/symon.conf
  99. 6 2
      symon/symon/symon.h
  100. 0 2
      symon/symon/symonnet.c

+ 27 - 2
symon/CHANGELOG

@@ -1,3 +1,30 @@
+23/11/2009 - 2.80
+
+   - Removed all cvs ids, moved src control to git
+
+   - Added initial sensor probe for Linux which reads directly from hwmon. Note
+     that there is no conversion of the raw data to real voltage, temperature
+     or rotations.
+
+   - Added smart probe for NetBSD (Tito Dal Canton), Linux / FreeBSD / OpenBSD
+     (me). Note that smart values sometimes need per drive/per model
+     interpretation. Not all these probes have been tested thoroughly as they
+     require physical boxes to be tested on.
+
+   - Added libprobe; a library for code that is shared between probes,
+     e.g. smart decoding and cpu percentages calculation.
+
+   - platform/OpenBSD/sm_mem.c: more than 2^31 bytes of swap would overflow
+     calculation (Marco Pfatschbacher)
+
+   - client/SymuxClient.pm: typo fixed that clobbered total read/write
+     (Masahiro Yamagishi)
+
+   - client port now really optional in symon.conf
+
+   - platform/OpenBSD/sm_mbuf.c: patch from openbsd ports following h2k8 mcpl
+     changes (Stuart Henderson)
+
 07/04/2008 - 2.79
 
    - Top makefile will not compile symux - and not need librrd - if SYMON_ONLY
@@ -577,5 +604,3 @@
 01/10/2001 - Mon configuration is read from a mon.conf.
 29/09/2001 - Lexer had trouble dealing with ip-addresses. Cleaned up the number
              parsing code and removed a second comment reader.
-
-$Id: CHANGELOG,v 1.87 2008/04/07 06:01:05 dijkstra Exp $

+ 0 - 2
symon/HACKERS

@@ -1,5 +1,3 @@
-$Id: HACKERS,v 1.3 2008/01/30 12:06:49 dijkstra Exp $
-
 Adding a probe for a new platform
 ---------------------------------
 

+ 3 - 5
symon/INSTALL

@@ -23,7 +23,7 @@ Linux:    - r on /proc/net/dev: if
           - r on /proc/meminfo: mem
 
 all:
-          - r on <chroot>/etc/localtime for proper timezone logging
+          - r on chroot/etc/localtime for proper timezone logging
 
 Real quick on OpenBSD
 =====================
@@ -73,7 +73,7 @@ Less quick, but all OSes
      + you can define SYMON_ONLY if you do not want to compile symux / do not
        have rrdtool installed.
 
-     + symon/platform/<os>/Makefile.inc is read before Makefile.inc; define
+     + symon/platform/os/Makefile.inc is read before Makefile.inc; define
        your vars in the environment, or in Makefile.inc with != to force
        overwriting the defaults.
 
@@ -91,7 +91,7 @@ Less quick, but all OSes
   under /var/www.
 
 - Ensure that /etc/localtime is accessible by symon/symux. Failing this you
-  will get log messages in GMT. Note that etc is <chroot>/etc when symon
+  will get log messages in GMT. Note that etc is chroot/etc when symon
   chroots.
 
 - Both symon and symux will daemonize if started normally. Start them with
@@ -126,5 +126,3 @@ for FreeBSD, NetBSD and Linux.
 
 Willem Dijkstra - wpd@xs4all.nl
 
-$Id: INSTALL,v 1.23 2008/02/21 09:37:38 dijkstra Exp $
-

+ 0 - 2
symon/Makefile

@@ -1,5 +1,3 @@
-# $Id: Makefile,v 1.15 2008/01/30 13:19:40 dijkstra Exp $
-
 .ifdef SYMON_ONLY
 SUBDIR= lib symon
 .else

+ 1 - 3
symon/Makefile.inc

@@ -1,6 +1,4 @@
-# $Id: Makefile.inc,v 1.41 2008/01/30 13:19:40 dijkstra Exp $
-
-V=2.79
+V=2.80
 
 AR?=	ar
 CC?=	cc

+ 1 - 4
symon/TODO

@@ -9,13 +9,10 @@ TODO:
   should only read. clients should check incoming data for sanity.)
 
 - check for availability of rrd before compilation
-- upgrade percentages to a symon wide util; it is included seperately in all
-  cpu probes now.
+- release probe memory at config reload
 - same for pagetob and friends
 
 == longer term
 - change rrd to accommodate batch updates
 - write a muxer that supports unix pipes
 - test framework
-
-$Id: TODO,v 1.32 2008/02/20 08:17:17 dijkstra Exp $

+ 0 - 1
symon/client/Makefile

@@ -1,4 +1,3 @@
-# $Id: Makefile,v 1.3 2008/01/30 13:19:40 dijkstra Exp $
 OS!=uname -s
 .include "../platform/${OS}/Makefile.inc"
 .include "../Makefile.inc"

+ 9 - 3
symon/client/SymuxClient.pm

@@ -1,4 +1,3 @@
-# $Id: SymuxClient.pm,v 1.14 2008/01/30 13:19:40 dijkstra Exp $
 #
 # Copyright (c) 2001-2008 Willem Dijkstra
 # All rights reserved.
@@ -66,11 +65,18 @@ my $streamitem =
 	        m_drops => 13, m_wait => 14, m_drain => 15 },
      sensor => {value => 1},
      io     => {total_rxfers => 1, total_wxfers => 2, total_seeks => 3,
-		total_rbytes => 4, total_rbytes => 5 },
+		total_rbytes => 4, total_wbytes => 5 },
      pfq    => {sent_bytes => 1, sent_packets => 2, drop_bytes => 3,
 		drop_packets => 4},
      df     => {blocks => 1, bfree => 2, bavail => 3, files => 4, ffree => 5,
-		syncwrites => 6, asyncwrites => 7}};
+		syncwrites => 6, asyncwrites => 7},
+     smart  => {read_error_rate => 1, reallocated_sectors => 2, spin_retries => 3,
+                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}
+};
+
 sub new {
     my ($class, %arg) = @_;
     my $self;

+ 1 - 2
symon/client/getsymonitem.pl

@@ -1,8 +1,7 @@
 #!/usr/bin/perl
 #
-# $Id: getsymonitem.pl,v 1.2 2003/12/20 16:30:44 dijkstra Exp $
-#
 # Example program of how to use SymuxClient
+#
 
 use SymuxClient;
 

+ 21 - 12
symon/lib/Makefile

@@ -1,21 +1,30 @@
-# $Id: Makefile,v 1.14 2008/01/30 13:19:40 dijkstra Exp $
 OS!=uname -s
 .include "../platform/${OS}/Makefile.inc"
 .include "../Makefile.inc"
 
-SRCS=   error.c lex.c xmalloc.c net.c data.c
-OBJS+=	${SRCS:R:S/$/.o/g}
+SRCSsym=   	error.c lex.c xmalloc.c net.c data.c
+OBJSsym+=	${SRCSsym:R:S/$/.o/g}
+
+SRCSprobe=      percentages.c smart.c
+OBJSprobe+=     ${SRCSprobe:R:S/$/.o/g}
+
 CFLAGS+=-I../platform/${OS} -I.
 
-all: libsymon.a
+all: libsym.a libprobe.a
+
+${OBJSsym} ${OBJSprobe}: conf.h ../Makefile.inc Makefile
 
-${OBJS}: conf.h ../Makefile.inc
+libsym.a: ${OBJSsym}
+	@echo building standard library
+	@rm -f libsym.a
+	@${AR} cq libsym.a `${LORDER} ${OBJSsym} | ${TSORT}`
+	${RANLIB} libsym.a
 
-libsymon.a: ${OBJS}
-	@echo building standard symon library
-	@rm -f libsymon.a
-	@${AR} cq libsymon.a `${LORDER} ${OBJS} | ${TSORT}`
-	${RANLIB} libsymon.a
+libprobe.a: ${OBJSprobe}
+	@echo building probe helper library
+	@rm -f libprobe.a
+	@${AR} cq libprobe.a `${LORDER} ${OBJSprobe} | ${TSORT}`
+	${RANLIB} libprobe.a
 
 conf.h:  Makefile ../Makefile.inc
 	@echo Generating $@ on ${OS}
@@ -27,6 +36,6 @@ conf.h:  Makefile ../Makefile.inc
 	@if [ -f ../platform/${OS}/conf.sh ]; then sh ../platform/${OS}/conf.sh >> $@; fi
 
 clean:
-	rm -f conf.h libsymon.a ${OBJS}
+	rm -f conf.h libsym.a libprobe.a ${OBJSsym} ${OBJSprobe}
 
-install: libsymon.a
+install: libsym.a libprobe.a

+ 4 - 3
symon/lib/data.c

@@ -1,5 +1,3 @@
-/* $Id: data.c,v 1.36 2008/01/30 12:06:49 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -89,7 +87,7 @@ struct {
     { 'l', ":%lu", " %10lu", 12, sizeof(u_int32_t), (u_int64_t) 0xffffffff },
     { 's', ":%u", " %5u", 7, sizeof(u_int16_t), (u_int64_t) 0xffff },
     { 'c', ":%3.2f", " %3.2f", 8, sizeof(u_int16_t), (u_int64_t) 100 },
-    { 'b', ":%3u", " %3u", 5, sizeof(u_int8_t), (u_int64_t) 255 },
+    { 'b', ":%u", " %3u", 5, sizeof(u_int8_t), (u_int64_t) 255 },
     { '\0', NULL, NULL, 0, 0, 0 }
 };
 /* streams of <type> have the packedstream <form> */
@@ -112,6 +110,7 @@ struct {
     { MT_MEM2, "LLLLL" },
     { MT_IF2, "LLLLLLLLLL" },
     { MT_CPUIOW, "cccccc" },
+    { MT_SMART, "bbbbbbbbbbbb" },
     { MT_TEST, "LLLLDDDDllllssssccccbbbb" },
     { MT_EOT, "" }
 };
@@ -135,6 +134,7 @@ struct {
     { MT_MEM2, LXT_MEM },
     { MT_IF2, LXT_IF },
     { MT_CPUIOW, LXT_CPUIOW },
+    { MT_SMART, LXT_SMART },
     { MT_EOT, LXT_BADTOKEN }
 };
 /* parallel crc32 table */
@@ -605,6 +605,7 @@ ps2strn(struct packedstream * ps, char *buf, const int maxlen, int pretty)
         switch (vartype) {
         case 'b':
             bcopy(in, &b, sizeof(u_int8_t));
+            b &= 0xff;
             snprintf(out, strlenvar(vartype), formatstr, b);
             in++;
             break;

+ 19 - 6
symon/lib/data.h

@@ -1,5 +1,3 @@
-/* $Id: data.h,v 1.33 2008/01/30 12:06:49 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -143,8 +141,8 @@ SLIST_HEAD(muxlist, mux);
 
 /* Stream types
  *
- * Add new items at the bottom to preserve compatibility with older symon
- * instances
+ * Add new items at the bottom, before entries for test and eot to preserve
+ * compatibility with older symon instances
  */
 #define MT_IO1    0
 #define MT_CPU    1
@@ -161,8 +159,9 @@ SLIST_HEAD(muxlist, mux);
 #define MT_MEM2   12
 #define MT_IF2    13
 #define MT_CPUIOW 14
-#define MT_TEST   15
-#define MT_EOT    16
+#define MT_SMART  15
+#define MT_TEST   16
+#define MT_EOT    17
 
 /*
  * Unpacking of incoming packets is done via a packedstream structure. This
@@ -329,6 +328,20 @@ struct packedstream {
             u_int16_t midle;
             u_int16_t miowait;
         }      ps_cpuiow;
+        struct {
+            u_int8_t read_error_rate;
+            u_int8_t reallocated_sectors;
+            u_int8_t spin_retries;
+            u_int8_t air_flow_temp;
+            u_int8_t temperature;
+            u_int8_t reallocations;
+            u_int8_t current_pending;
+            u_int8_t uncorrectables;
+            u_int8_t soft_read_error_rate;
+            u_int8_t g_sense_error_rate;
+            u_int8_t temperature2;
+            u_int8_t free_fall_protection;
+        }      ps_smart;
     }     data;
 };
 

+ 0 - 2
symon/lib/error.c

@@ -1,5 +1,3 @@
-/* $Id: error.c,v 1.14 2007/02/11 20:07:31 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2004 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/lib/error.h

@@ -1,5 +1,3 @@
-/* $Id: error.h,v 1.11 2007/02/11 20:07:31 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2004 Willem Dijkstra
  * All rights reserved.

+ 7 - 5
symon/lib/lex.c

@@ -1,5 +1,3 @@
-/* $Id: lex.c,v 1.30 2008/01/30 12:06:50 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -96,6 +94,7 @@ static struct {
     { "second", LXT_SECOND },
     { "seconds", LXT_SECONDS },
     { "sensor", LXT_SENSOR },
+    { "smart", LXT_SMART },
     { "source", LXT_SOURCE },
     { "stream", LXT_STREAM },
     { "to", LXT_TO },
@@ -171,14 +170,16 @@ lex_copychar(struct lex *l)
 int
 lex_nextchar(struct lex *l)
 {
-    if (l == NULL)
+    if (l == NULL || l->eof)
         return 0;
 
     l->curpos++;
 
     if (l->curpos >= l->endpos)
-        if (!lex_readline(l))
+        if (!lex_readline(l)) {
+            l->eof = 1;
             return 0;
+        }
 
     if (l->buffer[l->curpos] == '\n')
         l->cline++;
@@ -208,7 +209,7 @@ lex_ungettoken(struct lex *l)
 int
 lex_nexttoken(struct lex *l)
 {
-    if (l == NULL)
+    if (l == NULL || l->eof)
         return 0;
 
     /* return same token as last time if it has been pushed back */
@@ -360,6 +361,7 @@ reset_lex(struct lex *l)
     l->tokpos = 0;
     l->type = LXY_UNKNOWN;
     l->unget = 0;
+    l->eof = 0;
     l->value = 0;
 }
 /* Destroy a lexical analyser */

+ 6 - 6
symon/lib/lex.h

@@ -1,5 +1,3 @@
-/* $Id: lex.h,v 1.26 2008/01/30 12:06:50 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -74,10 +72,11 @@
 #define LXT_SECOND    28
 #define LXT_SECONDS   29
 #define LXT_SENSOR    30
-#define LXT_SOURCE    31
-#define LXT_STREAM    32
-#define LXT_TO        33
-#define LXT_WRITE     34
+#define LXT_SMART     31
+#define LXT_SOURCE    32
+#define LXT_STREAM    33
+#define LXT_TO        34
+#define LXT_WRITE     35
 
 struct lex {
     char *buffer;               /* current line(s) */
@@ -91,6 +90,7 @@ struct lex {
     int endpos;                 /* current maxpos in buffer */
     int op;                     /* opcode of token, if string */
     int unget;                  /* bool; token pushed back */
+    int eof;                    /* bool; all tokens read */
     int tokpos;                 /* current position in token buffer */
     enum {
         LXY_STRING, LXY_NUMBER, LXY_UNKNOWN

+ 0 - 2
symon/lib/net.c

@@ -1,5 +1,3 @@
-/* $Id: net.c,v 1.14 2007/02/11 20:07:31 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2004 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/lib/net.h

@@ -1,5 +1,3 @@
-/* $Id: net.h,v 1.17 2007/12/11 14:17:59 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2007 Willem Dijkstra
  * All rights reserved.

+ 61 - 0
symon/lib/percentages.c

@@ -0,0 +1,61 @@
+/*
+ * The percentages function was written by William LeFebvre and is part
+ * of the 'top' utility. His copyright statement is below.
+ */
+
+/*
+ *  Top users/processes display for Unix
+ *  Version 3
+ *
+ *  This program may be freely redistributed,
+ *  but this entire comment MUST remain intact.
+ *
+ *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
+ *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
+ */
+
+#include <sys/types.h>
+
+#define UQUAD_MAX ((u_int64_t)0-1)
+#define QUAD_MAX ((int64_t)(UQUAD_MAX >> 1))
+
+/*
+ *  percentages(cnt, out, new, old, diffs) - calculate percentage change
+ *      between array "old" and "new", putting the percentages i "out".
+ *      "cnt" is size of each array and "diffs" is used for scratch space.
+ *      The array "old" is updated on each call.
+ *      The routine assumes modulo arithmetic.  This function is especially
+ *      useful on BSD mchines for calculating cpu state percentages.
+ */
+int
+percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
+{
+    int64_t change, total_change, *dp, half_total;
+    int i;
+
+    /* initialization */
+    total_change = 0;
+    dp = diffs;
+
+    /* calculate changes for each state and the overall change */
+    for (i = 0; i < cnt; i++) {
+        if ((change = *new - *old) < 0) {
+            /* this only happens when the counter wraps */
+            change = (QUAD_MAX - *old) + *new;
+        }
+        total_change += (*dp++ = change);
+        *old++ = *new++;
+    }
+
+    /* avoid divide by zero potential */
+    if (total_change == 0)
+        total_change = 1;
+
+    /* calculate percentages based on overall change, rounding up */
+    half_total = total_change / 2l;
+    for (i = 0; i < cnt; i++)
+        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
+
+    /* return the total in case the caller wants to use it */
+    return (total_change);
+}

+ 4 - 0
symon/lib/percentages.h

@@ -0,0 +1,4 @@
+#ifndef _SYMON_LIB_PERCENTAGES_H
+#define _SYMON_LIB_PERCENTAGES_H
+int percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs);
+#endif /* _SYMON_LIB_PERCENTAGES_H */

+ 104 - 0
symon/lib/smart.c

@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2009 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+#include <strings.h>
+
+#include "smart.h"
+
+/*
+ * smart_values are rewritten to a smart_report here. This function is reused
+ * across all platforms, as smart_values is the form the disks report the data
+ * back in.
+ */
+void
+smart_parse(struct smart_values *ds, struct smart_report *sr)
+{
+    int i;
+
+    bzero(sr, sizeof(struct smart_report));
+
+    for (i = 0; i < MAX_SMART_ATTRIBUTES; i++) {
+        switch (ds->attributes[i].id) {
+        case ATA_ATTRIBUTE_END:
+            /* end of attribute block reached */
+            return;
+            break;
+
+        case ATA_ATTRIBUTE_READ_ERROR_RATE:
+            sr->read_error_rate = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_REALLOCATED_SECTOR_COUNT:
+            sr->reallocated_sectors = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_SPIN_RETRY_COUNT:
+            sr->spin_retries = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_AIR_FLOW_TEMPERATURE:
+            sr->air_flow_temp = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_TEMPERATURE:
+            sr->temperature = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_REALLOCATION_EVENT_COUNT:
+            sr->reallocations = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_CURRENT_PENDING_SECTOR_COUNT:
+            sr->current_pending = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_UNCORRECTABLE_SECTOR_COUNT:
+            sr->uncorrectables = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_SOFT_READ_ERROR_RATE:
+            sr->soft_read_error_rate = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_G_SENSE_ERROR_RATE:
+            sr->g_sense_error_rate = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_TEMPERATURE2:
+            sr->temperature2 = ds->attributes[i].current;
+            break;
+
+        case ATA_ATTRIBUTE_FREE_FALL_PROTECTION:
+            sr->free_fall_protection = ds->attributes[i].current;
+            break;
+        }
+    }
+}

+ 80 - 0
symon/lib/smart.h

@@ -0,0 +1,80 @@
+#ifndef _SYMON_LIB_SMART_H
+#define _SYMON_LIB_SMART_H
+
+#define MAX_SMART_ATTRIBUTES 30
+
+/* The structures below are what the disks send back verbatim. Byte-alignment
+ * is mandatory here.
+ */
+#pragma pack(1)
+struct smart_attribute {
+    u_int8_t id;
+    u_int16_t flags;
+    u_int8_t current;
+    u_int8_t worst;
+    u_int8_t raw[6];
+    u_int8_t res;
+};
+
+/* smart_values structure should be 512 = one disk block exactly */
+struct smart_values {
+    u_int16_t rev;
+    struct smart_attribute attributes[MAX_SMART_ATTRIBUTES];
+    u_int8_t offline_status;
+    u_int8_t test_status;
+    u_int16_t offline_time;
+    u_int8_t vendor1;
+    u_int8_t offline_cap;
+    u_int16_t smart_cap;
+    u_int8_t errlog_capl;
+    u_int8_t vendor2;
+    u_int8_t stest_ctime;
+    u_int8_t etest_ctime;
+    u_int8_t ctest_ctime;
+    u_int8_t res[11];
+    u_int8_t vendor3[125];
+    u_int8_t sum;
+};
+#pragma pack()
+
+#ifndef DISK_BLOCK_LEN
+#define DISK_BLOCK_LEN                             512
+#endif
+
+#define SMART_CYLINDER                             0xc24f
+#define SMART_TIMEOUT                              600
+
+#define ATA_SMART_READ_VALUES                      0xd0
+
+#define ATA_ATTRIBUTE_END                          0x00
+#define ATA_ATTRIBUTE_READ_ERROR_RATE              0x01
+#define ATA_ATTRIBUTE_REALLOCATED_SECTOR_COUNT     0x05
+#define ATA_ATTRIBUTE_SPIN_RETRY_COUNT             0x0a
+#define ATA_ATTRIBUTE_AIR_FLOW_TEMPERATURE         0xbe
+#define ATA_ATTRIBUTE_TEMPERATURE                  0xc2
+#define ATA_ATTRIBUTE_REALLOCATION_EVENT_COUNT     0xc4
+#define ATA_ATTRIBUTE_CURRENT_PENDING_SECTOR_COUNT 0xc5
+#define ATA_ATTRIBUTE_UNCORRECTABLE_SECTOR_COUNT   0xc6
+#define ATA_ATTRIBUTE_SOFT_READ_ERROR_RATE         0xc9
+#define ATA_ATTRIBUTE_G_SENSE_ERROR_RATE           0xdd
+#define ATA_ATTRIBUTE_TEMPERATURE2                 0xe7
+#define ATA_ATTRIBUTE_FREE_FALL_PROTECTION         0xfe
+
+struct smart_report {
+    int read_error_rate;
+    int reallocated_sectors;
+    int spin_retries;
+    int air_flow_temp;
+    int temperature;
+    int reallocations;
+    int current_pending;
+    int uncorrectables;
+    int soft_read_error_rate;
+    int g_sense_error_rate;
+    int temperature2;
+    int free_fall_protection;
+};
+
+extern void smart_parse(struct smart_values *ds, struct smart_report *sr);
+
+#endif /* _SYMON_LIB_SMART_H */

+ 0 - 2
symon/lib/sylimits.h

@@ -1,5 +1,3 @@
-/* $Id: sylimits.h,v 1.8 2008/01/06 14:25:45 dijkstra Exp $ */
-
 #ifndef _LIB_LIMITS_H
 #define _LIB_LIMITS_H
 

+ 0 - 2
symon/lib/xmalloc.c

@@ -1,5 +1,3 @@
-/* $Id: xmalloc.c,v 1.8 2007/02/11 20:07:31 dijkstra Exp $ */
-
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland

+ 0 - 2
symon/lib/xmalloc.h

@@ -1,5 +1,3 @@
-/* $Id: xmalloc.h,v 1.7 2007/02/11 20:07:31 dijkstra Exp $ */
-
 /*
  * Author: Tatu Ylonen <ylo@cs.hut.fi>
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland

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

@@ -1,4 +1,3 @@
-# $Id: Makefile.inc,v 1.6 2008/01/30 13:19:40 dijkstra Exp $
 SYMON_LIBS?=-lkvm -ldevstat
 SYMUX_LIBS?=-lm
 

+ 10 - 1
symon/platform/FreeBSD/conf.sh

@@ -1,5 +1,4 @@
 #!/bin/sh
-# $Id: conf.sh,v 1.3 2005/03/20 16:17:22 dijkstra Exp $
 if grep -q "m_drops" /usr/include/sys/mbuf.h; then
     echo "#define HAS_MBUF_MDROPS	1"
 else
@@ -38,3 +37,13 @@ if grep -q "CPUSTATES" /usr/include/sys/resource.h; then
 else
     echo "#undef HAS_RESOURCE_CPUSTATE"
 fi
+if grep -q "IOCATAREQUEST" /usr/include/sys/ata.h; then
+    echo "#define HAS_IOCATAREQUEST 1"
+else
+    echo "#undef HAS_IOCATAREQUEST"
+fi
+if grep -q "ATA_SMART_CMD" /usr/include/sys/ata.h; then
+    echo "#define HAS_ATA_SMART_CMD 1"
+else
+    echo "#undef HAS_ATA_SMART_CMD"
+fi

+ 6 - 6
symon/platform/FreeBSD/platform.h

@@ -1,5 +1,3 @@
-/* $Id: platform.h,v 1.6 2007/02/11 20:07:31 dijkstra Exp $ */
-
 #ifndef _CONF_FREEBSD_H
 #define _CONF_FREEBSD_H
 
@@ -22,16 +20,18 @@
 
 union stream_parg {
     struct {
-        long time[CPUSTATES];
-        long old[CPUSTATES];
-        long diff[CPUSTATES];
-        int states[CPUSTATES];
+        long time1[CPUSTATES];
+        int64_t time2[CPUSTATES];
+        int64_t old[CPUSTATES];
+        int64_t diff[CPUSTATES];
+        int64_t states[CPUSTATES];
     } cp;
     struct {
         char rawdev[SYMON_DFNAMESIZE];
     } df;
     struct ifreq ifr;
     int sn;
+    int smart;
 };
 
 #endif

+ 10 - 68
symon/platform/FreeBSD/sm_cpu.c

@@ -1,10 +1,4 @@
-/* $Id: sm_cpu.c,v 1.5 2007/02/11 20:07:32 dijkstra Exp $ */
-
-/* The author of this code is Matthew Gream.
- *
- * The percentages function was written by William LeFebvre and is part
- * of the 'top' utility. His copyright statement is below.
- *
+/*
  * Copyright (c) 2004      Matthew Gream
  * All rights reserved.
  *
@@ -34,17 +28,6 @@
  *
  */
 
-/*
- *  Top users/processes display for Unix
- *  Version 3
- *
- *  This program may be freely redistributed,
- *  but this entire comment MUST remain intact.
- *
- *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
- *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
 /*
  * Get current cpu statistics in percentages (total of all counts = 100.0)
  * and returns them in symon_buf as
@@ -63,60 +46,14 @@
 #include <sys/sysctl.h>
 
 #include "error.h"
+#include "percentages.h"
 #include "symon.h"
 
-__BEGIN_DECLS
-int percentages(int, int *, long *, long *, long *);
-__END_DECLS
-
 /* Globals for this module all start with cp_ */
 static char cp_time_mib_str[] = "kern.cp_time";
 static int cp_time_mib[CTL_MAXNAME];
 static size_t cp_time_len = 0;
 static size_t cp_size;
-/*
- *  percentages(cnt, out, new, old, diffs) - calculate percentage change
- *      between array "old" and "new", putting the percentages i "out".
- *      "cnt" is size of each array and "diffs" is used for scratch space.
- *      The array "old" is updated on each call.
- *      The routine assumes modulo arithmetic.  This function is especially
- *      useful on BSD mchines for calculating cpu state percentages.
- */
-int
-percentages(int cnt, int *out, register long *new, register long *old, long *diffs)
-{
-    register int i;
-    register long change;
-    register long total_change;
-    register long *dp;
-    long half_total;
-
-    /* initialization */
-    total_change = 0;
-    dp = diffs;
-
-    /* calculate changes for each state and the overall change */
-    for (i = 0; i < cnt; i++) {
-        if (*new < *old)
-            change = (ULONG_MAX - *old) + *new;
-        else
-            change = *new - *old;
-        total_change += (*dp++ = change);
-        *old++ = *new++;
-    }
-
-    /* avoid divide by zero potential */
-    if (total_change == 0)
-        total_change = 1;
-
-    /* calculate percentages based on overall change, rounding up */
-    half_total = total_change / 2;
-    for (i = 0; i < cnt; i++)
-        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
-
-    /* return the total in case the caller wants to use it */
-    return total_change;
-}
 
 void
 init_cpu(struct stream *st)
@@ -129,7 +66,7 @@ init_cpu(struct stream *st)
         cp_time_len = 0;
     }
 
-    cp_size = sizeof(st->parg.cp.time);
+    cp_size = sizeof(st->parg.cp.time1);
     get_cpu(buf, sizeof(buf), st);
 
     info("started module cpu(%.200s)", st->arg);
@@ -144,17 +81,22 @@ gets_cpu()
 int
 get_cpu(char *symon_buf, int maxlen, struct stream *st)
 {
+    int i;
+
     if (!cp_time_len) {
         return 0;
     }
 
-    if (sysctl(cp_time_mib, cp_time_len, &st->parg.cp.time, &cp_size, NULL, 0) < 0) {
+    if (sysctl(cp_time_mib, cp_time_len, &st->parg.cp.time1, &cp_size, NULL, 0) < 0) {
         warning("%s:%d: sysctl kern.cp_time failed", __FILE__, __LINE__);
         return 0;
     }
 
     /* convert cp_time counts to percentages */
-    (void)percentages(CPUSTATES, st->parg.cp.states, st->parg.cp.time, st->parg.cp.old, st->parg.cp.diff);
+    for (i = 0; i < CPUSTATES; i++)
+        st->parg.cp.time2[i] = (int64_t) st->parg.cp.time1[i];
+
+    (void)percentages(CPUSTATES, st->parg.cp.states, st->parg.cp.time2, st->parg.cp.old, st->parg.cp.diff);
 
     return snpack(symon_buf, maxlen, st->arg, MT_CPU,
                   (double) (st->parg.cp.states[CP_USER] / 10.0),

+ 0 - 2
symon/platform/FreeBSD/sm_debug.c

@@ -1,5 +1,3 @@
-/* $Id: sm_debug.c,v 1.4 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c)      2004 Matthew Gream
  * Copyright (c) 2001-2005 Willem Dijkstra

+ 0 - 2
symon/platform/FreeBSD/sm_df.c

@@ -1,5 +1,3 @@
-/* $Id: sm_df.c,v 1.1 2007/02/11 20:08:19 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 Marc Balmer
  * All rights reserved.

+ 0 - 2
symon/platform/FreeBSD/sm_if.c

@@ -1,5 +1,3 @@
-/* $Id: sm_if.c,v 1.5 2007/12/11 14:17:59 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 Fredrik Soderblom
  * Copyright (c) 2005-2007 Willem Dijkstra

+ 0 - 2
symon/platform/FreeBSD/sm_io.c

@@ -1,5 +1,3 @@
-/* $Id: sm_io.c,v 1.5 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 J. Martin Petersen
  * All rights reserved.

+ 0 - 2
symon/platform/FreeBSD/sm_mbuf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mbuf.c,v 1.7 2007/04/20 18:53:24 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004 Matthew Gream
  * Copyright (c) 2003 Daniel Hartmeier

+ 0 - 2
symon/platform/FreeBSD/sm_mem.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mem.c,v 1.14 2008/03/21 13:22:03 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004      Matthew Gream
  * Copyright (c) 2001-2008 Willem Dijkstra

+ 0 - 2
symon/platform/FreeBSD/sm_pf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pf.c,v 1.6 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2002 Daniel Hartmeier
  * All rights reserved.

+ 0 - 2
symon/platform/FreeBSD/sm_pfq.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pfq.c,v 1.4 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 J. Martin Petersen
  * All rights reserved.

+ 0 - 2
symon/platform/FreeBSD/sm_proc.c

@@ -1,5 +1,3 @@
-/* $Id: sm_proc.c,v 1.9 2008/02/20 08:17:19 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004      Matthew Gream
  * Copyright (c) 2001-2008 Willem Dijkstra

+ 201 - 0
symon/platform/FreeBSD/sm_smart.c

@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2009 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ata.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "conf.h"
+#include "data.h"
+#include "error.h"
+#include "xmalloc.h"
+#include "smart.h"
+
+#ifdef HAS_IOCATAREQUEST
+#ifndef HAS_ATA_SMART_CMD
+#define ATA_SMART_CMD 0xb0
+#endif
+/* per drive storage structure */
+struct smart_device {
+    char name[MAXPATHLEN];
+    int fd;
+    int type;
+    int failed;
+    struct ata_ioc_request cmd;
+    struct smart_values data;
+};
+
+static struct smart_device *smart_devs = NULL;
+static int smart_cur = 0;
+
+void
+init_smart(struct stream *st)
+{
+    int i;
+    char drivename[MAXPATHLEN];
+    struct ata_ioc_request *p;
+
+    if (sizeof(struct smart_values) != DISK_BLOCK_LEN) {
+        fatal("smart: internal error: smart values structure is broken");
+    }
+
+    if (st->arg == NULL) {
+        fatal("smart: need a <device> argument");
+    }
+
+    bzero(drivename, MAXPATHLEN);
+    snprintf(drivename, MAXPATHLEN, "/dev/%s", st->arg);
+
+    /* look for drive in our global table */
+    for (i = 0; i < smart_cur; i++) {
+        if (strncmp(smart_devs[i].name, drivename, MAXPATHLEN) == 0) {
+            st->parg.smart = i;
+            return;
+        }
+    }
+
+    /* this is a new drive; allocate the command and data block */
+    if (smart_cur > SYMON_MAX_DOBJECTS) {
+        fatal("%s:%d: dynamic object limit (%d) exceeded for smart data",
+              __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
+    }
+
+    smart_devs = xrealloc(smart_devs, (smart_cur + 1) * sizeof(struct smart_device));
+
+    bzero(&smart_devs[smart_cur], sizeof(struct smart_device));
+
+    /* rewire all bufferlocations, as our addresses may have changed */
+    for (i = 0; i <= smart_cur; i++) {
+        smart_devs[i].cmd.data = (caddr_t)&smart_devs[i].data;
+    }
+
+    /* store drivename in new block */
+    snprintf(smart_devs[smart_cur].name, MAXPATHLEN, "%s", drivename);
+
+    /* populate ata command header */
+    p = &smart_devs[smart_cur].cmd;
+    p->u.ata.command = ATA_SMART_CMD;
+    p->timeout = SMART_TIMEOUT;
+    p->u.ata.feature = ATA_SMART_READ_VALUES;
+    p->u.ata.lba = SMART_CYLINDER << 8;
+    p->flags = ATA_CMD_READ;
+    p->count = DISK_BLOCK_LEN;
+
+    /* store filedescriptor to device */
+    smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
+
+    if (errno) {
+        fatal("smart: could not open '%s' for read; %.200s", drivename, strerror(errno));
+    }
+
+    /* store smart dev entry in stream to facilitate quick get */
+    st->parg.smart = smart_cur;
+
+    smart_cur++;
+
+    info("started module smart(%.200s)", st->arg);
+}
+
+void
+gets_smart()
+{
+    int i;
+
+    for (i = 0; i < smart_cur; i++) {
+        if (ioctl(smart_devs[i].fd, IOCATAREQUEST, &smart_devs[i].cmd) || smart_devs[i].cmd.error) {
+            warning("smart: ioctl for drive '%s' failed: %d",
+                    &smart_devs[i].name, errno);
+            smart_devs[i].failed = 1;
+        }
+
+        /* 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;
+}
+
+int
+get_smart(char *symon_buf, int maxlen, struct stream *st)
+{
+    struct smart_report sr;
+
+    if ((st->parg.smart < smart_cur) &&
+        (!smart_devs[st->parg.smart].failed))
+    {
+        smart_parse(&smart_devs[st->parg.smart].data, &sr);
+        return snpack(symon_buf, maxlen, st->arg, MT_SMART,
+                      sr.read_error_rate,
+                      sr.reallocated_sectors,
+                      sr.spin_retries,
+                      sr.air_flow_temp,
+                      sr.temperature,
+                      sr.reallocations,
+                      sr.current_pending,
+                      sr.uncorrectables,
+                      sr.soft_read_error_rate,
+                      sr.g_sense_error_rate,
+                      sr.temperature2,
+                      sr.free_fall_protection);
+    }
+
+    return 0;
+}
+#else
+void
+init_smart(struct stream *st)
+{
+    fatal("smart module not available");
+}
+void
+gets_smart()
+{
+    fatal("smart module not available");
+}
+int
+get_smart(char *symon_buf, int maxlen, struct stream *st)
+{
+    fatal("io module not available");
+
+    /* NOT REACHED */
+    return 0;
+}
+#endif

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

@@ -1,5 +1,3 @@
-# $Id: Makefile.inc,v 1.5 2008/02/21 09:37:47 dijkstra Exp $
-
 # LORDER and TSORT are non-functional and not needed on Linux. Tinker with
 # these at your own peril.
 LORDER=echo

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

@@ -1,5 +1,3 @@
-/* $Id: platform.h,v 1.10 2008/04/06 13:02:12 dijkstra Exp $ */
-
 #ifndef _CONF_LINUX_H
 #define _CONF_LINUX_H
 
@@ -37,26 +35,36 @@ union semun {
 #define CP_SOFTIRQ   6
 #define CP_STEAL     7
 
-#define MAX_PATH_LEN 1024
+#define MAX_PATH_LEN       1024
+#define DISK_BLOCK_LEN     512
+
+#define SENSOR_FAN       0
+#define SENSOR_IN        1
+#define SENSOR_TEMP      2
 
 union stream_parg {
     struct {
-        u_int64_t time[CPUSTATES];
-        u_int64_t old[CPUSTATES];
-        u_int64_t diff[CPUSTATES];
-        u_int64_t states[CPUSTATES];
+        int64_t time[CPUSTATES];
+        int64_t old[CPUSTATES];
+        int64_t diff[CPUSTATES];
+        int64_t states[CPUSTATES];
         char name[6];
     } cp;
     struct {
-        u_int64_t time[CPUSTATES];
-        u_int64_t old[CPUSTATES];
-        u_int64_t diff[CPUSTATES];
-        u_int64_t states[CPUSTATES];
+        int64_t time[CPUSTATES];
+        int64_t old[CPUSTATES];
+        int64_t diff[CPUSTATES];
+        int64_t states[CPUSTATES];
         char name[6];
     } cpw;
     struct {
         char mountpath[MAX_PATH_LEN];
     } df;
+    struct {
+        int type;
+        char path[MAX_PATH_LEN];
+    } sn;
+    int smart;
 };
 
 #endif

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

@@ -1,10 +1,4 @@
-/* $Id: sm_cpu.c,v 1.9 2008/01/30 12:06:50 dijkstra Exp $ */
-
-/* The author of this code is Willem Dijkstra (wpd@xs4all.nl).
- *
- * The percentages function was written by William LeFebvre and is part
- * of the 'top' utility. His copyright statement is below.
- *
+/*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
  *
@@ -34,17 +28,6 @@
  *
  */
 
-/*
- *  Top users/processes display for Unix
- *  Version 3
- *
- *  This program may be freely redistributed,
- *  but this entire comment MUST remain intact.
- *
- *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
- *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
 /*
  * Get current cpu statistics in percentages (total of all counts = 100.0)
  * and returns them in symon_buf as
@@ -65,57 +48,14 @@
 
 #include "conf.h"
 #include "error.h"
+#include "percentages.h"
 #include "symon.h"
 #include "xmalloc.h"
 
-__BEGIN_DECLS
-static int percentages(int, int64_t *, int64_t *, int64_t *, int64_t *);
-__END_DECLS
-
 /* Globals for this module all start with cp_ */
 static void *cp_buf = NULL;
 static int cp_size = 0;
 static int cp_maxsize = 0;
-/*
- *  percentages(cnt, out, new, old, diffs) - calculate percentage change
- *      between array "old" and "new", putting the percentages i "out".
- *      "cnt" is size of each array and "diffs" is used for scratch space.
- *      The array "old" is updated on each call.
- *      The routine assumes modulo arithmetic.  This function is especially
- *      useful on BSD mchines for calculating cpu state percentages.
- */
-static int
-percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
-{
-    int64_t change, total_change, *dp, half_total;
-    int i;
-
-    /* initialization */
-    total_change = 0;
-    dp = diffs;
-
-    /* calculate changes for each state and the overall change */
-    for (i = 0; i < cnt; i++) {
-        if ((change = *new - *old) < 0) {
-            /* this only happens when the counter wraps */
-            change = (QUAD_MAX - *old) + *new;
-        }
-        total_change += (*dp++ = change);
-        *old++ = *new++;
-    }
-
-    /* avoid divide by zero potential */
-    if (total_change == 0)
-        total_change = 1;
-
-    /* calculate percentages based on overall change, rounding up */
-    half_total = total_change / 2l;
-    for (i = 0; i < cnt; i++)
-        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
-
-    /* return the total in case the caller wants to use it */
-    return (total_change);
-}
 
 void
 init_cpu(struct stream *st)

+ 2 - 62
symon/platform/Linux/sm_cpuiow.c

@@ -1,10 +1,4 @@
-/* $Id: sm_cpuiow.c,v 1.2 2008/01/30 14:29:31 dijkstra Exp $ */
-
-/* The author of this code is Willem Dijkstra (wpd@xs4all.nl).
- *
- * The percentages function was written by William LeFebvre and is part
- * of the 'top' utility. His copyright statement is below.
- *
+/*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
  *
@@ -34,17 +28,6 @@
  *
  */
 
-/*
- *  Top users/processes display for Unix
- *  Version 3
- *
- *  This program may be freely redistributed,
- *  but this entire comment MUST remain intact.
- *
- *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
- *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
 /*
  * Get current cpu statistics in percentages (total of all counts = 100.0)
  * and returns them in symon_buf as
@@ -65,57 +48,14 @@
 
 #include "conf.h"
 #include "error.h"
+#include "percentages.h"
 #include "symon.h"
 #include "xmalloc.h"
 
-__BEGIN_DECLS
-static int percentages(int, int64_t *, int64_t *, int64_t *, int64_t *);
-__END_DECLS
-
 /* Globals for this module all start with cpw_ */
 static void *cpw_buf = NULL;
 static int cpw_size = 0;
 static int cpw_maxsize = 0;
-/*
- *  percentages(cnt, out, new, old, diffs) - calculate percentage change
- *      between array "old" and "new", putting the percentages i "out".
- *      "cnt" is size of each array and "diffs" is used for scratch space.
- *      The array "old" is updated on each call.
- *      The routine assumes modulo arithmetic.  This function is especially
- *      useful on BSD mchines for calculating cpu state percentages.
- */
-static int
-percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
-{
-    int64_t change, total_change, *dp, half_total;
-    int i;
-
-    /* initialization */
-    total_change = 0;
-    dp = diffs;
-
-    /* calculate changes for each state and the overall change */
-    for (i = 0; i < cnt; i++) {
-        if ((change = *new - *old) < 0) {
-            /* this only happens when the counter wraps */
-            change = (QUAD_MAX - *old) + *new;
-        }
-        total_change += (*dp++ = change);
-        *old++ = *new++;
-    }
-
-    /* avoid divide by zero potential */
-    if (total_change == 0)
-        total_change = 1;
-
-    /* calculate percentages based on overall change, rounding up */
-    half_total = total_change / 2l;
-    for (i = 0; i < cnt; i++)
-        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
-
-    /* return the total in case the caller wants to use it */
-    return (total_change);
-}
 
 void
 init_cpuiow(struct stream *st)

+ 2 - 4
symon/platform/Linux/sm_df.c

@@ -1,5 +1,3 @@
-/* $Id: sm_df.c,v 1.4 2007/11/29 07:47:51 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2007 Martin van der Werff
  * All rights reserved.
@@ -85,8 +83,8 @@ gets_df()
 u_int64_t
 fsbtoblk(u_int64_t num, u_int64_t fsbs, u_int64_t bs)
 {
-    return (((fsbs) != 0 && (fsbs) < (bs)) ? 
-        (num) / ((bs) / (fsbs)) : 
+    return (((fsbs) != 0 && (fsbs) < (bs)) ?
+        (num) / ((bs) / (fsbs)) :
         (num) * ((fsbs) / (bs)));
 }
 

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

@@ -1,5 +1,3 @@
-/* $Id: sm_if.c,v 1.9 2007/12/11 18:31:37 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2007 Willem Dijkstra
  * All rights reserved.

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

@@ -1,5 +1,3 @@
-/* $Id: sm_io.c,v 1.3 2008/04/06 13:02:12 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2006 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/platform/Linux/sm_mem.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mem.c,v 1.7 2008/01/30 14:29:31 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005-2007 Harm Schotanus
  * All rights reserved.

+ 157 - 0
symon/platform/Linux/sm_sensor.c

@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2009 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Get sensor data from the kernel via sysfs
+ *
+ * num : value
+ *
+ */
+
+#include "conf.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "error.h"
+#include "symon.h"
+#include "xmalloc.h"
+
+void
+privinit_sensor()
+{
+    /* EMPTY */
+}
+
+void
+init_sensor(struct stream *st)
+{
+    char buf[SYMON_MAX_OBJSIZE];
+    struct stat pathinfo;
+    char *name, *p;
+    int n;
+
+    /* sensors can be identified as using
+     *
+     * - a relative path; /sys/class/hwmon[/hwmon0][/device]/${arg}_input is
+     *   then assumed: hwmon0/fan1 or fan1
+     *
+     * - the full path, e.g. /sys/class/hwmon/hwmon0/fan1 or
+     *   /sys/class/hwmon/hwmon0/device/fan1
+     *
+     * - the full path outside of sysfs, this may be necessary for hwmon probes
+     *   that need to some calculation before returning usable results,
+     *   e.g. /symon/fan1
+     *
+     * Note that _input is always appended to the sensor argument.
+     */
+
+    if (strlen(st->arg) < 1)
+        fatal("sensor(): no valid argument");
+
+    /* Determine the sensor type */
+    if ((name = strrchr(st->arg, '/')))
+        name += 1;
+    else
+        name = st->arg;
+
+    if (sscanf(name, "fan%d", &n) == 1)
+        st->parg.sn.type = SENSOR_FAN;
+    else if (sscanf(name, "in%d", &n) == 1)
+        st->parg.sn.type = SENSOR_IN;
+    else if (sscanf(name, "temp%d", &n) == 1)
+        st->parg.sn.type = SENSOR_TEMP;
+    else
+        fatal("sensor(%.200s): '%s' is a unknown sensor type; expected fan/in/temp",
+              st->arg, name);
+
+    /* Find the sensor in sysfs */
+    p = &st->parg.sn.path[0];
+    if (st->arg[0] == '/') {
+        snprintf(p, MAX_PATH_LEN - 1, "%s_input", st->arg);
+        p[MAX_PATH_LEN - 1] = '\0';
+
+        if (stat(p, &pathinfo) < 0)
+            fatal("sensor(%.200s): could not find sensor at '%.200s'",
+                  st->arg, p);
+    } else {
+        snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/%s_input", st->arg);
+        p[MAX_PATH_LEN - 1] = '\0';
+
+        if (stat(p, &pathinfo) < 0) {
+            snprintf(p, MAX_PATH_LEN - 1, "/sys/class/hwmon/hwmon0/device/%s_input", st->arg);
+            p[MAX_PATH_LEN - 1] = '\0';
+
+            if (stat(p, &pathinfo) < 0)
+                fatal("sensor(%.200s): could not be found in /sys/class/hwmon/hwmon0[/device]/%s_input",
+                      st->arg, st->arg);
+        }
+    }
+
+    get_sensor(buf, sizeof(buf), st);
+
+    info("started module sensor(%.200s)", st->arg);
+}
+
+int
+get_sensor(char *symon_buf, int maxlen, struct stream *st)
+{
+    FILE *f;
+    double t;
+
+    if ((f = fopen(st->parg.sn.path, "r")) == NULL)
+        fatal("sensor(%s): cannot access %.200s: %.200s",
+              st->arg, st->parg.sn.path, strerror(errno));
+
+    if (fscanf(f, "%lf", &t) < 0) {
+        warning("sensor(%s): cannot read sensor value",
+                st->arg);
+        return 0;
+    }
+
+    if (fclose(f) < 0)
+        warning("sensor(%s): cannot close '%.200s'",
+                st->arg, st->parg.sn.path);
+
+    switch (st->parg.sn.type) {
+    case SENSOR_TEMP:
+    case SENSOR_IN:
+        t /= 1000.0;
+        break;
+    }
+
+    return snpack(symon_buf, maxlen, st->arg, MT_SENSOR, t);
+}

+ 173 - 0
symon/platform/Linux/sm_smart.c

@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2008-2009 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+#include <linux/hdreg.h>
+
+#include "conf.h"
+#include "data.h"
+#include "error.h"
+#include "xmalloc.h"
+#include "smart.h"
+
+/* Ata command register set for requesting smart values */
+static struct hd_drive_cmd_hdr smart_cmd = {
+    WIN_SMART, /* command code */
+    0, /* sector number */
+    SMART_READ_VALUES, /* feature */
+    1 /* sector count */
+};
+
+/* per drive storage structure */
+struct smart_device {
+    char name[MAX_PATH_LEN];
+    int fd;
+    int type;
+    int failed;
+    struct hd_drive_cmd_hdr cmd;
+    struct smart_values data;
+};
+
+static struct smart_device *smart_devs = NULL;
+static int smart_cur = 0;
+
+void
+init_smart(struct stream *st)
+{
+    int i;
+    char drivename[MAX_PATH_LEN];
+
+    if (sizeof(struct smart_values) != DISK_BLOCK_LEN) {
+        fatal("smart: internal error: smart values structure is broken");
+    }
+
+    if (st->arg == NULL) {
+        fatal("smart: need a <device> argument");
+    }
+
+    bzero(drivename, MAX_PATH_LEN);
+    snprintf(drivename, MAX_PATH_LEN, "/dev/%s", st->arg);
+
+    /* look for drive in our global table */
+    for (i = 0; i < smart_cur; i++) {
+        if (strncmp(smart_devs[i].name, drivename, MAX_PATH_LEN) == 0) {
+            st->parg.smart = i;
+            return;
+        }
+    }
+
+    /* this is a new drive; allocate the command and data block */
+    if (smart_cur > SYMON_MAX_DOBJECTS) {
+        fatal("%s:%d: dynamic object limit (%d) exceeded for smart data",
+              __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
+    }
+
+    smart_devs = xrealloc(smart_devs, (smart_cur + 1) * sizeof(struct smart_device));
+
+    bzero(&smart_devs[smart_cur], sizeof(struct smart_device));
+
+    /* 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);
+
+    if (errno) {
+        fatal("smart: could not open '%s' for read", drivename);
+    }
+
+    /* store smart dev entry in stream to facilitate quick get */
+    st->parg.smart = smart_cur;
+
+    smart_cur++;
+
+    info("started module smart(%.200s)", st->arg);
+}
+
+void
+gets_smart()
+{
+    int i;
+
+    for (i = 0; i < smart_cur; i++) {
+        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;
+        }
+
+        /* 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;
+}
+
+int
+get_smart(char *symon_buf, int maxlen, struct stream *st)
+{
+    struct smart_report sr;
+
+    if ((st->parg.smart < smart_cur) &&
+        (!smart_devs[st->parg.smart].failed))
+    {
+        smart_parse(&smart_devs[st->parg.smart].data, &sr);
+        return snpack(symon_buf, maxlen, st->arg, MT_SMART,
+                      sr.read_error_rate,
+                      sr.reallocated_sectors,
+                      sr.spin_retries,
+                      sr.air_flow_temp,
+                      sr.temperature,
+                      sr.reallocations,
+                      sr.current_pending,
+                      sr.uncorrectables,
+                      sr.soft_read_error_rate,
+                      sr.g_sense_error_rate,
+                      sr.temperature2,
+                      sr.free_fall_protection);
+    }
+
+    return 0;
+}

+ 1 - 1
symon/platform/NetBSD/Makefile.inc

@@ -1,2 +1,2 @@
-# $Id: Makefile.inc,v 1.5 2008/01/30 13:19:40 dijkstra Exp $
 RRDDIR?=/usr/pkg
+LIBS=-lutil

+ 8 - 6
symon/platform/NetBSD/platform.h

@@ -1,5 +1,3 @@
-/* $Id: platform.h,v 1.6 2007/07/05 13:14:05 dijkstra Exp $ */
-
 #ifndef _CONF_NETBSD_H
 #define _CONF_NETBSD_H
 
@@ -11,6 +9,8 @@
 
 #include <net/if.h>
 
+#include <stdio.h>
+
 #include "sylimits.h"
 
 #define SYMON_USER      "_symon"
@@ -22,18 +22,20 @@ union semun {
         int val;
 };
 
+#define MAX_PATH_LEN FILENAME_MAX
 union stream_parg {
     struct {
-        u_int64_t time[CPUSTATES];
-        u_int64_t old[CPUSTATES];
-        u_int64_t diff[CPUSTATES];
-        int states[CPUSTATES];
+        int64_t time[CPUSTATES];
+        int64_t old[CPUSTATES];
+        int64_t diff[CPUSTATES];
+        int64_t states[CPUSTATES];
     } cp;
     struct {
         char rawdev[SYMON_DFNAMESIZE];
     } df;
     struct ifdatareq ifr;
     int sn;
+    int smart;
 };
 
 #endif

+ 2 - 66
symon/platform/NetBSD/sm_cpu.c

@@ -1,10 +1,4 @@
-/* $Id: sm_cpu.c,v 1.5 2007/02/11 20:07:32 dijkstra Exp $ */
-
-/* The author of this code is Matthew Gream.
- *
- * The percentages function was written by William LeFebvre and is part
- * of the 'top' utility. His copyright statement is below.
- *
+/*
  * Copyright (c) 2004      Matthew Gream
  * All rights reserved.
  *
@@ -34,17 +28,6 @@
  *
  */
 
-/*
- *  Top users/processes display for Unix
- *  Version 3
- *
- *  This program may be freely redistributed,
- *  but this entire comment MUST remain intact.
- *
- *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
- *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
 /*
  * Get current cpu statistics in percentages (total of all counts = 100.0)
  * and returns them in symon_buf as
@@ -62,59 +45,12 @@
 #include <sys/sched.h>
 
 #include "error.h"
+#include "percentages.h"
 #include "symon.h"
 
-__BEGIN_DECLS
-int percentages(int, int *, u_int64_t *, u_int64_t *, u_int64_t *);
-__END_DECLS
-
 /* Globals for this module all start with cp_ */
 static int cp_time_mib[] = {CTL_KERN, KERN_CP_TIME};
 static size_t cp_size;
-/*
- *  percentages(cnt, out, new, old, diffs) - calculate percentage change
- *      between array "old" and "new", putting the percentages i "out".
- *      "cnt" is size of each array and "diffs" is used for scratch space.
- *      The array "old" is updated on each call.
- *      The routine assumes modulo arithmetic.  This function is especially
- *      useful on BSD mchines for calculating cpu state percentages.
- */
-int
-percentages(int cnt, int *out, register u_int64_t *new, register u_int64_t *old, u_int64_t *diffs)
-{
-    register int i;
-    register u_int64_t change;
-    register u_int64_t total_change;
-    register u_int64_t *dp;
-    u_int64_t half_total;
-
-    /* initialization */
-    total_change = 0;
-    dp = diffs;
-
-    /* calculate changes for each state and the overall change */
-    for (i = 0; i < cnt; i++) {
-        if (*new < *old)
-            change = (ULLONG_MAX - *old) + *new;
-        else
-            change = *new - *old;
-        total_change += (*dp++ = change);
-        *old++ = *new++;
-    }
-
-    /* avoid divide by zero potential */
-    if (total_change == 0)
-        total_change = 1;
-
-    /* calculate percentages based on overall change, rounding up */
-    half_total = total_change / 2;
-    for (i = 0; i < cnt; i++)
-        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
-
-    /* return the total in case the caller wants to use it */
-    return total_change;
-}
-
 void
 init_cpu(struct stream *st)
 {

+ 0 - 2
symon/platform/NetBSD/sm_debug.c

@@ -1,5 +1,3 @@
-/* $Id: sm_debug.c,v 1.5 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004      Matthew Gream
  * Copyright (c) 2001-2005 Willem Dijkstra

+ 0 - 2
symon/platform/NetBSD/sm_df.c

@@ -1,5 +1,3 @@
-/* $Id: sm_df.c,v 1.2 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 Marc Balmer
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_if.c

@@ -1,5 +1,3 @@
-/* $Id: sm_if.c,v 1.6 2007/12/11 14:17:59 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004-2007      Matthew Gream
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_io.c

@@ -1,5 +1,3 @@
-/* $Id: sm_io.c,v 1.5 2007/07/05 13:33:26 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2007      Willem Dijkstra
  * Copyright (c) 2004      Matthew Gream

+ 0 - 2
symon/platform/NetBSD/sm_mbuf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mbuf.c,v 1.4 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2003 Daniel Hartmeier
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_mem.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mem.c,v 1.4 2008/02/20 08:17:25 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_pf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pf.c,v 1.2 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2002 Daniel Hartmeier
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_pfq.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pfq.c,v 1.5 2007/07/09 12:32:16 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 J. Martin Petersen
  * All rights reserved.

+ 0 - 2
symon/platform/NetBSD/sm_proc.c

@@ -1,5 +1,3 @@
-/* $Id: sm_proc.c,v 1.6 2008/02/20 08:17:25 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004      Matthew Gream
  * Copyright (c) 2001-2008 Willem Dijkstra

+ 0 - 2
symon/platform/NetBSD/sm_sensor.c

@@ -1,5 +1,3 @@
-/* $Id: sm_sensor.c,v 1.4 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2004      Matthew Gream
  * All rights reserved.

+ 176 - 0
symon/platform/NetBSD/sm_smart.c

@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2008 Tito Dal Canton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dev/ata/atareg.h>
+#include <sys/ataio.h>
+#include <util.h>
+
+#include "conf.h"
+#include "data.h"
+#include "error.h"
+#include "xmalloc.h"
+#include "smart.h"
+
+/* per drive storage structure */
+struct smart_device {
+    char name[MAX_PATH_LEN];
+    int fd;
+    int type;
+    int failed;
+    struct atareq cmd;
+    struct smart_values data;
+};
+
+static struct smart_device *smart_devs = NULL;
+static int smart_size = 0;
+
+void
+init_smart(struct stream *st)
+{
+    int i;
+    char drivename[MAX_PATH_LEN];
+    struct smart_device *sd;
+
+    if (sizeof(struct smart_values) != DISK_BLOCK_LEN) {
+        fatal("smart: internal error: smart values structure is broken");
+    }
+
+    if (st->arg == NULL) {
+        fatal("smart: need a <device> argument");
+    }
+
+    bzero(drivename, MAX_PATH_LEN);
+    snprintf(drivename, MAX_PATH_LEN, "/dev/%s", st->arg);
+
+    /* look for drive in our global table */
+    for (i = 0; i < smart_size; i++) {
+        if (strncmp(smart_devs[i].name, drivename, MAX_PATH_LEN) == 0) {
+            st->parg.smart = i;
+            return;
+        }
+    }
+
+    /* this is a new drive; allocate the command and data block */
+    smart_size++;
+    smart_devs = xrealloc(smart_devs, smart_size * sizeof(struct smart_device));
+    sd = &smart_devs[smart_size - 1];
+    bzero(sd, sizeof(struct smart_device));
+
+    /* rewire all bufferlocations, as our addresses may have changed */
+    for (i = 0; i < smart_size; i++)
+        smart_devs[i].cmd.databuf = (caddr_t)&smart_devs[i].data;
+
+    /* 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) {
+            /* Device does not exist, retry using cooked name semantics */
+            if ((sd->fd = opendisk(drivename, O_RDONLY | O_NONBLOCK, sd->name, sizeof(sd->name), 1)) == -1) {
+                fatal("smart: could not open '%s' for read", drivename);
+            }
+        } else {
+            fatal("smart: could not open '%s' for read", drivename);
+        }
+    }
+
+    /* store smart dev entry in stream to facilitate quick get */
+    st->parg.smart = smart_size - 1;
+
+    info("started module smart(%.200s)", st->arg);
+}
+
+void
+gets_smart()
+{
+    int i;
+
+    for (i = 0; i < smart_size; i++) {
+        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;
+        }
+
+        /* 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;
+}
+
+int
+get_smart(char *symon_buf, int maxlen, struct stream *st)
+{
+    struct smart_report sr;
+
+    if ((st->parg.smart < smart_size) &&
+        (!smart_devs[st->parg.smart].failed))
+    {
+        smart_parse(&smart_devs[st->parg.smart].data, &sr);
+        return snpack(symon_buf, maxlen, st->arg, MT_SMART,
+                      sr.read_error_rate,
+                      sr.reallocated_sectors,
+                      sr.spin_retries,
+                      sr.air_flow_temp,
+                      sr.temperature,
+                      sr.reallocations,
+                      sr.current_pending,
+                      sr.uncorrectables,
+                      sr.soft_read_error_rate,
+                      sr.g_sense_error_rate,
+                      sr.temperature2,
+                      sr.free_fall_protection);
+    }
+
+    return 0;
+}

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

@@ -1,3 +1,2 @@
-# $Id: Makefile.inc,v 1.5 2008/01/30 13:19:40 dijkstra Exp $
 SYMUX_LIBS?=-L/usr/X11R6/lib -lfontconfig
 MANDIR?=man

+ 1 - 2
symon/platform/OpenBSD/platform.h

@@ -1,5 +1,3 @@
-/* $Id: platform.h,v 1.8 2007/05/12 16:46:27 dijkstra Exp $ */
-
 #ifndef _CONF_OPENBSD_H
 #define _CONF_OPENBSD_H
 
@@ -39,6 +37,7 @@ union stream_parg {
         int mib[5];
 #endif
     } sn;
+    int smart;
 };
 
 #endif

+ 2 - 58
symon/platform/OpenBSD/sm_cpu.c

@@ -1,10 +1,4 @@
-/* $Id: sm_cpu.c,v 1.26 2007/07/09 12:54:18 dijkstra Exp $ */
-
-/* The author of this code is Willem Dijkstra (wpd@xs4all.nl).
- *
- * The percentages function was written by William LeFebvre and is part
- * of the 'top' utility. His copyright statement is below.
- *
+/*
  * Copyright (c) 2001-2007 Willem Dijkstra
  * All rights reserved.
  *
@@ -34,17 +28,6 @@
  *
  */
 
-/*
- *  Top users/processes display for Unix
- *  Version 3
- *
- *  This program may be freely redistributed,
- *  but this entire comment MUST remain intact.
- *
- *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
- *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
- */
-
 /*
  * Get current cpu statistics in percentages (total of all counts = 100.0)
  * and returns them in symon_buf as
@@ -66,47 +49,8 @@
 #include <string.h>
 
 #include "error.h"
+#include "percentages.h"
 #include "symon.h"
-/*
- *  percentages(cnt, out, new, old, diffs) - calculate percentage change
- *      between array "old" and "new", putting the percentages i "out".
- *      "cnt" is size of each array and "diffs" is used for scratch space.
- *      The array "old" is updated on each call.
- *      The routine assumes modulo arithmetic.  This function is especially
- *      useful on BSD mchines for calculating cpu state percentages.
- */
-int
-percentages(int cnt, int64_t *out, int64_t *new, int64_t *old, int64_t *diffs)
-{
-    int64_t change, total_change, *dp, half_total;
-    int i;
-
-    /* initialization */
-    total_change = 0;
-    dp = diffs;
-
-    /* calculate changes for each state and the overall change */
-    for (i = 0; i < cnt; i++) {
-        if ((change = *new - *old) < 0) {
-            /* this only happens when the counter wraps */
-            change = (QUAD_MAX - *old) + *new;
-        }
-        total_change += (*dp++ = change);
-        *old++ = *new++;
-    }
-
-    /* avoid divide by zero potential */
-    if (total_change == 0)
-        total_change = 1;
-
-    /* calculate percentages based on overall change, rounding up */
-    half_total = total_change / 2l;
-    for (i = 0; i < cnt; i++)
-        *out++ = ((*diffs++ * 1000 + half_total) / total_change);
-
-    /* return the total in case the caller wants to use it */
-    return (total_change);
-}
 
 void
 init_cpu(struct stream *st)

+ 0 - 2
symon/platform/OpenBSD/sm_debug.c

@@ -1,5 +1,3 @@
-/* $Id: sm_debug.c,v 1.8 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2005 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/platform/OpenBSD/sm_df.c

@@ -1,5 +1,3 @@
-/* $Id: sm_df.c,v 1.4 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 Marc Balmer
  * All rights reserved.

+ 0 - 2
symon/platform/OpenBSD/sm_if.c

@@ -1,5 +1,3 @@
-/* $Id: sm_if.c,v 1.18 2007/12/11 14:17:59 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2007 Willem Dijkstra
  * All rights reserved.

+ 0 - 2
symon/platform/OpenBSD/sm_io.c

@@ -1,5 +1,3 @@
-/* $Id: sm_io.c,v 1.19 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2004 Willem Dijkstra
  * All rights reserved.

+ 48 - 10
symon/platform/OpenBSD/sm_mbuf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mbuf.c,v 1.8 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2003 Daniel Hartmeier
  * All rights reserved.
@@ -77,6 +75,8 @@ get_mbuf(char *symon_buf, int maxlen, struct stream *st)
     int totmem, totused, totmbufs, totpct;
     u_int32_t stats[15];
 
+    totmem = totused = 0;
+
     mib[0] = CTL_KERN;
     mib[1] = KERN_MBSTAT;
     size = sizeof(mbstat);
@@ -113,25 +113,63 @@ get_mbuf(char *symon_buf, int maxlen, struct stream *st)
         }
         if (!strcmp(name, "mbpl")) {
             bcopy(&pool, &mbpool, sizeof(pool));
-            flag |= 1;
+            flag |= (1 << 0);
         } else if (!strcmp(name, "mclpl")) {
             bcopy(&pool, &mclpool, sizeof(pool));
-            flag |= 2;
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 1);
+        } else if (!strcmp(name, "mcl2k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 2);
+        } else if (!strcmp(name, "mcl4k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 3);
+        } else if (!strcmp(name, "mcl8k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 4);
+        } else if (!strcmp(name, "mcl9k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 5);
+        } else if (!strcmp(name, "mcl12k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 6);
+        } else if (!strcmp(name, "mcl16k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 7);
+        } else if (!strcmp(name, "mcl64k")) {
+            bcopy(&pool, &mclpool, sizeof(pool));
+            totmem += mclpool.pr_npages * page_size;
+            totused += (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+            flag |= (1 << 8);
         }
-        if (flag == 3)
+        if (flag == 3 || flag == 509)
             break;
     }
-    if (flag != 3) {
-        warning("mbuf(%.200s) failed (flag != 3)", st->arg);
+
+    /* Check pre/post h2k8 mcpl */
+    if ((flag != 3) && (flag != 509)) {
+        warning("mbuf(%.200s) failed (%d)", st->arg, flag);
         return 0;
     }
 
     totmbufs = 0;
     for (i = 0; i < nmbtypes; ++i)
         totmbufs += mbstat.m_mtypes[i];
-    totmem = (mbpool.pr_npages + mclpool.pr_npages) * page_size;
-    totused = (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size +
-        (mclpool.pr_nget - mclpool.pr_nput) * mclpool.pr_size;
+    totmem += mbpool.pr_npages * page_size;
+    totused += (mbpool.pr_nget - mbpool.pr_nput) * mbpool.pr_size;
     totpct = (totmem == 0) ? 0 : ((totused * 100) / totmem);
 
     stats[0] = totmbufs;

+ 2 - 4
symon/platform/OpenBSD/sm_mem.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mem.c,v 1.23 2008/02/20 08:17:25 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -124,8 +122,8 @@ gets_mem()
         /* Total things up */
         for (i = 0; i < me_nswap; i++) {
             if (me_swdev[i].se_flags & SWF_ENABLE) {
-                me_stats[3] += (me_swdev[i].se_inuse * DEV_BSIZE);
-                me_stats[4] += (me_swdev[i].se_nblks * DEV_BSIZE);
+                me_stats[3] += ((u_int64_t)me_swdev[i].se_inuse * DEV_BSIZE);
+                me_stats[4] += ((u_int64_t)me_swdev[i].se_nblks * DEV_BSIZE);
             }
         }
     }

+ 0 - 2
symon/platform/OpenBSD/sm_pf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pf.c,v 1.13 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2002 Daniel Hartmeier
  * All rights reserved.

+ 0 - 2
symon/platform/OpenBSD/sm_pfq.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pfq.c,v 1.5 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2005 J. Martin Petersen
  * All rights reserved.

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

@@ -1,5 +1,3 @@
-/* $Id: sm_proc.c,v 1.9 2008/02/20 08:17:25 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.

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

@@ -1,5 +1,3 @@
-/* $Id: sm_sensor.c,v 1.11 2007/02/13 19:12:26 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2005 Willem Dijkstra
  * Copyright (c) 2006/2007 Constantine A. Murenin

+ 180 - 0
symon/platform/OpenBSD/sm_smart.c

@@ -0,0 +1,180 @@
+/*
+ * Copyright (c) 2009 Willem Dijkstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *    - Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    - Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ataio.h>
+#include <dev/ata/atavar.h>
+#include <dev/ic/wdcreg.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "conf.h"
+#include "data.h"
+#include "error.h"
+#include "xmalloc.h"
+#include "smart.h"
+
+/* per drive storage structure */
+struct smart_device {
+    char name[MAXPATHLEN];
+    int fd;
+    int type;
+    int failed;
+    struct atareq cmd;
+    struct smart_values data;
+};
+
+static struct smart_device *smart_devs = NULL;
+static int smart_cur = 0;
+
+void
+init_smart(struct stream *st)
+{
+    int i;
+    char drivename[MAXPATHLEN];
+    struct atareq *p;
+
+    if (sizeof(struct smart_values) != DISK_BLOCK_LEN) {
+        fatal("smart: internal error: smart values structure is broken");
+    }
+
+    if (st->arg == NULL) {
+        fatal("smart: need a <device> argument");
+    }
+
+    bzero(drivename, MAXPATHLEN);
+    snprintf(drivename, MAXPATHLEN, "/dev/%s", st->arg);
+
+    /* look for drive in our global table */
+    for (i = 0; i < smart_cur; i++) {
+        if (strncmp(smart_devs[i].name, drivename, MAXPATHLEN) == 0) {
+            st->parg.smart = i;
+            return;
+        }
+    }
+
+    /* this is a new drive; allocate the command and data block */
+    if (smart_cur > SYMON_MAX_DOBJECTS) {
+        fatal("%s:%d: dynamic object limit (%d) exceeded for smart data",
+              __FILE__, __LINE__, SYMON_MAX_DOBJECTS);
+    }
+
+    smart_devs = xrealloc(smart_devs, (smart_cur + 1) * sizeof(struct smart_device));
+
+    bzero(&smart_devs[smart_cur], sizeof(struct smart_device));
+
+    /* rewire all bufferlocations, as our addresses may have changed */
+    for (i = 0; i <= smart_cur; i++) {
+        smart_devs[i].cmd.databuf = (caddr_t)&smart_devs[i].data;
+    }
+
+    /* store drivename in new block */
+    snprintf(smart_devs[smart_cur].name, MAXPATHLEN, "%s", drivename);
+
+    /* populate ata command header */
+    p = &smart_devs[smart_cur].cmd;
+    p->command = ATAPI_SMART;
+    p->timeout = SMART_TIMEOUT;
+    p->features = ATA_SMART_READ_VALUES;
+    p->cylinder = htole16(SMART_CYLINDER);
+    p->flags = ATACMD_READ;
+    p->databuf = (caddr_t) &smart_devs[smart_cur].data;
+    p->datalen = DISK_BLOCK_LEN;
+
+    /* store filedescriptor to device */
+    smart_devs[smart_cur].fd = open(drivename, O_RDONLY | O_NONBLOCK);
+
+    if (errno) {
+        fatal("smart: could not open '%s' for read", drivename);
+    }
+
+    /* store smart dev entry in stream to facilitate quick get */
+    st->parg.smart = smart_cur;
+
+    smart_cur++;
+
+    info("started module smart(%.200s)", st->arg);
+}
+
+void
+gets_smart()
+{
+    int i;
+
+    for (i = 0; i < smart_cur; i++) {
+        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;
+        }
+
+        /* 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;
+}
+
+int
+get_smart(char *symon_buf, int maxlen, struct stream *st)
+{
+    struct smart_report sr;
+
+    if ((st->parg.smart < smart_cur) &&
+        (!smart_devs[st->parg.smart].failed))
+    {
+        smart_parse(&smart_devs[st->parg.smart].data, &sr);
+        return snpack(symon_buf, maxlen, st->arg, MT_SMART,
+                      sr.read_error_rate,
+                      sr.reallocated_sectors,
+                      sr.spin_retries,
+                      sr.air_flow_temp,
+                      sr.temperature,
+                      sr.reallocations,
+                      sr.current_pending,
+                      sr.uncorrectables,
+                      sr.soft_read_error_rate,
+                      sr.g_sense_error_rate,
+                      sr.temperature2,
+                      sr.free_fall_protection);
+    }
+
+    return 0;
+}

+ 0 - 2
symon/platform/stub/sm_cpu.c

@@ -1,5 +1,3 @@
-/* $Id: sm_cpu.c,v 1.3 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_cpuiow.c

@@ -1,5 +1,3 @@
-/* $Id: sm_cpuiow.c,v 1.1 2008/01/30 12:06:50 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_debug.c

@@ -1,5 +1,3 @@
-/* $Id: sm_debug.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_df.c

@@ -1,5 +1,3 @@
-/* $Id: sm_df.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_if.c

@@ -1,5 +1,3 @@
-/* $Id: sm_if.c,v 1.3 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_io.c

@@ -1,5 +1,3 @@
-/* $Id: sm_io.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_mbuf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mbuf.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_mem.c

@@ -1,5 +1,3 @@
-/* $Id: sm_mem.c,v 1.3 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_pf.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pf.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_pfq.c

@@ -1,5 +1,3 @@
-/* $Id: sm_pfq.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_proc.c

@@ -1,5 +1,3 @@
-/* $Id: sm_proc.c,v 1.3 2005/10/19 20:06:07 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

+ 0 - 2
symon/platform/stub/sm_sensor.c

@@ -1,5 +1,3 @@
-/* $Id: sm_sensor.c,v 1.2 2005/10/18 19:58:12 dijkstra Exp $ */
-
 #include <stdlib.h>
 
 #include "sylimits.h"

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

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

+ 1 - 2
symon/symon/Makefile

@@ -1,9 +1,8 @@
-# $Id: Makefile,v 1.41 2008/01/30 13:19:40 dijkstra Exp $
 OS!=uname -s
 .include "../platform/${OS}/Makefile.inc"
 .include "../Makefile.inc"
 
-LIBS+=	${SYMON_LIBS} -L../lib -lsymon
+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; \

+ 0 - 1
symon/symon/c_config.sh

@@ -1,5 +1,4 @@
 #!/bin/sh
-# $Id: c_config.sh,v 1.7 2005/02/25 15:10:10 dijkstra Exp $
 #
 # Create an example configuration file for symon on a host and print to stdout
 

+ 12 - 12
symon/symon/readconf.c

@@ -1,5 +1,3 @@
-/* $Id: readconf.c,v 1.29 2008/01/30 12:06:50 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -67,16 +65,17 @@ read_host_port(struct muxlist * mul, struct mux * mux, struct lex * l)
 
     /* check for port statement */
     if (!lex_nexttoken(l))
-        return 1;
-
-    if (l->op == LXT_PORT || l->op == LXT_COMMA)
-        lex_nexttoken(l);
-
-    if (l->type != LXY_NUMBER) {
-        lex_ungettoken(l);
         mux->port = xstrdup(default_symux_port);
-    } else {
-        mux->port = xstrdup((const char *) l->token);
+    else {
+        if (l->op == LXT_PORT || l->op == LXT_COMMA)
+            lex_nexttoken(l);
+
+        if (l->type != LXY_NUMBER) {
+            lex_ungettoken(l);
+            mux->port = xstrdup(default_symux_port);
+        } else {
+            mux->port = xstrdup((const char *) l->token);
+        }
     }
 
     bzero(&muxname, sizeof(muxname));
@@ -115,6 +114,7 @@ read_symon_args(struct mux * mux, struct lex * l)
         case LXT_PFQ:
         case LXT_PROC:
         case LXT_SENSOR:
+        case LXT_SMART:
             st = token2type(l->op);
             strncpy(&sn[0], l->token, _POSIX2_LINE_MAX);
 
@@ -153,7 +153,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}");
+            parse_error(l, "{cpu|cpuiow|df|if|if1|io|io1|mem|mem1|pf|pfq|mbuf|debug|proc|sensor|smart}");
             return 0;
             break;
         }

+ 0 - 2
symon/symon/readconf.h

@@ -1,5 +1,3 @@
-/* $Id: readconf.h,v 1.8 2007/02/11 20:07:32 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2004 Willem Dijkstra
  * All rights reserved.

+ 6 - 0
symon/symon/smart.conf

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

+ 7 - 6
symon/symon/symon.8

@@ -1,6 +1,6 @@
 .\"  -*- nroff -*-
 .\"
-.\" Copyright (c) 2001-2008 Willem Dijkstra
+.\" Copyright (c) 2001-2009 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 January 30, 2008
+.Dd November 23, 2009
 .Dt SYMON 8
 .Os
 .Sh NAME
@@ -108,7 +108,8 @@ monitor-rule = "monitor" "{" resources "}" [every]
 resources    = resource [ version ] ["(" argument ")"]
                [ ","|" " resources ]
 resource     = "cpu" | "cpuiow" | "debug" | "df" | "if" | "io"
-               "mbuf" | "mem" | "pf" | "pfq" | "proc" | "sensor"
+               "mbuf" | "mem" | "pf" | "pfq" | "proc" |
+               "sensor" | "smart"
 version      = number
 argument     = number | name
 every        = "every" time
@@ -178,8 +179,8 @@ 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, \%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, \%Constantine A. \%Murenin, J. \%Martin \%Petersen,
+\%Fredrik \%Soderblom, \%Harm \%Schotanus and \%Martin van der \%Werff.
 .Sh SEE ALSO
 .Xr symux 8

+ 1 - 2
symon/symon/symon.c

@@ -1,5 +1,3 @@
-/* $Id: symon.c,v 1.53 2008/02/12 12:43:04 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2008 Willem Dijkstra
  * All rights reserved.
@@ -85,6 +83,7 @@ struct funcmap streamfunc[] = {
     {MT_MEM2, 0, NULL, init_mem, gets_mem, get_mem},
     {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_EOT, 0, NULL, NULL, NULL}
 };
 

+ 1 - 2
symon/symon/symon.conf

@@ -1,7 +1,6 @@
 #
-# $Id: symon.conf,v 1.12 2004/02/26 22:48:08 dijkstra Exp $
-#
 # Demo configuration for symon. See symon(8) for BNF.
+#
 
 monitor { cpu(0),  mem,
 	  if(lo0),

+ 6 - 2
symon/symon/symon.h

@@ -1,5 +1,3 @@
-/* $Id: symon.h,v 1.37 2008/01/30 12:06:50 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2005 Willem Dijkstra
  * All rights reserved.
@@ -121,6 +119,12 @@ extern int get_sensor(char *, int, struct stream *);
 extern void init_df(struct stream *);
 extern void gets_df();
 extern int get_df(char *, int, struct stream *);
+
+/* sm_smart.c */
+extern void init_smart(struct stream *);
+extern void gets_smart();
+extern int get_smart(char *, int, struct stream *);
+
 __END_DECLS
 
 #endif                          /* _SYMON_SYMON_H */

+ 0 - 2
symon/symon/symonnet.c

@@ -1,5 +1,3 @@
-/* $Id: symonnet.c,v 1.17 2007/11/29 13:13:18 dijkstra Exp $ */
-
 /*
  * Copyright (c) 2001-2007 Willem Dijkstra
  * All rights reserved.

Some files were not shown because too many files changed in this diff