3 * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
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."
17 * - added -p <preload> to preload values from a file
19 * - busybox applet aware by <solar@gentoo.org>
27 #include <sys/types.h>
37 static int sysctl_read_setting(const char *setting, int output);
38 static int sysctl_write_setting(const char *setting, int output);
39 static int sysctl_preload_file(const char *filename, int output);
40 static int sysctl_display_all(const char *path, int output, int show_table);
45 static const char PROC_PATH[] = "/proc/sys/";
46 static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
49 static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter '%s'\n";
50 static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting '%s'\n";
51 static const char ERR_NO_EQUALS[] =
52 "error: '%s' must be of the form name=value\n";
53 static const char ERR_INVALID_KEY[] = "error: '%s' is an unknown key\n";
54 static const char ERR_UNKNOWN_WRITING[] =
55 "error: unknown error %d setting key '%s'\n";
56 static const char ERR_UNKNOWN_READING[] =
57 "error: unknown error %d reading key '%s'\n";
58 static const char ERR_PERMISSION_DENIED[] =
59 "error: permission denied on key '%s'\n";
60 static const char ERR_OPENING_DIR[] = "error: unable to open directory '%s'\n";
61 static const char ERR_PRELOAD_FILE[] =
62 "error: unable to open preload file '%s'\n";
63 static const char WARN_BAD_LINE[] =
64 "warning: %s(%d): invalid syntax, continuing...\n";
67 static void dwrite_str(int fd, const char *buf)
69 write(fd, buf, strlen(buf));
75 int sysctl_main(int argc, char **argv)
80 int switches_allowed = 1;
87 for (; argv && *argv && **argv; argv++) {
88 if (switches_allowed && **argv == '-') { /* we have a switch */
100 sysctl_preload_file(((argv && *argv
102 DEFAULT_PRELOAD), output);
105 switches_allowed = 0;
106 return sysctl_display_all(PROC_PATH, output,
107 ((*argv)[1] == 'a') ? 0 : 1);
112 bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
116 switches_allowed = 0;
118 retval = sysctl_write_setting(*argv, output);
120 sysctl_read_setting(*argv, output);
124 } /* end sysctl_main() */
129 * sysctl_preload_file
130 * preload the sysctl's from a conf file
131 * - we parse the file and then reform it (strip out whitespace)
133 #define PRELOAD_BUF 256
135 int sysctl_preload_file(const char *filename, int output)
138 char oneline[PRELOAD_BUF];
139 char buffer[PRELOAD_BUF];
140 char *name, *value, *ptr;
143 if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
144 bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
147 while (fgets(oneline, sizeof(oneline) - 1, fp)) {
148 oneline[sizeof(oneline) - 1] = 0;
151 ptr = (char *) oneline;
153 if (*ptr == '#' || *ptr == ';')
156 if (bb_strlen(ptr) < 2)
159 name = strtok(ptr, "=");
160 if (!name || !*name) {
161 bb_error_msg(WARN_BAD_LINE, filename, lineno);
167 value = strtok(NULL, "\n\r");
168 if (!value || !*value) {
169 bb_error_msg(WARN_BAD_LINE, filename, lineno);
173 while ((*value == ' ' || *value == '\t') && *value != 0)
175 strcpy(buffer, name);
177 strcat(buffer, value);
178 sysctl_write_setting(buffer, output);
182 } /* end sysctl_preload_file() */
186 * Write a single sysctl setting
188 int sysctl_write_setting(const char *setting, int output)
191 const char *name = setting;
194 char *tmpname, *outname, *cptr;
197 if (!name) /* probably dont' want to display this err */
200 if (!(equals = strchr(setting, '='))) {
201 bb_error_msg(ERR_NO_EQUALS, setting);
205 value = equals + sizeof(char); /* point to the value in name=value */
207 if (!*name || !*value || name == equals) {
208 bb_error_msg(ERR_MALFORMED_SETTING, setting);
212 tmpname = bb_xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
213 outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
215 while ((cptr = strchr(tmpname, '.')) != NULL)
218 while ((cptr = strchr(outname, '/')) != NULL)
221 if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
224 bb_error_msg(ERR_INVALID_KEY, outname);
227 bb_perror_msg(ERR_PERMISSION_DENIED, outname);
230 bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
235 dwrite_str(fd, value);
238 dwrite_str(STDOUT_FILENO, outname);
239 dwrite_str(STDOUT_FILENO, " = ");
241 dwrite_str(STDOUT_FILENO, value);
242 dwrite_str(STDOUT_FILENO, "\n");
249 } /* end sysctl_write_setting() */
253 * Read a sysctl setting
256 int sysctl_read_setting(const char *setting, int output)
259 char *tmpname, *outname, *cptr;
261 const char *name = setting;
264 if (!setting || !*setting)
265 bb_error_msg(ERR_INVALID_KEY, setting);
267 tmpname = concat_path_file(PROC_PATH, name);
268 outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
270 while ((cptr = strchr(tmpname, '.')) != NULL)
272 while ((cptr = strchr(outname, '/')) != NULL)
275 if ((fp = fopen(tmpname, "r")) == NULL) {
278 bb_error_msg(ERR_INVALID_KEY, outname);
281 bb_error_msg(ERR_PERMISSION_DENIED, outname);
284 bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
289 while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
291 dwrite_str(STDOUT_FILENO, outname);
292 dwrite_str(STDOUT_FILENO, " = ");
294 dwrite_str(STDOUT_FILENO, inbuf);
302 } /* end sysctl_read_setting() */
307 * Display all the sysctl settings
310 int sysctl_display_all(const char *path, int output, int show_table)
319 if (!(dp = opendir(path))) {
320 bb_perror_msg(ERR_OPENING_DIR, path);
323 while ((de = readdir(dp)) != NULL) {
324 tmpdir = concat_subpath_file(path, de->d_name);
327 if ((retval2 = stat(tmpdir, &ts)) != 0)
328 bb_perror_msg(tmpdir);
330 if (S_ISDIR(ts.st_mode)) {
331 sysctl_display_all(tmpdir, output, show_table);
334 sysctl_read_setting(tmpdir + bb_strlen(PROC_PATH),
344 } /* end sysctl_display_all() */
346 #ifdef STANDALONE_SYSCTL
347 int main(int argc, char **argv)
349 return sysctl_main(argc, argv);
351 const char *bb_applet_name = "sysctl";