source: MondoRescue/branches/2.2.9/mindi-busybox/procps/sysctl.c@ 2142

Last change on this file since 2142 was 1765, checked in by Bruno Cornec, 16 years ago

Update to busybox 1.7.2

File size: 7.3 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters
4 *
5 * Copyright 1999 George Staikos
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8 *
9 * Changelog:
10 * v1.01:
11 * - added -p <preload> to preload values from a file
12 * v1.01.1
13 * - busybox applet aware by <solar@gentoo.org>
14 *
15 */
16
17#include "libbb.h"
18
19/*
20 * Function Prototypes
21 */
22static int sysctl_read_setting(const char *setting, int output);
23static int sysctl_write_setting(const char *setting, int output);
24static int sysctl_preload_file(const char *filename, int output);
25static int sysctl_display_all(const char *path, int output, int show_table);
26
27/*
28 * Globals...
29 */
30static const char PROC_PATH[] ALIGN1 = "/proc/sys/";
31static const char DEFAULT_PRELOAD[] ALIGN1 = "/etc/sysctl.conf";
32
33/* error messages */
34static const char ERR_UNKNOWN_PARAMETER[] ALIGN1 =
35 "error: Unknown parameter '%s'\n";
36static const char ERR_MALFORMED_SETTING[] ALIGN1 =
37 "error: Malformed setting '%s'\n";
38static const char ERR_NO_EQUALS[] ALIGN1 =
39 "error: '%s' must be of the form name=value\n";
40static const char ERR_INVALID_KEY[] ALIGN1 =
41 "error: '%s' is an unknown key\n";
42static const char ERR_UNKNOWN_WRITING[] ALIGN1 =
43 "error: unknown error %d setting key '%s'\n";
44static const char ERR_UNKNOWN_READING[] ALIGN1 =
45 "error: unknown error %d reading key '%s'\n";
46static const char ERR_PERMISSION_DENIED[] ALIGN1 =
47 "error: permission denied on key '%s'\n";
48static const char ERR_PRELOAD_FILE[] ALIGN1 =
49 "error: cannot open preload file '%s'\n";
50static const char WARN_BAD_LINE[] ALIGN1 =
51 "warning: %s(%d): invalid syntax, continuing...\n";
52
53
54static void dwrite_str(int fd, const char *buf)
55{
56 write(fd, buf, strlen(buf));
57}
58
59/*
60 * sysctl_main()...
61 */
62int sysctl_main(int argc, char **argv);
63int sysctl_main(int argc, char **argv)
64{
65 int retval = 0;
66 int output = 1;
67 int write_mode = 0;
68 int switches_allowed = 1;
69
70 if (argc < 2)
71 bb_show_usage();
72
73 argv++;
74
75 for (; argv && *argv && **argv; argv++) {
76 if (switches_allowed && **argv == '-') { /* we have a switch */
77 switch ((*argv)[1]) {
78 case 'n':
79 output = 0;
80 break;
81 case 'w':
82 write_mode = 1;
83 switches_allowed = 0;
84 break;
85 case 'p':
86 argv++;
87 return
88 sysctl_preload_file(((argv && *argv
89 && **argv) ? *argv :
90 DEFAULT_PRELOAD), output);
91 case 'a':
92 case 'A':
93 switches_allowed = 0;
94 return sysctl_display_all(PROC_PATH, output,
95 ((*argv)[1] == 'a') ? 0 : 1);
96 case 'h':
97 case '?':
98 bb_show_usage();
99 default:
100 bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv);
101 bb_show_usage();
102 }
103 } else {
104 switches_allowed = 0;
105 if (write_mode)
106 retval = sysctl_write_setting(*argv, output);
107 else
108 sysctl_read_setting(*argv, output);
109 }
110 }
111 return retval;
112} /* end sysctl_main() */
113
114
115
116/*
117 * sysctl_preload_file
118 * preload the sysctl's from a conf file
119 * - we parse the file and then reform it (strip out whitespace)
120 */
121#define PRELOAD_BUF 256
122
123int sysctl_preload_file(const char *filename, int output)
124{
125 int lineno = 0;
126 char oneline[PRELOAD_BUF];
127 char buffer[PRELOAD_BUF];
128 char *name, *value, *ptr;
129 FILE *fp = NULL;
130
131 if (!filename || ((fp = fopen(filename, "r")) == NULL)) {
132 bb_error_msg_and_die(ERR_PRELOAD_FILE, filename);
133 }
134
135 while (fgets(oneline, sizeof(oneline) - 1, fp)) {
136 oneline[sizeof(oneline) - 1] = '\0';
137 lineno++;
138 trim(oneline);
139 ptr = (char *) oneline;
140
141 if (*ptr == '#' || *ptr == ';')
142 continue;
143
144 if (strlen(ptr) < 2)
145 continue;
146
147 name = strtok(ptr, "=");
148 if (!name || !*name) {
149 bb_error_msg(WARN_BAD_LINE, filename, lineno);
150 continue;
151 }
152
153 trim(name);
154
155 value = strtok(NULL, "\n\r");
156 if (!value || !*value) {
157 bb_error_msg(WARN_BAD_LINE, filename, lineno);
158 continue;
159 }
160
161 while ((*value == ' ' || *value == '\t') && *value != 0)
162 value++;
163 /* safe because sizeof(oneline) == sizeof(buffer) */
164 sprintf(buffer, "%s=%s", name, value);
165 sysctl_write_setting(buffer, output);
166 }
167 fclose(fp);
168 return 0;
169} /* end sysctl_preload_file() */
170
171
172/*
173 * Write a single sysctl setting
174 */
175int sysctl_write_setting(const char *setting, int output)
176{
177 int retval = 0;
178 const char *name = setting;
179 const char *value;
180 const char *equals;
181 char *tmpname, *outname, *cptr;
182 int fd = -1;
183
184 if (!name) /* probably dont' want to display this err */
185 return 0;
186
187 if (!(equals = strchr(setting, '='))) {
188 bb_error_msg(ERR_NO_EQUALS, setting);
189 return -1;
190 }
191
192 value = equals + sizeof(char); /* point to the value in name=value */
193
194 if (!*name || !*value || name == equals) {
195 bb_error_msg(ERR_MALFORMED_SETTING, setting);
196 return -2;
197 }
198
199 tmpname = xasprintf("%s%.*s", PROC_PATH, (int)(equals - name), name);
200 outname = xstrdup(tmpname + strlen(PROC_PATH));
201
202 while ((cptr = strchr(tmpname, '.')) != NULL)
203 *cptr = '/';
204
205 while ((cptr = strchr(outname, '/')) != NULL)
206 *cptr = '.';
207
208 fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
209 if (fd < 0) {
210 switch (errno) {
211 case ENOENT:
212 bb_error_msg(ERR_INVALID_KEY, outname);
213 break;
214 case EACCES:
215 bb_perror_msg(ERR_PERMISSION_DENIED, outname);
216 break;
217 default:
218 bb_error_msg(ERR_UNKNOWN_WRITING, errno, outname);
219 break;
220 }
221 retval = -1;
222 } else {
223 dwrite_str(fd, value);
224 close(fd);
225 if (output) {
226 dwrite_str(STDOUT_FILENO, outname);
227 dwrite_str(STDOUT_FILENO, " = ");
228 }
229 dwrite_str(STDOUT_FILENO, value);
230 dwrite_str(STDOUT_FILENO, "\n");
231 }
232
233 /* cleanup */
234 free(tmpname);
235 free(outname);
236 return retval;
237} /* end sysctl_write_setting() */
238
239
240/*
241 * Read a sysctl setting
242 *
243 */
244int sysctl_read_setting(const char *setting, int output)
245{
246 int retval = 0;
247 char *tmpname, *outname, *cptr;
248 char inbuf[1025];
249 const char *name = setting;
250 FILE *fp;
251
252 if (!setting || !*setting)
253 bb_error_msg(ERR_INVALID_KEY, setting);
254
255 tmpname = concat_path_file(PROC_PATH, name);
256 outname = xstrdup(tmpname + strlen(PROC_PATH));
257
258 while ((cptr = strchr(tmpname, '.')) != NULL)
259 *cptr = '/';
260 while ((cptr = strchr(outname, '/')) != NULL)
261 *cptr = '.';
262
263 if ((fp = fopen(tmpname, "r")) == NULL) {
264 switch (errno) {
265 case ENOENT:
266 bb_error_msg(ERR_INVALID_KEY, outname);
267 break;
268 case EACCES:
269 bb_error_msg(ERR_PERMISSION_DENIED, outname);
270 break;
271 default:
272 bb_error_msg(ERR_UNKNOWN_READING, errno, outname);
273 break;
274 }
275 retval = -1;
276 } else {
277 while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
278 if (output) {
279 dwrite_str(STDOUT_FILENO, outname);
280 dwrite_str(STDOUT_FILENO, " = ");
281 }
282 dwrite_str(STDOUT_FILENO, inbuf);
283 }
284 fclose(fp);
285 }
286
287 free(tmpname);
288 free(outname);
289 return retval;
290} /* end sysctl_read_setting() */
291
292
293
294/*
295 * Display all the sysctl settings
296 *
297 */
298int sysctl_display_all(const char *path, int output, int show_table)
299{
300 int retval = 0;
301 int retval2;
302 DIR *dp;
303 struct dirent *de;
304 char *tmpdir;
305 struct stat ts;
306
307 dp = opendir(path);
308 if (!dp) {
309 retval = -1;
310 } else {
311 while ((de = readdir(dp)) != NULL) {
312 tmpdir = concat_subpath_file(path, de->d_name);
313 if (tmpdir == NULL)
314 continue;
315 retval2 = stat(tmpdir, &ts);
316 if (retval2 != 0)
317 bb_perror_msg(tmpdir);
318 else {
319 if (S_ISDIR(ts.st_mode)) {
320 sysctl_display_all(tmpdir, output, show_table);
321 } else
322 retval |=
323 sysctl_read_setting(tmpdir + strlen(PROC_PATH),
324 output);
325
326 }
327 free(tmpdir);
328 } /* end while */
329 closedir(dp);
330 }
331
332 return retval;
333} /* end sysctl_display_all() */
Note: See TracBrowser for help on using the repository browser.