1 
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <errno.h>
6 #include <syscall.h>
7 
8 #include <sys/sysctl.h>
9 
10 typedef struct SysCtlEntry {
11     char	path[64];
12     int		type;
13     int		flags;
14     char	description[128];
15 } SysCtlEntry;
16 
17 #define SYSCTL_STR(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
18     { #_PATH, SYSCTL_TYPE_STR, _FLAGS, _DESCRIPTION },
19 #define SYSCTL_INT(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
20     { #_PATH, SYSCTL_TYPE_INT, _FLAGS, _DESCRIPTION },
21 #define SYSCTL_BOOL(_PATH, _FLAGS, _DESCRIPTION, _DEFAULT) \
22     { #_PATH, SYSCTL_TYPE_BOOL, _FLAGS, _DESCRIPTION },
23 SysCtlEntry SYSCTLTable[] = {
24     SYSCTL_LIST
25     { "", 0, 0, "" },
26 };
27 #undef SYSCTL_STR
28 #undef SYSCTL_INT
29 #undef SYSCTL_BOOL
30 
31 void
PrintVal(int idx)32 PrintVal(int idx)
33 {
34     switch (SYSCTLTable[idx].type) {
35 	case SYSCTL_TYPE_STR: {
36 	    SysCtlString scStr;
37 
38 	    OSSysCtl(SYSCTLTable[idx].path, &scStr, NULL);
39 	    printf("%s: %s\n", SYSCTLTable[idx].path, scStr.value);
40 	    break;
41 	}
42 	case SYSCTL_TYPE_INT: {
43 	    SysCtlInt scInt;
44 
45 	    OSSysCtl(SYSCTLTable[idx].path, &scInt, NULL);
46 	    printf("%s: %ld\n", SYSCTLTable[idx].path, scInt.value);
47 	    break;
48 	}
49 	case SYSCTL_TYPE_BOOL: {
50 	    SysCtlBool scBool;
51 
52 	    OSSysCtl(SYSCTLTable[idx].path, &scBool, NULL);
53 	    printf("%s: %s\n", SYSCTLTable[idx].path,
54 		    scBool.value ? "true" : "false");
55 	    break;
56 	}
57 	default:
58 	    printf("%s: Unsupported type\n", SYSCTLTable[idx].path);
59 	    break;
60     }
61 }
62 
63 void
UpdateVal(int idx,const char * val)64 UpdateVal(int idx, const char *val)
65 {
66     switch (SYSCTLTable[idx].type) {
67 	case SYSCTL_TYPE_STR: {
68 	    SysCtlString scStr;
69 
70 	    strncpy(scStr.value, val, sizeof(scStr.value) - 1);
71 	    OSSysCtl(SYSCTLTable[idx].path, NULL, &scStr);
72 	    break;
73 	}
74 	case SYSCTL_TYPE_INT: {
75 	    SysCtlInt scInt;
76 
77 	    scInt.value = atoi(val);
78 	    printf("%ld\n", scInt.value);
79 	    OSSysCtl(SYSCTLTable[idx].path, NULL, &scInt);
80 	    break;
81 	}
82 	case SYSCTL_TYPE_BOOL: {
83 	    SysCtlBool scBool;
84 
85 	    if (strcmp(val,"true") == 0)
86 		scBool.value = true;
87 	    else if (strcmp(val,"false") == 0)
88 		scBool.value = false;
89 	    else {
90 		printf("Value must be true or false\n");
91 		exit(1);
92 	    }
93 	    OSSysCtl(SYSCTLTable[idx].path, NULL, &scBool);
94 	    break;
95 	}
96 	default:
97 	    printf("%s: Unsupported type\n", SYSCTLTable[idx].path);
98 	    break;
99     }
100 }
101 
102 int
main(int argc,const char * argv[])103 main(int argc, const char *argv[])
104 {
105     if (argc == 2 && strcmp(argv[1],"-h") == 0) {
106 	printf("Usage: sysctl [NODE] [VALUE]\n");
107 	return 1;
108     }
109 
110     if (argc == 2 && strcmp(argv[1],"-d") == 0) {
111         printf("%-20s %s\n", "Name", "Description");
112 	for (int i = 0; SYSCTLTable[i].type != 0; i++) {
113 	    printf("%-20s %s\n",
114 		    SYSCTLTable[i].path,
115 		    SYSCTLTable[i].description);
116 	}
117 	return 0;
118     }
119 
120     if (argc == 2 || argc == 3) {
121 	for (int i = 0; SYSCTLTable[i].type != 0; i++) {
122 	    if (strcmp(SYSCTLTable[i].path, argv[1]) == 0) {
123 		if (argc == 2)
124 		    PrintVal(i);
125 		else
126 		    UpdateVal(i, argv[2]);
127 	    }
128 	}
129 
130 	return 0;
131     }
132 
133     for (int i = 0; SYSCTLTable[i].type != 0; i++) {
134 	PrintVal(i);
135     }
136 
137     return 0;
138 }
139 
140