add confSORT_QUEUE_BY_HOST and confBROKEN_SMTP_PEERS
[unix-history] / usr / src / usr.sbin / sysctl / sysctl.c
CommitLineData
33a39b1e 1/*
a42b3e1b
KB
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
33a39b1e
KM
4 *
5 * %sccs.include.redist.c%
6 */
7
8#ifndef lint
a42b3e1b
KB
9static char copyright[] =
10"@(#) Copyright (c) 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
33a39b1e
KM
12#endif /* not lint */
13
14#ifndef lint
a42b3e1b 15static char sccsid[] = "@(#)sysctl.c 8.1 (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>
b04cc8ac 24#include <machine/cpu.h>
3a9dd945 25
129fa670
KM
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>
5082da2b
KM
31#include <netinet/ip_var.h>
32#include <netinet/udp.h>
33#include <netinet/udp_var.h>
3a9dd945 34
33a39b1e 35#include <errno.h>
3a9dd945 36#include <stdio.h>
33a39b1e
KM
37#include <stdlib.h>
38#include <string.h>
33a39b1e 39
129fa670
KM
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;
759ce31c 45struct ctlname username[] = CTL_USER_NAMES;
1fdacbde 46struct ctlname debugname[CTL_DEBUG_MAXID];
b04cc8ac
KM
47#ifdef CTL_MACHDEP_NAMES
48struct ctlname machdepname[] = CTL_MACHDEP_NAMES;
49#endif
1fdacbde 50char names[BUFSIZ];
33a39b1e
KM
51
52struct list {
129fa670 53 struct ctlname *list;
33a39b1e 54 int size;
129fa670
KM
55};
56struct list toplist = { topname, CTL_MAXID };
57struct list secondlevel[] = {
33a39b1e
KM
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 */
1fdacbde 63 { 0, CTL_DEBUG_MAXID }, /* CTL_DEBUG */
33a39b1e 64 { hwname, HW_MAXID }, /* CTL_HW */
b04cc8ac
KM
65#ifdef CTL_MACHDEP_NAMES
66 { machdepname, CPU_MAXID }, /* CTL_MACHDEP */
67#else
33a39b1e 68 { 0, 0 }, /* CTL_MACHDEP */
b04cc8ac 69#endif
759ce31c 70 { username, USER_MAXID }, /* CTL_USER_NAMES */
33a39b1e
KM
71};
72
18ca9a3c 73int Aflag, aflag, nflag, wflag;
33a39b1e 74
b04cc8ac
KM
75/*
76 * Variables requiring special processing.
77 */
78#define CLOCK 0x00000001
79#define BOOTTIME 0x00000002
80#define CONSDEV 0x00000004
81
33a39b1e
KM
82int
83main(argc, argv)
84 int argc;
85 char *argv[];
86{
87 extern char *optarg;
88 extern int optind;
18ca9a3c 89 int ch, lvl1;
33a39b1e 90
18ca9a3c 91 while ((ch = getopt(argc, argv, "Aanw")) != EOF) {
33a39b1e
KM
92 switch (ch) {
93
94 case 'A':
95 Aflag = 1;
96 break;
97
98 case 'a':
99 aflag = 1;
100 break;
101
18ca9a3c
KM
102 case 'n':
103 nflag = 1;
104 break;
105
33a39b1e
KM
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) {
1fdacbde 118 debuginit();
18ca9a3c 119 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
129fa670 120 listall(topname[lvl1].ctl_name, &secondlevel[lvl1]);
33a39b1e
KM
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 */
129fa670
KM
133listall(prefix, lp)
134 char *prefix;
33a39b1e 135 struct list *lp;
129fa670 136{
18ca9a3c 137 int lvl2;
33a39b1e
KM
138 char *cp, name[BUFSIZ];
139
18ca9a3c
KM
140 if (lp->list == 0)
141 return;
129fa670 142 strcpy(name, prefix);
18ca9a3c
KM
143 cp = &name[strlen(name)];
144 *cp++ = '.';
129fa670
KM
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);
18ca9a3c 149 parse(name, Aflag);
33a39b1e
KM
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{
629efb73 162 int indx, type, state, size, len;
b04cc8ac 163 int special = 0;
33a39b1e
KM
164 void *newval = 0;
165 int intval, newsize = 0;
129fa670
KM
166 quad_t quadval;
167 struct list *lp;
33a39b1e
KM
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++;
129fa670
KM
182 newval = cp;
183 newsize = strlen(cp);
33a39b1e 184 }
129fa670 185 if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
33a39b1e
KM
186 return;
187 mib[0] = indx;
1fdacbde
KM
188 if (indx == CTL_DEBUG)
189 debuginit();
33a39b1e
KM
190 lp = &secondlevel[indx];
191 if (lp->list == 0) {
192 fprintf(stderr, "%s: class is not implemented\n",
193 topname[indx]);
194 return;
195 }
18ca9a3c 196 if (bufp == NULL) {
129fa670 197 listall(topname[indx].ctl_name, lp);
18ca9a3c
KM
198 return;
199 }
33a39b1e
KM
200 if ((indx = findname(string, "second", &bufp, lp)) == -1)
201 return;
202 mib[1] = indx;
129fa670
KM
203 type = lp->list[indx].ctl_type;
204 len = 2;
33a39b1e
KM
205 switch (mib[0]) {
206
207 case CTL_KERN:
208 switch (mib[1]) {
629efb73
KM
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;
33a39b1e
KM
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:
b04cc8ac 239 special |= CLOCK;
33a39b1e 240 break;
3c56a5f8 241 case KERN_BOOTTIME:
b04cc8ac 242 special |= BOOTTIME;
3c56a5f8 243 break;
33a39b1e
KM
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);
18ca9a3c
KM
255 if (!nflag)
256 fprintf(stdout, "%s: ", string);
257 fprintf(stdout, "%.2f %.2f %.2f\n",
33a39b1e
KM
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:
129fa670
KM
268 if (mib[1] == PF_INET) {
269 len = sysctl_inet(string, &bufp, mib, flags, &type);
270 if (len >= 0)
271 break;
272 return;
273 }
33a39b1e
KM
274 if (flags == 0)
275 return;
276 fprintf(stderr, "Use netstat to view %s information\n", string);
277 return;
278
33a39b1e 279 case CTL_DEBUG:
1fdacbde
KM
280 mib[2] = CTL_DEBUG_VALUE;
281 len = 3;
282 break;
283
33a39b1e 284 case CTL_MACHDEP:
b04cc8ac
KM
285#ifdef CPU_CONSDEV
286 if (mib[1] == CPU_CONSDEV)
287 special |= CONSDEV;
288#endif
289 break;
290
291 case CTL_FS:
759ce31c 292 case CTL_USER:
33a39b1e
KM
293 break;
294
295 default:
296 fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
297 return;
298
299 }
129fa670
KM
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;
33a39b1e 311
129fa670
KM
312 case CTLTYPE_QUAD:
313 sscanf(newval, "%qd", &quadval);
314 newval = &quadval;
315 newsize = sizeof quadval;
316 break;
317 }
318 }
33a39b1e 319 size = BUFSIZ;
129fa670 320 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
33a39b1e
KM
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 }
b04cc8ac 340 if (special & CLOCK) {
33a39b1e
KM
341 struct clockinfo *clkp = (struct clockinfo *)buf;
342
18ca9a3c
KM
343 if (!nflag)
344 fprintf(stdout, "%s: ", string);
33a39b1e 345 fprintf(stdout,
18ca9a3c
KM
346 "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
347 clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
33a39b1e
KM
348 return;
349 }
b04cc8ac 350 if (special & BOOTTIME) {
3c56a5f8
KM
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 }
b04cc8ac
KM
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 }
129fa670
KM
370 switch (type) {
371 case CTLTYPE_INT:
18ca9a3c
KM
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 }
129fa670
KM
382 return;
383
384 case CTLTYPE_STRING:
18ca9a3c
KM
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 }
129fa670
KM
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
1fdacbde
KM
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
129fa670
KM
445struct ctlname inetname[] = CTL_IPPROTO_NAMES;
446struct ctlname ipname[] = IPCTL_NAMES;
447struct ctlname icmpname[] = ICMPCTL_NAMES;
5082da2b 448struct ctlname udpname[] = UDPCTL_NAMES;
129fa670
KM
449struct list inetlist = { inetname, IPPROTO_MAXID };
450struct list inetvars[] = {
5082da2b
KM
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 */
129fa670
KM
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;
5082da2b 491 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
129fa670
KM
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);
33a39b1e
KM
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++)
cdbdb4d7
CT
528 if (namelist->list[i].ctl_name != NULL &&
529 strcmp(name, namelist->list[i].ctl_name) == 0)
33a39b1e
KM
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
31ac5c9a
KM
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");
33a39b1e
KM
545 exit(1);
546}