aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2003-12-24 06:02:11 +0000
committerEric Andersen <andersen@codepoet.org>2003-12-24 06:02:11 +0000
commitb90502828cd2178efa049a96f7bbbd9ae6355130 (patch)
tree14bd4dbe18d14426d154d656e77426c0ac9c0feb
parent5089534be00aaaf16c2ffcf2a7ed8d742d583e5a (diff)
downloadbusybox-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.h3
-rw-r--r--include/usage.h21
-rw-r--r--procps/Config.in6
-rw-r--r--procps/Makefile.in1
-rw-r--r--procps/sysctl.c372
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
75config CONFIG_SYSCTL
76 bool "sysctl"
77 default n
78 help
79 sysctl - configure kernel parameters at runtime
80
75endmenu 81endmenu
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
28PROCPS-$(CONFIG_PIDOF) += pidof.o 28PROCPS-$(CONFIG_PIDOF) += pidof.o
29PROCPS-$(CONFIG_PS) += ps.o 29PROCPS-$(CONFIG_PS) += ps.o
30PROCPS-$(CONFIG_RENICE) += renice.o 30PROCPS-$(CONFIG_RENICE) += renice.o
31PROCPS-$(CONFIG_SYSCTL) += sysctl.o
31PROCPS-$(CONFIG_TOP) += top.o 32PROCPS-$(CONFIG_TOP) += top.o
32PROCPS-$(CONFIG_UPTIME) += uptime.o 33PROCPS-$(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 */
37static int sysctl_usage(void);
38static int sysctl_read_setting(const char *setting, int output);
39static int sysctl_write_setting(const char *setting, int output);
40static int sysctl_preload_file(const char *filename, int output);
41static int sysctl_display_all(const char *path, int output, int show_table);
42
43/*
44 * Globals...
45 */
46static const char *PROC_PATH = "/proc/sys/";
47static const char *DEFAULT_PRELOAD = "/etc/sysctl.conf";
48
49/* error messages */
50static const char *ERR_UNKNOWN_PARAMETER = "error: Unknown parameter '%s'\n";
51static const char *ERR_MALFORMED_SETTING = "error: Malformed setting '%s'\n";
52static const char *ERR_NO_EQUALS =
53 "error: '%s' must be of the form name=value\n";
54static const char *ERR_INVALID_KEY = "error: '%s' is an unknown key\n";
55static const char *ERR_UNKNOWN_WRITING =
56 "error: unknown error %d setting key '%s'\n";
57static const char *ERR_UNKNOWN_READING =
58 "error: unknown error %d reading key '%s'\n";
59static const char *ERR_PERMISSION_DENIED =
60 "error: permission denied on key '%s'\n";
61static const char *ERR_OPENING_DIR = "error: unable to open directory '%s'\n";
62static const char *ERR_PRELOAD_FILE =
63 "error: unable to open preload file '%s'\n";
64static const char *WARN_BAD_LINE =
65 "warning: %s(%d): invalid syntax, continuing...\n";
66
67
68/*
69 * sysctl_main()...
70 */
71int 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 */
125int 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 */
137int 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 */
191int 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 */
267int 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 */
327int 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
368int main(int argc, char **argv)
369{
370 return sysctl_main(argc, argv);
371}
372#endif