Commit | Line | Data |
---|---|---|
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 | |
9 | char 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 | |
15 | static char sccsid[] = "@(#)sysctl.c 5.1 (Berkeley) %G%"; | |
16 | #endif /* not lint */ | |
17 | ||
18 | #include <sys/types.h> | |
19 | #include <sys/stat.h> | |
20 | #include <sys/sysctl.h> | |
21 | #include <sys/socket.h> | |
22 | #include <vm/vm_param.h> | |
23 | #include <errno.h> | |
24 | #include <stdlib.h> | |
25 | #include <string.h> | |
26 | #include <stdio.h> | |
27 | ||
28 | char *topname[] = CTL_NAMES; | |
29 | char *kernname[] = CTL_KERN_NAMES; | |
30 | char *vmname[] = CTL_VM_NAMES; | |
31 | char *netname[] = CTL_NET_NAMES; | |
32 | char *hwname[] = CTL_HW_NAMES; | |
33 | ||
34 | struct list { | |
35 | char **list; | |
36 | int size; | |
37 | } secondlevel[] = { | |
38 | { 0, 0 }, /* CTL_UNSPEC */ | |
39 | { kernname, KERN_MAXID }, /* CTL_KERN */ | |
40 | { vmname, VM_MAXID }, /* CTL_VM */ | |
41 | { 0, 0 }, /* CTL_FS */ | |
42 | { netname, NET_MAXID }, /* CTL_NET */ | |
43 | { 0, 0 }, /* CTL_DEBUG */ | |
44 | { hwname, HW_MAXID }, /* CTL_HW */ | |
45 | { 0, 0 }, /* CTL_MACHDEP */ | |
46 | }; | |
47 | ||
48 | int Aflag, aflag, wflag; | |
49 | ||
50 | int | |
51 | main(argc, argv) | |
52 | int argc; | |
53 | char *argv[]; | |
54 | { | |
55 | extern char *optarg; | |
56 | extern int optind; | |
57 | int ch; | |
58 | ||
59 | while ((ch = getopt(argc, argv, "Aaw")) != EOF) { | |
60 | switch (ch) { | |
61 | ||
62 | case 'A': | |
63 | Aflag = 1; | |
64 | break; | |
65 | ||
66 | case 'a': | |
67 | aflag = 1; | |
68 | break; | |
69 | ||
70 | case 'w': | |
71 | wflag = 1; | |
72 | break; | |
73 | ||
74 | default: | |
75 | usage(); | |
76 | } | |
77 | } | |
78 | argc -= optind; | |
79 | argv += optind; | |
80 | ||
81 | if (Aflag || aflag) { | |
82 | listall(); | |
83 | exit(0); | |
84 | } | |
85 | if (argc == 0) | |
86 | usage(); | |
87 | while (argc-- > 0) | |
88 | parse(*argv, 1); | |
89 | exit(0); | |
90 | } | |
91 | ||
92 | /* | |
93 | * List all variables known to the system. | |
94 | */ | |
95 | listall() | |
96 | { | |
97 | struct list *lp; | |
98 | int lvl1, lvl2; | |
99 | char *cp, name[BUFSIZ]; | |
100 | ||
101 | for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) { | |
102 | lp = &secondlevel[lvl1]; | |
103 | if (lp->list == 0) | |
104 | continue; | |
105 | strcpy(name, topname[lvl1]); | |
106 | cp = &name[strlen(name)]; | |
107 | *cp++ = '.'; | |
108 | for (lvl2 = 1; lvl2 < lp->size; lvl2++) { | |
109 | strcpy(cp, lp->list[lvl2]); | |
110 | parse(name, Aflag); | |
111 | } | |
112 | } | |
113 | } | |
114 | ||
115 | /* | |
116 | * Parse a name into a MIB entry. | |
117 | * Lookup and print out the MIB entry if it exists. | |
118 | * Set a new value if requested. | |
119 | */ | |
120 | parse(string, flags) | |
121 | char *string; | |
122 | int flags; | |
123 | { | |
124 | int indx, size; | |
125 | int isclockrate = 0; | |
126 | void *newval = 0; | |
127 | int intval, newsize = 0; | |
128 | struct list top, *lp; | |
129 | int mib[CTL_MAXNAME]; | |
130 | char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; | |
131 | ||
132 | bufp = buf; | |
133 | snprintf(buf, BUFSIZ, "%s", string); | |
134 | if ((cp = strchr(string, '=')) != NULL) { | |
135 | if (!wflag) { | |
136 | fprintf(stderr, "Must specify -w to set variables\n"); | |
137 | exit(2); | |
138 | } | |
139 | *strchr(buf, '=') = '\0'; | |
140 | *cp++ = '\0'; | |
141 | while (isspace(*cp)) | |
142 | cp++; | |
143 | if (isdigit(*cp)) { | |
144 | intval = atoi(cp); | |
145 | newval = &intval; | |
146 | newsize = sizeof intval; | |
147 | } else { | |
148 | newval = cp; | |
149 | newsize = strlen(cp); | |
150 | } | |
151 | } | |
152 | top.list = topname; | |
153 | top.size = CTL_MAXID; | |
154 | if ((indx = findname(string, "top", &bufp, &top)) == -1) | |
155 | return; | |
156 | mib[0] = indx; | |
157 | lp = &secondlevel[indx]; | |
158 | if (lp->list == 0) { | |
159 | fprintf(stderr, "%s: class is not implemented\n", | |
160 | topname[indx]); | |
161 | return; | |
162 | } | |
163 | if ((indx = findname(string, "second", &bufp, lp)) == -1) | |
164 | return; | |
165 | mib[1] = indx; | |
166 | if (bufp) { | |
167 | fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); | |
168 | return; | |
169 | } | |
170 | switch (mib[0]) { | |
171 | ||
172 | case CTL_KERN: | |
173 | switch (mib[1]) { | |
174 | case KERN_VNODE: | |
175 | case KERN_FILE: | |
176 | if (flags == 0) | |
177 | return; | |
178 | fprintf(stderr, | |
179 | "Use pstat to view %s information\n", string); | |
180 | return; | |
181 | case KERN_PROC: | |
182 | if (flags == 0) | |
183 | return; | |
184 | fprintf(stderr, | |
185 | "Use ps to view %s information\n", string); | |
186 | return; | |
187 | case KERN_CLOCKRATE: | |
188 | isclockrate = 1; | |
189 | break; | |
190 | } | |
191 | break; | |
192 | ||
193 | case CTL_HW: | |
194 | break; | |
195 | ||
196 | case CTL_VM: | |
197 | if (mib[1] == VM_LOADAVG) { | |
198 | double loads[3]; | |
199 | ||
200 | getloadavg(loads, 3); | |
201 | fprintf(stdout, "%s: %.2f %.2f %.2f\n", string, | |
202 | loads[0], loads[1], loads[2]); | |
203 | return; | |
204 | } | |
205 | if (flags == 0) | |
206 | return; | |
207 | fprintf(stderr, | |
208 | "Use vmstat or systat to view %s information\n", string); | |
209 | return; | |
210 | ||
211 | case CTL_NET: | |
212 | if (flags == 0) | |
213 | return; | |
214 | fprintf(stderr, "Use netstat to view %s information\n", string); | |
215 | return; | |
216 | ||
217 | case CTL_FS: | |
218 | case CTL_DEBUG: | |
219 | case CTL_MACHDEP: | |
220 | break; | |
221 | ||
222 | default: | |
223 | fprintf(stderr, "Illegal top level value: %d\n", mib[0]); | |
224 | return; | |
225 | ||
226 | } | |
227 | ||
228 | size = BUFSIZ; | |
229 | if (sysctl(mib, 2, buf, &size, newsize ? newval : 0, newsize) == -1) { | |
230 | if (flags == 0) | |
231 | return; | |
232 | switch (errno) { | |
233 | case EOPNOTSUPP: | |
234 | fprintf(stderr, "%s: value is not available\n", string); | |
235 | return; | |
236 | case ENOTDIR: | |
237 | fprintf(stderr, "%s: specification is incomplete\n", | |
238 | string); | |
239 | return; | |
240 | case ENOMEM: | |
241 | fprintf(stderr, "%s: type is unknown to this program\n", | |
242 | string); | |
243 | return; | |
244 | default: | |
245 | perror(string); | |
246 | return; | |
247 | } | |
248 | } | |
249 | if (isclockrate) { | |
250 | struct clockinfo *clkp = (struct clockinfo *)buf; | |
251 | ||
252 | fprintf(stdout, | |
253 | "%s: hz = %d, tick = %d, profhz = %d, stathz = %d\n", | |
254 | string, clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); | |
255 | return; | |
256 | } | |
257 | if (size == sizeof(int) && !isprint(buf[0])) | |
258 | if (newsize == 0) | |
259 | fprintf(stdout, "%s = %d\n", string, *(int *)buf); | |
260 | else | |
261 | fprintf(stdout, "%s: %d -> %d\n", string, *(int *)buf, | |
262 | *(int *)newval); | |
263 | else | |
264 | if (newsize == 0) | |
265 | fprintf(stdout, "%s = %s\n", string, buf); | |
266 | else | |
267 | fprintf(stdout, "%s: %s -> %s\n", string, buf, newval); | |
268 | return; | |
269 | } | |
270 | ||
271 | /* | |
272 | * Scan a list of names searching for a particular name. | |
273 | */ | |
274 | findname(string, level, bufp, namelist) | |
275 | char *string; | |
276 | char *level; | |
277 | char **bufp; | |
278 | struct list *namelist; | |
279 | { | |
280 | char *name; | |
281 | int i; | |
282 | ||
283 | if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { | |
284 | fprintf(stderr, "%s: incomplete specification\n", string); | |
285 | return (-1); | |
286 | } | |
287 | for (i = 0; i < namelist->size; i++) | |
288 | if (!strcmp(name, namelist->list[i])) | |
289 | break; | |
290 | if (i == namelist->size) { | |
291 | fprintf(stderr, "%s level name %s in %s is invalid\n", | |
292 | level, name, string); | |
293 | return (-1); | |
294 | } | |
295 | return (i); | |
296 | } | |
297 | ||
298 | usage() | |
299 | { | |
300 | ||
301 | (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n", | |
302 | "sysctl [-w] variable ...", "sysctl -a", "sysctl -A"); | |
303 | exit(1); | |
304 | } |