--- old/usr/src/cmd/rpcsvc/rstat_proc.c	2017-05-26 19:24:03.541583270 -0400
+++ /dev/null	2017-05-26 19:24:03.000000000 -0400
@@ -1,1100 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
-/*
- * rstat service:  built with rstat.x
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <signal.h>
-#include <utmpx.h>
-#include <nlist.h>
-#include <fcntl.h>
-#include <syslog.h>
-#include <kstat.h>
-
-#include <rpc/rpc.h>
-
-#include <sys/socket.h>
-#include <sys/cpuvar.h>
-#include <sys/sysinfo.h>
-#include <sys/systm.h>
-#include <errno.h>
-#include <sys/stropts.h>
-#include <sys/tihdr.h>
-#include <sys/sysmacros.h>
-
-#include <net/if.h>
-#include <inet/mib2.h>
-
-#include "rstat.h"
-#include "rstat_v2.h"
-
-typedef struct {
-	kstat_t	sys;
-	kstat_t	vm;
-} _cpu_stats_t;
-
-/*
- *	system and cpu stats
- */
-static	kstat_ctl_t	*kc;		/* libkstat cookie */
-static	int	ncpus;
-static	_cpu_stats_t	*cpu_stats_list = NULL;
-static	kstat_t	*system_misc_ksp;
-static	kstat_named_t *boot_time_knp;
-static	kstat_named_t *avenrun_1min_knp, *avenrun_5min_knp, *avenrun_15min_knp;
-static	int	hz;
-static	struct	timeval btm;		/* boottime */
-
-/*
- *	network interface stats
- */
-
-typedef struct mib_item_s {
-	struct mib_item_s	*next_item;
-	long			group;
-	long			mib_id;
-	long			length;
-	char			*valp;
-} mib_item_t;
-
-mib_item_t	*netstat_item;
-
-/*
- * disk stats
- */
-
-struct diskinfo {
-	struct diskinfo *next;
-	kstat_t *ks;
-	kstat_io_t kios;
-};
-
-#define	NULLDISK (struct diskinfo *)0
-static	struct diskinfo zerodisk = { NULL, NULL };
-static	struct diskinfo *firstdisk = NULLDISK;
-static	struct diskinfo *lastdisk = NULLDISK;
-static	struct diskinfo *snip = NULLDISK;
-static	int ndisks;
-
-/*
- * net stats
- */
-
-struct netinfo {
-	struct netinfo *next;
-	kstat_t	*ks;
-	kstat_named_t *ipackets;
-	kstat_named_t *opackets;
-	kstat_named_t *ierrors;
-	kstat_named_t *oerrors;
-	kstat_named_t *collisions;
-};
-
-#define	NULLNET (struct netinfo *)0
-static	struct netinfo zeronet = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-static	struct netinfo *firstnet = NULLNET;
-static	struct netinfo *lastnet = NULLNET;
-static	struct netinfo *netsnip = NULLNET;
-static	int nnets;
-
-/*
- *  Define EXIT_WHEN_IDLE if you are able to have this program invoked
- *  automatically on demand (as from inetd).  When defined, the service
- *  will terminated after being idle for 120 seconds.
- */
-
-#define	EXIT_WHEN_IDLE	1
-
-int sincelastreq = 0;		/* number of alarms since last request */
-#ifdef EXIT_WHEN_IDLE
-#define	CLOSEDOWN 120		/* how long to wait before exiting */
-#endif /* def EXIT_WHEN_IDLE */
-
-statstime stats_s3;
-statsvar stats_s4;
-/* V2 support for backwards compatibility to pre-5.0 systems */
-statsswtch stats_s2;
-
-static int stat_is_init = 0;
-
-static	void	fail(int, char *, ...);
-static	void	safe_zalloc(void **, int, int);
-static	kid_t	safe_kstat_read(kstat_ctl_t *, kstat_t *, void *);
-static	kstat_t	*safe_kstat_lookup(kstat_ctl_t *, char *, int, char *);
-static	void	*safe_kstat_data_lookup(kstat_t *, char *);
-static	void	system_stat_init(void);
-static	int	system_stat_load(void);
-static	void	init_disks(void);
-static	int	diskinfo_load(void);
-static	void	init_net(void);
-static	int	netinfo_load(void);
-
-static	void	updatestat(int);
-
-static	mib_item_t	*mibget(int sd);
-static	int	mibopen(void);
-static  char	*octetstr(char *buf, Octet_t *op, int code);
-
-static	void	kstat_copy(kstat_t *, kstat_t *, int);
-
-static	char	*cmdname = "rpc.rstatd";
-
-#define	CPU_STAT(ksp, name)	(((kstat_named_t *)safe_kstat_data_lookup( \
-				    (ksp), (name)))->value.ui64)
-static	_cpu_stats_t	cpu_stats_all = { 0 };
-
-static void
-stat_init(void)
-{
-	struct utmpx *utmpx, utmpx_id;
-
-	stat_is_init = 1;
-
-	if ((kc = kstat_open()) == NULL)
-		fail(1, "kstat_open(): can't open /dev/kstat");
-
-	/*
-	 * Preallocate minimal set of drive entries.
-	 */
-
-	if (stats_s4.dk_xfer.dk_xfer_val == NULL) {
-		stats_s4.dk_xfer.dk_xfer_len = RSTAT_DK_NDRIVE;
-		stats_s4.dk_xfer.dk_xfer_val =
-		    (int *)calloc(RSTAT_DK_NDRIVE, sizeof (int));
-	}
-
-	system_stat_init();
-	init_disks();
-	init_net();
-
-	/*
-	 * To get the boot time, use utmpx, which is per-zone, but fall back
-	 * to the system-wide kstat if utmpx is hosed for any reason.
-	 */
-	utmpx_id.ut_type = BOOT_TIME;
-	if ((utmpx = getutxid(&utmpx_id)) != NULL)
-		btm = utmpx->ut_tv;
-	else {
-		btm.tv_sec = boot_time_knp->value.ul;
-		btm.tv_usec = 0; /* don't bother with usecs for boot time */
-	}
-	endutxent();
-	stats_s4.boottime.tv_sec =
-		stats_s2.boottime.tv_sec =
-		stats_s3.boottime.tv_sec = btm.tv_sec;
-	stats_s4.boottime.tv_usec =
-		stats_s2.boottime.tv_usec =
-		stats_s3.boottime.tv_usec = btm.tv_usec;
-
-	updatestat(0);
-	alarm(1);
-	signal(SIGALRM, updatestat);
-	sleep(2);		/* allow for one wake-up */
-}
-
-statsvar *
-rstatproc_stats_4_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	if (! stat_is_init)
-		stat_init();
-#ifdef EXIT_WHEN_IDLE
-	sincelastreq = 0;
-#endif
-	return (&stats_s4);
-}
-
-statstime *
-rstatproc_stats_3_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	if (! stat_is_init)
-		stat_init();
-#ifdef EXIT_WHEN_IDLE
-	sincelastreq = 0;
-#endif
-	return (&stats_s3);
-}
-
-statsswtch *
-rstatproc_stats_2_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	if (! stat_is_init)
-		stat_init();
-#ifdef EXIT_WHEN_IDLE
-	sincelastreq = 0;
-#endif
-	return (&stats_s2);
-}
-
-
-uint_t *
-rstatproc_havedisk_4_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	return (rstatproc_havedisk_3_svc(argp, svcrq));
-}
-
-uint_t *
-rstatproc_havedisk_3_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	static uint_t have;
-
-	if (! stat_is_init)
-		stat_init();
-#ifdef EXIT_WHEN_IDLE
-	sincelastreq = 0;
-#endif
-	have = (ndisks != 0);
-	return (&have);
-}
-
-uint_t *
-rstatproc_havedisk_2_svc(argp, svcrq)
-void *argp;
-struct svc_req *svcrq;
-{
-	return (rstatproc_havedisk_3_svc(argp, svcrq));
-}
-
-void
-updatestat(int ignored)
-{
-extern int _rpcpmstart;		 /* Started by a port monitor ? */
-extern int _rpcsvcdirty;	 /* Still serving ? */
-
-#ifdef DEBUG
-	fprintf(stderr, "entering updatestat\n");
-#endif
-#ifdef EXIT_WHEN_IDLE
-	if (_rpcpmstart && sincelastreq >= CLOSEDOWN && !_rpcsvcdirty) {
-#ifdef DEBUG
-		fprintf(stderr, "about to closedown\n");
-#endif
-		exit(0);
-	}
-	sincelastreq++;
-#endif /* def EXIT_WHEN_IDLE */
-
-	(void) alarm(0);
-#ifdef DEBUG
-	fprintf(stderr, "boottime: %d %d\n", stats_s3.boottime.tv_sec,
-		stats_s3.boottime.tv_usec);
-#endif
-	while (system_stat_load() || diskinfo_load() || netinfo_load()) {
-		(void) kstat_chain_update(kc);
-		system_stat_init();
-		init_disks();
-		init_net();
-	}
-	stats_s4.cp_time.cp_time_len = CPU_STATES;
-	if (stats_s4.cp_time.cp_time_val == NULL)
-		stats_s4.cp_time.cp_time_val =
-		malloc(stats_s4.cp_time.cp_time_len * sizeof (int));
-	stats_s2.cp_time[RSTAT_CPU_USER] =
-	stats_s3.cp_time[RSTAT_CPU_USER] =
-	stats_s4.cp_time.cp_time_val[RSTAT_CPU_USER] =
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user");
-	stats_s2.cp_time[RSTAT_CPU_NICE] =
-	stats_s3.cp_time[RSTAT_CPU_NICE] =
-	stats_s4.cp_time.cp_time_val[RSTAT_CPU_NICE] =
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait");
-	stats_s2.cp_time[RSTAT_CPU_SYS] =
-	stats_s3.cp_time[RSTAT_CPU_SYS] =
-	stats_s4.cp_time.cp_time_val[RSTAT_CPU_SYS] =
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel");
-	stats_s2.cp_time[RSTAT_CPU_IDLE] =
-	stats_s3.cp_time[RSTAT_CPU_IDLE] =
-	stats_s4.cp_time.cp_time_val[RSTAT_CPU_IDLE] =
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle");
-
-#ifdef DEBUG
-	fprintf(stderr, "cpu: %d %d %d %d\n",
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_user"),
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_wait"),
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_kernel"),
-		CPU_STAT(&cpu_stats_all.sys, "cpu_ticks_idle"));
-	fprintf(stderr, "cp_time: %d %d %d %d\n",
-		stats_s3.cp_time[RSTAT_CPU_USER],
-		stats_s3.cp_time[RSTAT_CPU_NICE],
-		stats_s3.cp_time[RSTAT_CPU_SYS],
-		stats_s3.cp_time[RSTAT_CPU_IDLE]);
-#endif
-
-	/* current time */
-	gettimeofday((struct timeval *)&stats_s3.curtime, NULL);
-	stats_s4.curtime = stats_s3.curtime;
-
-	stats_s2.v_pgpgin =
-	stats_s3.v_pgpgin =
-	stats_s4.v_pgpgin = CPU_STAT(&cpu_stats_all.vm, "pgpgin");
-	stats_s2.v_pgpgout =
-	stats_s3.v_pgpgout =
-	stats_s4.v_pgpgout = CPU_STAT(&cpu_stats_all.vm, "pgpgout");
-	stats_s2.v_pswpin =
-	stats_s3.v_pswpin =
-	stats_s4.v_pswpin = CPU_STAT(&cpu_stats_all.vm, "pgswapin");
-	stats_s2.v_pswpout =
-	stats_s3.v_pswpout =
-	stats_s4.v_pswpout = CPU_STAT(&cpu_stats_all.vm, "pgswapout");
-	stats_s3.v_intr = CPU_STAT(&cpu_stats_all.sys, "intr");
-	stats_s3.v_intr -= hz*(stats_s3.curtime.tv_sec - btm.tv_sec) +
-		hz*(stats_s3.curtime.tv_usec - btm.tv_usec)/1000000;
-	stats_s2.v_intr =
-	stats_s4.v_intr = stats_s3.v_intr;
-	/* swtch not in V1 */
-	stats_s2.v_swtch =
-	stats_s3.v_swtch =
-	stats_s4.v_swtch = CPU_STAT(&cpu_stats_all.sys, "pswitch");
-
-#ifdef DEBUG
-	fprintf(stderr,
-		"pgin: %d pgout: %d swpin: %d swpout: %d intr: %d swtch: %d\n",
-		stats_s3.v_pgpgin,
-		stats_s3.v_pgpgout,
-		stats_s3.v_pswpin,
-		stats_s3.v_pswpout,
-		stats_s3.v_intr,
-		stats_s3.v_swtch);
-#endif
-	/*
-	 * V2 and V3 of rstat are limited to RSTAT_DK_NDRIVE drives
-	 */
-	memcpy(stats_s3.dk_xfer, stats_s4.dk_xfer.dk_xfer_val,
-		RSTAT_DK_NDRIVE * sizeof (int));
-	memcpy(stats_s2.dk_xfer, stats_s4.dk_xfer.dk_xfer_val,
-		RSTAT_DK_NDRIVE * sizeof (int));
-#ifdef DEBUG
-	fprintf(stderr, "dk_xfer: %d %d %d %d\n",
-		stats_s4.dk_xfer.dk_xfer_val[0],
-		stats_s4.dk_xfer.dk_xfer_val[1],
-		stats_s4.dk_xfer.dk_xfer_val[2],
-		stats_s4.dk_xfer.dk_xfer_val[3]);
-#endif
-
-	stats_s2.if_ipackets =
-	stats_s3.if_ipackets = stats_s4.if_ipackets;
-	/* no s2 opackets */
-	stats_s3.if_opackets = stats_s4.if_opackets;
-	stats_s2.if_ierrors =
-	stats_s3.if_ierrors = stats_s4.if_ierrors;
-	stats_s2.if_oerrors =
-	stats_s3.if_oerrors = stats_s4.if_oerrors;
-	stats_s2.if_collisions =
-	stats_s3.if_collisions = stats_s4.if_collisions;
-
-	stats_s2.avenrun[0] =
-	stats_s3.avenrun[0] =
-	stats_s4.avenrun[0] = avenrun_1min_knp->value.ul;
-	stats_s2.avenrun[1] =
-	stats_s3.avenrun[1] =
-	stats_s4.avenrun[1] = avenrun_5min_knp->value.ul;
-	stats_s2.avenrun[2] =
-	stats_s3.avenrun[2] =
-	stats_s4.avenrun[2] = avenrun_15min_knp->value.ul;
-#ifdef DEBUG
-	fprintf(stderr, "avenrun: %d %d %d\n", stats_s3.avenrun[0],
-		stats_s3.avenrun[1], stats_s3.avenrun[2]);
-#endif
-	signal(SIGALRM, updatestat);
-	alarm(1);
-}
-
-/* --------------------------------- MIBGET -------------------------------- */
-
-static mib_item_t *
-mibget(int sd)
-{
-	int			flags;
-	int			j, getcode;
-	struct strbuf		ctlbuf, databuf;
-	char			buf[512];
-	struct T_optmgmt_req	*tor = (struct T_optmgmt_req *)buf;
-	struct T_optmgmt_ack	*toa = (struct T_optmgmt_ack *)buf;
-	struct T_error_ack	*tea = (struct T_error_ack *)buf;
-	struct opthdr		*req;
-	mib_item_t		*first_item = NULL;
-	mib_item_t		*last_item  = NULL;
-	mib_item_t		*temp;
-
-	tor->PRIM_type = T_SVR4_OPTMGMT_REQ;
-	tor->OPT_offset = sizeof (struct T_optmgmt_req);
-	tor->OPT_length = sizeof (struct opthdr);
-	tor->MGMT_flags = T_CURRENT;
-	req = (struct opthdr *)&tor[1];
-	req->level = MIB2_IP;		/* any MIB2_xxx value ok here */
-	req->name  = 0;
-	req->len   = 0;
-
-	ctlbuf.buf = buf;
-	ctlbuf.len = tor->OPT_length + tor->OPT_offset;
-	flags = 0;
-	if (putmsg(sd, &ctlbuf, NULL, flags) == -1) {
-		perror("mibget: putmsg(ctl) failed");
-		goto error_exit;
-	}
-	/*
-	 * each reply consists of a ctl part for one fixed structure
-	 * or table, as defined in mib2.h.  The format is a T_OPTMGMT_ACK,
-	 * containing an opthdr structure.  level/name identify the entry,
-	 * len is the size of the data part of the message.
-	 */
-	req = (struct opthdr *)&toa[1];
-	ctlbuf.maxlen = sizeof (buf);
-	/*CSTYLED*/
-	for (j = 1; ; j++) {
-		flags = 0;
-		getcode = getmsg(sd, &ctlbuf, NULL, &flags);
-		if (getcode == -1) {
-#ifdef DEBUG_MIB
-			perror("mibget getmsg(ctl) failed");
-			fprintf(stderr, "#   level   name    len\n");
-			i = 0;
-			for (last_item = first_item; last_item;
-				last_item = last_item->next_item)
-				fprintf(stderr, "%d  %4d   %5d   %d\n", ++i,
-					last_item->group,
-					last_item->mib_id,
-					last_item->length);
-#endif /* DEBUG_MIB */
-			goto error_exit;
-		}
-		if (getcode == 0 &&
-			(ctlbuf.len >= sizeof (struct T_optmgmt_ack)) &&
-			(toa->PRIM_type == T_OPTMGMT_ACK) &&
-			(toa->MGMT_flags == T_SUCCESS) &&
-			req->len == 0) {
-#ifdef DEBUG_MIB
-			fprintf(stderr,
-		"mibget getmsg() %d returned EOD (level %d, name %d)\n",
-				j, req->level, req->name);
-#endif /* DEBUG_MIB */
-			return (first_item);		/* this is EOD msg */
-		}
-
-		if (ctlbuf.len >= sizeof (struct T_error_ack) &&
-			(tea->PRIM_type == T_ERROR_ACK)) {
-#ifdef DEBUG_MIB
-			fprintf(stderr,
-	"mibget %d gives T_ERROR_ACK: TLI_error = 0x%x, UNIX_error = 0x%x\n",
-				j, getcode, tea->TLI_error, tea->UNIX_error);
-#endif /* DEBUG_MIB */
-			errno = (tea->TLI_error == TSYSERR)
-				? tea->UNIX_error : EPROTO;
-			goto error_exit;
-		}
-
-		if (getcode != MOREDATA ||
-			(ctlbuf.len < sizeof (struct T_optmgmt_ack)) ||
-			(toa->PRIM_type != T_OPTMGMT_ACK) ||
-			(toa->MGMT_flags != T_SUCCESS)) {
-#ifdef DEBUG_MIB
-			fprintf(stderr,
-	"mibget getmsg(ctl) %d returned %d, ctlbuf.len = %d, PRIM_type = %d\n",
-				j, getcode, ctlbuf.len, toa->PRIM_type);
-			if (toa->PRIM_type == T_OPTMGMT_ACK)
-				fprintf(stderr,
-	"T_OPTMGMT_ACK: MGMT_flags = 0x%x, req->len = %d\n",
-					toa->MGMT_flags, req->len);
-#endif /* DEBUG_MIB */
-			errno = ENOMSG;
-			goto error_exit;
-		}
-
-		temp = malloc(sizeof (mib_item_t));
-		if (!temp) {
-			perror("mibget malloc failed");
-			goto error_exit;
-		}
-		if (last_item)
-			last_item->next_item = temp;
-		else
-			first_item = temp;
-		last_item = temp;
-		last_item->next_item = NULL;
-		last_item->group = req->level;
-		last_item->mib_id = req->name;
-		last_item->length = req->len;
-		last_item->valp = malloc(req->len);
-#ifdef DEBUG_MIB
-		fprintf(stderr,
-			"msg %d:  group = %4d   mib_id = %5d   length = %d\n",
-			j, last_item->group, last_item->mib_id,
-			last_item->length);
-#endif /* DEBUG_MIB */
-		databuf.maxlen = last_item->length;
-		databuf.buf    = last_item->valp;
-		databuf.len    = 0;
-		flags = 0;
-		getcode = getmsg(sd, NULL, &databuf, &flags);
-		if (getcode == -1) {
-			perror("mibget getmsg(data) failed");
-			goto error_exit;
-		} else if (getcode != 0) {
-			fprintf(stderr,
-"mibget getmsg(data) returned %d, databuf.maxlen = %d, databuf.len = %d\n",
-				getcode, databuf.maxlen, databuf.len);
-			goto error_exit;
-		}
-	}
-
-error_exit:
-	while (first_item) {
-		last_item = first_item;
-		first_item = first_item->next_item;
-		if (last_item->valp) {
-			free(last_item->valp);
-		}
-		free(last_item);
-	}
-	return (first_item);
-}
-
-static int
-mibopen(void)
-{
-	int	sd;
-
-	/* gives us ip w/ arp on top */
-	sd = open("/dev/arp", O_RDWR);
-	if (sd == -1) {
-		perror("arp open");
-		close(sd);
-		return (-1);
-	}
-	if (ioctl(sd, I_PUSH, "tcp") == -1) {
-		perror("tcp I_PUSH");
-		close(sd);
-		return (-1);
-	}
-	if (ioctl(sd, I_PUSH, "udp") == -1) {
-		perror("udp I_PUSH");
-		close(sd);
-		return (-1);
-	}
-	return (sd);
-}
-
-static char *
-octetstr(char *buf, Octet_t *op, int code)
-{
-	int	i;
-	char	*cp;
-
-	cp = buf;
-	if (op)
-		for (i = 0; i < op->o_length; i++)
-			switch (code) {
-			case 'd':
-				sprintf(cp, "%d.", 0xff & op->o_bytes[i]);
-				cp = strchr(cp, '\0');
-				break;
-			case 'a':
-				*cp++ = op->o_bytes[i];
-				break;
-			case 'h':
-			default:
-				sprintf(cp, "%02x:", 0xff & op->o_bytes[i]);
-				cp += 3;
-				break;
-			}
-	if (code != 'a' && cp != buf)
-		cp--;
-	*cp = '\0';
-	return (buf);
-}
-
-static void
-fail(int do_perror, char *message, ...)
-{
-	va_list args;
-
-	va_start(args, message);
-	fprintf(stderr, "%s: ", cmdname);
-	vfprintf(stderr, message, args);
-	va_end(args);
-	if (do_perror)
-		fprintf(stderr, ": %s", strerror(errno));
-	fprintf(stderr, "\n");
-	exit(2);
-}
-
-static void
-safe_zalloc(void **ptr, int size, int free_first)
-{
-	if (free_first && *ptr != NULL)
-		free(*ptr);
-	if ((*ptr = malloc(size)) == NULL)
-		fail(1, "malloc failed");
-	memset(*ptr, 0, size);
-}
-
-kid_t
-safe_kstat_read(kstat_ctl_t *kctl, kstat_t *ksp, void *data)
-{
-	kid_t kstat_chain_id = kstat_read(kctl, ksp, data);
-
-	if (kstat_chain_id == -1)
-		fail(1, "kstat_read(%x, '%s') failed", kctl, ksp->ks_name);
-	return (kstat_chain_id);
-}
-
-kstat_t *
-safe_kstat_lookup(kstat_ctl_t *kctl, char *ks_module, int ks_instance,
-	char *ks_name)
-{
-	kstat_t *ksp = kstat_lookup(kctl, ks_module, ks_instance, ks_name);
-
-	if (ksp == NULL)
-		fail(0, "kstat_lookup('%s', %d, '%s') failed",
-			ks_module == NULL ? "" : ks_module,
-			ks_instance,
-			ks_name == NULL ? "" : ks_name);
-	return (ksp);
-}
-
-void *
-safe_kstat_data_lookup(kstat_t *ksp, char *name)
-{
-	void *fp = kstat_data_lookup(ksp, name);
-
-	if (fp == NULL) {
-		fail(0, "kstat_data_lookup('%s', '%s') failed",
-			ksp->ks_name, name);
-	}
-	return (fp);
-}
-
-/*
- * Get various KIDs for subsequent system_stat_load operations.
- */
-
-static void
-system_stat_init(void)
-{
-	kstat_t *ksp;
-	int i, nvmks;
-
-	/*
-	 * Global statistics
-	 */
-
-	system_misc_ksp	= safe_kstat_lookup(kc, "unix", 0, "system_misc");
-
-	safe_kstat_read(kc, system_misc_ksp, NULL);
-	boot_time_knp = safe_kstat_data_lookup(system_misc_ksp, "boot_time");
-	avenrun_1min_knp = safe_kstat_data_lookup(system_misc_ksp,
-		"avenrun_1min");
-	avenrun_5min_knp = safe_kstat_data_lookup(system_misc_ksp,
-		"avenrun_5min");
-	avenrun_15min_knp = safe_kstat_data_lookup(system_misc_ksp,
-		"avenrun_15min");
-
-	/*
-	 * Per-CPU statistics
-	 */
-
-	ncpus = 0;
-	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
-		if (strcmp(ksp->ks_module, "cpu") == 0 &&
-		    strcmp(ksp->ks_name, "sys") == 0)
-			ncpus++;
-
-	safe_zalloc((void **)&cpu_stats_list, ncpus * sizeof (*cpu_stats_list),
-	    1);
-
-	ncpus = 0;
-	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next)
-		if (strcmp(ksp->ks_module, "cpu") == 0 &&
-		    strcmp(ksp->ks_name, "sys") == 0 &&
-		    kstat_read(kc, ksp, NULL) != -1) {
-			kstat_copy(ksp, &cpu_stats_list[ncpus].sys,
-			    1);
-			if ((ksp = kstat_lookup(kc, "cpu", ksp->ks_instance,
-			    "vm")) != NULL && kstat_read(kc, ksp, NULL) != -1)
-				kstat_copy(ksp, &cpu_stats_list[ncpus].vm, 1);
-			else
-				fail(0, "couldn't find per-CPU VM statistics");
-			ncpus++;
-		    }
-
-	if (ncpus == 0)
-		fail(0, "couldn't find per-CPU statistics");
-}
-
-/*
- * load statistics, summing across CPUs where needed
- */
-
-static int
-system_stat_load(void)
-{
-	int i, j;
-	_cpu_stats_t cs;
-	ulong_t *np, *tp;
-
-	/*
-	 * Global statistics
-	 */
-
-	safe_kstat_read(kc, system_misc_ksp, NULL);
-
-	/*
-	 * Per-CPU statistics.
-	 */
-
-	for (i = 0; i < ncpus; i++) {
-		if (kstat_read(kc, &cpu_stats_list[i].sys, NULL) == -1 ||
-		    kstat_read(kc, &cpu_stats_list[i].vm, NULL) == -1)
-			return (1);
-		if (i == 0) {
-			kstat_copy(&cpu_stats_list[0].sys, &cpu_stats_all.sys,
-			    1);
-			kstat_copy(&cpu_stats_list[0].vm, &cpu_stats_all.vm, 1);
-		} else {
-			kstat_named_t *nkp;
-			kstat_named_t *tkp;
-
-			/*
-			 * Other CPUs' statistics are accumulated in
-			 * cpu_stats_all, initialized at the first iteration of
-			 * the loop.
-			 */
-			nkp = (kstat_named_t *)cpu_stats_all.sys.ks_data;
-			tkp = (kstat_named_t *)cpu_stats_list[i].sys.ks_data;
-			for (j = 0; j < cpu_stats_list[i].sys.ks_ndata; j++)
-				(nkp++)->value.ui64 += (tkp++)->value.ui64;
-			nkp = (kstat_named_t *)cpu_stats_all.vm.ks_data;
-			tkp = (kstat_named_t *)cpu_stats_list[i].vm.ks_data;
-			for (j = 0; j < cpu_stats_list[i].vm.ks_ndata; j++)
-				(nkp++)->value.ui64 += (tkp++)->value.ui64;
-		}
-	}
-	return (0);
-}
-
-static int
-kscmp(kstat_t *ks1, kstat_t *ks2)
-{
-	int cmp;
-
-	cmp = strcmp(ks1->ks_module, ks2->ks_module);
-	if (cmp != 0)
-		return (cmp);
-	cmp = ks1->ks_instance - ks2->ks_instance;
-	if (cmp != 0)
-		return (cmp);
-	return (strcmp(ks1->ks_name, ks2->ks_name));
-}
-
-static void
-init_disks(void)
-{
-	struct diskinfo *disk, *prevdisk, *comp;
-	kstat_t *ksp;
-
-	ndisks = 0;
-	disk = &zerodisk;
-
-	/*
-	 * Patch the snip in the diskinfo list (see below)
-	 */
-	if (snip)
-		lastdisk->next = snip;
-
-	for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) {
-
-		if (ksp->ks_type != KSTAT_TYPE_IO ||
-		    strcmp(ksp->ks_class, "disk") != 0)
-			continue;
-		prevdisk = disk;
-		if (disk->next)
-			disk = disk->next;
-		else {
-			safe_zalloc((void **)&disk->next,
-			    sizeof (struct diskinfo), 0);
-			disk = disk->next;
-			disk->next = NULLDISK;
-		}
-		disk->ks = ksp;
-		memset((void *)&disk->kios, 0, sizeof (kstat_io_t));
-		disk->kios.wlastupdate = disk->ks->ks_crtime;
-		disk->kios.rlastupdate = disk->ks->ks_crtime;
-
-		/*
-		 * Insertion sort on (ks_module, ks_instance, ks_name)
-		 */
-		comp = &zerodisk;
-		while (kscmp(disk->ks, comp->next->ks) > 0)
-			comp = comp->next;
-		if (prevdisk != comp) {
-			prevdisk->next = disk->next;
-			disk->next = comp->next;
-			comp->next = disk;
-			disk = prevdisk;
-		}
-		ndisks++;
-	}
-	/*
-	 * Put a snip in the linked list of diskinfos.  The idea:
-	 * If there was a state change such that now there are fewer
-	 * disks, we snip the list and retain the tail, rather than
-	 * freeing it.  At the next state change, we clip the tail back on.
-	 * This prevents a lot of malloc/free activity, and it's simpler.
-	 */
-	lastdisk = disk;
-	snip = disk->next;
-	disk->next = NULLDISK;
-
-	firstdisk = zerodisk.next;
-
-	if (ndisks > stats_s4.dk_xfer.dk_xfer_len) {
-		stats_s4.dk_xfer.dk_xfer_len = ndisks;
-		safe_zalloc((void **)&stats_s4.dk_xfer.dk_xfer_val,
-			ndisks * sizeof (int), 1);
-	}
-}
-
-static int
-diskinfo_load(void)
-{
-	struct diskinfo *disk;
-	int i;
-
-	for (disk = firstdisk, i = 0; disk; disk = disk->next, i++) {
-		if (kstat_read(kc, disk->ks, (void *)&disk->kios) == -1)
-			return (1);
-		stats_s4.dk_xfer.dk_xfer_val[i] = disk->kios.reads +
-			disk->kios.writes;
-	}
-	return (0);
-}
-
-static void
-init_net(void)
-{
-	static int sd;
-	mib_item_t *item;
-	mib2_ipAddrEntry_t *ap;
-	char namebuf[KSTAT_STRLEN];
-	struct netinfo *net, *prevnet, *comp;
-	kstat_t *ksp;
-
-	if (sd) {
-		close(sd);
-	}
-	while (netstat_item) {
-		item = netstat_item;
-		netstat_item = netstat_item->next_item;
-		if (item->valp) {
-			free(item->valp);
-		}
-		free(item);
-	}
-	sd = mibopen();
-	if (sd == -1) {
-#ifdef DEBUG
-		fprintf(stderr, "mibopen() failed\n");
-#endif
-		sd = 0;
-	} else {
-		if ((netstat_item = mibget(sd)) == NULL) {
-#ifdef DEBUG
-			fprintf(stderr, "mibget() failed\n");
-#endif
-			close(sd);
-			sd = 0;
-		}
-	}
-#ifdef DEBUG
-	fprintf(stderr, "mibget returned item: %x\n", netstat_item);
-#endif
-
-	nnets = 0;
-	net = &zeronet;
-
-	if (netsnip)
-		lastnet->next = netsnip;
-
-	for (item = netstat_item; item; item = item->next_item) {
-#ifdef DEBUG_MIB
-		fprintf(stderr, "\n--- Item %x ---\n", item);
-		fprintf(stderr,
-		"Group = %d, mib_id = %d, length = %d, valp = 0x%x\n",
-		item->group, item->mib_id, item->length,
-		item->valp);
-#endif
-		if (item->group != MIB2_IP || item->mib_id != MIB2_IP_20)
-			continue;
-		ap = (mib2_ipAddrEntry_t *)item->valp;
-		for (; (char *)ap < item->valp + item->length; ap++) {
-
-			octetstr(namebuf, &ap->ipAdEntIfIndex, 'a');
-#ifdef DEBUG
-			fprintf(stderr, "%s ", namebuf);
-#endif
-			if (strlen(namebuf) == 0)
-				continue;
-			/*
-			 * We found a device of interest.
-			 * Now, let's see if there's a kstat for it.
-			 * First we try to query the "link" kstats in case
-			 * the link is renamed. If that fails, fallback
-			 * to legacy ktats for those non-GLDv3 links.
-			 */
-			if (((ksp = kstat_lookup(kc, "link", 0, namebuf))
-			    == NULL) && ((ksp = kstat_lookup(kc, NULL, -1,
-			    namebuf)) == NULL)) {
-				continue;
-			}
-			if (ksp->ks_type != KSTAT_TYPE_NAMED)
-				continue;
-			if (kstat_read(kc, ksp, NULL) == -1)
-				continue;
-			prevnet = net;
-			if (net->next)
-				net = net->next;
-			else {
-				safe_zalloc((void **)&net->next,
-					sizeof (struct netinfo), 0);
-				net = net->next;
-				net->next = NULLNET;
-			}
-			net->ks = ksp;
-			net->ipackets	= kstat_data_lookup(net->ks,
-				"ipackets");
-			net->opackets	= kstat_data_lookup(net->ks,
-				"opackets");
-			net->ierrors	= kstat_data_lookup(net->ks,
-				"ierrors");
-			net->oerrors	= kstat_data_lookup(net->ks,
-				"oerrors");
-			net->collisions	= kstat_data_lookup(net->ks,
-				"collisions");
-			/*
-			 * Insertion sort on the name
-			 */
-			comp = &zeronet;
-			while (strcmp(net->ks->ks_name,
-			    comp->next->ks->ks_name) > 0)
-				comp = comp->next;
-			if (prevnet != comp) {
-				prevnet->next = net->next;
-				net->next = comp->next;
-				comp->next = net;
-				net = prevnet;
-			}
-			nnets++;
-		}
-#ifdef DEBUG
-		fprintf(stderr, "\n");
-#endif
-	}
-	/*
-	 * Put a snip in the linked list of netinfos.  The idea:
-	 * If there was a state change such that now there are fewer
-	 * nets, we snip the list and retain the tail, rather than
-	 * freeing it.  At the next state change, we clip the tail back on.
-	 * This prevents a lot of malloc/free activity, and it's simpler.
-	 */
-	lastnet = net;
-	netsnip = net->next;
-	net->next = NULLNET;
-
-	firstnet = zeronet.next;
-}
-
-static int
-netinfo_load(void)
-{
-	struct netinfo *net;
-
-	if (netstat_item == NULL) {
-#ifdef DEBUG
-		fprintf(stderr, "No net stats\n");
-#endif
-		return (0);
-	}
-
-	stats_s4.if_ipackets =
-	stats_s4.if_opackets =
-	stats_s4.if_ierrors =
-	stats_s4.if_oerrors =
-	stats_s4.if_collisions = 0;
-
-	for (net = firstnet; net; net = net->next) {
-		if (kstat_read(kc, net->ks, NULL) == -1)
-			return (1);
-		if (net->ipackets)
-			stats_s4.if_ipackets	+= net->ipackets->value.ul;
-		if (net->opackets)
-			stats_s4.if_opackets	+= net->opackets->value.ul;
-		if (net->ierrors)
-			stats_s4.if_ierrors	+= net->ierrors->value.ul;
-		if (net->oerrors)
-			stats_s4.if_oerrors	+= net->oerrors->value.ul;
-		if (net->collisions)
-			stats_s4.if_collisions	+= net->collisions->value.ul;
-	}
-#ifdef DEBUG
-	fprintf(stderr,
-	    "ipackets: %d opackets: %d ierrors: %d oerrors: %d colls: %d\n",
-		stats_s4.if_ipackets,
-		stats_s4.if_opackets,
-		stats_s4.if_ierrors,
-		stats_s4.if_oerrors,
-		stats_s4.if_collisions);
-#endif
-	return (0);
-}
-
-static void
-kstat_copy(kstat_t *src, kstat_t *dst, int fr)
-{
-	if (fr)
-		free(dst->ks_data);
-	*dst = *src;
-	if (src->ks_data != NULL) {
-		safe_zalloc(&dst->ks_data, src->ks_data_size, 0);
-		(void) memcpy(dst->ks_data, src->ks_data, src->ks_data_size);
-	} else {
-		dst->ks_data = NULL;
-		dst->ks_data_size = 0;
-	}
-}
