date and time created 93/03/30 23:48:06 by mckusick
[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
15static 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
28char *topname[] = CTL_NAMES;
29char *kernname[] = CTL_KERN_NAMES;
30char *vmname[] = CTL_VM_NAMES;
31char *netname[] = CTL_NET_NAMES;
32char *hwname[] = CTL_HW_NAMES;
33
34struct 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
48int Aflag, aflag, wflag;
49
50int
51main(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 */
95listall()
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 */
120parse(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 */
274findname(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
298usage()
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}