kinfo_proc => sysctl
[unix-history] / usr / src / usr.sbin / sysctl / sysctl.c
CommitLineData
33a39b1e
KM
1/*
2 * Copyright (c) 1993 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
9char copyright[] =
10"@(#) Copyright (c) 1993 The Regents of the University of California.\n\
11 All rights reserved.\n";
12#endif /* not lint */
13
14#ifndef lint
3c56a5f8 15static char sccsid[] = "@(#)sysctl.c 5.11 (Berkeley) %G%";
33a39b1e
KM
16#endif /* not lint */
17
3a9dd945 18#include <sys/param.h>
629efb73 19#include <sys/gmon.h>
33a39b1e
KM
20#include <sys/stat.h>
21#include <sys/sysctl.h>
22#include <sys/socket.h>
23#include <vm/vm_param.h>
3a9dd945 24
129fa670
KM
25#include <netinet/in.h>
26#include <netinet/in_systm.h>
27#include <netinet/ip.h>
28#include <netinet/ip_icmp.h>
29#include <netinet/icmp_var.h>
5082da2b
KM
30#include <netinet/ip_var.h>
31#include <netinet/udp.h>
32#include <netinet/udp_var.h>
3a9dd945 33
33a39b1e 34#include <errno.h>
3a9dd945 35#include <stdio.h>
33a39b1e
KM
36#include <stdlib.h>
37#include <string.h>
33a39b1e 38
129fa670
KM
39struct ctlname topname[] = CTL_NAMES;
40struct ctlname kernname[] = CTL_KERN_NAMES;
41struct ctlname vmname[] = CTL_VM_NAMES;
42struct ctlname netname[] = CTL_NET_NAMES;
43struct ctlname hwname[] = CTL_HW_NAMES;
759ce31c 44struct ctlname username[] = CTL_USER_NAMES;
1fdacbde
KM
45struct ctlname debugname[CTL_DEBUG_MAXID];
46char names[BUFSIZ];
33a39b1e
KM
47
48struct list {
129fa670 49 struct ctlname *list;
33a39b1e 50 int size;
129fa670
KM
51};
52struct list toplist = { topname, CTL_MAXID };
53struct list secondlevel[] = {
33a39b1e
KM
54 { 0, 0 }, /* CTL_UNSPEC */
55 { kernname, KERN_MAXID }, /* CTL_KERN */
56 { vmname, VM_MAXID }, /* CTL_VM */
57 { 0, 0 }, /* CTL_FS */
58 { netname, NET_MAXID }, /* CTL_NET */
1fdacbde 59 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
33a39b1e
KM
60 { hwname, HW_MAXID }, /* CTL_HW */
61 { 0, 0 }, /* CTL_MACHDEP */
759ce31c 62 { username, USER_MAXID }, /* CTL_USER_NAMES */
33a39b1e
KM
63};
64
18ca9a3c 65int Aflag, aflag, nflag, wflag;
33a39b1e
KM
66
67int
68main(argc, argv)
69 int argc;
70 char *argv[];
71{
72 extern char *optarg;
73 extern int optind;
18ca9a3c 74 int ch, lvl1;
33a39b1e 75
18ca9a3c 76 while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
33a39b1e
KM
77 switch (ch) {
78
79 case 'A':
80 Aflag = 1;
81 break;
82
83 case 'a':
84 aflag = 1;
85 break;
86
18ca9a3c
KM
87 case 'n':
88 nflag = 1;
89 break;
90
33a39b1e
KM
91 case 'w':
92 wflag = 1;
93 break;
94
95 default:
96 usage();
97 }
98 }
99 argc -= optind;
100 argv += optind;
101
102 if (Aflag || aflag) {
1fdacbde 103 debuginit();
18ca9a3c 104 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
129fa670 105 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
33a39b1e
KM
106 exit(0);
107 }
108 if (argc == 0)
109 usage();
110 while (argc-- > 0)
111 parse(*argv, 1);
112 exit(0);
113}
114
115/*
116 * List all variables known to the system.
117 */
129fa670
KM
118listall(prefix, lp)
119 char *prefix;
33a39b1e 120 struct list *lp;
129fa670 121{
18ca9a3c 122 int lvl2;
33a39b1e
KM
123 char *cp, name[BUFSIZ];
124
18ca9a3c
KM
125 if (lp->list == 0)
126 return;
129fa670 127 strcpy(name, prefix);
18ca9a3c
KM
128 cp = &name[strlen(name)];
129 *cp++ = '.';
129fa670
KM
130 for (lvl2 = 0; lvl2 < lp->size; lvl2++) {
131 if (lp->list[lvl2].ctl_name == 0)
132 continue;
133 strcpy(cp, lp->list[lvl2].ctl_name);
18ca9a3c 134 parse(name, Aflag);
33a39b1e
KM
135 }
136}
137
138/*
139 * Parse a name into a MIB entry.
140 * Lookup and print out the MIB entry if it exists.
141 * Set a new value if requested.
142 */
143parse(string, flags)
144 char *string;
145 int flags;
146{
629efb73 147 int indx, type, state, size, len;
33a39b1e 148 int isclockrate = 0;
3c56a5f8 149 int isboottime = 0;
33a39b1e
KM
150 void *newval = 0;
151 int intval, newsize = 0;
129fa670
KM
152 quad_t quadval;
153 struct list *lp;
33a39b1e
KM
154 int mib[CTL_MAXNAME];
155 char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
156
157 bufp = buf;
158 snprintf(buf, BUFSIZ, "%s", string);
159 if ((cp = strchr(string, '=')) != NULL) {
160 if (!wflag) {
161 fprintf(stderr, "Must specify -w to set variables\n");
162 exit(2);
163 }
164 *strchr(buf, '=') = '\0';
165 *cp++ = '\0';
166 while (isspace(*cp))
167 cp++;
129fa670
KM
168 newval = cp;
169 newsize = strlen(cp);
33a39b1e 170 }
129fa670 171 if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
33a39b1e
KM
172 return;
173 mib[0] = indx;
1fdacbde
KM
174 if (indx == CTL_DEBUG)
175 debuginit();
33a39b1e
KM
176 lp = &secondlevel[indx];
177 if (lp->list == 0) {
178 fprintf(stderr, "%s: class is not implemented\n",
179 topname[indx]);
180 return;
181 }
18ca9a3c 182 if (bufp == NULL) {
129fa670 183 listall(topname[indx].ctl_name, lp);
18ca9a3c
KM
184 return;
185 }
33a39b1e
KM
186 if ((indx = findname(string, "second", &bufp, lp)) == -1)
187 return;
188 mib[1] = indx;
129fa670
KM
189 type = lp->list[indx].ctl_type;
190 len = 2;
33a39b1e
KM
191 switch (mib[0]) {
192
193 case CTL_KERN:
194 switch (mib[1]) {
629efb73
KM
195 case KERN_PROF:
196 mib[2] = GPROF_STATE;
197 size = sizeof state;
198 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
199 if (flags == 0)
200 return;
201 if (!nflag)
202 fprintf(stdout, "%s: ", string);
203 fprintf(stderr,
204 "kernel is not compiled for profiling\n");
205 return;
206 }
207 if (!nflag)
208 fprintf(stdout, "%s: %s\n", string,
209 state == GMON_PROF_OFF ? "off" : "running");
210 return;
33a39b1e
KM
211 case KERN_VNODE:
212 case KERN_FILE:
213 if (flags == 0)
214 return;
215 fprintf(stderr,
216 "Use pstat to view %s information\n", string);
217 return;
218 case KERN_PROC:
219 if (flags == 0)
220 return;
221 fprintf(stderr,
222 "Use ps to view %s information\n", string);
223 return;
224 case KERN_CLOCKRATE:
225 isclockrate = 1;
226 break;
3c56a5f8
KM
227 case KERN_BOOTTIME:
228 isboottime = 1;
229 break;
33a39b1e
KM
230 }
231 break;
232
233 case CTL_HW:
234 break;
235
236 case CTL_VM:
237 if (mib[1] == VM_LOADAVG) {
238 double loads[3];
239
240 getloadavg(loads, 3);
18ca9a3c
KM
241 if (!nflag)
242 fprintf(stdout, "%s: ", string);
243 fprintf(stdout, "%.2f %.2f %.2f\n",
33a39b1e
KM
244 loads[0], loads[1], loads[2]);
245 return;
246 }
247 if (flags == 0)
248 return;
249 fprintf(stderr,
250 "Use vmstat or systat to view %s information\n", string);
251 return;
252
253 case CTL_NET:
129fa670
KM
254 if (mib[1] == PF_INET) {
255 len = sysctl_inet(string, &bufp, mib, flags, &type);
256 if (len >= 0)
257 break;
258 return;
259 }
33a39b1e
KM
260 if (flags == 0)
261 return;
262 fprintf(stderr, "Use netstat to view %s information\n", string);
263 return;
264
33a39b1e 265 case CTL_DEBUG:
1fdacbde
KM
266 mib[2] = CTL_DEBUG_VALUE;
267 len = 3;
268 break;
269
270 case CTL_FS:
33a39b1e 271 case CTL_MACHDEP:
759ce31c 272 case CTL_USER:
33a39b1e
KM
273 break;
274
275 default:
276 fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
277 return;
278
279 }
129fa670
KM
280 if (bufp) {
281 fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
282 return;
283 }
284 if (newsize > 0) {
285 switch (type) {
286 case CTLTYPE_INT:
287 intval = atoi(newval);
288 newval = &intval;
289 newsize = sizeof intval;
290 break;
33a39b1e 291
129fa670
KM
292 case CTLTYPE_QUAD:
293 sscanf(newval, "%qd", &quadval);
294 newval = &quadval;
295 newsize = sizeof quadval;
296 break;
297 }
298 }
33a39b1e 299 size = BUFSIZ;
129fa670 300 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
33a39b1e
KM
301 if (flags == 0)
302 return;
303 switch (errno) {
304 case EOPNOTSUPP:
305 fprintf(stderr, "%s: value is not available\n", string);
306 return;
307 case ENOTDIR:
308 fprintf(stderr, "%s: specification is incomplete\n",
309 string);
310 return;
311 case ENOMEM:
312 fprintf(stderr, "%s: type is unknown to this program\n",
313 string);
314 return;
315 default:
316 perror(string);
317 return;
318 }
319 }
320 if (isclockrate) {
321 struct clockinfo *clkp = (struct clockinfo *)buf;
322
18ca9a3c
KM
323 if (!nflag)
324 fprintf(stdout, "%s: ", string);
33a39b1e 325 fprintf(stdout,
18ca9a3c
KM
326 "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
327 clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
33a39b1e
KM
328 return;
329 }
3c56a5f8
KM
330 if (isboottime) {
331 struct timeval *btp = (struct timeval *)buf;
332
333 if (!nflag)
334 fprintf(stdout, "%s = %s\n", string,
335 ctime(&btp->tv_sec));
336 else
337 fprintf(stdout, "%d\n", btp->tv_sec);
338 return;
339 }
129fa670
KM
340 switch (type) {
341 case CTLTYPE_INT:
18ca9a3c
KM
342 if (newsize == 0) {
343 if (!nflag)
344 fprintf(stdout, "%s = ", string);
345 fprintf(stdout, "%d\n", *(int *)buf);
346 } else {
347 if (!nflag)
348 fprintf(stdout, "%s: %d -> ", string,
349 *(int *)buf);
350 fprintf(stdout, "%d\n", *(int *)newval);
351 }
129fa670
KM
352 return;
353
354 case CTLTYPE_STRING:
18ca9a3c
KM
355 if (newsize == 0) {
356 if (!nflag)
357 fprintf(stdout, "%s = ", string);
358 fprintf(stdout, "%s\n", buf);
359 } else {
360 if (!nflag)
361 fprintf(stdout, "%s: %s -> ", string, buf);
362 fprintf(stdout, "%s\n", newval);
363 }
129fa670
KM
364 return;
365
366 case CTLTYPE_QUAD:
367 if (newsize == 0) {
368 if (!nflag)
369 fprintf(stdout, "%s = ", string);
370 fprintf(stdout, "%qd\n", *(quad_t *)buf);
371 } else {
372 if (!nflag)
373 fprintf(stdout, "%s: %qd -> ", string,
374 *(quad_t *)buf);
375 fprintf(stdout, "%qd\n", *(quad_t *)newval);
376 }
377 return;
378
379 case CTLTYPE_STRUCT:
380 fprintf(stderr, "%s: unknown structure returned\n",
381 string);
382 return;
383
384 default:
385 case CTLTYPE_NODE:
386 fprintf(stderr, "%s: unknown type returned\n",
387 string);
388 return;
389 }
390}
391
1fdacbde
KM
392/*
393 * Initialize the set of debugging names
394 */
395debuginit()
396{
397 int mib[3], size, loc, i;
398
399 if (secondlevel[CTL_DEBUG].list != 0)
400 return;
401 secondlevel[CTL_DEBUG].list = debugname;
402 mib[0] = CTL_DEBUG;
403 mib[2] = CTL_DEBUG_NAME;
404 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
405 mib[1] = i;
406 size = BUFSIZ - loc;
407 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
408 continue;
409 debugname[i].ctl_name = &names[loc];
410 debugname[i].ctl_type = CTLTYPE_INT;
411 loc += size;
412 }
413}
414
129fa670
KM
415struct ctlname inetname[] = CTL_IPPROTO_NAMES;
416struct ctlname ipname[] = IPCTL_NAMES;
417struct ctlname icmpname[] = ICMPCTL_NAMES;
5082da2b 418struct ctlname udpname[] = UDPCTL_NAMES;
129fa670
KM
419struct list inetlist = { inetname, IPPROTO_MAXID };
420struct list inetvars[] = {
5082da2b
KM
421 { ipname, IPCTL_MAXID }, /* ip */
422 { icmpname, ICMPCTL_MAXID }, /* icmp */
423 { 0, 0 }, /* igmp */
424 { 0, 0 }, /* ggmp */
425 { 0, 0 },
426 { 0, 0 },
427 { 0, 0 }, /* tcp */
428 { 0, 0 },
429 { 0, 0 }, /* egp */
430 { 0, 0 },
431 { 0, 0 },
432 { 0, 0 },
433 { 0, 0 }, /* pup */
434 { 0, 0 },
435 { 0, 0 },
436 { 0, 0 },
437 { 0, 0 },
438 { udpname, UDPCTL_MAXID }, /* udp */
129fa670
KM
439};
440
441/*
442 * handle internet requests
443 */
444sysctl_inet(string, bufpp, mib, flags, typep)
445 char *string;
446 char **bufpp;
447 int mib[];
448 int flags;
449 int *typep;
450{
451 struct list *lp;
452 int indx;
453
454 if (*bufpp == NULL) {
455 listall(string, &inetlist);
456 return (-1);
457 }
458 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
459 return (-1);
460 mib[2] = indx;
5082da2b 461 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
129fa670
KM
462 lp = &inetvars[indx];
463 else if (!flags)
464 return (-1);
465 else {
466 fprintf(stderr, "%s: no variables defined for this protocol\n",
467 string);
468 return (-1);
469 }
470 if (*bufpp == NULL) {
471 listall(string, lp);
472 return (-1);
473 }
474 if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
475 return (-1);
476 mib[3] = indx;
477 *typep = lp->list[indx].ctl_type;
478 return (4);
33a39b1e
KM
479}
480
481/*
482 * Scan a list of names searching for a particular name.
483 */
484findname(string, level, bufp, namelist)
485 char *string;
486 char *level;
487 char **bufp;
488 struct list *namelist;
489{
490 char *name;
491 int i;
492
493 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
494 fprintf(stderr, "%s: incomplete specification\n", string);
495 return (-1);
496 }
497 for (i = 0; i < namelist->size; i++)
cdbdb4d7
CT
498 if (namelist->list[i].ctl_name != NULL &&
499 strcmp(name, namelist->list[i].ctl_name) == 0)
33a39b1e
KM
500 break;
501 if (i == namelist->size) {
502 fprintf(stderr, "%s level name %s in %s is invalid\n",
503 level, name, string);
504 return (-1);
505 }
506 return (i);
507}
508
509usage()
510{
511
31ac5c9a
KM
512 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
513 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
514 "sysctl [-n] -a", "sysctl [-n] -A");
33a39b1e
KM
515 exit(1);
516}