Home | History | Annotate | Line # | Download | only in sysctl
sysctl.c revision 1.82
      1  1.82    atatat /*	$NetBSD: sysctl.c,v 1.82 2004/03/20 05:22:41 atatat Exp $ */
      2  1.75    atatat 
      3  1.75    atatat /*-
      4  1.75    atatat  * Copyright (c) 2003 The NetBSD Foundation, Inc.
      5  1.75    atatat  *	All rights reserved.
      6  1.75    atatat  *
      7  1.75    atatat  * This code is derived from software contributed to The NetBSD Foundation
      8  1.75    atatat  * by Andrew Brown.
      9  1.75    atatat  *
     10  1.75    atatat  * Redistribution and use in source and binary forms, with or without
     11  1.75    atatat  * modification, are permitted provided that the following conditions
     12  1.75    atatat  * are met:
     13  1.75    atatat  * 1. Redistributions of source code must retain the above copyright
     14  1.75    atatat  *    notice, this list of conditions and the following disclaimer.
     15  1.75    atatat  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.75    atatat  *    notice, this list of conditions and the following disclaimer in the
     17  1.75    atatat  *    documentation and/or other materials provided with the distribution.
     18  1.75    atatat  * 3. Neither the name of The NetBSD Foundation nor the names of its
     19  1.75    atatat  *    contributors may be used to endorse or promote products derived
     20  1.75    atatat  *    from this software without specific prior written permission.
     21  1.75    atatat  *
     22  1.75    atatat  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     23  1.75    atatat  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     24  1.75    atatat  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     25  1.75    atatat  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     26  1.75    atatat  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     27  1.75    atatat  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     28  1.75    atatat  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     29  1.75    atatat  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     30  1.75    atatat  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     31  1.75    atatat  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     32  1.75    atatat  * POSSIBILITY OF SUCH DAMAGE.
     33  1.75    atatat  */
     34   1.9   thorpej 
     35   1.1       cgd /*
     36   1.1       cgd  * Copyright (c) 1993
     37   1.1       cgd  *	The Regents of the University of California.  All rights reserved.
     38   1.1       cgd  *
     39   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     40   1.1       cgd  * modification, are permitted provided that the following conditions
     41   1.1       cgd  * are met:
     42   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     43   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     44   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     45   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     46   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     47  1.71       agc  * 3. Neither the name of the University nor the names of its contributors
     48   1.1       cgd  *    may be used to endorse or promote products derived from this software
     49   1.1       cgd  *    without specific prior written permission.
     50   1.1       cgd  *
     51   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     52   1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     53   1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     54   1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     55   1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     56   1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     57   1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     58   1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     59   1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     60   1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     61   1.1       cgd  * SUCH DAMAGE.
     62   1.1       cgd  */
     63   1.1       cgd 
     64  1.14  christos #include <sys/cdefs.h>
     65   1.1       cgd #ifndef lint
     66  1.14  christos __COPYRIGHT(
     67   1.1       cgd "@(#) Copyright (c) 1993\n\
     68  1.14  christos 	The Regents of the University of California.  All rights reserved.\n");
     69   1.1       cgd #endif /* not lint */
     70   1.1       cgd 
     71   1.1       cgd #ifndef lint
     72   1.9   thorpej #if 0
     73   1.9   thorpej static char sccsid[] = "@(#)sysctl.c	8.1 (Berkeley) 6/6/93";
     74   1.9   thorpej #else
     75  1.82    atatat __RCSID("$NetBSD: sysctl.c,v 1.82 2004/03/20 05:22:41 atatat Exp $");
     76   1.9   thorpej #endif
     77   1.1       cgd #endif /* not lint */
     78   1.1       cgd 
     79  1.75    atatat #include <sys/types.h>
     80   1.1       cgd #include <sys/param.h>
     81   1.1       cgd #include <sys/sysctl.h>
     82  1.17   thorpej #include <sys/mount.h>
     83  1.22    bouyer #include <sys/resource.h>
     84  1.75    atatat #include <sys/stat.h>
     85  1.75    atatat #include <sys/sched.h>
     86  1.75    atatat #include <sys/socket.h>
     87   1.1       cgd #include <netinet/in.h>
     88   1.1       cgd #include <netinet/ip_var.h>
     89   1.8   thorpej #include <netinet/tcp.h>
     90   1.8   thorpej #include <netinet/tcp_timer.h>
     91   1.8   thorpej #include <netinet/tcp_var.h>
     92  1.24    itojun #include <netinet/icmp6.h>
     93  1.75    atatat #include <nfs/rpcv2.h>
     94  1.75    atatat #include <nfs/nfsproto.h>
     95  1.75    atatat #include <nfs/nfs.h>
     96  1.75    atatat #include <machine/cpu.h>
     97  1.20    itojun #include <netkey/key_var.h>
     98  1.20    itojun 
     99  1.75    atatat #include <assert.h>
    100  1.75    atatat #include <ctype.h>
    101  1.14  christos #include <err.h>
    102   1.1       cgd #include <errno.h>
    103  1.75    atatat #include <inttypes.h>
    104  1.75    atatat #include <stdarg.h>
    105   1.1       cgd #include <stdio.h>
    106   1.1       cgd #include <stdlib.h>
    107   1.1       cgd #include <string.h>
    108  1.75    atatat #include <time.h>
    109  1.15      tron #include <unistd.h>
    110   1.1       cgd 
    111  1.75    atatat /*
    112  1.75    atatat  * this needs to be able to do the printing and the setting
    113  1.75    atatat  */
    114  1.75    atatat #define HANDLER_PROTO const char *, const char *, char *, \
    115  1.75    atatat 	int *, u_int, const struct sysctlnode *, \
    116  1.75    atatat 	u_int, void *
    117  1.75    atatat #define HANDLER_ARGS const char *sname, const char *dname, char *value, \
    118  1.75    atatat 	int *name, u_int namelen, const struct sysctlnode *pnode, \
    119  1.75    atatat 	u_int type, void *v
    120  1.75    atatat #define DISPLAY_VALUE	0
    121  1.75    atatat #define DISPLAY_OLD	1
    122  1.75    atatat #define DISPLAY_NEW	2
    123  1.75    atatat 
    124  1.75    atatat /*
    125  1.75    atatat  * generic routines
    126  1.75    atatat  */
    127  1.75    atatat static struct handlespec *findprinter(const int *, u_int);
    128  1.75    atatat static struct handlespec *findwriter(const int *, u_int);
    129  1.75    atatat static void print_tree(int *, u_int, struct sysctlnode *, u_int, int);
    130  1.75    atatat static void write_number(int *, u_int, struct sysctlnode *, char *);
    131  1.75    atatat static void write_string(int *, u_int, struct sysctlnode *, char *);
    132  1.75    atatat static void display_number(const struct sysctlnode *, const char *,
    133  1.75    atatat 			   const void *, size_t, int);
    134  1.75    atatat static void display_string(const struct sysctlnode *, const char *,
    135  1.75    atatat 			   const void *, size_t, int);
    136  1.75    atatat static void display_struct(const struct sysctlnode *, const char *,
    137  1.75    atatat 			   const void *, size_t, int);
    138  1.75    atatat static void hex_dump(const unsigned char *, size_t);
    139  1.75    atatat static void usage(void);
    140  1.75    atatat static void parse(char *);
    141  1.82    atatat static void parse_create(char *);
    142  1.82    atatat static void parse_destroy(char *);
    143  1.75    atatat static void sysctlerror(int);
    144  1.56  christos 
    145  1.75    atatat /*
    146  1.75    atatat  * unexported from some place else (XXX tbd)
    147  1.75    atatat  */
    148  1.75    atatat int learn_tree(int *, u_int, struct sysctlnode *);
    149  1.78    atatat int sysctlbyname(const char *, void *, size_t *, void *, size_t);
    150  1.78    atatat int sysctlgetmibinfo(const char *, int *, u_int *,
    151  1.78    atatat 		     char *, size_t *, struct sysctlnode **);
    152  1.22    bouyer 
    153  1.75    atatat /*
    154  1.75    atatat  * "handlers"
    155  1.75    atatat  */
    156  1.75    atatat static void printother(HANDLER_PROTO);
    157  1.75    atatat static void kern_clockrate(HANDLER_PROTO);
    158  1.75    atatat static void kern_boottime(HANDLER_PROTO);
    159  1.75    atatat static void kern_consdev(HANDLER_PROTO);
    160  1.75    atatat static void kern_cp_time(HANDLER_PROTO);
    161  1.75    atatat static void vm_loadavg(HANDLER_PROTO);
    162  1.75    atatat static void proc_limit(HANDLER_PROTO);
    163  1.75    atatat #ifdef CPU_DISKINFO
    164  1.75    atatat static void machdep_diskinfo(HANDLER_PROTO);
    165  1.75    atatat #endif /* CPU_DISKINFO */
    166   1.1       cgd 
    167  1.75    atatat struct handlespec {
    168  1.75    atatat 	int ps_name[CTL_MAXNAME];
    169  1.75    atatat 	void (*ps_p)(HANDLER_PROTO);
    170  1.75    atatat 	void (*ps_w)(HANDLER_PROTO);
    171  1.75    atatat 	void *ps_d;
    172  1.75    atatat } handlers[] = {
    173  1.75    atatat 	{ { CTL_KERN, KERN_CLOCKRATE },	kern_clockrate },
    174  1.75    atatat 	{ { CTL_KERN, KERN_VNODE },	printother,	NULL,	"pstat" },
    175  1.75    atatat 	{ { CTL_KERN, KERN_PROC },	printother,	NULL,	"ps" },
    176  1.75    atatat 	{ { CTL_KERN, KERN_PROC2 },	printother,	NULL,	"ps" },
    177  1.75    atatat 	{ { CTL_KERN, KERN_PROC_ARGS },	printother,	NULL,	"ps" },
    178  1.75    atatat 	{ { CTL_KERN, KERN_FILE },	printother,	NULL,	"pstat" },
    179  1.75    atatat 	{ { CTL_KERN, KERN_NTPTIME },	printother,	NULL,
    180  1.75    atatat 	  "ntpdc -c kerninfo" },
    181  1.75    atatat 	{ { CTL_KERN, KERN_MSGBUF },	printother,	NULL,	"dmesg" },
    182  1.75    atatat 	{ { CTL_KERN, KERN_BOOTTIME },	kern_boottime },
    183  1.75    atatat 	{ { CTL_KERN, KERN_CONSDEV },	kern_consdev },
    184  1.80    atatat 	{ { CTL_KERN, KERN_CP_TIME, -1 }, kern_cp_time },
    185  1.75    atatat 	{ { CTL_KERN, KERN_CP_TIME },	kern_cp_time },
    186  1.75    atatat 	{ { CTL_KERN, KERN_SYSVIPC_INFO }, printother,	NULL,	"ipcs" },
    187  1.75    atatat 	{ { CTL_VM,   VM_METER },	printother,	NULL,
    188  1.75    atatat 	  "vmstat' or 'systat" },
    189  1.75    atatat 	{ { CTL_VM,   VM_LOADAVG },	vm_loadavg },
    190  1.75    atatat 	{ { CTL_VM,   VM_UVMEXP },	printother,	NULL,
    191  1.75    atatat 	  "vmstat' or 'systat" },
    192  1.75    atatat 	{ { CTL_VM,   VM_UVMEXP2 },	printother,	NULL,
    193  1.75    atatat 	  "vmstat' or 'systat" },
    194  1.75    atatat 	{ { CTL_VFS,  2 /* NFS */, NFS_NFSSTATS },
    195  1.75    atatat 					printother,	NULL,	"nfsstat" },
    196  1.75    atatat 	{ { CTL_NET },			printother,	NULL,	NULL },
    197  1.75    atatat 	{ { CTL_NET, PF_LOCAL },	printother,	NULL,	NULL },
    198  1.75    atatat 	{ { CTL_NET, PF_INET, IPPROTO_TCP, TCPCTL_IDENT },
    199  1.75    atatat 					printother,	NULL,	"identd" },
    200  1.75    atatat 	{ { CTL_NET, PF_INET6, IPPROTO_TCP, TCPCTL_IDENT },
    201  1.75    atatat 					printother,	NULL,	"identd" },
    202  1.75    atatat 
    203  1.75    atatat 	{ { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_DRLIST },
    204  1.79    atatat 					printother,	NULL,	"ndp" },
    205  1.75    atatat 	{ { CTL_NET, PF_INET6, IPPROTO_ICMPV6, ICMPV6CTL_ND6_PRLIST },
    206  1.79    atatat 					printother,	NULL,	"ndp" },
    207  1.75    atatat 
    208  1.75    atatat 
    209  1.75    atatat 	{ { CTL_NET, PF_KEY, KEYCTL_DUMPSA },
    210  1.75    atatat 					printother,	NULL,	"setkey" },
    211  1.75    atatat 	{ { CTL_NET, PF_KEY, KEYCTL_DUMPSP },
    212  1.75    atatat 					printother,	NULL,	"setkey" },
    213  1.75    atatat 	/* { { CTL_DEBUG },		printother,	NULL,	NULL }, */
    214  1.75    atatat 	{ { CTL_HW,   HW_DISKSTATS },	printother,	NULL,	"iostat" },
    215  1.75    atatat #ifdef CPU_CONSDEV
    216  1.75    atatat 	{ { CTL_MACHDEP, CPU_CONSDEV },	kern_consdev },
    217  1.75    atatat #endif /* CPU_CONSDEV */
    218  1.75    atatat #ifdef CPU_DISKINFO
    219  1.75    atatat 	{ { CTL_MACHDEP, CPU_DISKINFO },machdep_diskinfo },
    220  1.75    atatat #endif /* CPU_CONSDEV */
    221  1.75    atatat 	{ { CTL_DDB },			printother,	NULL,	NULL },
    222  1.75    atatat 	{ { CTL_PROC, -1, PROC_PID_LIMIT, -1, -1 }, proc_limit, proc_limit },
    223  1.75    atatat 	{ { CTL_UNSPEC }, },
    224   1.1       cgd };
    225  1.56  christos 
    226  1.75    atatat struct sysctlnode my_root = {
    227  1.75    atatat #if defined(lint)
    228  1.75    atatat 	0
    229  1.75    atatat #else /* defined(lint) */
    230  1.75    atatat 	.sysctl_flags = SYSCTL_ROOT|
    231  1.75    atatat 	    SYSCTL_TYPE(CTLTYPE_NODE),
    232  1.75    atatat 	.sysctl_size = sizeof(struct sysctlnode),
    233  1.75    atatat 	.sysctl_num = 0,
    234  1.75    atatat 	.sysctl_name = "(prog_root)",
    235  1.75    atatat #endif /* defined(lint) */
    236   1.1       cgd };
    237   1.1       cgd 
    238  1.75    atatat int	Aflag, aflag, Mflag, nflag, qflag, rflag, wflag, xflag;
    239  1.75    atatat int	req;
    240  1.65     lukem FILE	*warnfp = stderr;
    241   1.1       cgd 
    242   1.1       cgd /*
    243  1.75    atatat  * vah-riables n stuff
    244   1.1       cgd  */
    245  1.75    atatat char gsname[SYSCTL_NAMELEN * CTL_MAXNAME + CTL_MAXNAME],
    246  1.75    atatat 	gdname[10 * CTL_MAXNAME + CTL_MAXNAME];
    247  1.75    atatat char sep[2] = ".", *eq = " = ";
    248  1.75    atatat const char *lname[] = {
    249  1.75    atatat 	"top", "second", "third", "fourth", "fifth", "sixth",
    250  1.75    atatat 	"seventh", "eighth", "ninth", "tenth", "eleventh", "twelfth"
    251  1.75    atatat };
    252   1.1       cgd 
    253  1.22    bouyer /*
    254  1.75    atatat  * you've heard of main, haven't you?
    255  1.22    bouyer  */
    256   1.1       cgd int
    257  1.53    simonb main(int argc, char *argv[])
    258   1.1       cgd {
    259  1.27    tsarna 	char *fn = NULL;
    260  1.75    atatat 	int name[CTL_MAXNAME];
    261  1.75    atatat 	int ch;
    262   1.1       cgd 
    263  1.82    atatat 	while ((ch = getopt(argc, argv, "Aabef:Mnqrwx")) != -1) {
    264   1.1       cgd 		switch (ch) {
    265   1.1       cgd 		case 'A':
    266  1.75    atatat 			Aflag++;
    267   1.1       cgd 			break;
    268   1.1       cgd 		case 'a':
    269  1.75    atatat 			aflag++;
    270   1.1       cgd 			break;
    271  1.72     grant 		case 'e':
    272  1.75    atatat 			eq = "=";
    273  1.72     grant 			break;
    274  1.27    tsarna 		case 'f':
    275  1.27    tsarna 			fn = optarg;
    276  1.75    atatat 			wflag++;
    277  1.75    atatat 			break;
    278  1.75    atatat 		case 'M':
    279  1.75    atatat 			Mflag++;
    280  1.27    tsarna 			break;
    281   1.1       cgd 		case 'n':
    282  1.75    atatat 			nflag++;
    283   1.1       cgd 			break;
    284  1.58  sommerfe 		case 'q':
    285  1.75    atatat 			qflag++;
    286  1.75    atatat 			break;
    287  1.82    atatat 		case 'b':	/* FreeBSD compat */
    288  1.75    atatat 		case 'r':
    289  1.75    atatat 			rflag++;
    290  1.58  sommerfe 			break;
    291   1.1       cgd 		case 'w':
    292  1.75    atatat 			wflag++;
    293  1.75    atatat 			break;
    294  1.75    atatat 		case 'x':
    295  1.75    atatat 			xflag++;
    296   1.1       cgd 			break;
    297   1.1       cgd 		default:
    298   1.1       cgd 			usage();
    299   1.1       cgd 		}
    300   1.1       cgd 	}
    301  1.58  sommerfe 
    302  1.75    atatat 	argc -= optind;
    303  1.75    atatat 	argv += optind;
    304  1.75    atatat 
    305  1.58  sommerfe 	if (qflag && !wflag)
    306  1.58  sommerfe 		usage();
    307  1.75    atatat 	if (xflag && rflag)
    308  1.75    atatat 		usage();
    309  1.75    atatat 	/* if ((xflag || rflag) && wflag)
    310  1.75    atatat 		usage(); */
    311  1.75    atatat 	/* if (aflag && Mflag)
    312  1.75    atatat 		usage(); */
    313  1.79    atatat 	if ((Aflag || Mflag) && argc == 0 && fn == NULL)
    314  1.75    atatat 		aflag = 1;
    315  1.58  sommerfe 
    316  1.75    atatat 	if (Aflag)
    317  1.75    atatat 		warnfp = stdout;
    318  1.75    atatat 	req = 0;
    319   1.1       cgd 
    320  1.75    atatat 	if (aflag) {
    321  1.75    atatat 		print_tree(&name[0], 0, NULL, CTLTYPE_NODE, 1);
    322  1.75    atatat 		/* if (argc == 0) */
    323  1.75    atatat 		return (0);
    324   1.1       cgd 	}
    325  1.27    tsarna 
    326  1.27    tsarna 	if (fn) {
    327  1.27    tsarna 		FILE *fp;
    328  1.27    tsarna 		char *l;
    329  1.58  sommerfe 
    330  1.27    tsarna 		fp = fopen(fn, "r");
    331  1.27    tsarna 		if (fp == NULL) {
    332  1.27    tsarna 			err(1, "%s", fn);
    333  1.27    tsarna 		} else {
    334  1.75    atatat 			while ((l = fparseln(fp, NULL, NULL, NULL, 0)) != NULL)
    335  1.75    atatat 			{
    336  1.75    atatat 				if (*l) {
    337  1.75    atatat 					parse(l);
    338  1.75    atatat 					free(l);
    339  1.75    atatat 				}
    340  1.27    tsarna 			}
    341  1.27    tsarna 			fclose(fp);
    342  1.27    tsarna 		}
    343  1.75    atatat 		return (0);
    344  1.27    tsarna 	}
    345  1.75    atatat 
    346  1.75    atatat 	if (argc == 0)
    347  1.75    atatat 		usage();
    348  1.75    atatat 
    349  1.75    atatat 	while (argc-- > 0)
    350  1.75    atatat 		parse(*argv++);
    351  1.75    atatat 
    352  1.75    atatat 	return (0);
    353   1.1       cgd }
    354   1.1       cgd 
    355   1.1       cgd /*
    356  1.75    atatat  * ********************************************************************
    357  1.75    atatat  * how to find someone special to handle the reading (or maybe even
    358  1.75    atatat  * writing) of a particular node
    359  1.75    atatat  * ********************************************************************
    360   1.1       cgd  */
    361  1.75    atatat static struct handlespec *
    362  1.75    atatat findprinter(const int *name, u_int namelen)
    363  1.75    atatat {
    364  1.75    atatat 	struct handlespec *p;
    365  1.75    atatat 	int i, j;
    366  1.75    atatat 
    367  1.75    atatat 	if (namelen < 1)
    368  1.75    atatat 		return (NULL);
    369  1.75    atatat 
    370  1.75    atatat 	p = &handlers[0];
    371  1.75    atatat 	for (i = 0; p[i].ps_name[0] != CTL_UNSPEC; i++) {
    372  1.75    atatat 		for (j = 0; j < namelen; j++)
    373  1.75    atatat 			if (p[i].ps_name[j] != name[j] &&
    374  1.75    atatat 			    p[i].ps_name[j] != -1)
    375  1.75    atatat 				break;
    376  1.75    atatat 		if (j == namelen && p[i].ps_p != NULL)
    377  1.75    atatat 			return (&p[i]);
    378  1.75    atatat 	}
    379  1.75    atatat 
    380  1.75    atatat 	return (NULL);
    381  1.75    atatat }
    382  1.75    atatat 
    383  1.75    atatat static struct handlespec *
    384  1.75    atatat findwriter(const int *name, u_int namelen)
    385   1.1       cgd {
    386  1.75    atatat 	struct handlespec *p;
    387  1.75    atatat 	int i, j;
    388  1.75    atatat 
    389  1.75    atatat         if (namelen < 1)
    390  1.75    atatat                 return (NULL);
    391   1.1       cgd 
    392  1.75    atatat 	p = &handlers[0];
    393  1.75    atatat 	for (i = 0; p[i].ps_name[0] != CTL_UNSPEC; i++) {
    394  1.75    atatat 		for (j = 0; j < namelen; j++)
    395  1.75    atatat 			if (p[i].ps_name[j] != name[j] &&
    396  1.75    atatat 			    p[i].ps_name[j] != -1)
    397  1.75    atatat 				break;
    398  1.75    atatat 		if (j == namelen && p[i].ps_w != NULL)
    399  1.75    atatat 			return (&p[i]);
    400   1.1       cgd 	}
    401  1.75    atatat 
    402  1.75    atatat 	return (NULL);
    403   1.1       cgd }
    404   1.1       cgd 
    405   1.1       cgd /*
    406  1.75    atatat  * ********************************************************************
    407  1.75    atatat  * convert this special number to a special string so we can print the
    408  1.75    atatat  * mib
    409  1.75    atatat  * ********************************************************************
    410   1.1       cgd  */
    411  1.75    atatat static const char *
    412  1.75    atatat sf(u_int f)
    413   1.1       cgd {
    414  1.75    atatat 	static char s[256];
    415  1.75    atatat 	char *c;
    416  1.75    atatat 
    417  1.75    atatat 	s[0] = '\0';
    418  1.75    atatat 	c = "";
    419  1.75    atatat 
    420  1.75    atatat #define print_flag(_f, _s, _c, _q, _x) \
    421  1.75    atatat 	if ((/*CONSTCOND*/_x) ? \
    422  1.75    atatat 	    (((_f) & (_x)) == (__CONCAT(SYSCTL_,_q))) : \
    423  1.75    atatat 	    ((_f) & (__CONCAT(SYSCTL_,_q)))) { \
    424  1.75    atatat 		strlcat((_s), (_c), sizeof(_s)); \
    425  1.75    atatat 		strlcat((_s), __STRING(_q), sizeof(_s)); \
    426  1.75    atatat 		(_c) = ","; \
    427  1.75    atatat 		(_f) &= ~(__CONCAT(SYSCTL_,_q)|(_x)); \
    428  1.75    atatat 	}
    429  1.75    atatat 	print_flag(f, s, c, READONLY, SYSCTL_READWRITE);
    430  1.75    atatat 	print_flag(f, s, c, READONLY1, SYSCTL_READWRITE);
    431  1.75    atatat 	print_flag(f, s, c, READONLY2, SYSCTL_READWRITE);
    432  1.75    atatat 	print_flag(f, s, c, READWRITE, SYSCTL_READWRITE);
    433  1.75    atatat 	print_flag(f, s, c, ANYWRITE, 0);
    434  1.75    atatat 	print_flag(f, s, c, PRIVATE, 0);
    435  1.75    atatat 	print_flag(f, s, c, PERMANENT, 0);
    436  1.75    atatat 	print_flag(f, s, c, OWNDATA, 0);
    437  1.75    atatat 	print_flag(f, s, c, IMMEDIATE, 0);
    438  1.75    atatat 	print_flag(f, s, c, HEX, 0);
    439  1.75    atatat 	print_flag(f, s, c, ROOT, 0);
    440  1.75    atatat 	print_flag(f, s, c, ANYNUMBER, 0);
    441  1.75    atatat 	print_flag(f, s, c, HIDDEN, 0);
    442  1.75    atatat 	print_flag(f, s, c, ALIAS, 0);
    443  1.75    atatat #undef print_flag
    444  1.75    atatat 
    445  1.75    atatat 	if (f) {
    446  1.75    atatat 		char foo[9];
    447  1.75    atatat 		snprintf(foo, sizeof(foo), "%x", f);
    448  1.75    atatat 		strlcat(s, c, sizeof(s));
    449  1.75    atatat 		strlcat(s, foo, sizeof(s));
    450  1.75    atatat 	}
    451   1.1       cgd 
    452  1.75    atatat 	return (s);
    453  1.75    atatat }
    454  1.72     grant 
    455  1.75    atatat static const char *
    456  1.75    atatat st(u_int t)
    457  1.75    atatat {
    458   1.1       cgd 
    459  1.75    atatat 	switch (t) {
    460  1.75    atatat 	case CTLTYPE_NODE:
    461  1.75    atatat 		return "NODE";
    462  1.75    atatat 	case CTLTYPE_INT:
    463  1.75    atatat 		return "INT";
    464  1.75    atatat 	case CTLTYPE_STRING:
    465  1.75    atatat 		return "STRING";
    466  1.75    atatat 	case CTLTYPE_QUAD:
    467  1.75    atatat                 return "QUAD";
    468  1.75    atatat 	case CTLTYPE_STRUCT:
    469  1.75    atatat 		return "STRUCT";
    470  1.75    atatat 	}
    471   1.1       cgd 
    472  1.75    atatat 	return "???";
    473  1.75    atatat }
    474  1.46       chs 
    475  1.75    atatat /*
    476  1.75    atatat  * ********************************************************************
    477  1.75    atatat  * print this node and any others underneath it
    478  1.75    atatat  * ********************************************************************
    479  1.75    atatat  */
    480  1.75    atatat static void
    481  1.75    atatat print_tree(int *name, u_int namelen, struct sysctlnode *pnode, u_int type,
    482  1.75    atatat 	   int add)
    483  1.75    atatat {
    484  1.75    atatat 	struct sysctlnode *node;
    485  1.75    atatat 	int rc, ni;
    486  1.75    atatat 	size_t sz;
    487  1.75    atatat 	char *sp, *dp, n[20];
    488  1.75    atatat 	struct handlespec *p;
    489  1.75    atatat 
    490  1.75    atatat 	sp = &gsname[strlen(gsname)];
    491  1.75    atatat 	dp = &gdname[strlen(gdname)];
    492  1.75    atatat 
    493  1.75    atatat 	if (sp != &gsname[0] && dp == &gdname[0]) {
    494  1.75    atatat 		/*
    495  1.75    atatat 		 * aw...shucks.  now we must play catch up
    496  1.75    atatat 		 */
    497  1.75    atatat 		for (ni = 0; ni < namelen; ni++) {
    498  1.75    atatat 			(void)snprintf(n, sizeof(n), "%d", name[ni]);
    499  1.75    atatat 			if (ni > 0)
    500  1.75    atatat 				strncat(gdname, ".", sizeof(gdname));
    501  1.75    atatat 			strncat(gdname, n, sizeof(gdname));
    502   1.1       cgd 		}
    503  1.75    atatat 	}
    504   1.1       cgd 
    505  1.75    atatat 	if (pnode == NULL)
    506  1.75    atatat 		pnode = &my_root;
    507  1.75    atatat 	else if (add) {
    508  1.75    atatat 		snprintf(n, sizeof(n), "%d", pnode->sysctl_num);
    509  1.75    atatat 		if (namelen > 1) {
    510  1.75    atatat 			strncat(gsname, sep, sizeof(gsname));
    511  1.75    atatat 			strncat(gdname, ".", sizeof(gdname));
    512  1.75    atatat 		}
    513  1.75    atatat 		strncat(gsname, pnode->sysctl_name, sizeof(gsname));
    514  1.75    atatat 		strncat(gdname, n, sizeof(gdname));
    515  1.75    atatat 	}
    516  1.75    atatat 
    517  1.75    atatat 	if (Mflag && pnode != &my_root) {
    518  1.75    atatat 		if (nflag)
    519  1.75    atatat 			printf("%s: ", gdname);
    520  1.75    atatat 		else
    521  1.75    atatat 			printf("%s (%s): ", gsname, gdname);
    522  1.75    atatat 		printf("CTLTYPE_%s", st(type));
    523  1.75    atatat 		if (type == CTLTYPE_NODE) {
    524  1.75    atatat 			if (SYSCTL_FLAGS(pnode->sysctl_flags) & SYSCTL_ALIAS)
    525  1.75    atatat 				printf(", alias %d",
    526  1.75    atatat 				       pnode->sysctl_alias);
    527  1.75    atatat 			else
    528  1.75    atatat 				printf(", children %d/%d",
    529  1.75    atatat 				       pnode->sysctl_clen,
    530  1.75    atatat 				       pnode->sysctl_csize);
    531  1.75    atatat 		}
    532  1.75    atatat 		printf(", size %zu", pnode->sysctl_size);
    533  1.75    atatat 		printf(", flags 0x%x<%s>",
    534  1.75    atatat 		       SYSCTL_FLAGS(pnode->sysctl_flags),
    535  1.75    atatat 		       sf(SYSCTL_FLAGS(pnode->sysctl_flags)));
    536  1.75    atatat 		if (pnode->sysctl_func)
    537  1.75    atatat 			printf(", func=%p", pnode->sysctl_func);
    538  1.75    atatat 		printf(", ver=%d", pnode->sysctl_ver);
    539  1.75    atatat 		printf("\n");
    540  1.75    atatat 		if (type != CTLTYPE_NODE) {
    541  1.75    atatat 			*sp = *dp = '\0';
    542   1.1       cgd 			return;
    543   1.1       cgd 		}
    544  1.75    atatat 	}
    545  1.75    atatat 
    546  1.75    atatat 	/*
    547  1.75    atatat 	 * if this is an alias and we added our name, that means we
    548  1.75    atatat 	 * got here by recursing down into the tree, so skip it.  The
    549  1.75    atatat 	 * only way to print an aliased node is with either -M or by
    550  1.75    atatat 	 * name specifically.
    551  1.75    atatat 	 */
    552  1.75    atatat 	if (SYSCTL_FLAGS(pnode->sysctl_flags) & SYSCTL_ALIAS && add) {
    553  1.75    atatat 		*sp = *dp = '\0';
    554   1.1       cgd 		return;
    555  1.75    atatat 	}
    556   1.1       cgd 
    557  1.75    atatat 	p = findprinter(name, namelen);
    558  1.75    atatat 	if (type != CTLTYPE_NODE && p != NULL) {
    559  1.75    atatat 		(*p->ps_p)(gsname, gdname, NULL, name, namelen, pnode, type,
    560  1.75    atatat 			   p->ps_d);
    561  1.75    atatat 		*sp = *dp = '\0';
    562  1.75    atatat 		return;
    563  1.75    atatat 	}
    564   1.1       cgd 
    565  1.75    atatat 	if (type != CTLTYPE_NODE && pnode->sysctl_size == 0) {
    566  1.75    atatat 		rc = sysctl(&name[0], namelen, NULL, &sz, NULL, 0);
    567  1.75    atatat 		if (rc == -1) {
    568  1.75    atatat 			sysctlerror(1);
    569  1.75    atatat 			*sp = *dp = '\0';
    570  1.18   thorpej 			return;
    571  1.75    atatat 		}
    572  1.75    atatat 		if (sz == 0) {
    573  1.75    atatat 			if ((Aflag || req) && !Mflag)
    574  1.75    atatat 				printf("%s: node contains no data\n", gsname);
    575  1.75    atatat 			*sp = *dp = '\0';
    576  1.18   thorpej 			return;
    577  1.18   thorpej 		}
    578  1.75    atatat 	}
    579  1.75    atatat 	else
    580  1.75    atatat 		sz = pnode->sysctl_size;
    581  1.17   thorpej 
    582  1.75    atatat 	switch (type) {
    583  1.75    atatat 	case CTLTYPE_NODE: {
    584  1.75    atatat 		learn_tree(name, namelen, pnode);
    585  1.75    atatat 		node = pnode->sysctl_child;
    586  1.75    atatat 		if (node == NULL) {
    587  1.75    atatat 			if (p != NULL)
    588  1.75    atatat 				(*p->ps_p)(gsname, gdname, NULL, name, namelen,
    589  1.75    atatat 					   pnode, type, p->ps_d);
    590  1.75    atatat 			else if ((Aflag || req) && !Mflag)
    591  1.75    atatat 				printf("%s: no children\n", gsname);
    592  1.75    atatat 		}
    593  1.75    atatat 		else {
    594  1.75    atatat 			req = 0;
    595  1.75    atatat 			for (ni = 0; ni < pnode->sysctl_clen; ni++) {
    596  1.75    atatat 				name[namelen] = node[ni].sysctl_num;
    597  1.75    atatat 				if ((node[ni].sysctl_flags & SYSCTL_HIDDEN) &&
    598  1.75    atatat 				    !(Aflag || req))
    599  1.75    atatat 					continue;
    600  1.75    atatat 				print_tree(name, namelen + 1, &node[ni],
    601  1.75    atatat 					   SYSCTL_TYPE(node[ni].sysctl_flags),
    602  1.75    atatat 					   1);
    603  1.75    atatat 			}
    604  1.75    atatat 		}
    605   1.1       cgd 		break;
    606  1.75    atatat 	}
    607  1.75    atatat 	case CTLTYPE_INT: {
    608  1.75    atatat 		int i;
    609  1.75    atatat 		rc = sysctl(name, namelen, &i, &sz, NULL, 0);
    610  1.75    atatat 		if (rc == -1) {
    611  1.75    atatat 			sysctlerror(1);
    612  1.75    atatat 			break;
    613  1.75    atatat 		}
    614  1.75    atatat 		display_number(pnode, gsname, &i, sizeof(i), DISPLAY_VALUE);
    615  1.22    bouyer 		break;
    616  1.75    atatat 	}
    617  1.75    atatat 	case CTLTYPE_STRING: {
    618  1.75    atatat 		unsigned char buf[1024], *tbuf;
    619  1.75    atatat 		tbuf = buf;
    620  1.75    atatat 		sz = sizeof(buf);
    621  1.75    atatat 		rc = sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
    622  1.75    atatat 		if (rc == -1 && errno == ENOMEM) {
    623  1.75    atatat 			tbuf = malloc(sz);
    624  1.75    atatat 			if (tbuf == NULL) {
    625  1.75    atatat 				sysctlerror(1);
    626  1.75    atatat 				break;
    627  1.75    atatat 			}
    628  1.75    atatat 			rc = sysctl(&name[0], namelen, tbuf, &sz, NULL, 0);
    629  1.56  christos 		}
    630  1.75    atatat 		if (rc == -1)
    631  1.75    atatat 			sysctlerror(1);
    632  1.75    atatat 		else
    633  1.75    atatat 			display_string(pnode, gsname, buf, sz, DISPLAY_VALUE);
    634  1.75    atatat 		if (tbuf != buf)
    635  1.75    atatat 			free(tbuf);
    636  1.56  christos 		break;
    637   1.1       cgd 	}
    638  1.75    atatat 	case CTLTYPE_QUAD: {
    639  1.75    atatat 		u_quad_t q;
    640  1.75    atatat 		sz = sizeof(q);
    641  1.75    atatat 		rc = sysctl(&name[0], namelen, &q, &sz, NULL, 0);
    642  1.75    atatat 		if (rc == -1) {
    643  1.75    atatat 			sysctlerror(1);
    644  1.75    atatat 			break;
    645  1.75    atatat 		}
    646  1.75    atatat 		display_number(pnode, gsname, &q, sizeof(q), DISPLAY_VALUE);
    647  1.75    atatat 		break;
    648   1.1       cgd 	}
    649  1.75    atatat 	case CTLTYPE_STRUCT: {
    650  1.75    atatat 		/*
    651  1.75    atatat 		 * we shouldn't actually get here, but if we
    652  1.75    atatat 		 * do, would it be nice to have *something* to
    653  1.75    atatat 		 * do other than completely ignore the
    654  1.75    atatat 		 * request.
    655  1.75    atatat 		 */
    656  1.75    atatat 		unsigned char *d;
    657  1.75    atatat 		if ((d = malloc(sz)) == NULL) {
    658  1.75    atatat 			fprintf(warnfp, "%s: !malloc failed!\n", gsname);
    659   1.1       cgd 			break;
    660  1.75    atatat 		}
    661  1.75    atatat 		rc = sysctl(&name[0], namelen, d, &sz, NULL, 0);
    662  1.75    atatat 		if (rc == -1) {
    663  1.75    atatat 			sysctlerror(1);
    664   1.1       cgd 			break;
    665   1.1       cgd 		}
    666  1.75    atatat 		display_struct(pnode, gsname, d, sz, DISPLAY_VALUE);
    667  1.75    atatat 		free(d);
    668  1.75    atatat 		break;
    669   1.1       cgd 	}
    670  1.75    atatat 	default:
    671  1.75    atatat 		/* should i print an error here? */
    672  1.75    atatat 		break;
    673  1.75    atatat 	}
    674  1.75    atatat 
    675  1.75    atatat 	*sp = *dp = '\0';
    676  1.75    atatat }
    677  1.75    atatat 
    678  1.75    atatat /*
    679  1.75    atatat  * ********************************************************************
    680  1.75    atatat  * parse a request, possibly determining that it's a create or destroy
    681  1.75    atatat  * request
    682  1.75    atatat  * ********************************************************************
    683  1.75    atatat  */
    684  1.75    atatat static void
    685  1.75    atatat parse(char *l)
    686  1.75    atatat {
    687  1.75    atatat 	struct sysctlnode *node;
    688  1.75    atatat 	struct handlespec *w;
    689  1.75    atatat 	int name[CTL_MAXNAME];
    690  1.75    atatat 	u_int namelen, type;
    691  1.75    atatat 	char *key, *value, *dot;
    692  1.75    atatat 	size_t sz;
    693  1.75    atatat 
    694  1.75    atatat 	req = 1;
    695  1.75    atatat 	key = l;
    696  1.75    atatat 	value = strchr(l, '=');
    697  1.82    atatat 	if (value != NULL)
    698  1.75    atatat 		*value++ = '\0';
    699   1.1       cgd 
    700  1.75    atatat 	if ((dot = strpbrk(key, "./")) == NULL)
    701  1.75    atatat 		sep[0] = '.';
    702  1.75    atatat 	else
    703  1.75    atatat 		sep[0] = dot[0];
    704  1.75    atatat 	sep[1] = '\0';
    705   1.1       cgd 
    706  1.82    atatat 	while (key[0] == sep[0] && key[1] == sep[0]) {
    707  1.75    atatat 		if (value != NULL)
    708  1.75    atatat 			value[-1] = '=';
    709  1.82    atatat 		if (strncmp(key + 2, "create", 6) == 0 &&
    710  1.82    atatat 		    (key[8] == '=' || key[8] == sep[0]))
    711  1.82    atatat 			parse_create(key + 8 + (key[8] == '='));
    712  1.82    atatat 		else if (strncmp(key + 2, "destroy", 7) == 0 &&
    713  1.82    atatat 			 (key[9] == '=' || key[9] == sep[0]))
    714  1.82    atatat 			parse_destroy(key + 9 + (key[9] == '='));
    715   1.1       cgd 		else
    716  1.75    atatat 			fprintf(warnfp, "%s: unable to parse '%s'\n",
    717  1.75    atatat 				getprogname(), key);
    718  1.32    simonb 		return;
    719  1.32    simonb 	}
    720  1.32    simonb 
    721  1.75    atatat 	node = &my_root;
    722  1.75    atatat 	namelen = CTL_MAXNAME;
    723  1.75    atatat 	sz = sizeof(gsname);
    724  1.75    atatat 
    725  1.78    atatat 	if (sysctlgetmibinfo(key, &name[0], &namelen, gsname, &sz, &node) == -1)
    726  1.75    atatat 	{
    727  1.75    atatat 		fprintf(warnfp, "%s: %s level name '%s' in '%s' is invalid\n",
    728  1.75    atatat 			getprogname(), lname[namelen], gsname, l);
    729  1.75    atatat 		exit(1);
    730  1.75    atatat 	}
    731  1.75    atatat 
    732  1.75    atatat 	type = SYSCTL_TYPE(node->sysctl_flags);
    733  1.75    atatat 
    734  1.75    atatat 	if (value == NULL) {
    735  1.75    atatat 		print_tree(&name[0], namelen, node, type, 0);
    736  1.75    atatat 		gsname[0] = '\0';
    737  1.69       dsl 		return;
    738  1.69       dsl 	}
    739  1.69       dsl 
    740  1.82    atatat 	if (!wflag) {
    741  1.82    atatat 		fprintf(warnfp, "%s: Must specify -w to set variables\n",
    742  1.82    atatat 			getprogname());
    743  1.82    atatat 		exit(1);
    744  1.82    atatat 	}
    745  1.82    atatat 
    746  1.75    atatat 	if (type != CTLTYPE_NODE && (w = findwriter(name, namelen)) != NULL) {
    747  1.75    atatat 		(*w->ps_w)(gsname, gdname, value, name, namelen, node, type,
    748  1.75    atatat 			   w->ps_d);
    749  1.75    atatat 		gsname[0] = '\0';
    750  1.26      fvdl 		return;
    751  1.26      fvdl 	}
    752  1.58  sommerfe 
    753   1.1       cgd 	switch (type) {
    754  1.75    atatat 	case CTLTYPE_NODE:
    755  1.75    atatat 		/*
    756  1.75    atatat 		 * XXX old behavior is to print.  should we error instead?
    757  1.75    atatat 		 */
    758  1.75    atatat 		print_tree(&name[0], namelen, node, CTLTYPE_NODE, 1);
    759  1.75    atatat 		break;
    760   1.1       cgd 	case CTLTYPE_INT:
    761  1.75    atatat 		write_number(&name[0], namelen, node, value);
    762  1.75    atatat 		break;
    763   1.1       cgd 	case CTLTYPE_STRING:
    764  1.75    atatat 		write_string(&name[0], namelen, node, value);
    765  1.75    atatat 		break;
    766  1.75    atatat 	case CTLTYPE_QUAD:
    767  1.75    atatat 		write_number(&name[0], namelen, node, value);
    768  1.75    atatat 		break;
    769  1.75    atatat 	case CTLTYPE_STRUCT:
    770  1.75    atatat 		/*
    771  1.75    atatat 		 * XXX old behavior is to print.  should we error instead?
    772  1.75    atatat 		 */
    773  1.75    atatat 		/* fprintf(warnfp, "you can't write to %s\n", gsname); */
    774  1.75    atatat 		print_tree(&name[0], namelen, node, type, 0);
    775  1.75    atatat 		break;
    776  1.75    atatat 	}
    777  1.75    atatat }
    778  1.75    atatat 
    779  1.75    atatat /*
    780  1.75    atatat 
    781  1.75    atatat   //create=foo.bar.whatever...,
    782  1.75    atatat   [type=(int|quad|string|struct|node),]
    783  1.75    atatat   [size=###,]
    784  1.75    atatat   [n=###,]
    785  1.82    atatat   [flags=(iohxparw12),]
    786  1.75    atatat   [addr=0x####,|symbol=...|value=...]
    787  1.75    atatat 
    788  1.75    atatat   size is optional for some types.  type must be set before anything
    789  1.75    atatat   else.  nodes can have [r12whp], but nothing else applies.  if no
    790  1.75    atatat   size or type is given, node is asserted.  writeable is the default,
    791  1.75    atatat   with [r12w] being read-only, writeable below securelevel 1,
    792  1.75    atatat   writeable below securelevel 2, and unconditionally writeable
    793  1.75    atatat   respectively.  if you specify addr, it is assumed to be the name of
    794  1.75    atatat   a kernel symbol, if value, SYSCTL_OWNDATA will be asserted for
    795  1.75    atatat   strings, SYSCTL_IMMEDIATE for ints and u_quad_ts.  you cannot
    796  1.75    atatat   specify both value and addr.
    797  1.75    atatat 
    798  1.75    atatat */
    799  1.75    atatat 
    800  1.75    atatat static void
    801  1.82    atatat parse_create(char *l)
    802  1.75    atatat {
    803  1.75    atatat 	struct sysctlnode node;
    804  1.75    atatat 	size_t sz;
    805  1.75    atatat 	char *nname, *key, *value, *data, *addr, *c, *t;
    806  1.75    atatat 	int name[CTL_MAXNAME], i, rc, method, flags, rw;
    807  1.75    atatat 	u_int namelen, type;
    808  1.75    atatat 	u_quad_t q;
    809  1.75    atatat 	long li, lo;
    810  1.75    atatat 
    811  1.82    atatat 	if (!wflag) {
    812  1.82    atatat 		fprintf(warnfp, "%s: Must specify -w to create nodes\n",
    813  1.82    atatat 			getprogname());
    814  1.82    atatat 		exit(1);
    815  1.82    atatat 	}
    816  1.82    atatat 
    817  1.75    atatat 	/*
    818  1.75    atatat 	 * these are the pieces that make up the description of a new
    819  1.75    atatat 	 * node
    820  1.75    atatat 	 */
    821  1.75    atatat 	memset(&node, 0, sizeof(node));
    822  1.75    atatat 	node.sysctl_num = CTL_CREATE;  /* any number is fine */
    823  1.75    atatat 	flags = 0;
    824  1.75    atatat 	rw = -1;
    825  1.75    atatat 	type = 0;
    826  1.75    atatat 	sz = 0;
    827  1.75    atatat 	data = addr = NULL;
    828  1.75    atatat 	memset(name, 0, sizeof(name));
    829  1.75    atatat 	namelen = 0;
    830  1.75    atatat 	method = 0;
    831  1.75    atatat 
    832  1.75    atatat 	/*
    833  1.75    atatat 	 * misc stuff used when constructing
    834  1.75    atatat 	 */
    835  1.75    atatat 	i = 0;
    836  1.75    atatat 	q = 0;
    837  1.75    atatat 	key = NULL;
    838  1.75    atatat 	value = NULL;
    839  1.75    atatat 
    840  1.75    atatat 	/*
    841  1.75    atatat 	 * the name of the thing we're trying to create is first, so
    842  1.75    atatat 	 * pick it off.
    843  1.75    atatat 	 */
    844  1.75    atatat 	nname = l;
    845  1.75    atatat 	if ((c = strchr(nname, ',')) != NULL)
    846  1.75    atatat 		*c++ = '\0';
    847  1.75    atatat 
    848  1.75    atatat 	while (c != NULL) {
    849  1.75    atatat 
    850  1.75    atatat 		/*
    851  1.75    atatat 		 * pull off the next "key=value" pair
    852  1.75    atatat 		 */
    853  1.75    atatat 		key = c;
    854  1.75    atatat 		if ((t = strchr(key, '=')) != NULL) {
    855  1.75    atatat 			*t++ = '\0';
    856  1.75    atatat 			value = t;
    857  1.75    atatat 		}
    858  1.75    atatat 		else
    859  1.75    atatat 			value = NULL;
    860  1.75    atatat 
    861  1.75    atatat 		/*
    862  1.75    atatat 		 * if the "key" is "value", then that eats the rest of
    863  1.75    atatat 		 * the string, so we're done, otherwise bite it off at
    864  1.75    atatat 		 * the next comma.
    865  1.75    atatat 		 */
    866  1.75    atatat 		if (strcmp(key, "value") == 0) {
    867  1.75    atatat 			c = NULL;
    868  1.75    atatat 			data = value;
    869  1.75    atatat 			break;
    870  1.75    atatat 		}
    871  1.75    atatat 		else {
    872  1.75    atatat 			if ((c = strchr(value, ',')) != NULL)
    873  1.75    atatat 				*c++ = '\0';
    874  1.75    atatat 		}
    875  1.75    atatat 
    876  1.75    atatat 		/*
    877  1.75    atatat 		 * note that we (mostly) let the invoker of sysctl(8)
    878  1.75    atatat 		 * play rampant here and depend on the kernel to tell
    879  1.75    atatat 		 * them that they were wrong.  well...within reason.
    880  1.75    atatat 		 * we later check the various parameters against each
    881  1.75    atatat 		 * other to make sure it makes some sort of sense.
    882  1.75    atatat 		 */
    883  1.75    atatat 		if (strcmp(key, "addr") == 0) {
    884  1.75    atatat 			/*
    885  1.75    atatat 			 * we can't check these two.  only the kernel
    886  1.75    atatat 			 * can tell us when it fails to find the name
    887  1.75    atatat 			 * (or if the address is invalid).
    888  1.75    atatat 			 */
    889  1.75    atatat 			if (method != 0) {
    890  1.75    atatat 				fprintf(warnfp,
    891  1.75    atatat 				    "%s: %s: already have %s for new node\n",
    892  1.75    atatat 				    getprogname(), nname,
    893  1.75    atatat 				    method == CTL_CREATE ? "addr" : "symbol");
    894  1.75    atatat 				exit(1);
    895  1.75    atatat 			}
    896  1.75    atatat 			errno = 0;
    897  1.75    atatat 			addr = (void*)strtoul(value, &t, 0);
    898  1.75    atatat 			if (*t != '\0' || errno != 0) {
    899  1.75    atatat 				fprintf(warnfp,
    900  1.75    atatat 				    "%s: %s: '%s' is not a valid address\n",
    901  1.75    atatat 				    getprogname(), nname, value);
    902  1.75    atatat 				exit(1);
    903  1.75    atatat 			}
    904  1.75    atatat 			method = CTL_CREATE;
    905  1.75    atatat 		}
    906  1.75    atatat 		else if (strcmp(key, "symbol") == 0) {
    907  1.75    atatat 			if (method != 0) {
    908  1.75    atatat 				fprintf(warnfp,
    909  1.75    atatat 				    "%s: %s: already have %s for new node\n",
    910  1.75    atatat 				    getprogname(), nname,
    911  1.75    atatat 				    method == CTL_CREATE ? "addr" : "symbol");
    912  1.75    atatat 				exit(1);
    913  1.75    atatat 			}
    914  1.75    atatat 			addr = value;
    915  1.75    atatat 			method = CTL_CREATESYM;
    916  1.75    atatat 		}
    917  1.75    atatat 		else if (strcmp(key, "type") == 0) {
    918  1.75    atatat 			if (strcmp(value, "node") == 0)
    919  1.75    atatat 				type = CTLTYPE_NODE;
    920  1.75    atatat 			else if (strcmp(value, "int") == 0) {
    921  1.75    atatat 				sz = sizeof(int);
    922  1.75    atatat 				type = CTLTYPE_INT;
    923  1.75    atatat 			}
    924  1.75    atatat 			else if (strcmp(value, "string") == 0)
    925  1.75    atatat 				type = CTLTYPE_STRING;
    926  1.75    atatat 			else if (strcmp(value, "quad") == 0) {
    927  1.75    atatat 				sz = sizeof(u_quad_t);
    928  1.75    atatat 				type = CTLTYPE_QUAD;
    929  1.75    atatat 			}
    930  1.75    atatat 			else if (strcmp(value, "struct") == 0)
    931  1.75    atatat 				type = CTLTYPE_STRUCT;
    932  1.75    atatat 			else {
    933  1.75    atatat 				fprintf(warnfp,
    934  1.75    atatat 					"%s: %s: '%s' is not a valid type\n",
    935  1.75    atatat 					getprogname(), nname, value);
    936  1.75    atatat 				exit(1);
    937  1.75    atatat 			}
    938  1.75    atatat 		}
    939  1.75    atatat 		else if (strcmp(key, "size") == 0) {
    940  1.75    atatat 			errno = 0;
    941  1.75    atatat 			/*
    942  1.75    atatat 			 * yes, i know size_t is not an unsigned long,
    943  1.75    atatat 			 * but we can all agree that it ought to be,
    944  1.75    atatat 			 * right?
    945  1.75    atatat 			 */
    946  1.75    atatat 			sz = strtoul(value, &t, 0);
    947  1.75    atatat 			if (*t != '\0' || errno != 0) {
    948  1.75    atatat 				fprintf(warnfp,
    949  1.75    atatat 					"%s: %s: '%s' is not a valid size\n",
    950  1.75    atatat 					getprogname(), nname, value);
    951  1.75    atatat 				exit(1);
    952  1.75    atatat 			}
    953  1.75    atatat 		}
    954  1.75    atatat 		else if (strcmp(key, "n") == 0) {
    955  1.75    atatat 			errno = 0;
    956  1.75    atatat 			li = strtol(value, &t, 0);
    957  1.75    atatat 			node.sysctl_num = li;
    958  1.75    atatat 			lo = node.sysctl_num;
    959  1.75    atatat 			if (*t != '\0' || errno != 0 || li != lo || lo < 0) {
    960  1.75    atatat 				fprintf(warnfp,
    961  1.75    atatat 				    "%s: %s: '%s' is not a valid mib number\n",
    962  1.75    atatat 				    getprogname(), nname, value);
    963  1.75    atatat 				exit(1);
    964  1.75    atatat 			}
    965  1.75    atatat 		}
    966  1.75    atatat 		else if (strcmp(key, "flags") == 0) {
    967  1.75    atatat 			t = value;
    968  1.75    atatat 			while (*t != '\0') {
    969  1.75    atatat 				switch (*t) {
    970  1.75    atatat 				case 'a':
    971  1.75    atatat 					flags |= SYSCTL_ANYWRITE;
    972  1.75    atatat 					break;
    973  1.75    atatat 				case 'h':
    974  1.75    atatat 					flags |= SYSCTL_HIDDEN;
    975  1.75    atatat 					break;
    976  1.75    atatat 				case 'i':
    977  1.75    atatat 					flags |= SYSCTL_IMMEDIATE;
    978  1.75    atatat 					break;
    979  1.75    atatat 				case 'o':
    980  1.75    atatat 					flags |= SYSCTL_OWNDATA;
    981  1.75    atatat 					break;
    982  1.75    atatat 				case 'p':
    983  1.75    atatat 					flags |= SYSCTL_PRIVATE;
    984  1.75    atatat 					break;
    985  1.75    atatat 				case 'x':
    986  1.75    atatat 					flags |= SYSCTL_HEX;
    987  1.75    atatat 					break;
    988  1.75    atatat 
    989  1.75    atatat 				case 'r':
    990  1.75    atatat 					rw = SYSCTL_READONLY;
    991  1.75    atatat 					break;
    992  1.75    atatat 				case '1':
    993  1.75    atatat 					rw = SYSCTL_READONLY1;
    994  1.75    atatat 					break;
    995  1.75    atatat 				case '2':
    996  1.75    atatat 					rw = SYSCTL_READONLY2;
    997  1.75    atatat 					break;
    998  1.75    atatat 				case 'w':
    999  1.75    atatat 					rw = SYSCTL_READWRITE;
   1000  1.75    atatat 					break;
   1001  1.75    atatat 				default:
   1002  1.75    atatat 					fprintf(warnfp,
   1003  1.75    atatat 					   "%s: %s: '%c' is not a valid flag\n",
   1004  1.75    atatat 					    getprogname(), nname, *t);
   1005  1.75    atatat 					exit(1);
   1006  1.75    atatat 				}
   1007  1.75    atatat 				t++;
   1008  1.75    atatat 			}
   1009  1.75    atatat 		}
   1010  1.75    atatat 		else {
   1011  1.75    atatat 			fprintf(warnfp, "%s: %s: unrecognized keyword '%s'\n",
   1012  1.75    atatat 				getprogname(), nname, key);
   1013  1.75    atatat 			exit(1);
   1014  1.75    atatat 		}
   1015  1.75    atatat 	}
   1016  1.75    atatat 
   1017  1.75    atatat 	/*
   1018  1.75    atatat 	 * now that we've finished parsing the given string, fill in
   1019  1.75    atatat 	 * anything they didn't specify
   1020  1.75    atatat 	 */
   1021  1.75    atatat 	if (type == 0)
   1022  1.75    atatat 		type = CTLTYPE_NODE;
   1023  1.75    atatat 
   1024  1.75    atatat 	/*
   1025  1.75    atatat 	 * the "data" can be interpreted various ways depending on the
   1026  1.75    atatat 	 * type of node we're creating, as can the size
   1027  1.75    atatat 	 */
   1028  1.75    atatat 	if (data != NULL) {
   1029  1.75    atatat 		if (addr != NULL) {
   1030  1.75    atatat 			fprintf(warnfp,
   1031  1.75    atatat 				"%s: %s: cannot specify both value and "
   1032  1.75    atatat 				"address\n", getprogname(), nname);
   1033  1.75    atatat 			exit(1);
   1034  1.75    atatat 		}
   1035  1.75    atatat 
   1036  1.75    atatat 		switch (type) {
   1037  1.75    atatat 		case CTLTYPE_INT:
   1038  1.75    atatat 			errno = 0;
   1039  1.75    atatat 			li = strtol(data, &t, 0);
   1040  1.75    atatat 			i = li;
   1041  1.75    atatat 			lo = i;
   1042  1.75    atatat 			if (*t != '\0' || errno != 0 || li != lo || lo < 0) {
   1043  1.75    atatat 				fprintf(warnfp,
   1044  1.75    atatat 					"%s: %s: '%s' is not a valid integer\n",
   1045  1.75    atatat 					getprogname(), nname, value);
   1046  1.75    atatat 				exit(1);
   1047  1.75    atatat 			}
   1048  1.75    atatat 			if (!(flags & SYSCTL_OWNDATA)) {
   1049  1.75    atatat 				flags |= SYSCTL_IMMEDIATE;
   1050  1.75    atatat 				node.sysctl_idata = i;
   1051  1.75    atatat 			}
   1052  1.75    atatat 			else
   1053  1.75    atatat 				node.sysctl_data = &i;
   1054  1.75    atatat 			if (sz == 0)
   1055  1.75    atatat 				sz = sizeof(int);
   1056  1.75    atatat 			break;
   1057  1.75    atatat 		case CTLTYPE_STRING:
   1058  1.75    atatat 			flags |= SYSCTL_OWNDATA;
   1059  1.75    atatat 			node.sysctl_data = data;
   1060  1.75    atatat 			if (sz == 0)
   1061  1.75    atatat 				sz = strlen(data) + 1;
   1062  1.75    atatat 			else if (sz < strlen(data) + 1) {
   1063  1.75    atatat 				fprintf(warnfp, "%s: %s: ignoring size=%zu for "
   1064  1.75    atatat 					"string node, too small for given "
   1065  1.75    atatat 					"value\n", getprogname(), nname, sz);
   1066  1.75    atatat 				sz = strlen(data) + 1;
   1067  1.75    atatat 			}
   1068  1.75    atatat 			break;
   1069  1.75    atatat 		case CTLTYPE_QUAD:
   1070  1.75    atatat 			errno = 0;
   1071  1.75    atatat 			q = strtouq(data, &t, 0);
   1072  1.75    atatat 			if (*t != '\0' || errno != 0) {
   1073  1.75    atatat 				fprintf(warnfp,
   1074  1.75    atatat 					"%s: %s: '%s' is not a valid quad\n",
   1075  1.75    atatat 					getprogname(), nname, value);
   1076  1.75    atatat 				exit(1);
   1077  1.75    atatat 			}
   1078  1.75    atatat 			if (!(flags & SYSCTL_OWNDATA)) {
   1079  1.75    atatat 				flags |= SYSCTL_IMMEDIATE;
   1080  1.75    atatat 				node.sysctl_qdata = q;
   1081  1.75    atatat 			}
   1082  1.75    atatat 			else
   1083  1.75    atatat 				node.sysctl_data = &q;
   1084  1.75    atatat 			if (sz == 0)
   1085  1.75    atatat 				sz = sizeof(u_quad_t);
   1086  1.75    atatat 			break;
   1087  1.75    atatat 		case CTLTYPE_STRUCT:
   1088  1.75    atatat 			fprintf(warnfp,
   1089  1.75    atatat 				"%s: %s: struct not initializable\n",
   1090  1.75    atatat 				getprogname(), nname);
   1091  1.75    atatat 			exit(1);
   1092  1.75    atatat 		}
   1093  1.75    atatat 
   1094  1.75    atatat 		/*
   1095  1.75    atatat 		 * these methods have all provided local starting
   1096  1.75    atatat 		 * values that the kernel must copy in
   1097  1.75    atatat 		 */
   1098  1.75    atatat 	}
   1099  1.75    atatat 
   1100  1.75    atatat 	/*
   1101  1.75    atatat 	 * hmm...no data, but we have an address of data.  that's
   1102  1.75    atatat 	 * fine.
   1103  1.75    atatat 	 */
   1104  1.75    atatat 	else if (addr != 0)
   1105  1.75    atatat 		node.sysctl_data = (void*)addr;
   1106  1.75    atatat 
   1107  1.75    atatat 	/*
   1108  1.75    atatat 	 * no data and no address?  well...okay.  we might be able to
   1109  1.75    atatat 	 * manage that.
   1110  1.75    atatat 	 */
   1111  1.75    atatat 	else if (type != CTLTYPE_NODE) {
   1112  1.75    atatat 		if (sz == 0) {
   1113  1.75    atatat 			fprintf(warnfp,
   1114  1.75    atatat 				"%s: %s: need a size or a starting value\n",
   1115  1.75    atatat 				getprogname(), nname);
   1116  1.75    atatat                         exit(1);
   1117  1.75    atatat                 }
   1118  1.75    atatat 		if (!(flags & SYSCTL_IMMEDIATE))
   1119  1.75    atatat 			flags |= SYSCTL_OWNDATA;
   1120  1.75    atatat 	}
   1121  1.75    atatat 
   1122  1.75    atatat 	/*
   1123  1.75    atatat 	 * now we do a few sanity checks on the description we've
   1124  1.75    atatat 	 * assembled
   1125  1.75    atatat 	 */
   1126  1.75    atatat 	if ((flags & SYSCTL_IMMEDIATE) &&
   1127  1.75    atatat 	    (type == CTLTYPE_STRING || type == CTLTYPE_STRUCT)) {
   1128  1.75    atatat 		fprintf(warnfp,
   1129  1.75    atatat 			"%s: %s: cannot make an immediate %s\n",
   1130  1.75    atatat 			getprogname(), nname,
   1131  1.75    atatat 			(type == CTLTYPE_STRING) ? "string" : "struct");
   1132  1.75    atatat 		exit(1);
   1133  1.75    atatat 	}
   1134  1.75    atatat 	if (type == CTLTYPE_NODE && node.sysctl_data != NULL) {
   1135  1.75    atatat 		fprintf(warnfp, "%s: %s: nodes do not have data\n",
   1136  1.75    atatat 			getprogname(), nname);
   1137  1.75    atatat 		exit(1);
   1138  1.75    atatat 	}
   1139  1.75    atatat 
   1140  1.75    atatat 	/*
   1141  1.75    atatat 	 * some types must have a particular size
   1142  1.75    atatat 	 */
   1143  1.75    atatat 	if (sz != 0) {
   1144  1.75    atatat 		if ((type == CTLTYPE_INT && sz != sizeof(int)) ||
   1145  1.75    atatat 		    (type == CTLTYPE_QUAD && sz != sizeof(u_quad_t)) ||
   1146  1.75    atatat 		    (type == CTLTYPE_NODE && sz != 0)) {
   1147  1.75    atatat 			fprintf(warnfp, "%s: %s: wrong size for type\n",
   1148  1.75    atatat 				getprogname(), nname);
   1149  1.75    atatat 			exit(1);
   1150  1.75    atatat 		}
   1151  1.75    atatat 	}
   1152  1.75    atatat 	else if (type == CTLTYPE_STRUCT) {
   1153  1.75    atatat 		fprintf(warnfp, "%s: %s: struct must have size\n",
   1154  1.75    atatat 			getprogname(), nname);
   1155  1.75    atatat 		exit(1);
   1156  1.75    atatat 	}
   1157  1.75    atatat 
   1158  1.75    atatat 	/*
   1159  1.75    atatat 	 * now...if no one said anything yet, we default nodes or
   1160  1.75    atatat 	 * any type that owns data being writeable, and everything
   1161  1.75    atatat 	 * else being readonly.
   1162  1.75    atatat 	 */
   1163  1.75    atatat 	if (rw == -1) {
   1164  1.75    atatat 		if (type == CTLTYPE_NODE ||
   1165  1.75    atatat 		    (flags & (SYSCTL_OWNDATA|SYSCTL_IMMEDIATE)))
   1166  1.75    atatat 			rw = SYSCTL_READWRITE;
   1167  1.75    atatat 		else
   1168  1.75    atatat 			rw = SYSCTL_READONLY;
   1169  1.75    atatat 	}
   1170  1.75    atatat 
   1171  1.75    atatat 	/*
   1172  1.75    atatat 	 * if a kernel address was specified, that can't be made
   1173  1.75    atatat 	 * writeable by us.
   1174  1.75    atatat 	if (rw != SYSCTL_READONLY && addr) {
   1175  1.75    atatat 		fprintf(warnfp, "%s: %s: kernel data can only be readable\n",
   1176  1.75    atatat 			getprogname(), nname);
   1177  1.75    atatat 		exit(1);
   1178  1.75    atatat 	}
   1179  1.75    atatat 	 */
   1180  1.75    atatat 
   1181  1.75    atatat 	/*
   1182  1.75    atatat 	 * what separator were they using in the full name of the new
   1183  1.75    atatat 	 * node?
   1184  1.75    atatat 	 */
   1185  1.75    atatat 	if ((t = strpbrk(nname, "./")) == NULL)
   1186  1.75    atatat 		sep[0] = '.';
   1187  1.75    atatat 	else
   1188  1.75    atatat 		sep[0] = t[0];
   1189  1.75    atatat 	sep[1] = '\0';
   1190  1.75    atatat 
   1191  1.75    atatat 	/*
   1192  1.75    atatat 	 * put it all together, now.  t'ain't much, is it?
   1193  1.75    atatat 	 */
   1194  1.75    atatat 	node.sysctl_flags = flags|rw|type;
   1195  1.75    atatat 	node.sysctl_size = sz;
   1196  1.75    atatat 	t = strrchr(nname, sep[0]);
   1197  1.75    atatat 	if (t != NULL)
   1198  1.75    atatat 		strlcpy(node.sysctl_name, t + 1, sizeof(node.sysctl_name));
   1199  1.75    atatat 	else
   1200  1.75    atatat 		strlcpy(node.sysctl_name, nname, sizeof(node.sysctl_name));
   1201  1.82    atatat 	if (t == nname)
   1202  1.82    atatat 		t = NULL;
   1203  1.75    atatat 
   1204  1.75    atatat 	/*
   1205  1.75    atatat 	 * if this is a new top-level node, then we don't need to find
   1206  1.75    atatat 	 * the mib for its parent
   1207  1.75    atatat 	 */
   1208  1.75    atatat 	if (t == NULL) {
   1209  1.75    atatat 		namelen = 0;
   1210  1.75    atatat 		gsname[0] = '\0';
   1211  1.75    atatat 	}
   1212  1.75    atatat 
   1213  1.75    atatat 	/*
   1214  1.75    atatat 	 * on the other hand, if it's not a top-level node...
   1215  1.75    atatat 	 */
   1216  1.75    atatat 	else {
   1217  1.75    atatat 		namelen = sizeof(name) / sizeof(name[0]);
   1218  1.75    atatat 		sz = sizeof(gsname);
   1219  1.75    atatat 		*t = '\0';
   1220  1.78    atatat 		rc = sysctlgetmibinfo(nname, &name[0], &namelen,
   1221  1.78    atatat 				      gsname, &sz, NULL);
   1222  1.75    atatat 		*t = sep[0];
   1223  1.75    atatat 		if (rc == -1) {
   1224  1.75    atatat 			fprintf(warnfp,
   1225  1.75    atatat 				"%s: %s level name '%s' in '%s' is invalid\n",
   1226  1.75    atatat 				getprogname(), lname[namelen], gsname, nname);
   1227  1.75    atatat 			exit(1);
   1228   1.1       cgd 		}
   1229  1.75    atatat 	}
   1230  1.75    atatat 
   1231  1.75    atatat 	/*
   1232  1.75    atatat 	 * yes, a new node is being created
   1233  1.75    atatat 	 */
   1234  1.75    atatat 	if (method != 0)
   1235  1.75    atatat 		name[namelen++] = method;
   1236  1.75    atatat 	else
   1237  1.75    atatat 		name[namelen++] = CTL_CREATE;
   1238  1.75    atatat 
   1239  1.75    atatat 	sz = sizeof(node);
   1240  1.75    atatat 	rc = sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
   1241  1.75    atatat 
   1242  1.75    atatat 	if (rc == -1) {
   1243  1.75    atatat 		fprintf(warnfp,
   1244  1.75    atatat 			"%s: %s: CTL_CREATE failed: %s\n",
   1245  1.75    atatat 			getprogname(), nname, strerror(errno));
   1246  1.75    atatat 		exit(1);
   1247  1.75    atatat 	}
   1248  1.75    atatat 	else if (!qflag && !nflag)
   1249  1.75    atatat 		printf("%s(%s): (created)\n", nname, st(type));
   1250  1.75    atatat }
   1251  1.75    atatat 
   1252  1.75    atatat static void
   1253  1.82    atatat parse_destroy(char *l)
   1254  1.75    atatat {
   1255  1.75    atatat 	struct sysctlnode node;
   1256  1.75    atatat 	size_t sz;
   1257  1.75    atatat 	int name[CTL_MAXNAME], rc;
   1258  1.75    atatat 	u_int namelen;
   1259  1.75    atatat 
   1260  1.82    atatat 	if (!wflag) {
   1261  1.82    atatat 		fprintf(warnfp, "%s: Must specify -w to destroy nodes\n",
   1262  1.82    atatat 			getprogname());
   1263  1.82    atatat 		exit(1);
   1264  1.82    atatat 	}
   1265  1.82    atatat 
   1266  1.75    atatat 	memset(name, 0, sizeof(name));
   1267  1.75    atatat 	namelen = sizeof(name) / sizeof(name[0]);
   1268  1.75    atatat 	sz = sizeof(gsname);
   1269  1.78    atatat 	rc = sysctlgetmibinfo(l, &name[0], &namelen, gsname, &sz, NULL);
   1270  1.75    atatat 	if (rc == -1) {
   1271  1.75    atatat 		fprintf(warnfp,
   1272  1.75    atatat 			"%s: %s level name '%s' in '%s' is invalid\n",
   1273  1.75    atatat 			getprogname(), lname[namelen], gsname, l);
   1274  1.75    atatat 		exit(1);
   1275  1.75    atatat 	}
   1276  1.75    atatat 
   1277  1.75    atatat 	memset(&node, 0, sizeof(node));
   1278  1.75    atatat 	node.sysctl_num = name[namelen - 1];
   1279  1.75    atatat 	name[namelen - 1] = CTL_DESTROY;
   1280  1.75    atatat 
   1281  1.75    atatat 	sz = sizeof(node);
   1282  1.75    atatat 	rc = sysctl(&name[0], namelen, &node, &sz, &node, sizeof(node));
   1283  1.75    atatat 
   1284  1.75    atatat 	if (rc == -1) {
   1285  1.75    atatat 		fprintf(warnfp,
   1286  1.75    atatat 			"%s: %s: CTL_DESTROY failed: %s\n",
   1287  1.75    atatat 			getprogname(), l, strerror(errno));
   1288  1.75    atatat 		exit(1);
   1289  1.75    atatat 	}
   1290  1.75    atatat 	else if (!qflag && !nflag)
   1291  1.75    atatat 		printf("%s(%s): (destroyed)\n", gsname,
   1292  1.75    atatat 		       st(SYSCTL_TYPE(node.sysctl_flags)));
   1293  1.75    atatat }
   1294  1.75    atatat 
   1295  1.75    atatat /*
   1296  1.75    atatat  * ********************************************************************
   1297  1.75    atatat  * when things go wrong...
   1298  1.75    atatat  * ********************************************************************
   1299  1.75    atatat  */
   1300  1.75    atatat static void
   1301  1.75    atatat usage(void)
   1302  1.75    atatat {
   1303  1.75    atatat 	const char *progname = getprogname();
   1304   1.1       cgd 
   1305  1.75    atatat 	(void)fprintf(stderr,
   1306  1.77      jmmv 		      "usage:\t%s %s\n"
   1307  1.75    atatat 		      "\t%s %s\n"
   1308  1.75    atatat 		      "\t%s %s\n"
   1309  1.75    atatat 		      "\t%s %s\n"
   1310  1.75    atatat 		      "\t%s %s\n"
   1311  1.75    atatat 		      "\t%s %s\n",
   1312  1.75    atatat 		      progname, "[-ne] [-x[x]|-r] variable ...",
   1313  1.75    atatat 		      progname, "[-ne] [-q] -w variable=value ...",
   1314  1.75    atatat 		      progname, "[-ne] -a",
   1315  1.75    atatat 		      progname, "[-ne] -A",
   1316  1.75    atatat 		      progname, "[-ne] -M",
   1317  1.75    atatat 		      progname, "[-ne] [-q] -f file");
   1318  1.75    atatat 	exit(1);
   1319  1.22    bouyer }
   1320  1.22    bouyer 
   1321  1.75    atatat void
   1322  1.75    atatat sysctlerror(int soft)
   1323  1.75    atatat {
   1324  1.75    atatat 	if (soft) {
   1325  1.75    atatat 		switch (errno) {
   1326  1.75    atatat 		case ENOENT:
   1327  1.75    atatat 		case ENOPROTOOPT:
   1328  1.75    atatat 		case ENOTDIR:
   1329  1.75    atatat 		case EOPNOTSUPP:
   1330  1.75    atatat 		case EPROTONOSUPPORT:
   1331  1.75    atatat 			if (Aflag || req)
   1332  1.75    atatat 				fprintf(warnfp,
   1333  1.75    atatat 					"%s: the value is not available\n",
   1334  1.75    atatat 					gsname);
   1335  1.75    atatat 			return;
   1336  1.22    bouyer 		}
   1337  1.75    atatat 	}
   1338  1.75    atatat 
   1339  1.75    atatat 	fprintf(warnfp, "%s: sysctl() failed with %s\n",
   1340  1.75    atatat 		gsname, strerror(errno));
   1341  1.75    atatat 	if (!soft)
   1342  1.75    atatat 		exit(1);
   1343  1.75    atatat }
   1344  1.75    atatat 
   1345  1.75    atatat /*
   1346  1.75    atatat  * ********************************************************************
   1347  1.75    atatat  * how to write to a "simple" node
   1348  1.75    atatat  * ********************************************************************
   1349  1.75    atatat  */
   1350  1.75    atatat static void
   1351  1.75    atatat write_number(int *name, u_int namelen, struct sysctlnode *node, char *value)
   1352  1.75    atatat {
   1353  1.75    atatat 	int ii, io;
   1354  1.75    atatat 	u_quad_t qi, qo;
   1355  1.75    atatat 	size_t si, so;
   1356  1.75    atatat 	int rc;
   1357  1.75    atatat 	void *i, *o;
   1358  1.75    atatat 	char *t;
   1359  1.75    atatat 
   1360  1.75    atatat 	si = so = 0;
   1361  1.75    atatat 	i = o = NULL;
   1362  1.75    atatat 	errno = 0;
   1363  1.75    atatat 	qi = strtouq(value, &t, 0);
   1364  1.75    atatat 	if (errno != 0) {
   1365  1.75    atatat 		fprintf(warnfp, "%s: value too large\n", value);
   1366  1.75    atatat 		exit(1);
   1367  1.75    atatat 	}
   1368  1.75    atatat 	if (*t != '\0') {
   1369  1.75    atatat 		fprintf(warnfp, "%s: not a number\n", value);
   1370  1.75    atatat 		exit(1);
   1371  1.75    atatat 	}
   1372  1.75    atatat 
   1373  1.75    atatat 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
   1374  1.75    atatat 	    case CTLTYPE_INT:
   1375  1.75    atatat 		ii = (int)qi;
   1376  1.75    atatat 		qo = ii;
   1377  1.75    atatat 		if (qo != qi) {
   1378  1.75    atatat 			fprintf(warnfp, "%s: value too large\n", value);
   1379  1.75    atatat 			exit(1);
   1380  1.75    atatat 		}
   1381  1.75    atatat 		o = &io;
   1382  1.75    atatat 		so = sizeof(io);
   1383  1.75    atatat 		i = &ii;
   1384  1.75    atatat 		si = sizeof(ii);
   1385  1.75    atatat 		break;
   1386  1.75    atatat 	case CTLTYPE_QUAD:
   1387  1.75    atatat 		o = &qo;
   1388  1.75    atatat 		so = sizeof(qo);
   1389  1.75    atatat 		i = &qi;
   1390  1.75    atatat 		si = sizeof(qi);
   1391  1.75    atatat 		break;
   1392  1.75    atatat 	}
   1393  1.75    atatat 
   1394  1.75    atatat 	rc = sysctl(name, namelen, o, &so, i, si);
   1395  1.75    atatat 	if (rc == -1)
   1396  1.75    atatat 		sysctlerror(0);
   1397  1.75    atatat 
   1398  1.75    atatat 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
   1399  1.75    atatat 	case CTLTYPE_INT:
   1400  1.75    atatat 		display_number(node, gsname, &io, sizeof(io), DISPLAY_OLD);
   1401  1.75    atatat 		display_number(node, gsname, &ii, sizeof(ii), DISPLAY_NEW);
   1402  1.75    atatat 		break;
   1403  1.75    atatat 	case CTLTYPE_QUAD:
   1404  1.75    atatat 		display_number(node, gsname, &qo, sizeof(qo), DISPLAY_OLD);
   1405  1.75    atatat 		display_number(node, gsname, &qi, sizeof(qi), DISPLAY_NEW);
   1406  1.75    atatat 		break;
   1407  1.75    atatat 	}
   1408  1.75    atatat }
   1409  1.75    atatat 
   1410  1.75    atatat static void
   1411  1.75    atatat write_string(int *name, u_int namelen, struct sysctlnode *node, char *value)
   1412  1.75    atatat {
   1413  1.75    atatat 	char *i, *o;
   1414  1.75    atatat 	size_t si, so;
   1415  1.75    atatat 	int rc;
   1416  1.75    atatat 
   1417  1.75    atatat 	i = value;
   1418  1.75    atatat 	si = strlen(i) + 1;
   1419  1.75    atatat 	so = node->sysctl_size;
   1420  1.75    atatat 	if (si > so && so != 0) {
   1421  1.75    atatat 		fprintf(warnfp, "%s: string too long\n", value);
   1422  1.75    atatat 		exit(1);
   1423  1.75    atatat 	}
   1424  1.75    atatat 	o = malloc(so);
   1425  1.75    atatat 	if (o == NULL) {
   1426  1.75    atatat 		fprintf(warnfp, "%s: !malloc failed!\n", gsname);
   1427  1.75    atatat 		exit(1);
   1428  1.75    atatat 	}
   1429  1.75    atatat 
   1430  1.75    atatat 	rc = sysctl(name, namelen, o, &so, i, si);
   1431  1.75    atatat 	if (rc == -1)
   1432  1.75    atatat 		sysctlerror(0);
   1433  1.75    atatat 
   1434  1.75    atatat 	display_string(node, gsname, o, so, DISPLAY_OLD);
   1435  1.75    atatat 	display_string(node, gsname, i, si, DISPLAY_NEW);
   1436  1.75    atatat 	free(o);
   1437  1.75    atatat }
   1438  1.75    atatat 
   1439  1.75    atatat /*
   1440  1.75    atatat  * ********************************************************************
   1441  1.75    atatat  * simple ways to print stuff consistently
   1442  1.75    atatat  * ********************************************************************
   1443  1.75    atatat  */
   1444  1.75    atatat static void
   1445  1.75    atatat display_number(const struct sysctlnode *node, const char *name,
   1446  1.75    atatat 	       const void *data, size_t sz, int n)
   1447  1.75    atatat {
   1448  1.75    atatat 	u_quad_t q;
   1449  1.75    atatat 	int i;
   1450  1.75    atatat 
   1451  1.75    atatat 	if (qflag)
   1452  1.75    atatat 		return;
   1453  1.75    atatat 	if ((nflag || rflag) && (n == DISPLAY_OLD))
   1454  1.75    atatat 		return;
   1455  1.75    atatat 
   1456  1.75    atatat 	if (rflag && n != DISPLAY_OLD) {
   1457  1.75    atatat 		fwrite(data, sz, 1, stdout);
   1458  1.75    atatat 		return;
   1459  1.75    atatat 	}
   1460  1.75    atatat 
   1461  1.75    atatat 	if (!nflag) {
   1462  1.75    atatat 		if (n == DISPLAY_VALUE)
   1463  1.75    atatat 			printf("%s%s", name, eq);
   1464  1.75    atatat 		else if (n == DISPLAY_OLD)
   1465  1.75    atatat 			printf("%s: ", name);
   1466  1.75    atatat 	}
   1467  1.75    atatat 
   1468  1.75    atatat 	if (xflag > 1) {
   1469  1.79    atatat 		if (n != DISPLAY_NEW)
   1470  1.79    atatat 			printf("\n");
   1471  1.75    atatat 		hex_dump(data, sz);
   1472  1.22    bouyer 		return;
   1473  1.75    atatat 	}
   1474  1.22    bouyer 
   1475  1.75    atatat 	switch (SYSCTL_TYPE(node->sysctl_flags)) {
   1476  1.75    atatat 	case CTLTYPE_INT:
   1477  1.75    atatat 		memcpy(&i, data, sz);
   1478  1.75    atatat 		if (xflag)
   1479  1.75    atatat 			printf("0x%0*x", (int)sz * 2, i);
   1480  1.75    atatat 		else if (node->sysctl_flags & SYSCTL_HEX)
   1481  1.75    atatat 			printf("%#x", i);
   1482  1.75    atatat 		else
   1483  1.75    atatat 			printf("%d", i);
   1484  1.75    atatat 		break;
   1485   1.1       cgd 	case CTLTYPE_QUAD:
   1486  1.75    atatat 		memcpy(&q, data, sz);
   1487  1.75    atatat 		if (xflag)
   1488  1.75    atatat 			printf("0x%0*" PRIx64, (int)sz * 2, q);
   1489  1.75    atatat 		else if (node->sysctl_flags & SYSCTL_HEX)
   1490  1.75    atatat 			printf("%#" PRIx64, q);
   1491  1.75    atatat 		else
   1492  1.75    atatat 			printf("%" PRIu64, q);
   1493  1.75    atatat 		break;
   1494  1.75    atatat 	}
   1495  1.75    atatat 
   1496  1.75    atatat 	if (n == DISPLAY_OLD)
   1497  1.75    atatat 		printf(" -> ");
   1498  1.75    atatat 	else
   1499  1.75    atatat 		printf("\n");
   1500  1.75    atatat }
   1501  1.75    atatat 
   1502  1.75    atatat static void
   1503  1.75    atatat display_string(const struct sysctlnode *node, const char *name,
   1504  1.75    atatat 	       const void *data, size_t sz, int n)
   1505  1.75    atatat {
   1506  1.75    atatat 	const unsigned char *buf = data;
   1507  1.75    atatat 	int ni;
   1508  1.75    atatat 
   1509  1.75    atatat 	if (qflag)
   1510  1.75    atatat 		return;
   1511  1.75    atatat 	if ((nflag || rflag) && (n == DISPLAY_OLD))
   1512  1.75    atatat 		return;
   1513  1.75    atatat 
   1514  1.75    atatat 	if (rflag && n != DISPLAY_OLD) {
   1515  1.75    atatat 		fwrite(data, sz, 1, stdout);
   1516  1.75    atatat 		return;
   1517  1.75    atatat 	}
   1518  1.75    atatat 
   1519  1.75    atatat 	if (!nflag) {
   1520  1.75    atatat 		if (n == DISPLAY_VALUE)
   1521  1.75    atatat 			printf("%s%s", name, eq);
   1522  1.75    atatat 		else if (n == DISPLAY_OLD)
   1523  1.75    atatat 			printf("%s: ", name);
   1524  1.75    atatat 	}
   1525  1.75    atatat 
   1526  1.75    atatat 	if (xflag > 1) {
   1527  1.79    atatat 		if (n != DISPLAY_NEW)
   1528  1.79    atatat 			printf("\n");
   1529  1.75    atatat 		hex_dump(data, sz);
   1530  1.75    atatat 		return;
   1531  1.75    atatat 	}
   1532  1.75    atatat 
   1533  1.75    atatat 	if (xflag || node->sysctl_flags & SYSCTL_HEX) {
   1534  1.75    atatat 		for (ni = 0; ni < (int)sz; ni++) {
   1535  1.75    atatat 			if (xflag)
   1536  1.75    atatat 				printf("%02x", buf[ni]);
   1537  1.75    atatat 			if (buf[ni] == '\0')
   1538  1.75    atatat 				break;
   1539  1.75    atatat 			if (!xflag)
   1540  1.75    atatat 				printf("\\x%2.2x", buf[ni]);
   1541   1.1       cgd 		}
   1542  1.75    atatat 	}
   1543  1.75    atatat 	else
   1544  1.75    atatat 		printf("%.*s", (int)sz, buf);
   1545  1.75    atatat 
   1546  1.75    atatat 	if (n == DISPLAY_OLD)
   1547  1.75    atatat 		printf(" -> ");
   1548  1.75    atatat 	else
   1549  1.75    atatat 		printf("\n");
   1550  1.75    atatat }
   1551  1.75    atatat 
   1552  1.75    atatat /*ARGSUSED*/
   1553  1.75    atatat static void
   1554  1.75    atatat display_struct(const struct sysctlnode *node, const char *name,
   1555  1.75    atatat 	       const void *data, size_t sz, int n)
   1556  1.75    atatat {
   1557  1.75    atatat 	const unsigned char *buf = data;
   1558  1.75    atatat 	int ni;
   1559  1.75    atatat 	size_t more;
   1560  1.75    atatat 
   1561  1.75    atatat 	if (qflag)
   1562  1.75    atatat 		return;
   1563  1.75    atatat 	if (!(xflag || rflag)) {
   1564  1.75    atatat 		if (Aflag || req)
   1565  1.75    atatat 			fprintf(warnfp,
   1566  1.75    atatat 				"%s: this type is unknown to this program\n",
   1567  1.75    atatat 				gsname);
   1568  1.75    atatat 		return;
   1569  1.75    atatat 	}
   1570  1.75    atatat 	if ((nflag || rflag) && (n == DISPLAY_OLD))
   1571   1.1       cgd 		return;
   1572   1.1       cgd 
   1573  1.75    atatat 	if (rflag && n != DISPLAY_OLD) {
   1574  1.75    atatat 		fwrite(data, sz, 1, stdout);
   1575   1.1       cgd 		return;
   1576  1.75    atatat 	}
   1577   1.1       cgd 
   1578  1.75    atatat         if (!nflag) {
   1579  1.75    atatat                 if (n == DISPLAY_VALUE)
   1580  1.75    atatat                         printf("%s%s", name, eq);
   1581  1.75    atatat                 else if (n == DISPLAY_OLD)
   1582  1.75    atatat                         printf("%s: ", name);
   1583  1.75    atatat         }
   1584  1.75    atatat 
   1585  1.75    atatat 	if (xflag > 1) {
   1586  1.79    atatat 		if (n != DISPLAY_NEW)
   1587  1.79    atatat 			printf("\n");
   1588  1.75    atatat 		hex_dump(data, sz);
   1589   1.1       cgd 		return;
   1590   1.1       cgd 	}
   1591  1.75    atatat 
   1592  1.75    atatat 	if (sz > 16) {
   1593  1.75    atatat 		more = sz - 16;
   1594  1.75    atatat 		sz = 16;
   1595  1.75    atatat 	}
   1596  1.75    atatat 	else
   1597  1.75    atatat 		more = 0;
   1598  1.75    atatat 	for (ni = 0; ni < (int)sz; ni++)
   1599  1.75    atatat 		printf("%02x", buf[ni]);
   1600  1.75    atatat 	if (more)
   1601  1.75    atatat 		printf("...(%zu more bytes)", more);
   1602  1.75    atatat 	printf("\n");
   1603  1.75    atatat }
   1604  1.75    atatat 
   1605  1.75    atatat static void
   1606  1.75    atatat hex_dump(const unsigned char *buf, size_t len)
   1607  1.75    atatat {
   1608  1.75    atatat 	int i, j;
   1609  1.75    atatat 	char line[80], tmp[12];
   1610  1.75    atatat 
   1611  1.75    atatat 	memset(line, ' ', sizeof(line));
   1612  1.75    atatat 	for (i = 0, j = 15; i < len; i++) {
   1613  1.75    atatat 		j = i % 16;
   1614  1.75    atatat 		/* reset line */
   1615  1.75    atatat 		if (j == 0) {
   1616  1.75    atatat 			line[58] = '|';
   1617  1.75    atatat 			line[77] = '|';
   1618  1.75    atatat 			line[78] = 0;
   1619  1.75    atatat 			snprintf(tmp, sizeof(tmp), "%07d", i);
   1620  1.75    atatat 			memcpy(&line[0], tmp, 7);
   1621  1.75    atatat 		}
   1622  1.75    atatat 		/* copy out hex version of byte */
   1623  1.75    atatat 		snprintf(tmp, sizeof(tmp), "%02x", buf[i]);
   1624  1.75    atatat 		memcpy(&line[9 + j * 3], tmp, 2);
   1625  1.75    atatat 		/* copy out plain version of byte */
   1626  1.75    atatat 		line[60 + j] = (isprint(buf[i])) ? buf[i] : '.';
   1627  1.75    atatat 		/* print a full line and erase it */
   1628  1.75    atatat 		if (j == 15) {
   1629  1.75    atatat 			printf("%s\n", line);
   1630  1.75    atatat 			memset(line, ' ', sizeof(line));
   1631  1.75    atatat 		}
   1632  1.75    atatat 	}
   1633  1.75    atatat 	if (line[0] != ' ')
   1634  1.75    atatat 		printf("%s\n", line);
   1635  1.75    atatat 	printf("%07zu bytes\n", len);
   1636   1.1       cgd }
   1637   1.1       cgd 
   1638   1.1       cgd /*
   1639  1.75    atatat  * ********************************************************************
   1640  1.75    atatat  * functions that handle particular nodes
   1641  1.75    atatat  * ********************************************************************
   1642   1.1       cgd  */
   1643  1.75    atatat /*ARGSUSED*/
   1644  1.14  christos static void
   1645  1.75    atatat printother(HANDLER_ARGS)
   1646   1.1       cgd {
   1647  1.75    atatat 	int rc;
   1648  1.75    atatat 	void *p;
   1649  1.75    atatat 	size_t sz1, sz2;
   1650   1.1       cgd 
   1651  1.75    atatat 	if (!(Aflag || req) || Mflag)
   1652   1.1       cgd 		return;
   1653  1.75    atatat 
   1654  1.75    atatat 	/*
   1655  1.75    atatat 	 * okay...you asked for it, so let's give it a go
   1656  1.75    atatat 	 */
   1657  1.75    atatat 	while (type != CTLTYPE_NODE && (xflag || rflag)) {
   1658  1.75    atatat 		rc = sysctl(name, namelen, NULL, &sz1, NULL, 0);
   1659  1.75    atatat 		if (rc == -1 || sz1 == 0)
   1660  1.75    atatat 			break;
   1661  1.75    atatat 		p = malloc(sz1);
   1662  1.75    atatat 		if (p == NULL)
   1663  1.75    atatat 			break;
   1664  1.75    atatat 		sz2 = sz1;
   1665  1.75    atatat 		rc = sysctl(name, namelen, p, &sz2, NULL, 0);
   1666  1.75    atatat 		if (rc == -1 || sz1 != sz2) {
   1667  1.75    atatat 			free(p);
   1668  1.75    atatat 			break;
   1669  1.75    atatat 		}
   1670  1.75    atatat 		display_struct(pnode, gsname, p, sz1, DISPLAY_VALUE);
   1671  1.75    atatat 		free(p);
   1672  1.75    atatat 		return;
   1673  1.75    atatat 	}
   1674  1.75    atatat 
   1675  1.75    atatat 	/*
   1676  1.75    atatat 	 * that didn't work...do we have a specific message for this
   1677  1.75    atatat 	 * thing?
   1678  1.75    atatat 	 */
   1679  1.75    atatat 	if (v != NULL) {
   1680  1.75    atatat 		fprintf(warnfp, "%s: use '%s' to view this information\n",
   1681  1.75    atatat 			gsname, (const char *)v);
   1682  1.75    atatat 		return;
   1683  1.75    atatat 	}
   1684  1.75    atatat 
   1685  1.75    atatat 	/*
   1686  1.75    atatat 	 * hmm...i wonder if we have any generic hints?
   1687  1.75    atatat 	 */
   1688  1.75    atatat 	switch (name[0]) {
   1689  1.75    atatat 	case CTL_NET:
   1690  1.75    atatat 		fprintf(warnfp, "%s: use 'netstat' to view this information\n",
   1691  1.75    atatat 			sname);
   1692  1.75    atatat 		break;
   1693  1.75    atatat 	case CTL_DEBUG:
   1694  1.75    atatat 		fprintf(warnfp, "%s: missing 'options DEBUG' from kernel?\n",
   1695  1.75    atatat 			sname);
   1696  1.75    atatat 		break;
   1697  1.75    atatat 	case CTL_DDB:
   1698  1.75    atatat 		fprintf(warnfp, "%s: missing 'options DDB' from kernel?\n",
   1699  1.75    atatat 			sname);
   1700  1.75    atatat 		break;
   1701   1.1       cgd 	}
   1702   1.1       cgd }
   1703   1.1       cgd 
   1704  1.75    atatat /*ARGSUSED*/
   1705  1.75    atatat static void
   1706  1.75    atatat kern_clockrate(HANDLER_ARGS)
   1707  1.75    atatat {
   1708  1.75    atatat 	struct clockinfo clkinfo;
   1709  1.75    atatat 	size_t sz;
   1710  1.75    atatat 	int rc;
   1711  1.75    atatat 
   1712  1.75    atatat 	sz = sizeof(clkinfo);
   1713  1.75    atatat 	rc = sysctl(name, namelen, &clkinfo, &sz, NULL, 0);
   1714  1.75    atatat 	if (rc == -1) {
   1715  1.75    atatat 		sysctlerror(1);
   1716  1.75    atatat 		return;
   1717  1.75    atatat 	}
   1718  1.75    atatat 	if (sz != sizeof(clkinfo))
   1719  1.75    atatat 		errx(1, "%s: !returned size wrong!", sname);
   1720  1.74  jonathan 
   1721  1.79    atatat 	if (xflag || rflag) {
   1722  1.75    atatat 		display_struct(pnode, sname, &clkinfo, sz,
   1723  1.75    atatat 			       DISPLAY_VALUE);
   1724  1.79    atatat 		return;
   1725  1.79    atatat 	}
   1726  1.75    atatat 	else if (!nflag)
   1727  1.75    atatat 		printf("%s: ", sname);
   1728  1.75    atatat 	printf("tick = %d, tickadj = %d, hz = %d, profhz = %d, stathz = %d\n",
   1729  1.75    atatat 	       clkinfo.tick, clkinfo.tickadj,
   1730  1.75    atatat 	       clkinfo.hz, clkinfo.profhz, clkinfo.stathz);
   1731  1.75    atatat }
   1732   1.1       cgd 
   1733  1.75    atatat /*ARGSUSED*/
   1734  1.75    atatat static void
   1735  1.75    atatat kern_boottime(HANDLER_ARGS)
   1736   1.1       cgd {
   1737  1.75    atatat 	struct timeval timeval;
   1738  1.75    atatat 	time_t boottime;
   1739  1.75    atatat 	size_t sz;
   1740  1.75    atatat 	int rc;
   1741  1.75    atatat 
   1742  1.75    atatat 	sz = sizeof(timeval);
   1743  1.75    atatat 	rc = sysctl(name, namelen, &timeval, &sz, NULL, 0);
   1744  1.75    atatat 	if (rc == -1) {
   1745  1.75    atatat 		sysctlerror(1);
   1746  1.75    atatat 		return;
   1747  1.75    atatat 	}
   1748  1.75    atatat 	if (sz != sizeof(timeval))
   1749  1.75    atatat 		errx(1, "%s: !returned size wrong!", sname);
   1750   1.1       cgd 
   1751  1.75    atatat 	boottime = timeval.tv_sec;
   1752  1.75    atatat 	if (xflag || rflag)
   1753  1.75    atatat 		display_struct(pnode, sname, &timeval, sz,
   1754  1.75    atatat 			       DISPLAY_VALUE);
   1755  1.75    atatat 	else if (!nflag)
   1756  1.75    atatat 		/* ctime() provides the \n */
   1757  1.75    atatat 		printf("%s%s%s", sname, eq, ctime(&boottime));
   1758  1.75    atatat 	else if (nflag == 1)
   1759  1.75    atatat 		printf("%ld\n", (long)boottime);
   1760  1.75    atatat 	else
   1761  1.75    atatat 		printf("%ld.%06ld\n", (long)timeval.tv_sec,
   1762  1.75    atatat 		       (long)timeval.tv_usec);
   1763  1.75    atatat }
   1764  1.20    itojun 
   1765  1.75    atatat /*ARGSUSED*/
   1766  1.75    atatat static void
   1767  1.75    atatat kern_consdev(HANDLER_ARGS)
   1768  1.20    itojun {
   1769  1.75    atatat 	dev_t cons;
   1770  1.75    atatat 	size_t sz;
   1771  1.75    atatat 	int rc;
   1772  1.75    atatat 
   1773  1.75    atatat 	sz = sizeof(cons);
   1774  1.75    atatat 	rc = sysctl(name, namelen, &cons, &sz, NULL, 0);
   1775  1.75    atatat 	if (rc == -1) {
   1776  1.75    atatat 		sysctlerror(1);
   1777  1.75    atatat 		return;
   1778  1.75    atatat 	}
   1779  1.75    atatat 	if (sz != sizeof(cons))
   1780  1.75    atatat 		errx(1, "%s: !returned size wrong!", sname);
   1781  1.20    itojun 
   1782  1.75    atatat 	if (xflag || rflag)
   1783  1.75    atatat 		display_struct(pnode, sname, &cons, sz,
   1784  1.75    atatat 			       DISPLAY_VALUE);
   1785  1.75    atatat 	else if (!nflag)
   1786  1.75    atatat 		printf("%s%s%s\n", sname, eq, devname(cons, S_IFCHR));
   1787  1.75    atatat 	else
   1788  1.75    atatat 		printf("0x%x\n", cons);
   1789  1.75    atatat }
   1790  1.17   thorpej 
   1791  1.75    atatat /*ARGSUSED*/
   1792  1.75    atatat static void
   1793  1.75    atatat kern_cp_time(HANDLER_ARGS)
   1794  1.17   thorpej {
   1795  1.80    atatat 	u_int64_t *cp_time;
   1796  1.80    atatat 	size_t sz, osz;
   1797  1.80    atatat 	int rc, i, n;
   1798  1.80    atatat 	char s[sizeof("kern.cp_time.nnnnnn")];
   1799  1.80    atatat 	const char *tname;
   1800  1.80    atatat 
   1801  1.80    atatat 	/*
   1802  1.80    atatat 	 * three things to do here.
   1803  1.80    atatat 	 * case 1: get sum (no Aflag and namelen == 2)
   1804  1.80    atatat 	 * case 2: get specific processor (namelen == 3)
   1805  1.80    atatat 	 * case 3: get all processors (Aflag and namelen == 2)
   1806  1.80    atatat 	 */
   1807  1.80    atatat 
   1808  1.80    atatat 	if (namelen == 2 && Aflag) {
   1809  1.80    atatat 		sz = sizeof(n);
   1810  1.80    atatat 		rc = sysctlbyname("hw.ncpu", &n, &sz, NULL, 0);
   1811  1.80    atatat 		if (rc != 0)
   1812  1.80    atatat 			return; /* XXX print an error, eh? */
   1813  1.81    atatat 		n++; /* Add on space for the sum. */
   1814  1.80    atatat 		sz = n * sizeof(u_int64_t) * CPUSTATES;
   1815  1.80    atatat 	}
   1816  1.80    atatat 	else {
   1817  1.81    atatat 		n = -1; /* Just print one data set. */
   1818  1.80    atatat 		sz = sizeof(u_int64_t) * CPUSTATES;
   1819  1.80    atatat 	}
   1820  1.80    atatat 
   1821  1.80    atatat 	cp_time = malloc(sz);
   1822  1.80    atatat 	if (cp_time == NULL) {
   1823  1.80    atatat 		sysctlerror(1);
   1824  1.80    atatat 		return;
   1825  1.80    atatat 	}
   1826  1.81    atatat 
   1827  1.80    atatat 	osz = sz;
   1828  1.81    atatat 	rc = sysctl(name, namelen, cp_time + (n != -1) * CPUSTATES, &osz,
   1829  1.81    atatat 		    NULL, 0);
   1830  1.75    atatat 
   1831  1.75    atatat 	if (rc == -1) {
   1832  1.75    atatat 		sysctlerror(1);
   1833  1.80    atatat 		free(cp_time);
   1834  1.75    atatat 		return;
   1835  1.75    atatat 	}
   1836  1.81    atatat 
   1837  1.81    atatat 	/*
   1838  1.81    atatat 	 * Check, but account for space we'll occupy with the sum.
   1839  1.81    atatat 	 */
   1840  1.81    atatat 	if (osz != sz - (n != -1) * CPUSTATES * sizeof(u_int64_t))
   1841  1.75    atatat 		errx(1, "%s: !returned size wrong!", sname);
   1842  1.17   thorpej 
   1843  1.81    atatat 	/*
   1844  1.81    atatat 	 * Compute the actual sum.  Two calls would be easier (we
   1845  1.81    atatat 	 * could just call ourselves recursively above), but the
   1846  1.81    atatat 	 * numbers wouldn't add up.
   1847  1.81    atatat 	 */
   1848  1.81    atatat 	if (n != -1) {
   1849  1.81    atatat 		memset(cp_time, 0, sizeof(u_int64_t) * CPUSTATES);
   1850  1.81    atatat 		for (i = 1; i < n; i++) {
   1851  1.81    atatat 			cp_time[CP_USER] += cp_time[i * CPUSTATES + CP_USER];
   1852  1.81    atatat                         cp_time[CP_NICE] += cp_time[i * CPUSTATES + CP_NICE];
   1853  1.81    atatat                         cp_time[CP_SYS] += cp_time[i * CPUSTATES + CP_SYS];
   1854  1.81    atatat                         cp_time[CP_INTR] += cp_time[i * CPUSTATES + CP_INTR];
   1855  1.81    atatat                         cp_time[CP_IDLE] += cp_time[i * CPUSTATES + CP_IDLE];
   1856  1.81    atatat 		}
   1857  1.81    atatat 	}
   1858  1.81    atatat 
   1859  1.80    atatat 	tname = sname;
   1860  1.80    atatat 	for (i = 0; n == -1 || i < n; i++) {
   1861  1.81    atatat 		if (i > 0) {
   1862  1.81    atatat 			(void)snprintf(s, sizeof(s), "%s%s%d", sname, sep,
   1863  1.81    atatat 				       i - 1);
   1864  1.80    atatat 			tname = s;
   1865  1.80    atatat 		}
   1866  1.80    atatat 		if (xflag || rflag)
   1867  1.80    atatat 			display_struct(pnode, tname, cp_time + (i * CPUSTATES),
   1868  1.80    atatat 				       sizeof(u_int64_t) * CPUSTATES,
   1869  1.80    atatat 				       DISPLAY_VALUE);
   1870  1.80    atatat 		else {
   1871  1.80    atatat 			if (!nflag)
   1872  1.80    atatat 				printf("%s: ", tname);
   1873  1.80    atatat 			printf("user = %" PRIu64
   1874  1.80    atatat 			       ", nice = %" PRIu64
   1875  1.80    atatat 			       ", sys = %" PRIu64
   1876  1.80    atatat 			       ", intr = %" PRIu64
   1877  1.80    atatat 			       ", idle = %" PRIu64
   1878  1.80    atatat 			       "\n",
   1879  1.80    atatat 			       cp_time[i * CPUSTATES + CP_USER],
   1880  1.80    atatat 			       cp_time[i * CPUSTATES + CP_NICE],
   1881  1.80    atatat 			       cp_time[i * CPUSTATES + CP_SYS],
   1882  1.80    atatat 			       cp_time[i * CPUSTATES + CP_INTR],
   1883  1.80    atatat 			       cp_time[i * CPUSTATES + CP_IDLE]);
   1884  1.80    atatat 		}
   1885  1.81    atatat 		/*
   1886  1.81    atatat 		 * Just printing the one node.
   1887  1.81    atatat 		 */
   1888  1.80    atatat 		if (n == -1)
   1889  1.80    atatat 			break;
   1890  1.79    atatat 	}
   1891  1.80    atatat 
   1892  1.80    atatat 	free(cp_time);
   1893  1.17   thorpej }
   1894  1.17   thorpej 
   1895  1.75    atatat /*ARGSUSED*/
   1896  1.75    atatat static void
   1897  1.75    atatat vm_loadavg(HANDLER_ARGS)
   1898  1.22    bouyer {
   1899  1.75    atatat 	struct loadavg loadavg;
   1900  1.75    atatat 	size_t sz;
   1901  1.75    atatat 	int rc;
   1902  1.75    atatat 
   1903  1.75    atatat 	sz = sizeof(loadavg);
   1904  1.75    atatat 	rc = sysctl(name, namelen, &loadavg, &sz, NULL, 0);
   1905  1.75    atatat 	if (rc == -1) {
   1906  1.75    atatat 		sysctlerror(1);
   1907  1.75    atatat 		return;
   1908  1.75    atatat 	}
   1909  1.75    atatat 	if (sz != sizeof(loadavg))
   1910  1.75    atatat 		errx(1, "%s: !returned size wrong!", sname);
   1911  1.75    atatat 
   1912  1.79    atatat 	if (xflag || rflag) {
   1913  1.75    atatat 		display_struct(pnode, sname, &loadavg, sz,
   1914  1.75    atatat 			       DISPLAY_VALUE);
   1915  1.79    atatat 		return;
   1916  1.79    atatat 	}
   1917  1.79    atatat 	if (!nflag)
   1918  1.75    atatat 		printf("%s: ", sname);
   1919  1.75    atatat 	printf("%.2f %.2f %.2f\n",
   1920  1.75    atatat 	       (double) loadavg.ldavg[0] / loadavg.fscale,
   1921  1.75    atatat 	       (double) loadavg.ldavg[1] / loadavg.fscale,
   1922  1.75    atatat 	       (double) loadavg.ldavg[2] / loadavg.fscale);
   1923   1.1       cgd }
   1924   1.1       cgd 
   1925  1.75    atatat /*ARGSUSED*/
   1926  1.75    atatat static void
   1927  1.75    atatat proc_limit(HANDLER_ARGS)
   1928   1.1       cgd {
   1929  1.75    atatat 	u_quad_t olim, *newp, nlim;
   1930  1.75    atatat 	size_t osz, nsz;
   1931  1.75    atatat 	char *t;
   1932  1.75    atatat 	int rc;
   1933  1.75    atatat 
   1934  1.75    atatat 	osz = sizeof(olim);
   1935  1.75    atatat 	if (value != NULL) {
   1936  1.75    atatat 		nsz = sizeof(nlim);
   1937  1.75    atatat 		newp = &nlim;
   1938  1.75    atatat 		if (strcmp(value, "unlimited") == 0)
   1939  1.75    atatat 			nlim = RLIM_INFINITY;
   1940  1.75    atatat 		else {
   1941  1.75    atatat 			errno = 0;
   1942  1.75    atatat 			nlim = strtouq(value, &t, 0);
   1943  1.75    atatat 			if (*t != '\0' || errno != 0) {
   1944  1.75    atatat 				fprintf(warnfp,
   1945  1.75    atatat 					"%s: %s: '%s' is not a valid limit\n",
   1946  1.75    atatat 					getprogname(), sname, value);
   1947  1.75    atatat 				exit(1);
   1948  1.75    atatat 			}
   1949  1.75    atatat 		}
   1950  1.75    atatat 	}
   1951  1.75    atatat 	else {
   1952  1.75    atatat 		nsz = 0;
   1953  1.75    atatat 		newp = NULL;
   1954  1.75    atatat 	}
   1955  1.75    atatat 
   1956  1.75    atatat 	rc = sysctl(name, namelen, &olim, &osz, newp, nsz);
   1957  1.75    atatat 	if (rc == -1) {
   1958  1.75    atatat 		sysctlerror(newp == NULL);
   1959  1.75    atatat 		return;
   1960  1.75    atatat 	}
   1961  1.75    atatat 
   1962  1.75    atatat 	if (newp && qflag)
   1963  1.75    atatat 		return;
   1964  1.75    atatat 
   1965  1.75    atatat 	if (rflag || xflag || olim != RLIM_INFINITY)
   1966  1.75    atatat 		display_number(pnode, sname, &olim, sizeof(olim),
   1967  1.75    atatat 			       newp ? DISPLAY_OLD : DISPLAY_VALUE);
   1968  1.75    atatat 	else
   1969  1.75    atatat 		display_string(pnode, sname, "unlimited", 10,
   1970  1.75    atatat 			       newp ? DISPLAY_OLD : DISPLAY_VALUE);
   1971   1.1       cgd 
   1972  1.75    atatat 	if (newp) {
   1973  1.75    atatat 		if (rflag || xflag || nlim != RLIM_INFINITY)
   1974  1.75    atatat 			display_number(pnode, sname, &nlim, sizeof(nlim),
   1975  1.75    atatat 				       DISPLAY_NEW);
   1976  1.75    atatat 		else
   1977  1.75    atatat 			display_string(pnode, sname, "unlimited", 10,
   1978  1.75    atatat 				       DISPLAY_NEW);
   1979   1.1       cgd 	}
   1980   1.1       cgd }
   1981   1.1       cgd 
   1982  1.75    atatat #ifdef CPU_DISKINFO
   1983  1.75    atatat /*ARGSUSED*/
   1984  1.14  christos static void
   1985  1.75    atatat machdep_diskinfo(HANDLER_ARGS)
   1986   1.1       cgd {
   1987  1.75    atatat 	struct disklist *dl;
   1988  1.75    atatat 	struct biosdisk_info *bi;
   1989  1.75    atatat 	struct nativedisk_info *ni;
   1990  1.75    atatat 	int rc;
   1991  1.75    atatat 	size_t sz;
   1992  1.75    atatat 	uint i, b, lim;
   1993  1.75    atatat 
   1994  1.75    atatat 	rc = sysctl(name, namelen, NULL, &sz, NULL, 0);
   1995  1.75    atatat 	if (rc == -1) {
   1996  1.75    atatat 		sysctlerror(1);
   1997  1.75    atatat 		return;
   1998  1.75    atatat 	}
   1999  1.75    atatat 	dl = malloc(sz);
   2000  1.75    atatat 	if (dl == NULL) {
   2001  1.75    atatat 		sysctlerror(1);
   2002  1.75    atatat 		return;
   2003  1.75    atatat 	}
   2004  1.75    atatat 	rc = sysctl(name, namelen, dl, &sz, NULL, 0);
   2005  1.75    atatat 	if (rc == -1) {
   2006  1.75    atatat 		sysctlerror(1);
   2007  1.75    atatat 		return;
   2008  1.75    atatat 	}
   2009  1.45       cgd 
   2010  1.75    atatat 	if (!nflag)
   2011  1.75    atatat 		printf("%s: ", sname);
   2012  1.75    atatat 	lim = dl->dl_nbiosdisks;
   2013  1.75    atatat 	if (lim > MAX_BIOSDISKS)
   2014  1.75    atatat 		lim = MAX_BIOSDISKS;
   2015  1.75    atatat 	for (bi = dl->dl_biosdisks, i = 0; i < lim; bi++, i++)
   2016  1.75    atatat 		printf("%x:%" PRIu64 "(%d/%d/%d),%x ",
   2017  1.75    atatat 		       bi->bi_dev, bi->bi_lbasecs,
   2018  1.75    atatat 		       bi->bi_cyl, bi->bi_head, bi->bi_sec,
   2019  1.75    atatat 		       bi->bi_flags);
   2020  1.75    atatat 	lim = dl->dl_nnativedisks;
   2021  1.75    atatat 	ni = dl->dl_nativedisks;
   2022  1.75    atatat 	bi = dl->dl_biosdisks;
   2023  1.75    atatat 	/* LINTED -- pointer casts are tedious */
   2024  1.75    atatat 	if ((char *)&ni[lim] != (char *)dl + sz) {
   2025  1.75    atatat 		fprintf(warnfp, "size mismatch\n");
   2026  1.75    atatat 		return;
   2027  1.75    atatat 	}
   2028  1.75    atatat 	for (i = 0; i < lim; ni++, i++) {
   2029  1.75    atatat 		char t = ':';
   2030  1.75    atatat 		printf(" %.*s", (int)sizeof ni->ni_devname,
   2031  1.75    atatat 		       ni->ni_devname);
   2032  1.75    atatat 		for (b = 0; b < ni->ni_nmatches; t = ',', b++)
   2033  1.75    atatat 			printf("%c%x", t,
   2034  1.75    atatat 			       bi[ni->ni_biosmatches[b]].bi_dev);
   2035  1.75    atatat 	}
   2036  1.75    atatat 	printf("\n");
   2037   1.1       cgd }
   2038  1.75    atatat #endif /* CPU_DISKINFO */
   2039