*** wmmon.c.orig	Tue May 19 16:13:16 1998
--- wmmon.c	Fri Dec 31 12:05:34 1999
***************
*** 28,33 ****
--- 28,44 ----
  	Changes:
  	----
  
+ 	12/01/1999 (Stephen Kiernan, sk-ports@vegamuse.org)
+ 		* Change to revert to real userid and groupid
+ 		  after kvm_openfiles is accomplished.
+ 		  (Patch from Steve Reid, sreid@sea-to-sky.net)
+ 	05/24/1999 (Stephen Kiernan, sk-ports@vegamuse.org)
+ 		* Ported to FreeBSD 4.0
+ 	12/11/1998 (Stephen Kiernan, sk-ports@vegamuse.org)
+ 		* Ported to FreeBSD 2.2, 3.0
+ 		* Based on code from the FreeBSD 2.2 version of top
+ 		  by Christos Zoulas, Steven Wallace, and
+ 		  Wolfram Schneider
  	18/05/1998 (Antoine Nulle, warp@xs4all.nl)
  		* MEM/SWAP/UPTIME only updated when visible
  		* Using global file descriptors to reduce file
***************
*** 72,81 ****
--- 83,109 ----
  #include <fcntl.h>
  #include <unistd.h>
  
+ #include <errno.h>
+ 
  #include <sys/wait.h>
  #include <sys/param.h>
  #include <sys/types.h>
  
+ #include <kvm.h>
+ #include <limits.h>
+ #include <osreldate.h>
+ #include <sys/conf.h>
+ #include <sys/dkstat.h>
+ #if __FreeBSD_version >= 300000
+ #include <devstat.h>
+ #endif
+ #include <sys/sysctl.h>
+ #include <sys/time.h>
+ #if __FreeBSD_version < 400005
+ #include <sys/rlist.h>
+ #endif
+ #include <sys/vmmeter.h>
+ 
  #include <X11/Xlib.h>
  #include <X11/xpm.h>
  #include <X11/extensions/shape.h>
***************
*** 106,117 ****
--- 134,193 ----
  FILE	*fp_stat;
  FILE	*fp_loadavg;
  
+ kvm_t	*kvmd = NULL;
+ struct nlist nl[] = {
+ #define N_CNT		0
+ 	{ "_cnt" },
+ #define N_BUFSPACE	1
+ 	{ "_bufspace" },
+ #define N_CP_TIME	2
+ 	{ "_cp_time" },
+ #define N_AVERUN	3
+ 	{ "_averunnable" },
+ #if __FreeBSD_version >= 300000
+ #define N_TK_NIN        4
+         { "_tk_nin" },
+ #define N_TK_NOUT      	5 
+         { "_tk_nout" },
+ #else
+ #define N_DK_NDRIVE	4
+ 	{ "_dk_ndrive" },
+ #define N_DK_WDS	5
+ 	{ "_dk_wds" },
+ #endif
+ #if __FreeBSD_version < 400000
+ #define VM_SWAPLIST	6
+ 	{ "_swaplist" },
+ #define VM_SWDEVT	7
+ 	{ "_swdevt" },
+ #define VM_NSWAP	8
+ 	{ "_nswap" },
+ #define VM_NSWDEV	9
+ 	{ "_nswdev" },
+ #define VM_DMMAX	10
+ 	{ "_dmmax" },
+ #endif
+ 	{ "" }
+ };
+ int	psize;
+ int	pshift;
+ long	*cur_dk_wds;
+ long	*last_dk_wds;
+ int	ndrives;
+ char	errbuf[_POSIX2_LINE_MAX];
+ static int swappgsin = -1;
+ static int swappgsout = -1;
+ 
  /* functions */
  void usage(void);
  void printversion(void);
  void DrawStats(int *, int, int, int, int);
  void DrawStats_io(int *, int, int, int, int);
  
+ #if defined(__FreeBSD__) || defined(__NetBSD__)
+ int swapmode( long *retavail, long *retfree);
+ #endif /* __FreeBSD__ || __NetBSD__ */
+ 
  void wmmon_routine(int, char **);
  
  void main(int argc, char *argv[]) {
***************
*** 154,159 ****
--- 230,241 ----
  		}
  	}
  
