sysctl.c - ubase - suckless linux base utils | |
git clone git://git.suckless.org/ubase | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
sysctl.c (3285B) | |
--- | |
1 /* See LICENSE file for copyright and license details. */ | |
2 #include <fcntl.h> | |
3 #include <limits.h> | |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
6 #include <string.h> | |
7 #include <unistd.h> | |
8 | |
9 #include "text.h" | |
10 #include "util.h" | |
11 | |
12 static void | |
13 replacestr(char *s, int a, int b) | |
14 { | |
15 for (; *s; s++) | |
16 if (*s == a) | |
17 *s = b; | |
18 } | |
19 | |
20 static int | |
21 getsysctl(char *variable, char **value) | |
22 { | |
23 char path[PATH_MAX]; | |
24 char *p; | |
25 char *buf, *tmp, c; | |
26 int fd; | |
27 ssize_t n; | |
28 size_t sz, i; | |
29 | |
30 replacestr(variable, '.', '/'); | |
31 | |
32 strlcpy(path, "/proc/sys/", sizeof(path)); | |
33 if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) { | |
34 replacestr(variable, '/', '.'); | |
35 return -1; | |
36 } | |
37 | |
38 replacestr(variable, '/', '.'); | |
39 | |
40 fd = open(path, O_RDONLY); | |
41 if (fd < 0) | |
42 return -1; | |
43 | |
44 i = 0; | |
45 sz = 1; | |
46 buf = NULL; | |
47 while (1) { | |
48 n = read(fd, &c, 1); | |
49 if (n < 0) { | |
50 close(fd); | |
51 free(buf); | |
52 return -1; | |
53 } | |
54 if (n == 0) | |
55 break; | |
56 if (i == sz - 1) { | |
57 sz *= 2; | |
58 tmp = realloc(buf, sz); | |
59 if (!tmp) { | |
60 close(fd); | |
61 free(buf); | |
62 return -1; | |
63 } | |
64 buf = tmp; | |
65 } | |
66 buf[i++] = c; | |
67 } | |
68 buf[i] = '\0'; | |
69 | |
70 p = strrchr(buf, '\n'); | |
71 if (p) | |
72 *p = '\0'; | |
73 | |
74 *value = buf; | |
75 | |
76 close(fd); | |
77 | |
78 return 0; | |
79 } | |
80 | |
81 static int | |
82 setsysctl(char *variable, char *value) | |
83 { | |
84 char path[PATH_MAX]; | |
85 int fd; | |
86 ssize_t n; | |
87 | |
88 replacestr(variable, '.', '/'); | |
89 | |
90 strlcpy(path, "/proc/sys/", sizeof(path)); | |
91 if (strlcat(path, variable, sizeof(path)) >= sizeof(path)) { | |
92 replacestr(variable, '/', '.'); | |
93 return -1; | |
94 } | |
95 | |
96 replacestr(variable, '/', '.'); | |
97 | |
98 fd = open(path, O_WRONLY); | |
99 if (fd < 0) | |
100 return -1; | |
101 | |
102 n = write(fd, value, strlen(value)); | |
103 if ((size_t)n != strlen(value)) { | |
104 close(fd); | |
105 return -1; | |
106 } | |
107 | |
108 close(fd); | |
109 | |
110 return 0; | |
111 } | |
112 | |
113 static int | |
114 parsepair(char *pair) | |
115 { | |
116 char *p; | |
117 char *variable; | |
118 char *value; | |
119 | |
120 for (p = pair; *p; p++) { | |
121 if (p[0] == '.' && p[1] == '.') { | |
122 weprintf("malformed input: %s\n", pair); | |
123 return -1; | |
124 } | |
125 } | |
126 p = strchr(pair, '='); | |
127 if (p) { | |
128 if (p[1] == '\0') { | |
129 weprintf("malformed input: %s\n", pair); | |
130 return -1; | |
131 } | |
132 *p = '\0'; | |
133 value = &p[1]; | |
134 } else { | |
135 value = NULL; | |
136 } | |
137 variable = pair; | |
138 if (value) { | |
139 if (setsysctl(variable, value) < 0) { | |
140 weprintf("failed to set sysctl for %s\n", variab… | |
141 return -1; | |
142 } | |
143 } else { | |
144 if (getsysctl(variable, &value) < 0) { | |
145 weprintf("failed to get sysctl for %s\n", variab… | |
146 return -1; | |
147 } | |
148 printf("%s = %s\n", variable, value); | |
149 free(value); | |
150 } | |
151 | |
152 return 0; | |
153 } | |
154 | |
155 static void | |
156 usage(void) | |
157 { | |
158 eprintf("usage: %s [-p file] variable[=value]...\n", argv0); | |
159 } | |
160 | |
161 int | |
162 main(int argc, char *argv[]) | |
163 { | |
164 FILE *fp; | |
165 char *buf = NULL, *p; | |
166 char *file = NULL; | |
167 size_t size = 0; | |
168 int i; | |
169 int r = 0; | |
170 | |
171 ARGBEGIN { | |
172 case 'p': | |
173 file = EARGF(usage()); | |
174 break; | |
175 default: | |
176 usage(); | |
177 } ARGEND; | |
178 | |
179 if (!file && argc < 1) | |
180 usage(); | |
181 | |
182 if (!file) { | |
183 for (i = 0; i < argc; i++) | |
184 if (parsepair(argv[i]) < 0) | |
185 r = 1; | |
186 } else { | |
187 fp = fopen(file, "r"); | |
188 if (!fp) | |
189 eprintf("fopen %s:", file); | |
190 while (agetline(&buf, &size, fp) != -1) { | |
191 p = buf; | |
192 for (p = buf; *p == ' ' || *p == '\t'; p++) | |
193 ; | |
194 if (*p == '#' || *p == '\n') | |
195 continue; | |
196 for (p = buf; *p; p++) { | |
197 if (*p == '\n') { | |
198 *p = '\0'; | |
199 break; | |
200 } | |
201 } | |
202 p = buf; | |
203 if (parsepair(p) < 0) | |
204 r = 1; | |
205 } | |
206 if (ferror(fp)) | |
207 eprintf("%s: read error:", file); | |
208 free(buf); | |
209 fclose(fp); | |
210 } | |
211 | |
212 return r; | |
213 } |