fetch.c revision 77583
112891Swpaul/*-
212891Swpaul * Copyright (c) 1980, 1992, 1993
312891Swpaul *	The Regents of the University of California.  All rights reserved.
412891Swpaul *
512891Swpaul * Redistribution and use in source and binary forms, with or without
612891Swpaul * modification, are permitted provided that the following conditions
712891Swpaul * are met:
812891Swpaul * 1. Redistributions of source code must retain the above copyright
912891Swpaul *    notice, this list of conditions and the following disclaimer.
1012891Swpaul * 2. Redistributions in binary form must reproduce the above copyright
1112891Swpaul *    notice, this list of conditions and the following disclaimer in the
1212891Swpaul *    documentation and/or other materials provided with the distribution.
1312891Swpaul * 3. All advertising materials mentioning features or use of this software
1412891Swpaul *    must display the following acknowledgement:
1512891Swpaul *	This product includes software developed by the University of
1612891Swpaul *	California, Berkeley and its contributors.
1712891Swpaul * 4. Neither the name of the University nor the names of its contributors
1812891Swpaul *    may be used to endorse or promote products derived from this software
1912891Swpaul *    without specific prior written permission.
2012891Swpaul *
2112891Swpaul * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2212891Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2312891Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2412891Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2512891Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2612891Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2712891Swpaul * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2812891Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2912891Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3012891Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3112891Swpaul * SUCH DAMAGE.
3212891Swpaul *
3312891Swpaul * $FreeBSD: head/usr.bin/systat/fetch.c 77583 2001-06-01 13:29:19Z tmm $
3412891Swpaul */
3512891Swpaul
3612891Swpaul#ifndef lint
3712891Swpaulstatic char sccsid[] = "@(#)fetch.c	8.1 (Berkeley) 6/6/93";
3812891Swpaul#endif /* not lint */
3912891Swpaul
4012891Swpaul#include <sys/types.h>
4112891Swpaul#include <sys/sysctl.h>
4212891Swpaul
4312891Swpaul#include <errno.h>
4412891Swpaul#include <err.h>
4512891Swpaul#include <string.h>
4612891Swpaul#include <stdlib.h>
4712891Swpaul
4812891Swpaul#include "systat.h"
4912891Swpaul#include "extern.h"
5012891Swpaul
5112891Swpaulint
5212891Swpaulkvm_ckread(a, b, l)
5312891Swpaul	void *a, *b;
5412891Swpaul	int l;
5512891Swpaul{
5612891Swpaul	if (kvm_read(kd, (u_long)a, b, l) != l) {
5712891Swpaul		if (verbose)
5812891Swpaul			error("error reading kmem at %x", a);
5912891Swpaul		return (0);
6012891Swpaul	}
6112891Swpaul	else
6212891Swpaul		return (1);
6312891Swpaul}
6412891Swpaul
6512891Swpaulvoid getsysctl(name, ptr, len)
6612891Swpaul	char *name;
6712891Swpaul	void *ptr;
6812891Swpaul	size_t len;
6912891Swpaul{
7012891Swpaul	int err;
7112891Swpaul	size_t nlen = len;
7212891Swpaul	if ((err = sysctlbyname(name, ptr, &nlen, NULL, 0)) != 0) {
7312891Swpaul		error("sysctl(%s...) failed: %s", name,
7412891Swpaul		    strerror(errno));
7512891Swpaul	}
7612891Swpaul	if (nlen != len) {
7712891Swpaul		error("sysctl(%s...) expected %lu, got %lu", name,
7812891Swpaul		    (unsigned long)len, (unsigned long)nlen);
7912891Swpaul    }
8012891Swpaul}
8112891Swpaul
8212891Swpaul/*
8312891Swpaul * Read sysctl data with variable size. Try some times (with increasing
8412891Swpaul * buffers), fail if still too small.
8512891Swpaul * This is needed sysctls with possibly raplidly increasing data sizes,
8612891Swpaul * but imposes little overhead in the case of constant sizes.
8712891Swpaul * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds
8812891Swpaul * the requested data.
8912891Swpaul * If szp is not NULL, the size of the returned data will be written into *szp.
9012891Swpaul */
9112891Swpaul
9212891Swpaul/* Some defines: Number of tries. */
9312891Swpaul#define SD_NTRIES  10
9412891Swpaul/* Percent of over-allocation (initial) */
9512891Swpaul#define SD_MARGIN  10
9612891Swpaul/*
9712891Swpaul * Factor for over-allocation in percent (the margin is increased by this on
9812891Swpaul * any failed try).
9912891Swpaul */
10012891Swpaul#define SD_FACTOR  50
10112891Swpaul/* Maximum supported MIB depth */
10212891Swpaul#define SD_MAXMIB  16
10312891Swpaul
10412891Swpaulchar *
10512891Swpaulsysctl_dynread(n, szp)
10612891Swpaul	char *n;
10712891Swpaul	size_t *szp;
10812891Swpaul{
10912891Swpaul	char   *rv = NULL;
11012891Swpaul	int    mib[SD_MAXMIB];
11112891Swpaul	size_t mibsz = SD_MAXMIB;
11212891Swpaul	size_t mrg = SD_MARGIN;
11312891Swpaul	size_t sz;
11412891Swpaul	int i;
11512891Swpaul
11612891Swpaul	/* cache the MIB */
11712891Swpaul	if (sysctlnametomib(n, mib, &mibsz) == -1) {
11812891Swpaul		if (errno == ENOMEM) {
11912891Swpaul			error("XXX: SD_MAXMIB too small, please bump!");
12012891Swpaul		}
12112891Swpaul		return NULL;
12212891Swpaul	}
12312891Swpaul	for (i = 0; i < SD_NTRIES; i++) {
12412891Swpaul		/* get needed buffer size */
12512891Swpaul		if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1)
12612891Swpaul			break;
12712891Swpaul		sz += sz * mrg / 100;
12812891Swpaul		if ((rv = (char *)malloc(sz)) == NULL) {
12912891Swpaul			error("Out of memory!");
13012891Swpaul			return NULL;
13112891Swpaul		}
13212891Swpaul		if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) {
13312891Swpaul			free(rv);
13412891Swpaul			rv = NULL;
13512891Swpaul			if (errno == ENOMEM) {
13612891Swpaul				mrg += mrg * SD_FACTOR / 100;
13712891Swpaul			} else
13812891Swpaul				break;
13912891Swpaul		} else {
14012891Swpaul			/* success */
14112891Swpaul			if (szp != NULL)
14212891Swpaul				*szp = sz;
14312891Swpaul			break;
14412891Swpaul		}
14512891Swpaul	}
14612891Swpaul
14712891Swpaul	return rv;
14812891Swpaul}
14912891Swpaul