158888Smckusick /* 258888Smckusick * Copyright (c) 1993 The Regents of the University of California. 358888Smckusick * All rights reserved. 458888Smckusick * 558888Smckusick * %sccs.include.redist.c% 658888Smckusick */ 758888Smckusick 858888Smckusick #ifndef lint 958888Smckusick char copyright[] = 1058888Smckusick "@(#) Copyright (c) 1993 The Regents of the University of California.\n\ 1158888Smckusick All rights reserved.\n"; 1258888Smckusick #endif /* not lint */ 1358888Smckusick 1458888Smckusick #ifndef lint 15*58910Smckusick static char sccsid[] = "@(#)sysctl.c 5.2 (Berkeley) 04/01/93"; 1658888Smckusick #endif /* not lint */ 1758888Smckusick 1858888Smckusick #include <sys/types.h> 1958888Smckusick #include <sys/stat.h> 2058888Smckusick #include <sys/sysctl.h> 2158888Smckusick #include <sys/socket.h> 2258888Smckusick #include <vm/vm_param.h> 2358888Smckusick #include <errno.h> 2458888Smckusick #include <stdlib.h> 2558888Smckusick #include <string.h> 2658888Smckusick #include <stdio.h> 2758888Smckusick 2858888Smckusick char *topname[] = CTL_NAMES; 2958888Smckusick char *kernname[] = CTL_KERN_NAMES; 3058888Smckusick char *vmname[] = CTL_VM_NAMES; 3158888Smckusick char *netname[] = CTL_NET_NAMES; 3258888Smckusick char *hwname[] = CTL_HW_NAMES; 3358888Smckusick 3458888Smckusick struct list { 3558888Smckusick char **list; 3658888Smckusick int size; 3758888Smckusick } secondlevel[] = { 3858888Smckusick { 0, 0 }, /* CTL_UNSPEC */ 3958888Smckusick { kernname, KERN_MAXID }, /* CTL_KERN */ 4058888Smckusick { vmname, VM_MAXID }, /* CTL_VM */ 4158888Smckusick { 0, 0 }, /* CTL_FS */ 4258888Smckusick { netname, NET_MAXID }, /* CTL_NET */ 4358888Smckusick { 0, 0 }, /* CTL_DEBUG */ 4458888Smckusick { hwname, HW_MAXID }, /* CTL_HW */ 4558888Smckusick { 0, 0 }, /* CTL_MACHDEP */ 4658888Smckusick }; 4758888Smckusick 48*58910Smckusick int Aflag, aflag, nflag, wflag; 4958888Smckusick 5058888Smckusick int 5158888Smckusick main(argc, argv) 5258888Smckusick int argc; 5358888Smckusick char *argv[]; 5458888Smckusick { 5558888Smckusick extern char *optarg; 5658888Smckusick extern int optind; 57*58910Smckusick int ch, lvl1; 5858888Smckusick 59*58910Smckusick while ((ch = getopt(argc, argv, "Aanw")) != EOF) { 6058888Smckusick switch (ch) { 6158888Smckusick 6258888Smckusick case 'A': 6358888Smckusick Aflag = 1; 6458888Smckusick break; 6558888Smckusick 6658888Smckusick case 'a': 6758888Smckusick aflag = 1; 6858888Smckusick break; 6958888Smckusick 70*58910Smckusick case 'n': 71*58910Smckusick nflag = 1; 72*58910Smckusick break; 73*58910Smckusick 7458888Smckusick case 'w': 7558888Smckusick wflag = 1; 7658888Smckusick break; 7758888Smckusick 7858888Smckusick default: 7958888Smckusick usage(); 8058888Smckusick } 8158888Smckusick } 8258888Smckusick argc -= optind; 8358888Smckusick argv += optind; 8458888Smckusick 8558888Smckusick if (Aflag || aflag) { 86*58910Smckusick for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++) 87*58910Smckusick listall(lvl1); 8858888Smckusick exit(0); 8958888Smckusick } 9058888Smckusick if (argc == 0) 9158888Smckusick usage(); 9258888Smckusick while (argc-- > 0) 9358888Smckusick parse(*argv, 1); 9458888Smckusick exit(0); 9558888Smckusick } 9658888Smckusick 9758888Smckusick /* 9858888Smckusick * List all variables known to the system. 9958888Smckusick */ 100*58910Smckusick listall(lvl1) 101*58910Smckusick int lvl1; 10258888Smckusick { 10358888Smckusick struct list *lp; 104*58910Smckusick int lvl2; 10558888Smckusick char *cp, name[BUFSIZ]; 10658888Smckusick 107*58910Smckusick lp = &secondlevel[lvl1]; 108*58910Smckusick if (lp->list == 0) 109*58910Smckusick return; 110*58910Smckusick strcpy(name, topname[lvl1]); 111*58910Smckusick cp = &name[strlen(name)]; 112*58910Smckusick *cp++ = '.'; 113*58910Smckusick for (lvl2 = 1; lvl2 < lp->size; lvl2++) { 114*58910Smckusick strcpy(cp, lp->list[lvl2]); 115*58910Smckusick parse(name, Aflag); 11658888Smckusick } 11758888Smckusick } 11858888Smckusick 11958888Smckusick /* 12058888Smckusick * Parse a name into a MIB entry. 12158888Smckusick * Lookup and print out the MIB entry if it exists. 12258888Smckusick * Set a new value if requested. 12358888Smckusick */ 12458888Smckusick parse(string, flags) 12558888Smckusick char *string; 12658888Smckusick int flags; 12758888Smckusick { 12858888Smckusick int indx, size; 12958888Smckusick int isclockrate = 0; 13058888Smckusick void *newval = 0; 13158888Smckusick int intval, newsize = 0; 13258888Smckusick struct list top, *lp; 13358888Smckusick int mib[CTL_MAXNAME]; 13458888Smckusick char *cp, *bufp, buf[BUFSIZ], strval[BUFSIZ]; 13558888Smckusick 13658888Smckusick bufp = buf; 13758888Smckusick snprintf(buf, BUFSIZ, "%s", string); 13858888Smckusick if ((cp = strchr(string, '=')) != NULL) { 13958888Smckusick if (!wflag) { 14058888Smckusick fprintf(stderr, "Must specify -w to set variables\n"); 14158888Smckusick exit(2); 14258888Smckusick } 14358888Smckusick *strchr(buf, '=') = '\0'; 14458888Smckusick *cp++ = '\0'; 14558888Smckusick while (isspace(*cp)) 14658888Smckusick cp++; 14758888Smckusick if (isdigit(*cp)) { 14858888Smckusick intval = atoi(cp); 14958888Smckusick newval = &intval; 15058888Smckusick newsize = sizeof intval; 15158888Smckusick } else { 15258888Smckusick newval = cp; 15358888Smckusick newsize = strlen(cp); 15458888Smckusick } 15558888Smckusick } 15658888Smckusick top.list = topname; 15758888Smckusick top.size = CTL_MAXID; 15858888Smckusick if ((indx = findname(string, "top", &bufp, &top)) == -1) 15958888Smckusick return; 16058888Smckusick mib[0] = indx; 16158888Smckusick lp = &secondlevel[indx]; 16258888Smckusick if (lp->list == 0) { 16358888Smckusick fprintf(stderr, "%s: class is not implemented\n", 16458888Smckusick topname[indx]); 16558888Smckusick return; 16658888Smckusick } 167*58910Smckusick if (bufp == NULL) { 168*58910Smckusick listall(indx); 169*58910Smckusick return; 170*58910Smckusick } 17158888Smckusick if ((indx = findname(string, "second", &bufp, lp)) == -1) 17258888Smckusick return; 17358888Smckusick mib[1] = indx; 17458888Smckusick if (bufp) { 17558888Smckusick fprintf(stderr, "name %s in %s is unknown\n", *bufp, string); 17658888Smckusick return; 17758888Smckusick } 17858888Smckusick switch (mib[0]) { 17958888Smckusick 18058888Smckusick case CTL_KERN: 18158888Smckusick switch (mib[1]) { 18258888Smckusick case KERN_VNODE: 18358888Smckusick case KERN_FILE: 18458888Smckusick if (flags == 0) 18558888Smckusick return; 18658888Smckusick fprintf(stderr, 18758888Smckusick "Use pstat to view %s information\n", string); 18858888Smckusick return; 18958888Smckusick case KERN_PROC: 19058888Smckusick if (flags == 0) 19158888Smckusick return; 19258888Smckusick fprintf(stderr, 19358888Smckusick "Use ps to view %s information\n", string); 19458888Smckusick return; 19558888Smckusick case KERN_CLOCKRATE: 19658888Smckusick isclockrate = 1; 19758888Smckusick break; 19858888Smckusick } 19958888Smckusick break; 20058888Smckusick 20158888Smckusick case CTL_HW: 20258888Smckusick break; 20358888Smckusick 20458888Smckusick case CTL_VM: 20558888Smckusick if (mib[1] == VM_LOADAVG) { 20658888Smckusick double loads[3]; 20758888Smckusick 20858888Smckusick getloadavg(loads, 3); 209*58910Smckusick if (!nflag) 210*58910Smckusick fprintf(stdout, "%s: ", string); 211*58910Smckusick fprintf(stdout, "%.2f %.2f %.2f\n", 21258888Smckusick loads[0], loads[1], loads[2]); 21358888Smckusick return; 21458888Smckusick } 21558888Smckusick if (flags == 0) 21658888Smckusick return; 21758888Smckusick fprintf(stderr, 21858888Smckusick "Use vmstat or systat to view %s information\n", string); 21958888Smckusick return; 22058888Smckusick 22158888Smckusick case CTL_NET: 22258888Smckusick if (flags == 0) 22358888Smckusick return; 22458888Smckusick fprintf(stderr, "Use netstat to view %s information\n", string); 22558888Smckusick return; 22658888Smckusick 22758888Smckusick case CTL_FS: 22858888Smckusick case CTL_DEBUG: 22958888Smckusick case CTL_MACHDEP: 23058888Smckusick break; 23158888Smckusick 23258888Smckusick default: 23358888Smckusick fprintf(stderr, "Illegal top level value: %d\n", mib[0]); 23458888Smckusick return; 23558888Smckusick 23658888Smckusick } 23758888Smckusick 23858888Smckusick size = BUFSIZ; 23958888Smckusick if (sysctl(mib, 2, buf, &size, newsize ? newval : 0, newsize) == -1) { 24058888Smckusick if (flags == 0) 24158888Smckusick return; 24258888Smckusick switch (errno) { 24358888Smckusick case EOPNOTSUPP: 24458888Smckusick fprintf(stderr, "%s: value is not available\n", string); 24558888Smckusick return; 24658888Smckusick case ENOTDIR: 24758888Smckusick fprintf(stderr, "%s: specification is incomplete\n", 24858888Smckusick string); 24958888Smckusick return; 25058888Smckusick case ENOMEM: 25158888Smckusick fprintf(stderr, "%s: type is unknown to this program\n", 25258888Smckusick string); 25358888Smckusick return; 25458888Smckusick default: 25558888Smckusick perror(string); 25658888Smckusick return; 25758888Smckusick } 25858888Smckusick } 25958888Smckusick if (isclockrate) { 26058888Smckusick struct clockinfo *clkp = (struct clockinfo *)buf; 26158888Smckusick 262*58910Smckusick if (!nflag) 263*58910Smckusick fprintf(stdout, "%s: ", string); 26458888Smckusick fprintf(stdout, 265*58910Smckusick "hz = %d, tick = %d, profhz = %d, stathz = %d\n", 266*58910Smckusick clkp->hz, clkp->tick, clkp->profhz, clkp->stathz); 26758888Smckusick return; 26858888Smckusick } 269*58910Smckusick if (size == sizeof(int) && !(isprint(buf[0]) && isprint(buf[1]) && 270*58910Smckusick isprint(buf[2]) && isprint(buf[3]))) 271*58910Smckusick if (newsize == 0) { 272*58910Smckusick if (!nflag) 273*58910Smckusick fprintf(stdout, "%s = ", string); 274*58910Smckusick fprintf(stdout, "%d\n", *(int *)buf); 275*58910Smckusick } else { 276*58910Smckusick if (!nflag) 277*58910Smckusick fprintf(stdout, "%s: %d -> ", string, 278*58910Smckusick *(int *)buf); 279*58910Smckusick fprintf(stdout, "%d\n", *(int *)newval); 280*58910Smckusick } 28158888Smckusick else 282*58910Smckusick if (newsize == 0) { 283*58910Smckusick if (!nflag) 284*58910Smckusick fprintf(stdout, "%s = ", string); 285*58910Smckusick fprintf(stdout, "%s\n", buf); 286*58910Smckusick } else { 287*58910Smckusick if (!nflag) 288*58910Smckusick fprintf(stdout, "%s: %s -> ", string, buf); 289*58910Smckusick fprintf(stdout, "%s\n", newval); 290*58910Smckusick } 29158888Smckusick return; 29258888Smckusick } 29358888Smckusick 29458888Smckusick /* 29558888Smckusick * Scan a list of names searching for a particular name. 29658888Smckusick */ 29758888Smckusick findname(string, level, bufp, namelist) 29858888Smckusick char *string; 29958888Smckusick char *level; 30058888Smckusick char **bufp; 30158888Smckusick struct list *namelist; 30258888Smckusick { 30358888Smckusick char *name; 30458888Smckusick int i; 30558888Smckusick 30658888Smckusick if (namelist->list == 0 || (name = strsep(bufp, ".")) == NULL) { 30758888Smckusick fprintf(stderr, "%s: incomplete specification\n", string); 30858888Smckusick return (-1); 30958888Smckusick } 31058888Smckusick for (i = 0; i < namelist->size; i++) 31158888Smckusick if (!strcmp(name, namelist->list[i])) 31258888Smckusick break; 31358888Smckusick if (i == namelist->size) { 31458888Smckusick fprintf(stderr, "%s level name %s in %s is invalid\n", 31558888Smckusick level, name, string); 31658888Smckusick return (-1); 31758888Smckusick } 31858888Smckusick return (i); 31958888Smckusick } 32058888Smckusick 32158888Smckusick usage() 32258888Smckusick { 32358888Smckusick 32458888Smckusick (void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n", 32558888Smckusick "sysctl [-w] variable ...", "sysctl -a", "sysctl -A"); 32658888Smckusick exit(1); 32758888Smckusick } 328