1 /* vi: set sw=4 ts=4: */
3 * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
5 * Copyright 1999 George Staikos
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
11 * - added -p <preload> to preload values from a file
13 * - busybox applet aware by <solar@gentoo.org>
22 #include <sys/types.h>
31 static int sysctl_read_setting(const char *setting, int output);
32 static int sysctl_write_setting(const char *setting, int output);
33 static int sysctl_preload_file(const char *filename, int output);
34 static int sysctl_display_all(const char *path, int output, int show_table);
39 static const char PROC_PATH[] = "/proc/sys/";
40 static const char DEFAULT_PRELOAD[] = "/etc/sysctl.conf";
43 static const char ERR_UNKNOWN_PARAMETER[] = "error: Unknown parameter '%s'\n";
44 static const char ERR_MALFORMED_SETTING[] = "error: Malformed setting '%s'\n";
45 static const char ERR_NO_EQUALS[] =
46 "error: '%s' must be of the form name=value\n";
47 static const char ERR_INVALID_KEY[] = "error: '%s' is an unknown key\n";
48 static const char ERR_UNKNOWN_WRITING[] =
49 "error: unknown error %d setting key '%s'\n";
50 static const char ERR_UNKNOWN_READING[] =
51 "error: unknown error %d reading key '%s'\n";
52 static const char ERR_PERMISSION_DENIED[] =
53 "error: permission denied on key '%s'\n";
54 static const char ERR_PRELOAD_FILE[] =
55 "error: unable to open preload file '%s'\n";
56 static const char WARN_BAD_LINE[] =
57 "warning: %s(%d): invalid syntax, continuing...\n";
60 static void dwrite_str(int fd, const char *buf)
62 write(fd, buf, strlen(buf));
68 int sysctl_main(int argc, char **argv)
73 int switches_allowed = 1;
80 for (; argv && *argv && **argv; argv++) {
81 if (switches_allowed && **argv == '-') { /* we have a switch */
93 sysctl_preload_file(((argv && *argv
95 DEFAULT_PRELOAD), output);
99 return sysctl_display_all(PROC_PATH, output,
100 ((*argv)[1] == 'a') ? 0 : 1);
105 bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
109 switches_allowed = 0;
111 retval = sysctl_write_setting(*argv, output);
113 sysctl_read_setting(*argv, output);
117 } /* end sysctl_main() */
122 * sysctl_preload_file
123 * preload the sysctl's from a conf file
124 * - we parse the file and then reform it (strip out whitespace)
126 #define PRELOAD_BUF 256
128 int sysctl_preload_file(const char *filename, int output)
131 char oneline[PRELOAD_BUF];
132 char buffer[PRELOAD_BUF];
133 char *name, *value, *ptr;
136 if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
137 bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
140 while (fgets(oneline, sizeof(oneline) - 1, fp)) {
141 oneline[sizeof(oneline) - 1] = 0;
144 ptr = (char *) oneline;
146 if (*ptr == '#' || *ptr == ';')
152 name = strtok(ptr, "=");
153 if (!name || !*name) {
154 bb_error_msg(WARN_BAD_LINE, filename, lineno);
160 value = strtok(NULL, "\n\r");
161 if (!value || !*value) {
162 bb_error_msg(WARN_BAD_LINE, filename, lineno);
166 while ((*value == ' ' || *value == '\t') && *value != 0)
168 strcpy(buffer, name);
170 strcat(buffer, value);
171 sysctl_write_setting(buffer, output);
175 } /* end sysctl_preload_file() */
179 * Write a single sysctl setting
181 int sysctl_write_setting(const char *setting, int output)
184 const char *name = setting;
187 char *tmpname, *outname, *cptr;
190 if (!name) /* probably dont' want to display this err */
193 if (!(equals = strchr(setting, '='))) {
194 bb_error_msg(ERR_NO_EQUALS, setting);
198 value = equals + sizeof(char); /* point to the value in name=value */
200 if (!*name || !*value || name == equals) {
201 bb_error_msg(ERR_MALFORMED_SETTING, setting);
205 tmpname = bb_xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
206 outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
208 while ((cptr = strchr(tmpname, '.')) != NULL)
211 while ((cptr = strchr(outname, '/')) != NULL)
214 if ((fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0) {
217 bb_error_msg(ERR_INVALID_KEY, outname);
220 bb_perror_msg(ERR_PERMISSION_DENIED, outname);
223 bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
228 dwrite_str(fd, value);
231 dwrite_str(STDOUT_FILENO, outname);
232 dwrite_str(STDOUT_FILENO, " = ");
234 dwrite_str(STDOUT_FILENO, value);
235 dwrite_str(STDOUT_FILENO, "\n");
242 } /* end sysctl_write_setting() */
246 * Read a sysctl setting
249 int sysctl_read_setting(const char *setting, int output)
252 char *tmpname, *outname, *cptr;
254 const char *name = setting;
257 if (!setting || !*setting)
258 bb_error_msg(ERR_INVALID_KEY, setting);
260 tmpname = concat_path_file(PROC_PATH, name);
261 outname = bb_xstrdup(tmpname + strlen(PROC_PATH));
263 while ((cptr = strchr(tmpname, '.')) != NULL)
265 while ((cptr = strchr(outname, '/')) != NULL)
268 if ((fp = fopen(tmpname, "r")) == NULL) {
271 bb_error_msg(ERR_INVALID_KEY, outname);
274 bb_error_msg(ERR_PERMISSION_DENIED, outname);
277 bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
282 while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
284 dwrite_str(STDOUT_FILENO, outname);
285 dwrite_str(STDOUT_FILENO, " = ");
287 dwrite_str(STDOUT_FILENO, inbuf);
295 } /* end sysctl_read_setting() */
300 * Display all the sysctl settings
303 int sysctl_display_all(const char *path, int output, int show_table)
312 if (!(dp = bb_opendir(path))) {
315 while ((de = readdir(dp)) != NULL) {
316 tmpdir = concat_subpath_file(path, de->d_name);
319 if ((retval2 = stat(tmpdir, &ts)) != 0)
320 bb_perror_msg(tmpdir);
322 if (S_ISDIR(ts.st_mode)) {
323 sysctl_display_all(tmpdir, output, show_table);
326 sysctl_read_setting(tmpdir + strlen(PROC_PATH),
336 } /* end sysctl_display_all() */