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