$NetBSD: patch-ab,v 1.15 2006/08/13 07:33:37 xtraeme Exp $

--- src/sysdeps/netbsd.c.orig	2006-03-30 00:23:37.000000000 +0200
+++ src/sysdeps/netbsd.c	2006-08-13 09:25:55.000000000 +0200
@@ -63,7 +63,8 @@
 {
    static int mib[] = { CTL_KERN, KERN_CP_TIME };
    u_int64_t cp_time[ncpus][CPUSTATES];
-   int len, n;
+   int n;
+   size_t len;
 
    if (ncpus > 1) {
        len = sizeof(cp_time[0]);
@@ -94,7 +95,7 @@
 {
 	static int mib[] = { CTL_HW, HW_NCPU };
 	int ncpus;
-	int len = sizeof(int);
+	size_t len = sizeof(int);
 
 	if (sysctl(mib, 2, &ncpus, &len, NULL, 0) < 0)
 		return 1;
@@ -109,39 +110,33 @@
 #include <sys/proc.h>
 #include <sys/sysctl.h>
 #include <uvm/uvm_extern.h>
-#include <kvm.h>
 
 #include <utmp.h>
 
-static struct nlist nl[] = {
-#define X_UVM_EXP    0
-   { "_uvmexp" },
-   { NULL }
-};
-
-extern	kvm_t	*kvmd;
-
 void
 gkrellm_sys_proc_read_data(void)
 {
-   static int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL };
+   int mib[6];
    double avenrun;
 	guint	n_forks = 0, n_processes = 0;
-   struct uvmexp *uvmexp;
-   int len, i;
-
-   if (sysctl(mib, 3, NULL, &len, NULL, 0) >= 0) {
-      n_processes = len / sizeof(struct kinfo_proc);
-   }
-
-   /* get name list if it is not done yet */
-   if (kvmd == NULL) return;
-   if (nl[0].n_type == 0) kvm_nlist(kvmd, nl);
+   struct uvmexp_sysctl uvmexp;
+   size_t size;
 
-   if (nl[0].n_type != 0) {
-      uvmexp = (struct uvmexp *)nl[X_UVM_EXP].n_value;
-      if (kvm_read(kvmd, (u_long)&uvmexp->forks, &i, sizeof(i)) == sizeof(i))
-	 n_forks = i;
+   mib[0] = CTL_KERN;
+   mib[1] = KERN_PROC2;
+   mib[2] = KERN_PROC_ALL;
+   mib[3] = 0;
+   mib[4] = sizeof(struct kinfo_proc2);
+   mib[5] = 0;
+   if (sysctl(mib, 6, NULL, &size, NULL, 0) >= 0) {
+      n_processes = size / sizeof(struct kinfo_proc2);
+   }
+
+   mib[0] = CTL_VM;
+   mib[1] = VM_UVMEXP2;
+   size = sizeof(uvmexp);
+   if (sysctl(mib, 2, &uvmexp, &size, NULL, 0) >= 0) {
+      n_forks = uvmexp.forks;
    }
 
    if (getloadavg(&avenrun, 1) <= 0)
@@ -183,6 +178,96 @@
 
 
 /* ===================================================================== */
+/* Memory/Swap monitor interface */
+
+#include <sys/vmmeter.h>
+#include <sys/sysctl.h>
+#include <uvm/uvm_extern.h>
+
+
+void
+gkrellm_sys_mem_read_data(void)
+{
+   int mib[2];
+   guint64 total, used, free, shared, buffers, cached;
+   struct vmtotal vmt;
+   struct uvmexp_sysctl uvmexp;
+   size_t len;
+
+   mib[0] = CTL_VM;
+   mib[1] = VM_METER;
+   len = sizeof(vmt);
+   if (sysctl(mib, 2, &vmt, &len, NULL, 0) < 0)
+      memset(&vmt, 0, sizeof(vmt));
+
+   mib[0] = CTL_VM;
+   mib[1] = VM_UVMEXP2;
+   len = sizeof(uvmexp);
+   if (sysctl(mib, 2, &uvmexp, &len, NULL, 0) < 0)
+      memset(&uvmexp, 0, sizeof(uvmexp));
+
+   total = uvmexp.npages << uvmexp.pageshift;
+
+   /* not sure of what must be computed */
+   free = (uvmexp.inactive + uvmexp.free) << uvmexp.pageshift;
+   shared = vmt.t_rmshr << uvmexp.pageshift;
+
+   /* can't use "uvmexp.active << uvmexp.pageshift" here because the
+    * display for "free" uses "total - used" which is very wrong. */
+   used = total - free;
+
+   /* don't know how to get those values */
+   buffers = 0;
+   cached = 0;
+
+   gkrellm_mem_assign_data(total, used, free, shared, buffers, cached);
+
+}
+
+void
+gkrellm_sys_swap_read_data(void)
+{
+   static int pgout, pgin;
+   int mib[2];
+   struct uvmexp_sysctl uvmexp;
+   size_t len;
+   static gulong swapin = 0, swapout = 0;
+   guint64 swap_total, swap_used;
+
+   mib[0] = CTL_VM;
+   mib[1] = VM_UVMEXP2;
+   len = sizeof(uvmexp);
+   if (sysctl(mib, 2, &uvmexp, &len, NULL, 0) < 0)
+      memset(&uvmexp, 0, sizeof(uvmexp));
+
+   /* show only the pages located on the disk and not in memory */
+   swap_total = (guint64) (uvmexp.swpages << uvmexp.pageshift);
+   swap_used = (guint64) (uvmexp.swpgonly << uvmexp.pageshift);
+
+   /* For page in/out operations, uvmexp struct doesn't seem to be reliable */
+
+   /* if the number of swapped pages that are in memory (inuse - only) is
+    * greater that the previous value (pgin), we count this a "page in" */
+   if (uvmexp.swpginuse - uvmexp.swpgonly > pgin)
+      swapin += uvmexp.swpginuse - uvmexp.swpgonly - pgin;
+   pgin = uvmexp.swpginuse - uvmexp.swpgonly;
+
+   /* same for page out */
+   if (uvmexp.swpgonly > pgout)
+      swapout += uvmexp.swpgonly - pgout;
+   pgout = uvmexp.swpgonly;
+
+   gkrellm_swap_assign_data(swap_total, swap_used, swapin, swapout);
+}
+
+gboolean
+gkrellm_sys_mem_init(void)
+	{
+	return TRUE;
+	}
+
+
+/* ===================================================================== */
 /* Sensor monitor interface */
 
   /* Tables of voltage correction factors and offsets derived from the
@@ -295,7 +380,7 @@
    int fd;			/* file desc. for /dev/sysmon */
    int id = 0;			/* incremented for each sensor */
    int type;
-   char *s, base_name[32];
+   char *s, base_name[33];
    gboolean	found_sensors = FALSE;
 
    /* check if some sensor is configured */
@@ -336,3 +421,158 @@
    return found_sensors;
 }
 
+
+/* ===================================================================== */
+/* Disk monitor interface */
+
+#include <sys/dkstat.h>
+#include <sys/disk.h>
+#include <sys/sysctl.h>
+
+#ifdef HW_IOSTATS
+#define HW_DISKSTATS	HW_IOSTATS
+#define disk_sysctl	io_sysctl
+#define dk_rbytes	rbytes
+#define dk_wbytes	wbytes
+#define dk_name		name
+#endif
+
+gboolean
+gkrellm_sys_disk_init(void)
+{
+	int mib[3] = { CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl) };
+	size_t size;
+
+	/* Just test if the sysctl call works */
+	if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1)
+		return (FALSE);
+
+	return (TRUE);
+}
+
+void
+gkrellm_sys_disk_read_data(void)
+{
+	int i, n_disks, mib[3] = { CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl) };
+	size_t size;
+	guint64 rbytes, wbytes;
+	struct disk_sysctl *dk_drives;
+
+	if (sysctl(mib, 3, NULL, &size, NULL, 0) == -1)
+		return;
+	dk_drives = malloc(size);
+	if (dk_drives == NULL)
+		return;
+	n_disks = size / sizeof(struct disk_sysctl);
+
+	if (sysctl(mib, 3, dk_drives, &size, NULL, 0) == -1)
+		return;
+
+	for (i = 0; i < n_disks; i++) {
+#if __NetBSD_Version__ >= 106110000
+		rbytes = dk_drives[i].dk_rbytes;
+		wbytes = dk_drives[i].dk_wbytes;
+#else
+		rbytes = dk_drives[i].dk_bytes;
+		wbytes = 0;
+#endif
+
+		gkrellm_disk_assign_data_by_name(dk_drives[i].dk_name, rbytes, wbytes, FALSE);
+	}
+
+	free(dk_drives);
+}
+
+gchar *
+gkrellm_sys_disk_name_from_device(gint device_number, gint unit_number,
+			gint *order)
+	{
+	return NULL;	/* disk data by device not implemented */
+	}
+
+gint
+gkrellm_sys_disk_order_from_name(gchar *name)
+	{
+	return -1;  /* append disk charts as added */
+	}
+
+#if __NetBSD_Version__ >= 399000100
+
+#include "../inet.h"
+
+#include <errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp_fsm.h>
+
+static const struct gkrellm_inet_fam {
+	sa_family_t family;
+	const char *mib;
+} families[] = { {AF_INET, "net.inet.tcp.pcblist"},
+#ifdef INET6
+    {AF_INET6, "net.inet6.tcp6.pcblist"},
+#endif
+    {0, NULL} };
+
+void
+gkrellm_sys_inet_read_tcp_data()
+{
+	ActiveTCP tcp;
+	int mib[CTL_MAXNAME], i;
+	size_t sz;
+	u_int namelen;
+	struct kinfo_pcb *pcbt = NULL;
+	const struct gkrellm_inet_fam *pf = families;
+
+	while (pf->mib != NULL) {
+		sz = CTL_MAXNAME;
+		if (sysctlnametomib(pf->mib, mib, &sz) == -1)
+			return;
+		namelen = sz;
+
+		mib[namelen++] = PCB_ALL;
+		mib[namelen++] = 0;
+		mib[namelen++] = sizeof(struct kinfo_pcb);
+		mib[namelen++] = INT_MAX;
+
+		sz = 0;
+		pcbt = NULL;
+		if (sysctl(&mib[0], namelen, pcbt, &sz, NULL, 0) == -1)
+			return;
+		pcbt = malloc(sz);
+		if (pcbt == NULL)
+			return;
+		if (sysctl(&mib[0], namelen, pcbt, &sz, NULL, 0) == -1)
+			return;
+
+		sz /= sizeof(struct kinfo_pcb);
+		for (i = 0; i < sz; i++) {
+			tcp.family = pf->family;
+			if (pf->family == AF_INET) {
+				struct sockaddr_in *sin =
+				    (struct sockaddr_in *)&pcbt[i].ki_dst;
+				tcp.remote_addr.s_addr = sin->sin_addr.s_addr;
+				tcp.remote_port = sin->sin_port;
+
+				sin = (struct sockaddr_in *)&pcbt[i].ki_src;
+				tcp.local_port = sin->sin_port;
+#ifdef INET6
+			} else { /* AF_INET6 */
+				struct sockaddr_in6 *sin =
+				    (struct sockaddr_in6 *)&pcbt[i].ki_dst;
+				memcpy(&tcp.remote_addr6, &sin->sin6_addr,
+				    sizeof(struct in6_addr));
+				tcp.remote_port = sin->sin6_port;
+
+				sin = (struct sockaddr_in6 *)&pcbt[i].ki_src;
+				tcp.local_port = sin->sin6_port;
+#endif
+			}
+			if (pcbt[i].ki_tstate == TCPS_ESTABLISHED)
+				gkrellm_inet_log_tcp_port_data(&tcp);
+		}
+		free(pcbt);
+		pf++;
+	}
+}
+#endif
