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.3 (Berkeley) 04/01/93"; 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, nflag, 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, lvl1; 58 59 while ((ch = getopt(argc, argv, "Aanw")) != 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 'n': 71 nflag = 1; 72 break; 73 74 case 'w': 75 wflag = 1; 76 break; 77 78 default: 79 usage(); 80 } 81 } 82 argc -= optind; 83 argv += optind; 84 85 if (Aflag || aflag) { 86 for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 87 listall(lvl1); 88 exit(0); 89 } 90 if (argc == 0) 91 usage(); 92 while (argc-- > 0) 93 parse(*argv, 1); 94 exit(0); 95 } 96 97 /* 98 * List all variables known to the system. 99 */ 100 listall(lvl1) 101 int lvl1; 102 { 103 struct list *lp; 104 int lvl2; 105 char *cp, name[BUFSIZ]; 106 107 lp = &secondlevel[lvl1]; 108 if (lp->list == 0) 109 return; 110 strcpy(name, topname[lvl1]); 111 cp = &name[strlen(name)]; 112 *cp++ = '.'; 113 for (lvl2 = 1; lvl2 < lp->size; lvl2++) { 114 strcpy(cp, lp->list[lvl2]); 115 parse(name, Aflag); 116 } 117 } 118 119 /* 120 * Parse a name into a MIB entry. 121 * Lookup and print out the MIB entry if it exists. 122 * Set a new value if requested. 123 */ 124 parse(string, flags) 125 char *string; 126 int flags; 127 { 128 int indx, size; 129 int isclockrate = 0; 130 void *newval = 0; 131 int intval, newsize = 0; 132 struct list top, *lp; 133 int mib[CTL_MAXNAME]; 134 char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 135 136 bufp = buf; 137 snprintf(buf, BUFSIZ, "%s", string); 138 if ((cp = strchr(string, '=')) != NULL) { 139 if (!wflag) { 140 fprintf(stderr, "Must specify -w to set variables\n"); 141 exit(2); 142 } 143 *strchr(buf, '=') = '\0'; 144 *cp++ = '\0'; 145 while (isspace(*cp)) 146 cp++; 147 if (isdigit(*cp)) { 148 intval = atoi(cp); 149 newval = &intval; 150 newsize = sizeof intval; 151 } else { 152 newval = cp; 153 newsize = strlen(cp); 154 } 155 } 156 top.list = topname; 157 top.size = CTL_MAXID; 158 if ((indx = findname(string, "top", &bufp, &top)) == -1) 159 return; 160 mib[0] = indx; 161 lp = &secondlevel[indx]; 162 if (lp->list == 0) { 163 fprintf(stderr, "%s: class is not implemented\n", 164 topname[indx]); 165 return; 166 } 167 if (bufp == NULL) { 168 listall(indx); 169 return; 170 } 171 if ((indx = findname(string, "second", &bufp, lp)) == -1) 172 return; 173 mib[1] = indx; 174 if (bufp) { 175 fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 176 return; 177 } 178 switch (mib[0]) { 179 180 case CTL_KERN: 181 switch (mib[1]) { 182 case KERN_VNODE: 183 case KERN_FILE: 184 if (flags == 0) 185 return; 186 fprintf(stderr, 187 "Use pstat to view %s information\n", string); 188 return; 189 case KERN_PROC: 190 if (flags == 0) 191 return; 192 fprintf(stderr, 193 "Use ps to view %s information\n", string); 194 return; 195 case KERN_CLOCKRATE: 196 isclockrate = 1; 197 break; 198 } 199 break; 200 201 case CTL_HW: 202 break; 203 204 case CTL_VM: 205 if (mib[1] == VM_LOADAVG) { 206 double loads[3]; 207 208 getloadavg(loads, 3); 209 if (!nflag) 210 fprintf(stdout, "%s: ", string); 211 fprintf(stdout, "%.2f %.2f %.2f\n", 212 loads[0], loads[1], loads[2]); 213 return; 214 } 215 if (flags == 0) 216 return; 217 fprintf(stderr, 218 "Use vmstat or systat to view %s information\n", string); 219 return; 220 221 case CTL_NET: 222 if (flags == 0) 223 return; 224 fprintf(stderr, "Use netstat to view %s information\n", string); 225 return; 226 227 case CTL_FS: 228 case CTL_DEBUG: 229 case CTL_MACHDEP: 230 break; 231 232 default: 233 fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 234 return; 235 236 } 237 238 size = BUFSIZ; 239 if (sysctl(mib, 2, buf, &size, newsize ? newval : 0, newsize) == -1) { 240 if (flags == 0) 241 return; 242 switch (errno) { 243 case EOPNOTSUPP: 244 fprintf(stderr, "%s: value is not available\n", string); 245 return; 246 case ENOTDIR: 247 fprintf(stderr, "%s: specification is incomplete\n", 248 string); 249 return; 250 case ENOMEM: 251 fprintf(stderr, "%s: type is unknown to this program\n", 252 string); 253 return; 254 default: 255 perror(string); 256 return; 257 } 258 } 259 if (isclockrate) { 260 struct clockinfo *clkp = (struct clockinfo *)buf; 261 262 if (!nflag) 263 fprintf(stdout, "%s: ", string); 264 fprintf(stdout, 265 "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 266 clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 267 return; 268 } 269 if (size == sizeof(int) && !(isprint(buf[0]) && isprint(buf[1]) && 270 isprint(buf[2]) && isprint(buf[3]))) 271 if (newsize == 0) { 272 if (!nflag) 273 fprintf(stdout, "%s = ", string); 274 fprintf(stdout, "%d\n", *(int *)buf); 275 } else { 276 if (!nflag) 277 fprintf(stdout, "%s: %d -> ", string, 278 *(int *)buf); 279 fprintf(stdout, "%d\n", *(int *)newval); 280 } 281 else 282 if (newsize == 0) { 283 if (!nflag) 284 fprintf(stdout, "%s = ", string); 285 fprintf(stdout, "%s\n", buf); 286 } else { 287 if (!nflag) 288 fprintf(stdout, "%s: %s -> ", string, buf); 289 fprintf(stdout, "%s\n", newval); 290 } 291 return; 292 } 293 294 /* 295 * Scan a list of names searching for a particular name. 296 */ 297 findname(string, level, bufp, namelist) 298 char *string; 299 char *level; 300 char **bufp; 301 struct list *namelist; 302 { 303 char *name; 304 int i; 305 306 if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 307 fprintf(stderr, "%s: incomplete specification\n", string); 308 return (-1); 309 } 310 for (i = 0; i < namelist->size; i++) 311 if (!strcmp(name, namelist->list[i])) 312 break; 313 if (i == namelist->size) { 314 fprintf(stderr, "%s level name %s in %s is invalid\n", 315 level, name, string); 316 return (-1); 317 } 318 return (i); 319 } 320 321 usage() 322 { 323 324 (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n", 325 "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...", 326 "sysctl [-n] -a", "sysctl [-n] -A"); 327 exit(1); 328 } 329