diff options
author | Eric Andersen <andersen@codepoet.org> | 2003-12-24 06:02:11 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2003-12-24 06:02:11 +0000 |
commit | b90502828cd2178efa049a96f7bbbd9ae6355130 (patch) | |
tree | 14bd4dbe18d14426d154d656e77426c0ac9c0feb | |
parent | 5089534be00aaaf16c2ffcf2a7ed8d742d583e5a (diff) | |
download | busybox-w32-b90502828cd2178efa049a96f7bbbd9ae6355130.tar.gz busybox-w32-b90502828cd2178efa049a96f7bbbd9ae6355130.tar.bz2 busybox-w32-b90502828cd2178efa049a96f7bbbd9ae6355130.zip |
Patch from Ned Ludd, solar at gentoo dot org:
I had previously provided you with a patch to help complete busybox's
props suite, but have heard no word back. Sense then I've made use of as
many of busybox's native API settings as I could find and would really
love for you to include support for this. If there is something more I
need to do to get this supported added in please let me know.
-rw-r--r-- | include/applets.h | 3 | ||||
-rw-r--r-- | include/usage.h | 21 | ||||
-rw-r--r-- | procps/Config.in | 6 | ||||
-rw-r--r-- | procps/Makefile.in | 1 | ||||
-rw-r--r-- | procps/sysctl.c | 372 |
5 files changed, 403 insertions, 0 deletions
diff --git a/include/applets.h b/include/applets.h index 1119a9ea6..e348516ea 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -553,6 +553,9 @@ | |||
553 | #ifdef CONFIG_SYNC | 553 | #ifdef CONFIG_SYNC |
554 | APPLET(sync, sync_main, _BB_DIR_BIN, _BB_SUID_NEVER) | 554 | APPLET(sync, sync_main, _BB_DIR_BIN, _BB_SUID_NEVER) |
555 | #endif | 555 | #endif |
556 | #ifdef CONFIG_SYSCTL | ||
557 | APPLET(sysctl, sysctl_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | ||
558 | #endif | ||
556 | #ifdef CONFIG_SYSLOGD | 559 | #ifdef CONFIG_SYSLOGD |
557 | APPLET(syslogd, syslogd_main, _BB_DIR_SBIN, _BB_SUID_NEVER) | 560 | APPLET(syslogd, syslogd_main, _BB_DIR_SBIN, _BB_SUID_NEVER) |
558 | #endif | 561 | #endif |
diff --git a/include/usage.h b/include/usage.h index bd78a5381..c8716d24d 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -2266,6 +2266,27 @@ | |||
2266 | #define USAGE_IPC_LOG(a) | 2266 | #define USAGE_IPC_LOG(a) |
2267 | #endif | 2267 | #endif |
2268 | 2268 | ||
2269 | #ifdef CONFIG_SYSCTL | ||
2270 | #define sysctl_trivial_usage \ | ||
2271 | "[OPTIONS]... [VALUE]...\n" | ||
2272 | #define sysctl_full_usage | ||
2273 | "sysctl - configure kernel parameters at runtime\n\n" \ | ||
2274 | "Options:\n" \ | ||
2275 | "\t-n\tUse this option to disable printing of the key name when printing values.\n" \ | ||
2276 | "\t-e\tUse this option to ignore errors about unknown keys.\n" \ | ||
2277 | "\t-w\tUse this option when you want to change a sysctl setting.\n" \ | ||
2278 | "\t-p\tLoad in sysctl settings from the file specified or /etc/sysctl.conf if none given.\n" \ | ||
2279 | "\t-a\tDisplay all values currently available.\n" \ | ||
2280 | "\t-A\tDisplay all values currently available in table form." | ||
2281 | |||
2282 | #define sysctl_example_usage | ||
2283 | "sysctl [-n] [-e] variable ...\n" \ | ||
2284 | "sysctl [-n] [-e] -w variable=value ...\n" \ | ||
2285 | "sysctl [-n] [-e] -a\n" \ | ||
2286 | "sysctl [-n] [-e] -p <file>\t(default /etc/sysctl.conf)\n" \ | ||
2287 | "sysctl [-n] [-e] -A\n" | ||
2288 | #endif | ||
2289 | |||
2269 | #define syslogd_trivial_usage \ | 2290 | #define syslogd_trivial_usage \ |
2270 | "[OPTION]..." | 2291 | "[OPTION]..." |
2271 | #define syslogd_full_usage \ | 2292 | #define syslogd_full_usage \ |
diff --git a/procps/Config.in b/procps/Config.in index 14808e034..8d557972c 100644 --- a/procps/Config.in +++ b/procps/Config.in | |||
@@ -72,5 +72,11 @@ config CONFIG_UPTIME | |||
72 | the system has been running, how many users are currently logged | 72 | the system has been running, how many users are currently logged |
73 | on, and the system load averages for the past 1, 5, and 15 minutes. | 73 | on, and the system load averages for the past 1, 5, and 15 minutes. |
74 | 74 | ||
75 | config CONFIG_SYSCTL | ||
76 | bool "sysctl" | ||
77 | default n | ||
78 | help | ||
79 | sysctl - configure kernel parameters at runtime | ||
80 | |||
75 | endmenu | 81 | endmenu |
76 | 82 | ||
diff --git a/procps/Makefile.in b/procps/Makefile.in index 9d2d27391..723dd9ffb 100644 --- a/procps/Makefile.in +++ b/procps/Makefile.in | |||
@@ -28,6 +28,7 @@ PROCPS-$(CONFIG_KILL) += kill.o | |||
28 | PROCPS-$(CONFIG_PIDOF) += pidof.o | 28 | PROCPS-$(CONFIG_PIDOF) += pidof.o |
29 | PROCPS-$(CONFIG_PS) += ps.o | 29 | PROCPS-$(CONFIG_PS) += ps.o |
30 | PROCPS-$(CONFIG_RENICE) += renice.o | 30 | PROCPS-$(CONFIG_RENICE) += renice.o |
31 | PROCPS-$(CONFIG_SYSCTL) += sysctl.o | ||
31 | PROCPS-$(CONFIG_TOP) += top.o | 32 | PROCPS-$(CONFIG_TOP) += top.o |
32 | PROCPS-$(CONFIG_UPTIME) += uptime.o | 33 | PROCPS-$(CONFIG_UPTIME) += uptime.o |
33 | 34 | ||
diff --git a/procps/sysctl.c b/procps/sysctl.c new file mode 100644 index 000000000..f1799af00 --- /dev/null +++ b/procps/sysctl.c | |||
@@ -0,0 +1,372 @@ | |||
1 | |||
2 | /* | ||
3 | * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters | ||
4 | * | ||
5 | * | ||
6 | * "Copyright 1999 George Staikos | ||
7 | * This file may be used subject to the terms and conditions of the | ||
8 | * GNU General Public License Version 2, or any later version | ||
9 | * at your option, as published by the Free Software Foundation. | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details." | ||
14 | * | ||
15 | * Changelog: | ||
16 | * v1.01: | ||
17 | * - added -p <preload> to preload values from a file | ||
18 | * v1.01.1 | ||
19 | * - busybox applet aware by <solar@gentoo.org> | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <stdio.h> | ||
24 | #include <stdlib.h> | ||
25 | #include <unistd.h> | ||
26 | #include <sys/stat.h> | ||
27 | #include <sys/types.h> | ||
28 | #include <dirent.h> | ||
29 | #include <string.h> | ||
30 | #include <errno.h> | ||
31 | #include <fcntl.h> | ||
32 | #include "busybox.h" | ||
33 | |||
34 | /* | ||
35 | * Function Prototypes | ||
36 | */ | ||
37 | static int sysctl_usage(void); | ||
38 | static int sysctl_read_setting(const char *setting, int output); | ||
39 | static int sysctl_write_setting(const char *setting, int output); | ||
40 | static int sysctl_preload_file(const char *filename, int output); | ||
41 | static int sysctl_display_all(const char *path, int output, int show_table); | ||
42 | |||
43 | /* | ||
44 | * Globals... | ||
45 | */ | ||
46 | static const char *PROC_PATH = "/proc/sys/"; | ||
47 | static const char *DEFAULT_PRELOAD = "/etc/sysctl.conf"; | ||
48 | |||
49 | /* error messages */ | ||
50 | static const char *ERR_UNKNOWN_PARAMETER = "error: Unknown parameter '%s'\n"; | ||
51 | static const char *ERR_MALFORMED_SETTING = "error: Malformed setting '%s'\n"; | ||
52 | static const char *ERR_NO_EQUALS = | ||
53 | "error: '%s' must be of the form name=value\n"; | ||
54 | static const char *ERR_INVALID_KEY = "error: '%s' is an unknown key\n"; | ||
55 | static const char *ERR_UNKNOWN_WRITING = | ||
56 | "error: unknown error %d setting key '%s'\n"; | ||
57 | static const char *ERR_UNKNOWN_READING = | ||
58 | "error: unknown error %d reading key '%s'\n"; | ||
59 | static const char *ERR_PERMISSION_DENIED = | ||
60 | "error: permission denied on key '%s'\n"; | ||
61 | static const char *ERR_OPENING_DIR = "error: unable to open directory '%s'\n"; | ||
62 | static const char *ERR_PRELOAD_FILE = | ||
63 | "error: unable to open preload file '%s'\n"; | ||
64 | static const char *WARN_BAD_LINE = | ||
65 | "warning: %s(%d): invalid syntax, continuing...\n"; | ||
66 | |||
67 | |||
68 | /* | ||
69 | * sysctl_main()... | ||
70 | */ | ||
71 | int sysctl_main(int argc, char **argv) | ||
72 | { | ||
73 | int retval = 0; | ||
74 | int output = 1; | ||
75 | int write_mode = 0; | ||
76 | int switches_allowed = 1; | ||
77 | |||
78 | if (argc < 2) | ||
79 | return sysctl_usage(); | ||
80 | |||
81 | argv++; | ||
82 | |||
83 | for (; argv && *argv && **argv; argv++) { | ||
84 | if (switches_allowed && **argv == '-') { /* we have a switch */ | ||
85 | switch ((*argv)[1]) { | ||
86 | case 'n': | ||
87 | output = 0; | ||
88 | break; | ||
89 | case 'w': | ||
90 | write_mode = 1; | ||
91 | switches_allowed = 0; | ||
92 | break; | ||
93 | case 'p': | ||
94 | argv++; | ||
95 | return | ||
96 | sysctl_preload_file(((argv && *argv | ||
97 | && **argv) ? *argv : | ||
98 | DEFAULT_PRELOAD), output); | ||
99 | case 'a': | ||
100 | case 'A': | ||
101 | switches_allowed = 0; | ||
102 | return sysctl_display_all(PROC_PATH, output, | ||
103 | ((*argv)[1] == 'a') ? 0 : 1); | ||
104 | case 'h': | ||
105 | case '?': | ||
106 | return sysctl_usage(); | ||
107 | default: | ||
108 | bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv); | ||
109 | return sysctl_usage(); | ||
110 | } | ||
111 | } else { | ||
112 | switches_allowed = 0; | ||
113 | if (write_mode) | ||
114 | retval = sysctl_write_setting(*argv, output); | ||
115 | else | ||
116 | sysctl_read_setting(*argv, output); | ||
117 | } | ||
118 | } | ||
119 | return retval; | ||
120 | } /* end sysctl_main() */ | ||
121 | |||
122 | /* | ||
123 | * Display the sysctl_usage format | ||
124 | */ | ||
125 | int sysctl_usage() | ||
126 | { | ||
127 | bb_show_usage(); | ||
128 | return -1; | ||
129 | } /* end sysctl_usage() */ | ||
130 | |||
131 | |||
132 | /* | ||
133 | * sysctl_preload_file | ||
134 | * preload the sysctl's from a conf file | ||
135 | * - we parse the file and then reform it (strip out whitespace) | ||
136 | */ | ||
137 | int sysctl_preload_file(const char *filename, int output) | ||
138 | { | ||
139 | int lineno = 0; | ||
140 | char oneline[256]; | ||
141 | char buffer[256]; | ||
142 | char *name, *value, *ptr; | ||
143 | FILE *fp = NULL; | ||
144 | |||
145 | if (!filename || ((fp = fopen(filename, "r")) == NULL)) { | ||
146 | bb_error_msg(ERR_PRELOAD_FILE, filename); | ||
147 | return 1; | ||
148 | } | ||
149 | |||
150 | while (fgets(oneline, sizeof(oneline) - 1, fp)) { | ||
151 | oneline[sizeof(oneline) - 1] = 0; | ||
152 | lineno++; | ||
153 | trim(oneline); | ||
154 | ptr = (char *) oneline; | ||
155 | |||
156 | if (*ptr == '#' || *ptr == ';') | ||
157 | continue; | ||
158 | |||
159 | if (bb_strlen(ptr) < 2) | ||
160 | continue; | ||
161 | |||
162 | name = strtok(ptr, "="); | ||
163 | if (!name || !*name) { | ||
164 | bb_error_msg(WARN_BAD_LINE, filename, lineno); | ||
165 | continue; | ||
166 | } | ||
167 | |||
168 | trim(name); | ||
169 | |||
170 | value = strtok(NULL, "\n\r"); | ||
171 | if (!value || !*value) { | ||
172 | bb_error_msg(WARN_BAD_LINE, filename, lineno); | ||
173 | continue; | ||
174 | } | ||
175 | |||
176 | while ((*value == ' ' || *value == '\t') && *value != 0) | ||
177 | value++; | ||
178 | strncpy(buffer, name, sizeof(buffer)); | ||
179 | strncat(buffer, "=", sizeof(buffer)); | ||
180 | strncat(buffer, value, sizeof(buffer)); | ||
181 | sysctl_write_setting(buffer, output); | ||
182 | } | ||
183 | fclose(fp); | ||
184 | return 0; | ||
185 | } /* end sysctl_preload_file() */ | ||
186 | |||
187 | |||
188 | /* | ||
189 | * Write a single sysctl setting | ||
190 | */ | ||
191 | int sysctl_write_setting(const char *setting, int output) | ||
192 | { | ||
193 | int retval = 0; | ||
194 | const char *name = setting; | ||
195 | const char *value; | ||
196 | const char *equals; | ||
197 | char *tmpname, *outname, *cptr; | ||
198 | int fd = -1; | ||
199 | |||
200 | if (!name) /* probably dont' want to display this err */ | ||
201 | return 0; | ||
202 | |||
203 | if (!(equals = index(setting, '='))) { | ||
204 | bb_error_msg(ERR_NO_EQUALS, setting); | ||
205 | return -1; | ||
206 | } | ||
207 | |||
208 | value = equals + sizeof(char); /* point to the value in name=value */ | ||
209 | |||
210 | if (!*name || !*value || name == equals) { | ||
211 | bb_error_msg(ERR_MALFORMED_SETTING, setting); | ||
212 | return -2; | ||
213 | } | ||
214 | |||
215 | tmpname = | ||
216 | (char *) xmalloc((equals - name + 1 + bb_strlen(PROC_PATH)) * | ||
217 | sizeof(char)); | ||
218 | outname = (char *) xmalloc((equals - name + 1) * sizeof(char)); | ||
219 | |||
220 | strcpy(tmpname, PROC_PATH); | ||
221 | strncat(tmpname, name, (int) (equals - name)); | ||
222 | tmpname[equals - name + bb_strlen(PROC_PATH)] = 0; | ||
223 | strncpy(outname, name, (int) (equals - name)); | ||
224 | outname[equals - name] = 0; | ||
225 | |||
226 | while ((cptr = strchr(tmpname, '.')) != NULL) | ||
227 | *cptr = '/'; | ||
228 | |||
229 | while ((cptr = strchr(outname, '/')) != NULL) | ||
230 | *cptr = '.'; | ||
231 | |||
232 | if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) { | ||
233 | switch (errno) { | ||
234 | case ENOENT: | ||
235 | bb_error_msg(ERR_INVALID_KEY, outname); | ||
236 | break; | ||
237 | case EACCES: | ||
238 | bb_perror_msg(ERR_PERMISSION_DENIED, outname); | ||
239 | break; | ||
240 | default: | ||
241 | bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname); | ||
242 | break; | ||
243 | } | ||
244 | retval = -1; | ||
245 | } else { | ||
246 | write(fd, value, bb_strlen(value)); | ||
247 | close(fd); | ||
248 | if (output) { | ||
249 | write(STDOUT_FILENO, outname, bb_strlen(outname)); | ||
250 | write(STDOUT_FILENO, " = ", 3); | ||
251 | } | ||
252 | write(STDOUT_FILENO, value, bb_strlen(value)); | ||
253 | write(STDOUT_FILENO, "\n", 1); | ||
254 | } | ||
255 | |||
256 | /* cleanup */ | ||
257 | free(tmpname); | ||
258 | free(outname); | ||
259 | return retval; | ||
260 | } /* end sysctl_write_setting() */ | ||
261 | |||
262 | |||
263 | /* | ||
264 | * Read a sysctl setting | ||
265 | * | ||
266 | */ | ||
267 | int sysctl_read_setting(const char *setting, int output) | ||
268 | { | ||
269 | int retval = 0; | ||
270 | char *tmpname, *outname, *cptr; | ||
271 | char inbuf[1025]; | ||
272 | const char *name = setting; | ||
273 | FILE *fp; | ||
274 | |||
275 | if (!setting || !*setting) | ||
276 | bb_error_msg(ERR_INVALID_KEY, setting); | ||
277 | |||
278 | tmpname = | ||
279 | (char *) xmalloc((bb_strlen(name) + bb_strlen(PROC_PATH) + 1) * | ||
280 | sizeof(char)); | ||
281 | outname = (char *) xmalloc((bb_strlen(name) + 1) * sizeof(char)); | ||
282 | |||
283 | strcpy(tmpname, PROC_PATH); | ||
284 | strcat(tmpname, name); | ||
285 | strcpy(outname, name); | ||
286 | |||
287 | while ((cptr = strchr(tmpname, '.')) != NULL) | ||
288 | *cptr = '/'; | ||
289 | while ((cptr = strchr(outname, '/')) != NULL) | ||
290 | *cptr = '.'; | ||
291 | |||
292 | if ((fp = fopen(tmpname, "r")) == NULL) { | ||
293 | switch (errno) { | ||
294 | case ENOENT: | ||
295 | bb_error_msg(ERR_INVALID_KEY, outname); | ||
296 | break; | ||
297 | case EACCES: | ||
298 | bb_error_msg(ERR_PERMISSION_DENIED, outname); | ||
299 | break; | ||
300 | default: | ||
301 | bb_error_msg(ERR_UNKNOWN_READING, errno, outname); | ||
302 | break; | ||
303 | } | ||
304 | retval = -1; | ||
305 | } else { | ||
306 | while (fgets(inbuf, sizeof(inbuf) - 1, fp)) { | ||
307 | if (output) { | ||
308 | write(STDOUT_FILENO, outname, bb_strlen(outname)); | ||
309 | write(STDOUT_FILENO, " = ", 3); | ||
310 | } | ||
311 | write(STDOUT_FILENO, inbuf, bb_strlen(inbuf)); | ||
312 | } | ||
313 | fclose(fp); | ||
314 | } | ||
315 | |||
316 | free(tmpname); | ||
317 | free(outname); | ||
318 | return retval; | ||
319 | } /* end sysctl_read_setting() */ | ||
320 | |||
321 | |||
322 | |||
323 | /* | ||
324 | * Display all the sysctl settings | ||
325 | * | ||
326 | */ | ||
327 | int sysctl_display_all(const char *path, int output, int show_table) | ||
328 | { | ||
329 | int retval = 0; | ||
330 | int retval2; | ||
331 | DIR *dp; | ||
332 | struct dirent *de; | ||
333 | char *tmpdir; | ||
334 | struct stat ts; | ||
335 | |||
336 | if (!(dp = opendir(path))) { | ||
337 | bb_perror_msg(ERR_OPENING_DIR, path); | ||
338 | retval = -1; | ||
339 | } else { | ||
340 | readdir(dp); | ||
341 | readdir(dp); /* skip . and .. */ | ||
342 | while ((de = readdir(dp)) != NULL) { | ||
343 | tmpdir = | ||
344 | (char *) xmalloc(bb_strlen(path) + bb_strlen(de->d_name) + 2); | ||
345 | strcpy(tmpdir, path); | ||
346 | strcat(tmpdir, de->d_name); | ||
347 | if ((retval2 = stat(tmpdir, &ts)) != 0) | ||
348 | bb_perror_msg(tmpdir); | ||
349 | else { | ||
350 | if (S_ISDIR(ts.st_mode)) { | ||
351 | strcat(tmpdir, "/"); | ||
352 | sysctl_display_all(tmpdir, output, show_table); | ||
353 | } else | ||
354 | retval |= | ||
355 | sysctl_read_setting(tmpdir + bb_strlen(PROC_PATH), | ||
356 | output); | ||
357 | |||
358 | } | ||
359 | free(tmpdir); | ||
360 | } /* end while */ | ||
361 | closedir(dp); | ||
362 | } | ||
363 | |||
364 | return retval; | ||
365 | } /* end sysctl_display_all() */ | ||
366 | |||
367 | #ifdef STANDALONE_SYSCTL | ||
368 | int main(int argc, char **argv) | ||
369 | { | ||
370 | return sysctl_main(argc, argv); | ||
371 | } | ||
372 | #endif | ||