+ 	if( checkversion() < 0 )
+ 	{
+ 		fprintf( stderr, devstat_errbuf );
+ 		exit(1);
+ 	}
+ 
  	wmmon_routine(argc, argv);
  }
  
***************
*** 213,238 ****
  	long		istat;
  	long		idle;
  
! 	FILE		*fp;
! 	char		temp[128];
  	char		*p;
  
! 	int			xpm_X = 0, xpm_Y = 0;
  
  	long		online_time = 0;
  	long		ref_time = 0;
  	long		cnt_time;
  
! 
! 	fp = fopen("/proc/uptime", "r");
! 	fp_meminfo = fopen("/proc/meminfo", "r");
! 	fp_loadavg = fopen("/proc/loadavg", "r");
! 	fp_stat = fopen("/proc/stat", "r");
! 
! 	if (fp) {
! 		fscanf(fp, "%ld", &online_time);
  		ref_time = time(0);
! 		fclose(fp);
  	}
  
  	for (i=0; i<MAX_STAT_DEVICES; i++) {
--- 295,363 ----
  	long		istat;
  	long		idle;
  
! 	int		mib[2];
! 	size_t		size;
! 	struct timeval	boottime;
  	char		*p;
  
! 	int		xpm_X = 0, xpm_Y = 0;
  
  	long		online_time = 0;
  	long		ref_time = 0;
  	long		cnt_time;
  
! 	mib[0] = CTL_KERN;
! 	mib[1] = KERN_BOOTTIME;
! 	size = sizeof(boottime);
! 	if ((sysctl(mib, 2, &boottime, &size, NULL, 0)!=-1) &&
! 	    (boottime.tv_sec != 0)) {
  		ref_time = time(0);
! 		online_time = ref_time - boottime.tv_sec + 30;
! 	}
! 
! 	psize = getpagesize();
! 	for (pshift = 0, psize = getpagesize(); psize>1; pshift++, psize>>=1)
! 		continue;
! 	pshift -= 10;
! 	psize = getpagesize();
! 
! 	if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
! 	if (kvmd==NULL) { fprintf(stderr, "kvm_openfiles: %s\n", errbuf); exit(errno); }
! 
! 	/* We're sgid kmem. Give up privs. */
! 	if (setgid(getgid()) != 0) { perror("setgid"); exit(errno); }
! 
! 	/* If we're suid, give that up too. */
! 	if (setuid(getuid()) != 0) { perror("seguid"); exit(errno); }
! 
! 	if (kvmd) {
! 		if (kvm_nlist(kvmd, nl) >= 0) {
! 			struct nlist *nlp;
! 
! 			for( nlp = nl; *nlp->n_name != '\0'; nlp++ ) {
! 				if( nlp->n_type == 0 )
! 					fprintf (stderr, "kvm_nlist: Symbol '%s' not found\n", nlp->n_name);
! 			}
! 		
! #if __FreeBSD_version >= 300000
! 			ndrives = getnumdevs();
! #else
! 			if (nl[0].n_type != 0) {
! 				(void) kvm_read(kvmd, nl[N_DK_NDRIVE].n_value, (char *)&ndrives, sizeof(ndrives));
! 				if (ndrives > 0) {
! 					cur_dk_wds = calloc(ndrives, sizeof(long));
! 					last_dk_wds = calloc(ndrives, sizeof(long));
! 					bzero(last_dk_wds, sizeof(long) * ndrives);
! 				}
! #endif
! 				fprintf (stderr, "Monitoring %d devices for activity.\n", ndrives);
! #if __FreeBSD_version < 300000
! 			}
! #endif
! 		}
! 		else {
! 			fprintf( stderr, "kvm_nlist: %s\n", kvm_geterr(kvmd) );
! 		}
  	}
  
  	for (i=0; i<MAX_STAT_DEVICES; i++) {
***************
*** 246,261 ****
  	if (RIGHT_ACTION) right_action = strdup(RIGHT_ACTION);
  	if (MIDDLE_ACTION) middle_action = strdup(MIDDLE_ACTION);
  
! 	strcpy(temp, "/etc/wmmonrc");
! 	parse_rcfile(temp, wmmon_keys);
  
! 	p = getenv("HOME");
! 	strcpy(temp, p);
! 	strcat(temp, "/.wmmonrc");
! 	parse_rcfile(temp, wmmon_keys);
  	
! 	strcpy(temp, "/etc/wmmonrc.fixed");
! 	parse_rcfile(temp, wmmon_keys);
  
  	stat_online = checksysdevs();
  
--- 371,390 ----
  	if (RIGHT_ACTION) right_action = strdup(RIGHT_ACTION);
  	if (MIDDLE_ACTION) middle_action = strdup(MIDDLE_ACTION);
  
! 	parse_rcfile("/etc/wmmonrc", wmmon_keys);
  
! 	if ((p = getenv("HOME")) != NULL) {
! #define RCFILE "/.wmmonrc"
! 		int tmpsize = strlen(p) + sizeof(RCFILE) + 1;
! 		char *tmp = malloc(tmpsize);
! 		if (tmp != NULL) {
! 			snprintf(tmp, tmpsize, "%s" RCFILE, p);
! 			parse_rcfile(tmp, wmmon_keys);
! 			free(tmp);
! 		}
! 	}
  	
! 	parse_rcfile("/etc/wmmonrc.fixed", wmmon_keys);
  
  	stat_online = checksysdevs();
  
***************
*** 484,489 ****
--- 613,623 ----
  	st->rt_idle = idle - st->idlelast;
  	st->idlelast = idle;
  
+ 	/* There's a problem here with values crossing
+ 	   the max long size barrier becoming negative --
+ 	   things restabilize after some time, but a
+ 	   better solution needs to be designed
+          */
  	st->rt_stat = istat - st->statlast;
  	st->statlast = istat;
  
***************
*** 499,543 ****
  
  void update_stat_mem(stat_dev *st, stat_dev *st2) {
  
! 	char	temp[128];
! 	unsigned long free, shared, buffers, cached;
  
! 	freopen("/proc/meminfo", "r", fp_meminfo);
! 	while (fgets(temp, 128, fp_meminfo)) {
! 		if (strstr(temp, "Mem:")) {
! 			sscanf(temp, "Mem: %ld %ld %ld %ld %ld %ld",
! 			       &st->rt_idle, &st->rt_stat,
! 			       &free, &shared, &buffers, &cached);
! 			st->rt_idle >>= 10;
! 			st->rt_stat -= buffers+cached;
! 			st->rt_stat >>= 10;
! //			break;
! 		}
! 		if (strstr(temp, "Swap:")) {
! 			sscanf(temp, "Swap: %ld %ld", &st2->rt_idle, &st2->rt_stat);
! 			st2->rt_idle >>= 10;
! 			st2->rt_stat >>= 10;
! 			break;
  		}
  	}
  }
  
  void update_stat_swp(stat_dev *st) {
  
! 	char	temp[128];
  
! 	fseek(fp_meminfo, 0, SEEK_SET);
! 	while (fgets(temp, 128, fp_meminfo)) {
! 		if (strstr(temp, "Swap:")) {
! 			sscanf(temp, "Swap: %ld %ld", &st->rt_idle, &st->rt_stat);
! 			st->rt_idle >>= 10;
! 			st->rt_stat >>= 10;
! 			break;
  		}
  	}
  
  }
  
  /*******************************************************************************\
  |* get_statistics															   *|
  \*******************************************************************************/
--- 633,887 ----
  
  void update_stat_mem(stat_dev *st, stat_dev *st2) {
  
! 	unsigned long buffers;
  
! 	if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
! 	if (kvmd==NULL) { fprintf(stderr, "kvm_openfiles: %s\n", errbuf); exit(errno); }
! 	if (kvmd) {
! 		if (kvm_nlist(kvmd, nl) >= 0) {
! 			if (nl[0].n_type != 0) {
! 				static int first_time_done = 0;
! 				int dpagein, dpageout;
! 				struct vmmeter sum;
! 
! 				if ((kvm_read(kvmd, nl[N_CNT].n_value, (char *)&sum, sizeof(sum))==sizeof(sum)) &&
! 				    (kvm_read(kvmd, nl[N_BUFSPACE].n_value, (char *)&buffers, sizeof(buffers))==sizeof(buffers))) {
! 					st->rt_idle = (sum.v_page_count - (buffers/psize) - sum.v_wire_count) << pshift;
! 					st->rt_stat = sum.v_active_count << pshift;
! 
! 					if (swappgsin < 0) {
! 						dpagein = 0;
! 						dpageout = 0;
! 					}
! 					else {
! 						dpagein = (sum.v_swappgsin - swappgsin) << pshift;
! 						dpageout = (sum.v_swappgsout - swappgsout) << pshift;
! 					}
! 					swappgsin = sum.v_swappgsin;
! 					swappgsout = sum.v_swappgsout;
! 
! 					if ((dpagein>0) || (dpageout>0) || (first_time_done==0)) {
! 						swapmode(&st2->rt_idle, &st2->rt_stat);
! 						st2->rt_stat = st2->rt_idle - st2->rt_stat;
! 					}
! 					first_time_done = 1;
! 				}
! 			}
  		}
  	}
  }
  
  void update_stat_swp(stat_dev *st) {
  
! 	if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
! 	if (kvmd==NULL) { fprintf(stderr, "kvm_openfiles: %s\n", errbuf); exit(errno); }
! 	if (kvmd) {
! 		if (kvm_nlist(kvmd, nl) >= 0) {
! 			if (nl[0].n_type != 0) {
! 				static int first_time_done = 0;
! 				int dpagein, dpageout;
! 
! 				struct vmmeter sum;
! 				if (kvm_read(kvmd, nl[N_CNT].n_value, (char *)&sum, sizeof(sum))==sizeof(sum)) {
! 					if (swappgsin < 0) {
! 						dpagein = 0;
! 						dpageout = 0;
! 					}
! 					else {
! 						dpagein = (sum.v_swappgsin - swappgsin) << pshift;
! 						dpageout = (sum.v_swappgsout - swappgsout) << pshift;
! 					}
! 					swappgsin = sum.v_swappgsin;
! 					swappgsout = sum.v_swappgsout;
! 
! 					if ((dpagein>0) || (dpageout>0) || (first_time_done==0)) {
! 						swapmode(&st->rt_idle, &st->rt_stat);
! 						st->rt_stat = st->rt_idle - st->rt_stat;
! 					}
! 					first_time_done = 1;
! 				}
! 			}
! 		}
! 	}
! }
! 
! #if __FreeBSD_version < 400000
! /*
!  * swapmode for FreeBSD 2.x and 3.x is based on a program called swapinfo
!  * written by Kevin Lahey <kml@rokkaku.atl.ga.us>.
!  */
! 
! #define	SVAR(var) __STRING(var)	/* to force expansion */
! #define	KGET(idx, var)							\
! 	KGET1(idx, &var, sizeof(var), SVAR(var))
! #define	KGET1(idx, p, s, msg)						\
! 	KGET2(nl[idx].n_value, p, s, msg)
! #define	KGET2(addr, p, s, msg)						\
! 	if (kvm_read(kvmd, (u_long)(addr), p, s) != s) {		\
! 		return (0);                                             \
!        }
! #define	KGETRET(addr, p, s, msg)					\
! 	if (kvm_read(kvmd, (u_long)(addr), p, s) != s) {		\
! 		return (0);						\
! 	}
! #endif
! 
! 
! int swapmode( long *retavail, long *retfree)
! {
! 	int used, avail;
! #if  __FreeBSD_version >= 400000
! 	struct kvm_swap kvmswap;
! #else
! 	char *header;
! 	int hlen, nswap, nswdev, dmmax;
! 	int i, div, nfree, npfree;
! 	struct swdevt *sw;
! 	long blocksize, *perdev;
! 	u_long ptr;
! 	struct rlist head;
! #  if __FreeBSD_version >= 220000
! 	struct rlisthdr swaplist;
! #  else 
! 	struct rlist *swaplist;
! #  endif
! 	struct rlist *swapptr;
! #endif
! 
! 	/*
! 	 * Counter for error messages. If we reach the limit,
! 	 * stop reading information from swap devices and
! 	 * return zero. This prevent endless 'bad address'
! 	 * messages.
! 	 */
! 	static int warning = 10;
! 
! 	if (warning <= 0) {
! 	    /* a single warning */
! 	    if (!warning) {
! 		warning--;
! 		fprintf(stderr, 
! 			"Too much errors, stop reading swap devices ...\n");
! 		(void)sleep(3);
! 	    }
! 	    return(0);
! 	}
! 	warning--; /* decrease counter, see end of function */
! 
! #if  __FreeBSD_version >= 400000
! 	if( kvm_getswapinfo( kvmd, &kvmswap, 1, 0 ) < 0 ) {
! 		fprintf(stderr, "kvm_getswapinfo failed\n");
! 		return(0);
! 	}
! 
! 	*retavail = avail = kvmswap.ksw_total;
! 	used = kvmswap.ksw_used;
! 	*retfree = kvmswap.ksw_total - used;
! #else
! 	KGET(VM_NSWAP, nswap);
! 	if (!nswap) {
! 		fprintf(stderr, "No swap space available\n");
! 		return(0);
! 	}
! 
! 	KGET(VM_NSWDEV, nswdev);
! 	KGET(VM_DMMAX, dmmax);
! 	KGET1(VM_SWAPLIST, &swaplist, sizeof(swaplist), "swaplist");
! 	if ((sw = (struct swdevt *)malloc(nswdev * sizeof(*sw))) == NULL ||
! 	    (perdev = (long *)malloc(nswdev * sizeof(*perdev))) == NULL)
! 	{
! 		perror("malloc");
! 		exit(1);
! 	}
! 	KGET1(VM_SWDEVT, &ptr, sizeof ptr, "swdevt");
! 	KGET2(ptr, sw, nswdev * sizeof(*sw), "*swdevt");
  
! 	/* Count up swap space. */
! 	nfree = 0;
! 	memset(perdev, 0, nswdev * sizeof(*perdev));
! #if  __FreeBSD_version >= 220000
! 	swapptr = swaplist.rlh_list;
! 	while (swapptr) {
! #else
! 	while (swaplist) {
! #endif
! 		int	top, bottom, next_block;
! #if  __FreeBSD_version >= 220000
! 		KGET2(swapptr, &head, sizeof(struct rlist), "swapptr");
! #else
! 		KGET2(swaplist, &head, sizeof(struct rlist), "swaplist");
! #endif
! 
! 		top = head.rl_end;
! 		bottom = head.rl_start;
! 
! 		nfree += top - bottom + 1;
! 
! 		/*
! 		 * Swap space is split up among the configured disks.
! 		 *
! 		 * For interleaved swap devices, the first dmmax blocks
! 		 * of swap space some from the first disk, the next dmmax
! 		 * blocks from the next, and so on up to nswap blocks.
! 		 *
! 		 * The list of free space joins adjacent free blocks,
! 		 * ignoring device boundries.  If we want to keep track
! 		 * of this information per device, we'll just have to
! 		 * extract it ourselves.
! 		 */
! 
! 		while (top / dmmax != bottom / dmmax) {
! 			next_block = ((bottom + dmmax) / dmmax);
! 			perdev[(bottom / dmmax) % nswdev] +=
! 				next_block * dmmax - bottom;
! 			bottom = next_block * dmmax;
  		}
+ 		perdev[(bottom / dmmax) % nswdev] +=
+ 			top - bottom + 1;
+ 
+ #if  __FreeBSD_version >= 220000
+ 		swapptr = head.rl_next;
+ #else
+ 		swaplist = head.rl_next;
+ #endif
+ 	}
+ 
+ 	header = getbsize(&hlen, &blocksize);
+ 	div = blocksize / 512;
+ 	avail = npfree = 0;
+ 	for (i = 0; i < nswdev; i++) {
+ 		int xsize, xfree;
+ 
+ 		/*
+ 		 * Don't report statistics for partitions which have not
+ 		 * yet been activated via swapon(8).
+ 		 */
+ 
+ 		xsize = sw[i].sw_nblks;
+ 		xfree = perdev[i];
+ 		used = xsize - xfree;
+ 		npfree++;
+ 		avail += xsize;
  	}
  
+ 	/* 
+ 	 * If only one partition has been set up via swapon(8), we don't
+ 	 * need to bother with totals.
+ 	 */
+ 	*retavail = avail / 2;
+ 	*retfree = nfree / 2;
+ 	used = avail - nfree;
+ 	free(sw); free(perdev);
+ #endif /* __FreeBSD_version >= 400000 */
+ 
+ 	/* increase counter, no errors occurs */
+ 	warning++; 
+ 
+ 	return  (int)(((double)used / (double)avail * 100.0) + 0.5);
  }
  
+ 
+ 
  /*******************************************************************************\
  |* get_statistics															   *|
  \*******************************************************************************/
***************
*** 545,554 ****
  void get_statistics(char *devname, long *is, long *ds, long *idle) {
  
  	int	i;
! 	char	temp[128];
! 	char	*p;
! 	char	*tokens = " \t\n";
! 	float	f;
  	long	maxdiskio=0;
  
  	*is = 0;
--- 889,896 ----
  void get_statistics(char *devname, long *is, long *ds, long *idle) {
  
  	int	i;
! 	long	averun[3];
! 	long	cp_time[CPUSTATES];
  	long	maxdiskio=0;
  
  	*is = 0;
***************
*** 556,592 ****
  	*idle = 0;
  
  	if (!strncmp(devname, "cpu", 3)) {
! 		fseek(fp_stat, 0, SEEK_SET);
! 		while (fgets(temp, 128, fp_stat)) {
! 			if (strstr(temp, "cpu")) {
! 				p = strtok(temp, tokens);
! 				/* 1..3, 4 == idle, we don't want idle! */
! 				for (i=0; i<3; i++) {
! 					p = strtok(NULL, tokens);
! 					*ds += atol(p);
! 				}
! 				p = strtok(NULL, tokens);
! 				*idle = atol(p);
! 			}
! 		}
! 		fp_loadavg = freopen("/proc/loadavg", "r", fp_loadavg);
! 		fscanf(fp_loadavg, "%f", &f);
! 		*is = (long) (100 * f);
  	}
  
  	if (!strncmp(devname, "i/o", 3)) {
  
! 		fseek(fp_stat, 0, SEEK_SET);
! 		while (fgets(temp, 128, fp_stat)) {
! 			if (strstr(temp, "disk_rio") || strstr(temp, "disk_wio")) {
! 				p = strtok(temp, tokens);
! 				/* 1..4 */
! 				for (i=0; i<4; i++) {
! 					p = strtok(NULL, tokens);
! 					*ds += atol(p);
  				}
  			}
  		}
  		if (*ds > maxdiskio) maxdiskio = *ds;
  	}
  }
--- 898,1102 ----
  	*idle = 0;
  
  	if (!strncmp(devname, "cpu", 3)) {
! 		if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
! 	if (kvmd==NULL) { fprintf(stderr, "kvm_openfiles: %s\n", errbuf); exit(errno); }
! 		if (kvmd) {
! 			if (kvm_nlist(kvmd, nl) >= 0) {
! 				if (nl[0].n_type != 0) {
! 					if ((kvm_read(kvmd, nl[N_CP_TIME].n_value, (char *)&cp_time, sizeof(cp_time))==sizeof(cp_time)) &&
! 					    (kvm_read(kvmd, nl[N_AVERUN].n_value, (char *)&averun, sizeof(averun))==sizeof(averun))) {
! 						*is = (long) (100 * ((double)averun[0] / FSCALE));
! 
! 						for (i = 0; i < CPUSTATES; i++) {
! 							if (i != CP_IDLE) *ds += cp_time[i];
! 						}
! 						*idle = cp_time[CP_IDLE];
! 					}
! 				}
! 			}
! 		}
  	}
  
  	if (!strncmp(devname, "i/o", 3)) {
+ #if __FreeBSD_version < 300000
+ 		if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
+ 	if (kvmd==NULL) { fprintf(stderr, "kvm_openfiles: %s\n", errbuf); exit(errno); }
+ 		if (kvmd) {
+ 			if (kvm_nlist(kvmd, nl) >= 0) {
+ 				if (nl[0].n_type != 0) {
+ 					if (kvm_read(kvmd, nl[N_DK_WDS].n_value, (char *)cur_dk_wds, ndrives * sizeof(long))==(ndrives*sizeof(long))) {
+ 						for (i = 0; i < ndrives; i++) {
+ 							*ds += cur_dk_wds[i];
+ 						}
+ 					}
+ 				}
+ 			}
+ 		}
+ #else
+ 		static int                initted = 0;
+ 		static struct statinfo    last;
+ 		static struct statinfo    cur;
+ 		int                       ndevs = getnumdevs();
+ 		int                       gotdevs = 0;
+ 		long                      generation;
+ 		int                       num_devices_specified = 0;
+ 		int                       num_selected;
+ 		int                       num_selections;
+ 		int                       maxshowdevs = 10;
+ 		int                       num_matches = 0;
+ 		struct devstat_match     *matches = NULL;
+ 		struct device_selection  *dev_select = NULL;
+ 		char                    **specified_devices;
+ 		long                      select_generation;
+ 
+ 		if( !initted )
+ 		{
+ 			bzero( &cur, sizeof(cur) );
+ 			bzero( &last, sizeof(cur) );
+ 
+ 			cur.dinfo = (struct devinfo *)malloc( sizeof(struct devinfo) );
+ 			last.dinfo = (struct devinfo *)malloc( sizeof(struct devinfo) );
  
! 			bzero( cur.dinfo, sizeof(struct devinfo) );
! 			bzero( last.dinfo, sizeof(struct devinfo) );
! 
! 			specified_devices = (char **)malloc(sizeof(char *));
! 		}
! 		else
! 		{
! 			struct devinfo *tmp;
! 
! 			if (kvmd==NULL) kvmd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf);
! 			if (kvmd==NULL)
! 			{
! 				fprintf(stderr, "kvm_openfiles: %s\n", errbuf);
! 				exit(errno);
! 			}
! 			else
! 			{
! 		                (void)kvm_read( kvmd, nl[N_TK_NIN].n_value, &cur.tk_nin,
! 						sizeof(cur.tk_nin) );
! 		                (void)kvm_read( kvmd, nl[N_TK_NOUT].n_value, &cur.tk_nout,
! 						sizeof(cur.tk_nout) );
! 		                (void)kvm_read( kvmd, nl[N_CP_TIME].n_value,
! 						cur.cp_time, sizeof(cur.cp_time) );
! 			}
! 
! 			tmp = last.dinfo;
! 			memcpy( &last, &cur, sizeof(cur) );
! 			cur.dinfo = tmp;
! 
! 			last.busy_time = cur.busy_time;
! 		}
! 
! 		if( !gotdevs && ( getdevs( &cur ) >= 0 ) )
! 			gotdevs = 1;
! 
! 		if( gotdevs )
! 		{
! 			generation = cur.dinfo->generation;
! 			ndevs = cur.dinfo->numdevs;
! 
! 			if( !initted )
! 			{
! 				selectdevs( &dev_select, &num_selected, &num_selections,
! 					    &select_generation, generation, cur.dinfo->devices,
! 					    ndevs, matches, num_matches, specified_devices,
! 					    num_devices_specified, DS_SELECT_ONLY, maxshowdevs,
! 					    1 );
! 			}
! 			else
! 			{
! 				struct devinfo *tmpinfo;
! 				long tmp;
! 
! 				switch( getdevs( &cur ) )
! 				{
! 					case 1:
! 						selectdevs( &dev_select, &num_selected,
! 							    &num_selections, &select_generation,
! 							    generation, cur.dinfo->devices,
! 							    ndevs, matches, num_matches,
! 							    specified_devices,
! 							    num_devices_specified,
! 							    DS_SELECT_ONLY,
! 							    maxshowdevs, 1 );
! 
! 						if (kvmd==NULL)
! 						{
! 							fprintf(stderr, "kvm_openfiles: %s\n", errbuf);
! 							exit(errno);
! 						}
! 						else
! 						{
! 					                (void)kvm_read( kvmd, nl[N_TK_NIN].n_value, &cur.tk_nin,
! 									sizeof(cur.tk_nin) );
! 					                (void)kvm_read( kvmd, nl[N_TK_NOUT].n_value, &cur.tk_nout,
! 									sizeof(cur.tk_nout) );
! 					                (void)kvm_read( kvmd, nl[N_CP_TIME].n_value,
! 									cur.cp_time, sizeof(cur.cp_time) );
! 						}
! 
! 						tmpinfo = last.dinfo;
! 						memcpy( &last, &cur, sizeof(cur) );
! 						cur.dinfo = tmpinfo;
! 
! 						last.busy_time = cur.busy_time;
! 						break;
! 					default:
! 						break;
! 				}
! 
! 				selectdevs( &dev_select, &num_selected, &num_selections,
! 					    &select_generation, generation, cur.dinfo->devices,
! 					    ndevs, matches, num_matches, specified_devices,
! 					    num_devices_specified, DS_SELECT_ONLY, maxshowdevs,
! 					    1 );
! 
! 				tmp = cur.tk_nin;
! 				cur.tk_nin -= last.tk_nin;
! 				last.tk_nin = tmp;
! 				tmp = cur.tk_nout;
! 				cur.tk_nout -= last.tk_nout;
! 				last.tk_nout = tmp;
! 
! 				{
! 					register int dn;
! 					long double transfers_per_second;
! 					long double kb_per_transfer, mb_per_second;
! 					u_int64_t total_bytes, total_transfers, total_blocks;
! 					long double busy_seconds;
! 					long double blocks_per_second, ms_per_transaction;
! 
! 					busy_seconds = compute_etime( cur.busy_time, last.busy_time );
! 
! 					for( dn = 0; dn < ndevs; dn++ )
! 					{
! 						int di = dev_select[dn].position;
! 
! 						if( compute_stats( &cur.dinfo->devices[di],
! 								   &last.dinfo->devices[di],
! 								   busy_seconds,
! 								   &total_bytes,
! 								   &total_transfers,
! 								   &total_blocks,
! 								   &kb_per_transfer,
! 								   &transfers_per_second,
! 								   &mb_per_second,
! 								   &blocks_per_second,
! 								   &ms_per_transaction ) == 0 )
! 						{
! 							*ds += total_blocks;
! 						}
! 					}
  				}
  			}
+ 			initted = 1;
  		}
+ 
+ 		if( dev_select )
+ 			free( dev_select );
+ #endif
  		if (*ds > maxdiskio) maxdiskio = *ds;
  	}
  }
***************
*** 597,605 ****
  
  int checksysdevs(void) {
  
! 	strcpy(stat_device[0].name, "cpu0");
! 	strcpy(stat_device[1].name, "i/o");
! 	strcpy(stat_device[2].name, "sys");
  
  	return 3;
  }
--- 1107,1115 ----
  
  int checksysdevs(void) {
  
! 	strncpy(stat_device[0].name, "cpu0", 5);
! 	strncpy(stat_device[1].name, "i/o", 5);
! 	strncpy(stat_device[2].name, "sys", 5);
  
  	return 3;
  }
***************
*** 638,643 ****
--- 1148,1154 ----
  	int     *p;
  	int		d;
  
+ /*	printf ("size = %d, num = %d\n", size, num); */
  	pixels_per_byte = 100;
  	p = his;
  	for (j=0; j<num; j++) {
