11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1980, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 3087715Smarkm#include <sys/cdefs.h> 311590Srgrimes 3287715Smarkm__FBSDID("$FreeBSD: stable/11/usr.bin/systat/fetch.c 368931 2021-01-05 20:02:55Z mr $"); 3387715Smarkm 3487715Smarkm#ifdef lint 3587715Smarkmstatic const char sccsid[] = "@(#)fetch.c 8.1 (Berkeley) 6/6/93"; 3687715Smarkm#endif 3787715Smarkm 381590Srgrimes#include <sys/types.h> 3974671Stmm#include <sys/sysctl.h> 4074671Stmm 41200462Sdelphij#include <err.h> 4274671Stmm#include <errno.h> 4387715Smarkm#include <stdlib.h> 4474671Stmm#include <string.h> 4574671Stmm 461590Srgrimes#include "systat.h" 471590Srgrimes#include "extern.h" 481590Srgrimes 491590Srgrimesint 50175387Sdelphijkvm_ckread(void *a, void *b, int l) 511590Srgrimes{ 521590Srgrimes if (kvm_read(kd, (u_long)a, b, l) != l) { 531590Srgrimes if (verbose) 5487715Smarkm error("error reading kmem at %p", a); 551590Srgrimes return (0); 568874Srgrimes } 571590Srgrimes else 581590Srgrimes return (1); 591590Srgrimes} 6074671Stmm 61368931Smrvoid 62368931Smrgetsysctl(const char *name, void *ptr, size_t len) 6374671Stmm{ 6474671Stmm size_t nlen = len; 65368931Smr 6687715Smarkm if (sysctlbyname(name, ptr, &nlen, NULL, 0) != 0) { 67226396Sed error("sysctl(%s...) failed: %s", name, 6874671Stmm strerror(errno)); 6974671Stmm } 7074671Stmm if (nlen != len) { 71368931Smr error("sysctl(%s...) expected %zu, got %zu", name, len, nlen); 72368931Smr } 7374671Stmm} 7474671Stmm 7574671Stmm/* 76226396Sed * Read sysctl data with variable size. Try some times (with increasing 7774671Stmm * buffers), fail if still too small. 7874671Stmm * This is needed sysctls with possibly raplidly increasing data sizes, 7974671Stmm * but imposes little overhead in the case of constant sizes. 8074671Stmm * Returns NULL on error, or a pointer to freshly malloc()'ed memory that holds 8174671Stmm * the requested data. 8274671Stmm * If szp is not NULL, the size of the returned data will be written into *szp. 8374671Stmm */ 8474671Stmm 8574671Stmm/* Some defines: Number of tries. */ 8674671Stmm#define SD_NTRIES 10 8774671Stmm/* Percent of over-allocation (initial) */ 88226396Sed#define SD_MARGIN 10 89226396Sed/* 9074671Stmm * Factor for over-allocation in percent (the margin is increased by this on 9174671Stmm * any failed try). 9274671Stmm */ 9374671Stmm#define SD_FACTOR 50 9474671Stmm/* Maximum supported MIB depth */ 9574671Stmm#define SD_MAXMIB 16 9674671Stmm 9774671Stmmchar * 98175387Sdelphijsysctl_dynread(const char *n, size_t *szp) 9974671Stmm{ 10074671Stmm char *rv = NULL; 10174671Stmm int mib[SD_MAXMIB]; 10274671Stmm size_t mibsz = SD_MAXMIB; 10374671Stmm size_t mrg = SD_MARGIN; 10474671Stmm size_t sz; 10574671Stmm int i; 10674671Stmm 10774671Stmm /* cache the MIB */ 10874671Stmm if (sysctlnametomib(n, mib, &mibsz) == -1) { 10974671Stmm if (errno == ENOMEM) { 11074671Stmm error("XXX: SD_MAXMIB too small, please bump!"); 11174671Stmm } 11274671Stmm return NULL; 11374671Stmm } 11474671Stmm for (i = 0; i < SD_NTRIES; i++) { 11574671Stmm /* get needed buffer size */ 11674671Stmm if (sysctl(mib, mibsz, NULL, &sz, NULL, 0) == -1) 11774671Stmm break; 11874671Stmm sz += sz * mrg / 100; 11974671Stmm if ((rv = (char *)malloc(sz)) == NULL) { 12074671Stmm error("Out of memory!"); 12174671Stmm return NULL; 12274671Stmm } 12374671Stmm if (sysctl(mib, mibsz, rv, &sz, NULL, 0) == -1) { 12474671Stmm free(rv); 12574671Stmm rv = NULL; 12674671Stmm if (errno == ENOMEM) { 12774671Stmm mrg += mrg * SD_FACTOR / 100; 12874671Stmm } else 12974671Stmm break; 13074671Stmm } else { 13174671Stmm /* success */ 13274671Stmm if (szp != NULL) 13374671Stmm *szp = sz; 13474671Stmm break; 13574671Stmm } 13674671Stmm } 13774671Stmm 13874671Stmm return rv; 13974671Stmm} 140