add CTL_USER
[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
759ce31c 15static char sccsid[] = "@(#)sysctl.c 5.10 (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
KM
148 int isclockrate = 0;
149 void *newval = 0;
150 int intval, newsize = 0;
129fa670
KM
151 quad_t quadval;
152 struct list *lp;
33a39b1e
KM
153 int mib[CTL_MAXNAME];
154 char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ];
155
156 bufp = buf;
157 snprintf(buf, BUFSIZ, "%s", string);
158 if ((cp = strchr(string, '=')) != NULL) {
159 if (!wflag) {
160 fprintf(stderr, "Must specify -w to set variables\n");
161 exit(2);
162 }
163 *strchr(buf, '=') = '\0';
164 *cp++ = '\0';
165 while (isspace(*cp))
166 cp++;
129fa670
KM
167 newval = cp;
168 newsize = strlen(cp);
33a39b1e 169 }
129fa670 170 if ((indx = findname(string, "top", &bufp, &toplist)) == -1)
33a39b1e
KM
171 return;
172 mib[0] = indx;
1fdacbde
KM
173 if (indx == CTL_DEBUG)
174 debuginit();
33a39b1e
KM
175 lp = &secondlevel[indx];
176 if (lp->list == 0) {
177 fprintf(stderr, "%s: class is not implemented\n",
178 topname[indx]);
179 return;
180 }
18ca9a3c 181 if (bufp == NULL) {
129fa670 182 listall(topname[indx].ctl_name, lp);
18ca9a3c
KM
183 return;
184 }
33a39b1e
KM
185 if ((indx = findname(string, "second", &bufp, lp)) == -1)
186 return;
187 mib[1] = indx;
129fa670
KM
188 type = lp->list[indx].ctl_type;
189 len = 2;
33a39b1e
KM
190 switch (mib[0]) {
191
192 case CTL_KERN:
193 switch (mib[1]) {
629efb73
KM
194 case KERN_PROF:
195 mib[2] = GPROF_STATE;
196 size = sizeof state;
197 if (sysctl(mib, 3, &state, &size, NULL, 0) < 0) {
198 if (flags == 0)
199 return;
200 if (!nflag)
201 fprintf(stdout, "%s: ", string);
202 fprintf(stderr,
203 "kernel is not compiled for profiling\n");
204 return;
205 }
206 if (!nflag)
207 fprintf(stdout, "%s: %s\n", string,
208 state == GMON_PROF_OFF ? "off" : "running");
209 return;
33a39b1e
KM
210 case KERN_VNODE:
211 case KERN_FILE:
212 if (flags == 0)
213 return;
214 fprintf(stderr,
215 "Use pstat to view %s information\n", string);
216 return;
217 case KERN_PROC:
218 if (flags == 0)
219 return;
220 fprintf(stderr,
221 "Use ps to view %s information\n", string);
222 return;
223 case KERN_CLOCKRATE:
224 isclockrate = 1;
225 break;
226 }
227 break;
228
229 case CTL_HW:
230 break;
231
232 case CTL_VM:
233 if (mib[1] == VM_LOADAVG) {
234 double loads[3];
235
236 getloadavg(loads, 3);
18ca9a3c
KM
237 if (!nflag)
238 fprintf(stdout, "%s: ", string);
239 fprintf(stdout, "%.2f %.2f %.2f\n",
33a39b1e
KM
240 loads[0], loads[1], loads[2]);
241 return;
242 }
243 if (flags == 0)
244 return;
245 fprintf(stderr,
246 "Use vmstat or systat to view %s information\n", string);
247 return;
248
249 case CTL_NET:
129fa670
KM
250 if (mib[1] == PF_INET) {
251 len = sysctl_inet(string, &bufp, mib, flags, &type);
252 if (len >= 0)
253 break;
254 return;
255 }
33a39b1e
KM
256 if (flags == 0)
257 return;
258 fprintf(stderr, "Use netstat to view %s information\n", string);
259 return;
260
33a39b1e 261 case CTL_DEBUG:
1fdacbde
KM
262 mib[2] = CTL_DEBUG_VALUE;
263 len = 3;
264 break;
265
266 case CTL_FS:
33a39b1e 267 case CTL_MACHDEP:
759ce31c 268 case CTL_USER:
33a39b1e
KM
269 break;
270
271 default:
272 fprintf(stderr, "Illegal top level value: %d\n", mib[0]);
273 return;
274
275 }
129fa670
KM
276 if (bufp) {
277 fprintf(stderr, "name %s in %s is unknown\n", *bufp, string);
278 return;
279 }
280 if (newsize > 0) {
281 switch (type) {
282 case CTLTYPE_INT:
283 intval = atoi(newval);
284 newval = &intval;
285 newsize = sizeof intval;
286 break;
33a39b1e 287
129fa670
KM
288 case CTLTYPE_QUAD:
289 sscanf(newval, "%qd", &quadval);
290 newval = &quadval;
291 newsize = sizeof quadval;
292 break;
293 }
294 }
33a39b1e 295 size = BUFSIZ;
129fa670 296 if (sysctl(mib, len, buf, &size, newsize ? newval : 0, newsize) == -1) {
33a39b1e
KM
297 if (flags == 0)
298 return;
299 switch (errno) {
300 case EOPNOTSUPP:
301 fprintf(stderr, "%s: value is not available\n", string);
302 return;
303 case ENOTDIR:
304 fprintf(stderr, "%s: specification is incomplete\n",
305 string);
306 return;
307 case ENOMEM:
308 fprintf(stderr, "%s: type is unknown to this program\n",
309 string);
310 return;
311 default:
312 perror(string);
313 return;
314 }
315 }
316 if (isclockrate) {
317 struct clockinfo *clkp = (struct clockinfo *)buf;
318
18ca9a3c
KM
319 if (!nflag)
320 fprintf(stdout, "%s: ", string);
33a39b1e 321 fprintf(stdout,
18ca9a3c
KM
322 "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
323 clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
33a39b1e
KM
324 return;
325 }
129fa670
KM
326 switch (type) {
327 case CTLTYPE_INT:
18ca9a3c
KM
328 if (newsize == 0) {
329 if (!nflag)
330 fprintf(stdout, "%s = ", string);
331 fprintf(stdout, "%d\n", *(int *)buf);
332 } else {
333 if (!nflag)
334 fprintf(stdout, "%s: %d -> ", string,
335 *(int *)buf);
336 fprintf(stdout, "%d\n", *(int *)newval);
337 }
129fa670
KM
338 return;
339
340 case CTLTYPE_STRING:
18ca9a3c
KM
341 if (newsize == 0) {
342 if (!nflag)
343 fprintf(stdout, "%s = ", string);
344 fprintf(stdout, "%s\n", buf);
345 } else {
346 if (!nflag)
347 fprintf(stdout, "%s: %s -> ", string, buf);
348 fprintf(stdout, "%s\n", newval);
349 }
129fa670
KM
350 return;
351
352 case CTLTYPE_QUAD:
353 if (newsize == 0) {
354 if (!nflag)
355 fprintf(stdout, "%s = ", string);
356 fprintf(stdout, "%qd\n", *(quad_t *)buf);
357 } else {
358 if (!nflag)
359 fprintf(stdout, "%s: %qd -> ", string,
360 *(quad_t *)buf);
361 fprintf(stdout, "%qd\n", *(quad_t *)newval);
362 }
363 return;
364
365 case CTLTYPE_STRUCT:
366 fprintf(stderr, "%s: unknown structure returned\n",
367 string);
368 return;
369
370 default:
371 case CTLTYPE_NODE:
372 fprintf(stderr, "%s: unknown type returned\n",
373 string);
374 return;
375 }
376}
377
1fdacbde
KM
378/*
379 * Initialize the set of debugging names
380 */
381debuginit()
382{
383 int mib[3], size, loc, i;
384
385 if (secondlevel[CTL_DEBUG].list != 0)
386 return;
387 secondlevel[CTL_DEBUG].list = debugname;
388 mib[0] = CTL_DEBUG;
389 mib[2] = CTL_DEBUG_NAME;
390 for (loc = 0, i = 0; i < CTL_DEBUG_MAXID; i++) {
391 mib[1] = i;
392 size = BUFSIZ - loc;
393 if (sysctl(mib, 3, &names[loc], &size, NULL, 0) == -1)
394 continue;
395 debugname[i].ctl_name = &names[loc];
396 debugname[i].ctl_type = CTLTYPE_INT;
397 loc += size;
398 }
399}
400
129fa670
KM
401struct ctlname inetname[] = CTL_IPPROTO_NAMES;
402struct ctlname ipname[] = IPCTL_NAMES;
403struct ctlname icmpname[] = ICMPCTL_NAMES;
5082da2b 404struct ctlname udpname[] = UDPCTL_NAMES;
129fa670
KM
405struct list inetlist = { inetname, IPPROTO_MAXID };
406struct list inetvars[] = {
5082da2b
KM
407 { ipname, IPCTL_MAXID }, /* ip */
408 { icmpname, ICMPCTL_MAXID }, /* icmp */
409 { 0, 0 }, /* igmp */
410 { 0, 0 }, /* ggmp */
411 { 0, 0 },
412 { 0, 0 },
413 { 0, 0 }, /* tcp */
414 { 0, 0 },
415 { 0, 0 }, /* egp */
416 { 0, 0 },
417 { 0, 0 },
418 { 0, 0 },
419 { 0, 0 }, /* pup */
420 { 0, 0 },
421 { 0, 0 },
422 { 0, 0 },
423 { 0, 0 },
424 { udpname, UDPCTL_MAXID }, /* udp */
129fa670
KM
425};
426
427/*
428 * handle internet requests
429 */
430sysctl_inet(string, bufpp, mib, flags, typep)
431 char *string;
432 char **bufpp;
433 int mib[];
434 int flags;
435 int *typep;
436{
437 struct list *lp;
438 int indx;
439
440 if (*bufpp == NULL) {
441 listall(string, &inetlist);
442 return (-1);
443 }
444 if ((indx = findname(string, "third", bufpp, &inetlist)) == -1)
445 return (-1);
446 mib[2] = indx;
5082da2b 447 if (indx <= IPPROTO_UDP && inetvars[indx].list != NULL)
129fa670
KM
448 lp = &inetvars[indx];
449 else if (!flags)
450 return (-1);
451 else {
452 fprintf(stderr, "%s: no variables defined for this protocol\n",
453 string);
454 return (-1);
455 }
456 if (*bufpp == NULL) {
457 listall(string, lp);
458 return (-1);
459 }
460 if ((indx = findname(string, "fourth", bufpp, lp)) == -1)
461 return (-1);
462 mib[3] = indx;
463 *typep = lp->list[indx].ctl_type;
464 return (4);
33a39b1e
KM
465}
466
467/*
468 * Scan a list of names searching for a particular name.
469 */
470findname(string, level, bufp, namelist)
471 char *string;
472 char *level;
473 char **bufp;
474 struct list *namelist;
475{
476 char *name;
477 int i;
478
479 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) {
480 fprintf(stderr, "%s: incomplete specification\n", string);
481 return (-1);
482 }
483 for (i = 0; i < namelist->size; i++)
cdbdb4d7
CT
484 if (namelist->list[i].ctl_name != NULL &&
485 strcmp(name, namelist->list[i].ctl_name) == 0)
33a39b1e
KM
486 break;
487 if (i == namelist->size) {
488 fprintf(stderr, "%s level name %s in %s is invalid\n",
489 level, name, string);
490 return (-1);
491 }
492 return (i);
493}
494
495usage()
496{
497
31ac5c9a
KM
498 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
499 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
500 "sysctl [-n] -a", "sysctl [-n] -A");
33a39b1e
KM
501 exit(1);
502}