xref: /freebsd/sbin/sysctl/sysctl.c (revision dea673e932532f8f2d630dff2dcfc0c4a2eaf184)
1dea673e9SRodney W. Grimes /*
2dea673e9SRodney W. Grimes  * Copyright (c) 1993
3dea673e9SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
4dea673e9SRodney W. Grimes  *
5dea673e9SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
6dea673e9SRodney W. Grimes  * modification, are permitted provided that the following conditions
7dea673e9SRodney W. Grimes  * are met:
8dea673e9SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
9dea673e9SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
10dea673e9SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
11dea673e9SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
12dea673e9SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
13dea673e9SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
14dea673e9SRodney W. Grimes  *    must display the following acknowledgement:
15dea673e9SRodney W. Grimes  *	This product includes software developed by the University of
16dea673e9SRodney W. Grimes  *	California, Berkeley and its contributors.
17dea673e9SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
18dea673e9SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
19dea673e9SRodney W. Grimes  *    without specific prior written permission.
20dea673e9SRodney W. Grimes  *
21dea673e9SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22dea673e9SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23dea673e9SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24dea673e9SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25dea673e9SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26dea673e9SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27dea673e9SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28dea673e9SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29dea673e9SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30dea673e9SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31dea673e9SRodney W. Grimes  * SUCH DAMAGE.
32dea673e9SRodney W. Grimes  */
33dea673e9SRodney W. Grimes 
34dea673e9SRodney W. Grimes #ifndef lint
35dea673e9SRodney W. Grimes static char copyright[] =
36dea673e9SRodney W. Grimes "@(#) Copyright (c) 1993\n\
37dea673e9SRodney W. Grimes 	The Regents of the University of California.  All rights reserved.\n";
38dea673e9SRodney W. Grimes #endif /* not lint */
39dea673e9SRodney W. Grimes 
40dea673e9SRodney W. Grimes #ifndef lint
41dea673e9SRodney W. Grimes static char sccsid[] = "@(#)sysctl.c	8.1 (Berkeley) 6/6/93";
42dea673e9SRodney W. Grimes #endif /* not lint */
43dea673e9SRodney W. Grimes 
44dea673e9SRodney W. Grimes #include <sys/param.h>
45dea673e9SRodney W. Grimes #include <sys/gmon.h>
46dea673e9SRodney W. Grimes #include <sys/stat.h>
47dea673e9SRodney W. Grimes #include <sys/sysctl.h>
48dea673e9SRodney W. Grimes #include <sys/socket.h>
49dea673e9SRodney W. Grimes #include <vm/vm_param.h>
50dea673e9SRodney W. Grimes #include <machine/cpu.h>
51dea673e9SRodney W. Grimes 
52dea673e9SRodney W. Grimes #include <netinet/in.h>
53dea673e9SRodney W. Grimes #include <netinet/in_systm.h>
54dea673e9SRodney W. Grimes #include <netinet/ip.h>
55dea673e9SRodney W. Grimes #include <netinet/ip_icmp.h>
56dea673e9SRodney W. Grimes #include <netinet/icmp_var.h>
57dea673e9SRodney W. Grimes #include <netinet/ip_var.h>
58dea673e9SRodney W. Grimes #include <netinet/udp.h>
59dea673e9SRodney W. Grimes #include <netinet/udp_var.h>
60dea673e9SRodney W. Grimes 
61dea673e9SRodney W. Grimes #include <errno.h>
62dea673e9SRodney W. Grimes #include <stdio.h>
63dea673e9SRodney W. Grimes #include <stdlib.h>
64dea673e9SRodney W. Grimes #include <string.h>
65dea673e9SRodney W. Grimes 
66dea673e9SRodney W. Grimes struct ctlname topname[] = CTL_NAMES;
67dea673e9SRodney W. Grimes struct ctlname kernname[] = CTL_KERN_NAMES;
68dea673e9SRodney W. Grimes struct ctlname vmname[] = CTL_VM_NAMES;
69dea673e9SRodney W. Grimes struct ctlname netname[] = CTL_NET_NAMES;
70dea673e9SRodney W. Grimes struct ctlname hwname[] = CTL_HW_NAMES;
71dea673e9SRodney W. Grimes struct ctlname username[] = CTL_USER_NAMES;
72dea673e9SRodney W. Grimes struct ctlname debugname[CTL_DEBUG_MAXID];
73dea673e9SRodney W. Grimes #ifdef CTL_MACHDEP_NAMES
74dea673e9SRodney W. Grimes struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
75dea673e9SRodney W. Grimes #endif
76dea673e9SRodney W. Grimes char names[BUFSIZ];
77dea673e9SRodney W. Grimes 
78dea673e9SRodney W. Grimes struct list {
79dea673e9SRodney W. Grimes 	struct	ctlname *list;
80dea673e9SRodney W. Grimes 	int	size;
81dea673e9SRodney W. Grimes };
82dea673e9SRodney W. Grimes struct list toplist = { topname, CTL_MAXID };
83dea673e9SRodney W. Grimes struct list secondlevel[] = {
84dea673e9SRodney W. Grimes 	{ 0, 0 },			/* CTL_UNSPEC */
85dea673e9SRodney W. Grimes 	{ kernname, KERN_MAXID },	/* CTL_KERN */
86dea673e9SRodney W. Grimes 	{ vmname, VM_MAXID },		/* CTL_VM */
87dea673e9SRodney W. Grimes 	{ 0, 0 },			/* CTL_FS */
88dea673e9SRodney W. Grimes 	{ netname, NET_MAXID },		/* CTL_NET */
89dea673e9SRodney W. Grimes 	{ 0, CTL_DEBUG_MAXID },		/* CTL_DEBUG */
90dea673e9SRodney W. Grimes 	{ hwname, HW_MAXID },		/* CTL_HW */
91dea673e9SRodney W. Grimes #ifdef CTL_MACHDEP_NAMES
92dea673e9SRodney W. Grimes 	{ machdepname, CPU_MAXID },	/* CTL_MACHDEP */
93dea673e9SRodney W. Grimes #else
94dea673e9SRodney W. Grimes 	{ 0, 0 },			/* CTL_MACHDEP */
95dea673e9SRodney W. Grimes #endif
96dea673e9SRodney W. Grimes 	{ username, USER_MAXID },	/* CTL_USER_NAMES */
97dea673e9SRodney W. Grimes };
98dea673e9SRodney W. Grimes 
99dea673e9SRodney W. Grimes int	Aflag, aflag, nflag, wflag;
100dea673e9SRodney W. Grimes 
101dea673e9SRodney W. Grimes /*
102dea673e9SRodney W. Grimes  * Variables requiring special processing.
103dea673e9SRodney W. Grimes  */
104dea673e9SRodney W. Grimes #define	CLOCK		0x00000001
105dea673e9SRodney W. Grimes #define	BOOTTIME	0x00000002
106dea673e9SRodney W. Grimes #define	CONSDEV		0x00000004
107dea673e9SRodney W. Grimes 
108dea673e9SRodney W. Grimes int
109dea673e9SRodney W. Grimes main(argc, argv)
110dea673e9SRodney W. Grimes 	int argc;
111dea673e9SRodney W. Grimes 	char *argv[];
112dea673e9SRodney W. Grimes {
113dea673e9SRodney W. Grimes 	extern char *optarg;
114dea673e9SRodney W. Grimes 	extern int optind;
115dea673e9SRodney W. Grimes 	int ch, lvl1;
116dea673e9SRodney W. Grimes 
117dea673e9SRodney W. Grimes 	while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
118dea673e9SRodney W. Grimes 		switch (ch) {
119dea673e9SRodney W. Grimes 
120dea673e9SRodney W. Grimes 		case 'A':
121dea673e9SRodney W. Grimes 			Aflag = 1;
122dea673e9SRodney W. Grimes 			break;
123dea673e9SRodney W. Grimes 
124dea673e9SRodney W. Grimes 		case 'a':
125dea673e9SRodney W. Grimes 			aflag = 1;
126dea673e9SRodney W. Grimes 			break;
127dea673e9SRodney W. Grimes 
128dea673e9SRodney W. Grimes 		case 'n':
129dea673e9SRodney W. Grimes 			nflag = 1;
130dea673e9SRodney W. Grimes 			break;
131dea673e9SRodney W. Grimes 
132dea673e9SRodney W. Grimes 		case 'w':
133dea673e9SRodney W. Grimes 			wflag = 1;
134dea673e9SRodney W. Grimes 			break;
135dea673e9SRodney W. Grimes 
136dea673e9SRodney W. Grimes 		default:
137dea673e9SRodney W. Grimes 			usage();
138dea673e9SRodney W. Grimes 		}
139dea673e9SRodney W. Grimes 	}
140dea673e9SRodney W. Grimes 	argc -= optind;
141dea673e9SRodney W. Grimes 	argv += optind;
142dea673e9SRodney W. Grimes 
143dea673e9SRodney W. Grimes 	if (Aflag || aflag) {
144dea673e9SRodney W. Grimes 		debuginit();
145dea673e9SRodney W. Grimes 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
146dea673e9SRodney W. Grimes 			listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
147dea673e9SRodney W. Grimes 		exit(0);
148dea673e9SRodney W. Grimes 	}
149dea673e9SRodney W. Grimes 	if (argc == 0)
150dea673e9SRodney W. Grimes 		usage();
151dea673e9SRodney W. Grimes 	while (argc-- > 0)
152dea673e9SRodney W. Grimes 		parse(*argv, 1);
153dea673e9SRodney W. Grimes 	exit(0);
154dea673e9SRodney W. Grimes }
155dea673e9SRodney W. Grimes 
156dea673e9SRodney W. Grimes /*
157dea673e9SRodney W. Grimes  * List all variables known to the system.
158dea673e9SRodney W. Grimes  */
159dea673e9SRodney W. Grimes listall(prefix, lp)
160dea673e9SRodney W. Grimes 	char *prefix;
161dea673e9SRodney W. Grimes 	struct list *lp;
162dea673e9SRodney W. Grimes {
163dea673e9SRodney W. Grimes 	int lvl2;
164dea673e9SRodney W. Grimes 	char *cp, name[BUFSIZ];
165dea673e9SRodney W. Grimes 
166dea673e9SRodney W. Grimes 	if (lp->list == 0)
167dea673e9SRodney W. Grimes 		return;
168dea673e9SRodney W. Grimes 	strcpy(name, prefix);
169dea673e9SRodney W. Grimes 	cp = &name[strlen(name)];
170dea673e9SRodney W. Grimes 	*cp++ = '.';
171dea673e9SRodney W. Grimes 	for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
172dea673e9SRodney W. Grimes 		if (lp->list[lvl2].ctl_name == 0)
173dea673e9SRodney W. Grimes 			continue;
174dea673e9SRodney W. Grimes 		strcpy(cp, lp->list[lvl2].ctl_name);
175dea673e9SRodney W. Grimes 		parse(name, Aflag);
176dea673e9SRodney W. Grimes 	}
177dea673e9SRodney W. Grimes }
178dea673e9SRodney W. Grimes 
179dea673e9SRodney W. Grimes /*
180dea673e9SRodney W. Grimes  * Parse a name into a MIB entry.
181dea673e9SRodney W. Grimes  * Lookup and print out the MIB entry if it exists.
182dea673e9SRodney W. Grimes  * Set a new value if requested.
183dea673e9SRodney W. Grimes  */
184dea673e9SRodney W. Grimes parse(string, flags)
185dea673e9SRodney W. Grimes 	char *string;
186dea673e9SRodney W. Grimes 	int flags;
187dea673e9SRodney W. Grimes {
188dea673e9SRodney W. Grimes 	int indx, type, state, size, len;
189dea673e9SRodney W. Grimes 	int special = 0;
190dea673e9SRodney W. Grimes 	void *newval = 0;
191dea673e9SRodney W. Grimes 	int intval, newsize = 0;
192dea673e9SRodney W. Grimes 	quad_t quadval;
193dea673e9SRodney W. Grimes 	struct list *lp;
194dea673e9SRodney W. Grimes 	int mib[CTL_MAXNAME];
195dea673e9SRodney W. Grimes 	char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
196dea673e9SRodney W. Grimes 
197dea673e9SRodney W. Grimes 	bufp = buf;
198dea673e9SRodney W. Grimes 	snprintf(buf, BUFSIZ, "%s", string);
199dea673e9SRodney W. Grimes 	if ((cp = strchr(string, '=')) != NULL) {
200dea673e9SRodney W. Grimes 		if (!wflag) {
201dea673e9SRodney W. Grimes 			fprintf(stderr, "Must specify -w to set variables\n");
202dea673e9SRodney W. Grimes 			exit(2);
203dea673e9SRodney W. Grimes 		}
204dea673e9SRodney W. Grimes 		*strchr(buf, '=') = '\0';
205dea673e9SRodney W. Grimes 		*cp++ = '\0';
206dea673e9SRodney W. Grimes 		while (isspace(*cp))
207dea673e9SRodney W. Grimes 			cp++;
208dea673e9SRodney W. Grimes 		newval = cp;
209dea673e9SRodney W. Grimes 		newsize = strlen(cp);
210dea673e9SRodney W. Grimes 	}
211dea673e9SRodney W. Grimes 	if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
212dea673e9SRodney W. Grimes 		return;
213dea673e9SRodney W. Grimes 	mib[0] = indx;
214dea673e9SRodney W. Grimes 	if (indx == CTL_DEBUG)
215dea673e9SRodney W. Grimes 		debuginit();
216dea673e9SRodney W. Grimes 	lp = &secondlevel[indx];
217dea673e9SRodney W. Grimes 	if (lp->list == 0) {
218dea673e9SRodney W. Grimes 		fprintf(stderr, "%s: class is not implemented\n",
219dea673e9SRodney W. Grimes 		    topname[indx]);
220dea673e9SRodney W. Grimes 		return;
221dea673e9SRodney W. Grimes 	}
222dea673e9SRodney W. Grimes 	if (bufp == NULL) {
223dea673e9SRodney W. Grimes 		listall(topname[indx].ctl_name, lp);
224dea673e9SRodney W. Grimes 		return;
225dea673e9SRodney W. Grimes 	}
226dea673e9SRodney W. Grimes 	if ((indx = findname(string, "second", &bufp, lp)) == -1)
227dea673e9SRodney W. Grimes 		return;
228dea673e9SRodney W. Grimes 	mib[1] = indx;
229dea673e9SRodney W. Grimes 	type = lp->list[indx].ctl_type;
230dea673e9SRodney W. Grimes 	len = 2;
231dea673e9SRodney W. Grimes 	switch (mib[0]) {
232dea673e9SRodney W. Grimes 
233dea673e9SRodney W. Grimes 	case CTL_KERN:
234dea673e9SRodney W. Grimes 		switch (mib[1]) {
235dea673e9SRodney W. Grimes 		case KERN_PROF:
236dea673e9SRodney W. Grimes 			mib[2] = GPROF_STATE;
237dea673e9SRodney W. Grimes 			size = sizeof state;
238dea673e9SRodney W. Grimes 			if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
239dea673e9SRodney W. Grimes 				if (flags == 0)
240dea673e9SRodney W. Grimes 					return;
241dea673e9SRodney W. Grimes 				if (!nflag)
242dea673e9SRodney W. Grimes 					fprintf(stdout, "%s: ", string);
243dea673e9SRodney W. Grimes 				fprintf(stderr,
244dea673e9SRodney W. Grimes 				    "kernel is not compiled for profiling\n");
245dea673e9SRodney W. Grimes 				return;
246dea673e9SRodney W. Grimes 			}
247dea673e9SRodney W. Grimes 			if (!nflag)
248dea673e9SRodney W. Grimes 				fprintf(stdout, "%s: %s\n", string,
249dea673e9SRodney W. Grimes 				    state == GMON_PROF_OFF ? "off" : "running");
250dea673e9SRodney W. Grimes 			return;
251dea673e9SRodney W. Grimes 		case KERN_VNODE:
252dea673e9SRodney W. Grimes 		case KERN_FILE:
253dea673e9SRodney W. Grimes 			if (flags == 0)
254dea673e9SRodney W. Grimes 				return;
255dea673e9SRodney W. Grimes 			fprintf(stderr,
256dea673e9SRodney W. Grimes 			    "Use pstat to view %s information\n", string);
257dea673e9SRodney W. Grimes 			return;
258dea673e9SRodney W. Grimes 		case KERN_PROC:
259dea673e9SRodney W. Grimes 			if (flags == 0)
260dea673e9SRodney W. Grimes 				return;
261dea673e9SRodney W. Grimes 			fprintf(stderr,
262dea673e9SRodney W. Grimes 			    "Use ps to view %s information\n", string);
263dea673e9SRodney W. Grimes 			return;
264dea673e9SRodney W. Grimes 		case KERN_CLOCKRATE:
265dea673e9SRodney W. Grimes 			special |= CLOCK;
266dea673e9SRodney W. Grimes 			break;
267dea673e9SRodney W. Grimes 		case KERN_BOOTTIME:
268dea673e9SRodney W. Grimes 			special |= BOOTTIME;
269dea673e9SRodney W. Grimes 			break;
270dea673e9SRodney W. Grimes 		}
271dea673e9SRodney W. Grimes 		break;
272dea673e9SRodney W. Grimes 
273dea673e9SRodney W. Grimes 	case CTL_HW:
274dea673e9SRodney W. Grimes 		break;
275dea673e9SRodney W. Grimes 
276dea673e9SRodney W. Grimes 	case CTL_VM:
277dea673e9SRodney W. Grimes 		if (mib[1] == VM_LOADAVG) {
278dea673e9SRodney W. Grimes 			double loads[3];
279dea673e9SRodney W. Grimes 
280dea673e9SRodney W. Grimes 			getloadavg(loads, 3);
281dea673e9SRodney W. Grimes 			if (!nflag)
282dea673e9SRodney W. Grimes 				fprintf(stdout, "%s: ", string);
283dea673e9SRodney W. Grimes 			fprintf(stdout, "%.2f %.2f %.2f\n",
284dea673e9SRodney W. Grimes 			    loads[0], loads[1], loads[2]);
285dea673e9SRodney W. Grimes 			return;
286dea673e9SRodney W. Grimes 		}
287dea673e9SRodney W. Grimes 		if (flags == 0)
288dea673e9SRodney W. Grimes 			return;
289dea673e9SRodney W. Grimes 		fprintf(stderr,
290dea673e9SRodney W. Grimes 		    "Use vmstat or systat to view %s information\n", string);
291dea673e9SRodney W. Grimes 		return;
292dea673e9SRodney W. Grimes 
293dea673e9SRodney W. Grimes 	case CTL_NET:
294dea673e9SRodney W. Grimes 		if (mib[1] == PF_INET) {
295dea673e9SRodney W. Grimes 			len = sysctl_inet(string, &bufp, mib, flags, &type);
296dea673e9SRodney W. Grimes 			if (len >= 0)
297dea673e9SRodney W. Grimes 				break;
298dea673e9SRodney W. Grimes 			return;
299dea673e9SRodney W. Grimes 		}
300dea673e9SRodney W. Grimes 		if (flags == 0)
301dea673e9SRodney W. Grimes 			return;
302dea673e9SRodney W. Grimes 		fprintf(stderr, "Use netstat to view %s information\n", string);
303dea673e9SRodney W. Grimes 		return;
304dea673e9SRodney W. Grimes 
305dea673e9SRodney W. Grimes 	case CTL_DEBUG:
306dea673e9SRodney W. Grimes 		mib[2] = CTL_DEBUG_VALUE;
307dea673e9SRodney W. Grimes 		len = 3;
308dea673e9SRodney W. Grimes 		break;
309dea673e9SRodney W. Grimes 
310dea673e9SRodney W. Grimes 	case CTL_MACHDEP:
311dea673e9SRodney W. Grimes #ifdef CPU_CONSDEV
312dea673e9SRodney W. Grimes 		if (mib[1] == CPU_CONSDEV)
313dea673e9SRodney W. Grimes 			special |= CONSDEV;
314dea673e9SRodney W. Grimes #endif
315dea673e9SRodney W. Grimes 		break;
316dea673e9SRodney W. Grimes 
317dea673e9SRodney W. Grimes 	case CTL_FS:
318dea673e9SRodney W. Grimes 	case CTL_USER:
319dea673e9SRodney W. Grimes 		break;
320dea673e9SRodney W. Grimes 
321dea673e9SRodney W. Grimes 	default:
322dea673e9SRodney W. Grimes 		fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
323dea673e9SRodney W. Grimes 		return;
324dea673e9SRodney W. Grimes 
325dea673e9SRodney W. Grimes 	}
326dea673e9SRodney W. Grimes 	if (bufp) {
327dea673e9SRodney W. Grimes 		fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
328dea673e9SRodney W. Grimes 		return;
329dea673e9SRodney W. Grimes 	}
330dea673e9SRodney W. Grimes 	if (newsize > 0) {
331dea673e9SRodney W. Grimes 		switch (type) {
332dea673e9SRodney W. Grimes 		case CTLTYPE_INT:
333dea673e9SRodney W. Grimes 			intval = atoi(newval);
334dea673e9SRodney W. Grimes 			newval = &intval;
335dea673e9SRodney W. Grimes 			newsize = sizeof intval;
336dea673e9SRodney W. Grimes 			break;
337dea673e9SRodney W. Grimes 
338dea673e9SRodney W. Grimes 		case CTLTYPE_QUAD:
339dea673e9SRodney W. Grimes 			sscanf(newval, "%qd", &quadval);
340dea673e9SRodney W. Grimes 			newval = &quadval;
341dea673e9SRodney W. Grimes 			newsize = sizeof quadval;
342dea673e9SRodney W. Grimes 			break;
343dea673e9SRodney W. Grimes 		}
344dea673e9SRodney W. Grimes 	}
345dea673e9SRodney W. Grimes 	size = BUFSIZ;
346dea673e9SRodney W. Grimes 	if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
347dea673e9SRodney W. Grimes 		if (flags == 0)
348dea673e9SRodney W. Grimes 			return;
349dea673e9SRodney W. Grimes 		switch (errno) {
350dea673e9SRodney W. Grimes 		case EOPNOTSUPP:
351dea673e9SRodney W. Grimes 			fprintf(stderr, "%s: value is not available\n", string);
352dea673e9SRodney W. Grimes 			return;
353dea673e9SRodney W. Grimes 		case ENOTDIR:
354dea673e9SRodney W. Grimes 			fprintf(stderr, "%s: specification is incomplete\n",
355dea673e9SRodney W. Grimes 			    string);
356dea673e9SRodney W. Grimes 			return;
357dea673e9SRodney W. Grimes 		case ENOMEM:
358dea673e9SRodney W. Grimes 			fprintf(stderr, "%s: type is unknown to this program\n",
359dea673e9SRodney W. Grimes 			    string);
360dea673e9SRodney W. Grimes 			return;
361dea673e9SRodney W. Grimes 		default:
362dea673e9SRodney W. Grimes 			perror(string);
363dea673e9SRodney W. Grimes 			return;
364dea673e9SRodney W. Grimes 		}
365dea673e9SRodney W. Grimes 	}
366dea673e9SRodney W. Grimes 	if (special & CLOCK) {
367dea673e9SRodney W. Grimes 		struct clockinfo *clkp = (struct clockinfo *)buf;
368dea673e9SRodney W. Grimes 
369dea673e9SRodney W. Grimes 		if (!nflag)
370dea673e9SRodney W. Grimes 			fprintf(stdout, "%s: ", string);
371dea673e9SRodney W. Grimes 		fprintf(stdout,
372dea673e9SRodney W. Grimes 		    "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
373dea673e9SRodney W. Grimes 		    clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
374dea673e9SRodney W. Grimes 		return;
375dea673e9SRodney W. Grimes 	}
376dea673e9SRodney W. Grimes 	if (special & BOOTTIME) {
377dea673e9SRodney W. Grimes 		struct timeval *btp = (struct timeval *)buf;
378dea673e9SRodney W. Grimes 
379dea673e9SRodney W. Grimes 		if (!nflag)
380dea673e9SRodney W. Grimes 			fprintf(stdout, "%s = %s\n", string,
381dea673e9SRodney W. Grimes 			    ctime(&btp->tv_sec));
382dea673e9SRodney W. Grimes 		else
383dea673e9SRodney W. Grimes 			fprintf(stdout, "%d\n", btp->tv_sec);
384dea673e9SRodney W. Grimes 		return;
385dea673e9SRodney W. Grimes 	}
386dea673e9SRodney W. Grimes 	if (special & CONSDEV) {
387dea673e9SRodney W. Grimes 		dev_t dev = *(dev_t *)buf;
388dea673e9SRodney W. Grimes 
389dea673e9SRodney W. Grimes 		if (!nflag)
390dea673e9SRodney W. Grimes 			fprintf(stdout, "%s = %s\n", string,
391dea673e9SRodney W. Grimes 			    devname(dev, S_IFCHR));
392dea673e9SRodney W. Grimes 		else
393dea673e9SRodney W. Grimes 			fprintf(stdout, "0x%x\n", dev);
394dea673e9SRodney W. Grimes 		return;
395dea673e9SRodney W. Grimes 	}
396dea673e9SRodney W. Grimes 	switch (type) {
397dea673e9SRodney W. Grimes 	case CTLTYPE_INT:
398dea673e9SRodney W. Grimes 		if (newsize == 0) {
399dea673e9SRodney W. Grimes 			if (!nflag)
400dea673e9SRodney W. Grimes 				fprintf(stdout, "%s = ", string);
401dea673e9SRodney W. Grimes 			fprintf(stdout, "%d\n", *(int *)buf);
402dea673e9SRodney W. Grimes 		} else {
403dea673e9SRodney W. Grimes 			if (!nflag)
404dea673e9SRodney W. Grimes 				fprintf(stdout, "%s: %d -> ", string,
405dea673e9SRodney W. Grimes 				    *(int *)buf);
406dea673e9SRodney W. Grimes 			fprintf(stdout, "%d\n", *(int *)newval);
407dea673e9SRodney W. Grimes 		}
408dea673e9SRodney W. Grimes 		return;
409dea673e9SRodney W. Grimes 
410dea673e9SRodney W. Grimes 	case CTLTYPE_STRING:
411dea673e9SRodney W. Grimes 		if (newsize == 0) {
412dea673e9SRodney W. Grimes 			if (!nflag)
413dea673e9SRodney W. Grimes 				fprintf(stdout, "%s = ", string);
414dea673e9SRodney W. Grimes 			fprintf(stdout, "%s\n", buf);
415dea673e9SRodney W. Grimes 		} else {
416dea673e9SRodney W. Grimes 			if (!nflag)
417dea673e9SRodney W. Grimes 				fprintf(stdout, "%s: %s -> ", string, buf);
418dea673e9SRodney W. Grimes 			fprintf(stdout, "%s\n", newval);
419dea673e9SRodney W. Grimes 		}
420dea673e9SRodney W. Grimes 		return;
421dea673e9SRodney W. Grimes 
422dea673e9SRodney W. Grimes 	case CTLTYPE_QUAD:
423dea673e9SRodney W. Grimes 		if (newsize == 0) {
424dea673e9SRodney W. Grimes 			if (!nflag)
425dea673e9SRodney W. Grimes 				fprintf(stdout, "%s = ", string);
426dea673e9SRodney W. Grimes 			fprintf(stdout, "%qd\n", *(quad_t *)buf);
427dea673e9SRodney W. Grimes 		} else {
428dea673e9SRodney W. Grimes 			if (!nflag)
429dea673e9SRodney W. Grimes 				fprintf(stdout, "%s: %qd -> ", string,
430dea673e9SRodney W. Grimes 				    *(quad_t *)buf);
431dea673e9SRodney W. Grimes 			fprintf(stdout, "%qd\n", *(quad_t *)newval);
432dea673e9SRodney W. Grimes 		}
433dea673e9SRodney W. Grimes 		return;
434dea673e9SRodney W. Grimes 
435dea673e9SRodney W. Grimes 	case CTLTYPE_STRUCT:
436dea673e9SRodney W. Grimes 		fprintf(stderr, "%s: unknown structure returned\n",
437dea673e9SRodney W. Grimes 		    string);
438dea673e9SRodney W. Grimes 		return;
439dea673e9SRodney W. Grimes 
440dea673e9SRodney W. Grimes 	default:
441dea673e9SRodney W. Grimes 	case CTLTYPE_NODE:
442dea673e9SRodney W. Grimes 		fprintf(stderr, "%s: unknown type returned\n",
443dea673e9SRodney W. Grimes 		    string);
444dea673e9SRodney W. Grimes 		return;
445dea673e9SRodney W. Grimes 	}
446dea673e9SRodney W. Grimes }
447dea673e9SRodney W. Grimes 
448dea673e9SRodney W. Grimes /*
449dea673e9SRodney W. Grimes  * Initialize the set of debugging names
450dea673e9SRodney W. Grimes  */
451dea673e9SRodney W. Grimes debuginit()
452dea673e9SRodney W. Grimes {
453dea673e9SRodney W. Grimes 	int mib[3], size, loc, i;
454dea673e9SRodney W. Grimes 
455dea673e9SRodney W. Grimes 	if (secondlevel[CTL_DEBUG].list != 0)
456dea673e9SRodney W. Grimes 		return;
457dea673e9SRodney W. Grimes 	secondlevel[CTL_DEBUG].list = debugname;
458dea673e9SRodney W. Grimes 	mib[0] = CTL_DEBUG;
459dea673e9SRodney W. Grimes 	mib[2] = CTL_DEBUG_NAME;
460dea673e9SRodney W. Grimes 	for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
461dea673e9SRodney W. Grimes 		mib[1] = i;
462dea673e9SRodney W. Grimes 		size = BUFSIZ - loc;
463dea673e9SRodney W. Grimes 		if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
464dea673e9SRodney W. Grimes 			continue;
465dea673e9SRodney W. Grimes 		debugname[i].ctl_name = &names[loc];
466dea673e9SRodney W. Grimes 		debugname[i].ctl_type = CTLTYPE_INT;
467dea673e9SRodney W. Grimes 		loc += size;
468dea673e9SRodney W. Grimes 	}
469dea673e9SRodney W. Grimes }
470dea673e9SRodney W. Grimes 
471dea673e9SRodney W. Grimes struct ctlname inetname[] = CTL_IPPROTO_NAMES;
472dea673e9SRodney W. Grimes struct ctlname ipname[] = IPCTL_NAMES;
473dea673e9SRodney W. Grimes struct ctlname icmpname[] = ICMPCTL_NAMES;
474dea673e9SRodney W. Grimes struct ctlname udpname[] = UDPCTL_NAMES;
475dea673e9SRodney W. Grimes struct list inetlist = { inetname, IPPROTO_MAXID };
476dea673e9SRodney W. Grimes struct list inetvars[] = {
477dea673e9SRodney W. Grimes 	{ ipname, IPCTL_MAXID },	/* ip */
478dea673e9SRodney W. Grimes 	{ icmpname, ICMPCTL_MAXID },	/* icmp */
479dea673e9SRodney W. Grimes 	{ 0, 0 },			/* igmp */
480dea673e9SRodney W. Grimes 	{ 0, 0 },			/* ggmp */
481dea673e9SRodney W. Grimes 	{ 0, 0 },
482dea673e9SRodney W. Grimes 	{ 0, 0 },
483dea673e9SRodney W. Grimes 	{ 0, 0 },			/* tcp */
484dea673e9SRodney W. Grimes 	{ 0, 0 },
485dea673e9SRodney W. Grimes 	{ 0, 0 },			/* egp */
486dea673e9SRodney W. Grimes 	{ 0, 0 },
487dea673e9SRodney W. Grimes 	{ 0, 0 },
488dea673e9SRodney W. Grimes 	{ 0, 0 },
489dea673e9SRodney W. Grimes 	{ 0, 0 },			/* pup */
490dea673e9SRodney W. Grimes 	{ 0, 0 },
491dea673e9SRodney W. Grimes 	{ 0, 0 },
492dea673e9SRodney W. Grimes 	{ 0, 0 },
493dea673e9SRodney W. Grimes 	{ 0, 0 },
494dea673e9SRodney W. Grimes 	{ udpname, UDPCTL_MAXID },	/* udp */
495dea673e9SRodney W. Grimes };
496dea673e9SRodney W. Grimes 
497dea673e9SRodney W. Grimes /*
498dea673e9SRodney W. Grimes  * handle internet requests
499dea673e9SRodney W. Grimes  */
500dea673e9SRodney W. Grimes sysctl_inet(string, bufpp, mib, flags, typep)
501dea673e9SRodney W. Grimes 	char *string;
502dea673e9SRodney W. Grimes 	char **bufpp;
503dea673e9SRodney W. Grimes 	int mib[];
504dea673e9SRodney W. Grimes 	int flags;
505dea673e9SRodney W. Grimes 	int *typep;
506dea673e9SRodney W. Grimes {
507dea673e9SRodney W. Grimes 	struct list *lp;
508dea673e9SRodney W. Grimes 	int indx;
509dea673e9SRodney W. Grimes 
510dea673e9SRodney W. Grimes 	if (*bufpp == NULL) {
511dea673e9SRodney W. Grimes 		listall(string, &inetlist);
512dea673e9SRodney W. Grimes 		return (-1);
513dea673e9SRodney W. Grimes 	}
514dea673e9SRodney W. Grimes 	if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
515dea673e9SRodney W. Grimes 		return (-1);
516dea673e9SRodney W. Grimes 	mib[2] = indx;
517dea673e9SRodney W. Grimes 	if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
518dea673e9SRodney W. Grimes 		lp = &inetvars[indx];
519dea673e9SRodney W. Grimes 	else if (!flags)
520dea673e9SRodney W. Grimes 		return (-1);
521dea673e9SRodney W. Grimes 	else {
522dea673e9SRodney W. Grimes 		fprintf(stderr, "%s: no variables defined for this protocol\n",
523dea673e9SRodney W. Grimes 		    string);
524dea673e9SRodney W. Grimes 		return (-1);
525dea673e9SRodney W. Grimes 	}
526dea673e9SRodney W. Grimes 	if (*bufpp == NULL) {
527dea673e9SRodney W. Grimes 		listall(string, lp);
528dea673e9SRodney W. Grimes 		return (-1);
529dea673e9SRodney W. Grimes 	}
530dea673e9SRodney W. Grimes 	if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
531dea673e9SRodney W. Grimes 		return (-1);
532dea673e9SRodney W. Grimes 	mib[3] = indx;
533dea673e9SRodney W. Grimes 	*typep = lp->list[indx].ctl_type;
534dea673e9SRodney W. Grimes 	return (4);
535dea673e9SRodney W. Grimes }
536dea673e9SRodney W. Grimes 
537dea673e9SRodney W. Grimes /*
538dea673e9SRodney W. Grimes  * Scan a list of names searching for a particular name.
539dea673e9SRodney W. Grimes  */
540dea673e9SRodney W. Grimes findname(string, level, bufp, namelist)
541dea673e9SRodney W. Grimes 	char *string;
542dea673e9SRodney W. Grimes 	char *level;
543dea673e9SRodney W. Grimes 	char **bufp;
544dea673e9SRodney W. Grimes 	struct list *namelist;
545dea673e9SRodney W. Grimes {
546dea673e9SRodney W. Grimes 	char *name;
547dea673e9SRodney W. Grimes 	int i;
548dea673e9SRodney W. Grimes 
549dea673e9SRodney W. Grimes 	if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
550dea673e9SRodney W. Grimes 		fprintf(stderr, "%s: incomplete specification\n", string);
551dea673e9SRodney W. Grimes 		return (-1);
552dea673e9SRodney W. Grimes 	}
553dea673e9SRodney W. Grimes 	for (i = 0; i < namelist->size; i++)
554dea673e9SRodney W. Grimes 		if (namelist->list[i].ctl_name != NULL &&
555dea673e9SRodney W. Grimes 		    strcmp(name, namelist->list[i].ctl_name) == 0)
556dea673e9SRodney W. Grimes 			break;
557dea673e9SRodney W. Grimes 	if (i == namelist->size) {
558dea673e9SRodney W. Grimes 		fprintf(stderr, "%s level name %s in %s is invalid\n",
559dea673e9SRodney W. Grimes 		    level, name, string);
560dea673e9SRodney W. Grimes 		return (-1);
561dea673e9SRodney W. Grimes 	}
562dea673e9SRodney W. Grimes 	return (i);
563dea673e9SRodney W. Grimes }
564dea673e9SRodney W. Grimes 
565dea673e9SRodney W. Grimes usage()
566dea673e9SRodney W. Grimes {
567dea673e9SRodney W. Grimes 
568dea673e9SRodney W. Grimes 	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
569dea673e9SRodney W. Grimes 	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
570dea673e9SRodney W. Grimes 	    "sysctl [-n] -a", "sysctl [-n] -A");
571dea673e9SRodney W. Grimes 	exit(1);
572dea673e9SRodney W. Grimes }
573