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

Last change on this file since 821 was 821, checked in by Bruno Cornec, 14 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.