source: MondoRescue/branches/stable/mindi-busybox/procps/sysctl.c@ 821

Last change on this file since 821 was 821, checked in by Bruno Cornec, 18 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

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