xref: /csrg-svn/usr.sbin/sysctl/sysctl.c (revision 58911)
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*58911Smckusick static char sccsid[] = "@(#)sysctl.c	5.3 (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 
4858910Smckusick 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;
5758910Smckusick 	int ch, lvl1;
5858888Smckusick 
5958910Smckusick 	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 
7058910Smckusick 		case 'n':
7158910Smckusick 			nflag = 1;
7258910Smckusick 			break;
7358910Smckusick 
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) {
8658910Smckusick 		for (lvl1 = 1; lvl1 < CTL_MAXID; lvl1++)
8758910Smckusick 			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  */
10058910Smckusick listall(lvl1)
10158910Smckusick 	int lvl1;
10258888Smckusick {
10358888Smckusick 	struct list *lp;
10458910Smckusick 	int lvl2;
10558888Smckusick 	char *cp, name[BUFSIZ];
10658888Smckusick 
10758910Smckusick 	lp = &secondlevel[lvl1];
10858910Smckusick 	if (lp->list == 0)
10958910Smckusick 		return;
11058910Smckusick 	strcpy(name, topname[lvl1]);
11158910Smckusick 	cp = &name[strlen(name)];
11258910Smckusick 	*cp++ = '.';
11358910Smckusick 	for (lvl2 = 1; lvl2 < lp->size; lvl2++) {
11458910Smckusick 		strcpy(cp, lp->list[lvl2]);
11558910Smckusick 		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 	}
16758910Smckusick 	if (bufp == NULL) {
16858910Smckusick 		listall(indx);
16958910Smckusick 		return;
17058910Smckusick 	}
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);
20958910Smckusick 			if (!nflag)
21058910Smckusick 				fprintf(stdout, "%s: ", string);
21158910Smckusick 			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 
26258910Smckusick 		if (!nflag)
26358910Smckusick 			fprintf(stdout, "%s: ", string);
26458888Smckusick 		fprintf(stdout,
26558910Smckusick 		    "hz = %d, tick = %d, profhz = %d, stathz = %d\n",
26658910Smckusick 		    clkp->hz, clkp->tick, clkp->profhz, clkp->stathz);
26758888Smckusick 		return;
26858888Smckusick 	}
26958910Smckusick 	if (size == sizeof(int) && !(isprint(buf[0]) && isprint(buf[1]) &&
27058910Smckusick 	    isprint(buf[2]) && isprint(buf[3])))
27158910Smckusick 		if (newsize == 0) {
27258910Smckusick 			if (!nflag)
27358910Smckusick 				fprintf(stdout, "%s = ", string);
27458910Smckusick 			fprintf(stdout, "%d\n", *(int *)buf);
27558910Smckusick 		} else {
27658910Smckusick 			if (!nflag)
27758910Smckusick 				fprintf(stdout, "%s: %d -> ", string,
27858910Smckusick 				    *(int *)buf);
27958910Smckusick 			fprintf(stdout, "%d\n", *(int *)newval);
28058910Smckusick 		}
28158888Smckusick 	else
28258910Smckusick 		if (newsize == 0) {
28358910Smckusick 			if (!nflag)
28458910Smckusick 				fprintf(stdout, "%s = ", string);
28558910Smckusick 			fprintf(stdout, "%s\n", buf);
28658910Smckusick 		} else {
28758910Smckusick 			if (!nflag)
28858910Smckusick 				fprintf(stdout, "%s: %s -> ", string, buf);
28958910Smckusick 			fprintf(stdout, "%s\n", newval);
29058910Smckusick 		}
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 
324*58911Smckusick 	(void)fprintf(stderr, "usage:\t%s\n\t%s\n\t%s\n\t%s\n",
325*58911Smckusick 	    "sysctl [-n] variable ...", "sysctl [-n] -w variable=value ...",
326*58911Smckusick 	    "sysctl [-n] -a", "sysctl [-n] -A");
32758888Smckusick 	exit(1);
32858888Smckusick }
329