Bernhard Reutner-Fischer | e15d757 | 2006-06-02 20:56:16 +0000 | [diff] [blame] | 1 | /* vi: set sw=4 ts=4: */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 2 | /* |
| 3 | * Sysctl 1.01 - A utility to read and manipulate the sysctl parameters |
| 4 | * |
Rob Landley | 8b1f11d | 2006-04-17 21:49:34 +0000 | [diff] [blame] | 5 | * Copyright 1999 George Staikos |
Bernhard Reutner-Fischer | cb44816 | 2006-04-12 07:35:12 +0000 | [diff] [blame] | 6 | * |
| 7 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 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> |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 14 | * |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 15 | */ |
| 16 | |
Denis Vlasenko | b6adbf1 | 2007-05-26 19:00:18 +0000 | [diff] [blame] | 17 | #include "libbb.h" |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 18 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 19 | static int sysctl_read_setting(const char *setting); |
| 20 | static int sysctl_write_setting(const char *setting); |
| 21 | static int sysctl_display_all(const char *path); |
| 22 | static int sysctl_preload_file_and_exit(const char *filename); |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame^] | 23 | static void sysctl_dots_to_slashes(char *name); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 24 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 25 | static const char ETC_SYSCTL_CONF[] ALIGN1 = "/etc/sysctl.conf"; |
| 26 | static const char PROC_SYS[] ALIGN1 = "/proc/sys/"; |
| 27 | enum { strlen_PROC_SYS = sizeof(PROC_SYS) - 1 }; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 28 | |
| 29 | /* error messages */ |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 30 | static const char ERR_MALFORMED_SETTING[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 31 | "error: malformed setting '%s'"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 32 | static const char ERR_NO_EQUALS[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 33 | "error: '%s' must be of the form name=value"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 34 | static const char ERR_INVALID_KEY[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 35 | "error: '%s' is an unknown key"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 36 | static const char ERR_UNKNOWN_WRITING[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 37 | "error setting key '%s'"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 38 | static const char ERR_UNKNOWN_READING[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 39 | "error reading key '%s'"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 40 | static const char ERR_PERMISSION_DENIED[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 41 | "error: permission denied on key '%s'"; |
Denis Vlasenko | 6ca409e | 2007-08-12 20:58:27 +0000 | [diff] [blame] | 42 | static const char WARN_BAD_LINE[] ALIGN1 = |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 43 | "warning: %s(%d): invalid syntax, continuing"; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 44 | |
| 45 | |
Glenn L McGrath | ab82154 | 2003-12-26 02:19:34 +0000 | [diff] [blame] | 46 | static void dwrite_str(int fd, const char *buf) |
| 47 | { |
| 48 | write(fd, buf, strlen(buf)); |
| 49 | } |
| 50 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 51 | enum { |
| 52 | FLAG_SHOW_KEYS = 1 << 0, |
| 53 | FLAG_SHOW_KEY_ERRORS = 1 << 1, |
| 54 | FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */ |
| 55 | FLAG_SHOW_ALL = 1 << 3, |
| 56 | FLAG_PRELOAD_FILE = 1 << 4, |
| 57 | FLAG_WRITE = 1 << 5, |
| 58 | }; |
| 59 | |
Denis Vlasenko | 9b49a5e | 2007-10-11 10:05:36 +0000 | [diff] [blame] | 60 | int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
Denis Vlasenko | a60f84e | 2008-07-05 09:18:54 +0000 | [diff] [blame] | 61 | int sysctl_main(int argc UNUSED_PARAM, char **argv) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 62 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 63 | int retval; |
| 64 | int opt; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 65 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 66 | opt = getopt32(argv, "+neAapw"); /* '+' - stop on first non-option */ |
| 67 | argv += optind; |
| 68 | opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
| 69 | option_mask32 ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 70 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 71 | if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) |
| 72 | return sysctl_display_all(PROC_SYS); |
| 73 | if (opt & FLAG_PRELOAD_FILE) |
| 74 | return sysctl_preload_file_and_exit(*argv ? *argv : ETC_SYSCTL_CONF); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 75 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 76 | retval = 0; |
| 77 | while (*argv) { |
| 78 | if (opt & FLAG_WRITE) |
| 79 | retval |= sysctl_write_setting(*argv); |
| 80 | else |
| 81 | retval |= sysctl_read_setting(*argv); |
| 82 | argv++; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 83 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 84 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 85 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 86 | } /* end sysctl_main() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 87 | |
| 88 | /* |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 89 | * preload the sysctl's from a conf file |
| 90 | * - we parse the file and then reform it (strip out whitespace) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 91 | */ |
Glenn L McGrath | ab82154 | 2003-12-26 02:19:34 +0000 | [diff] [blame] | 92 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 93 | static int sysctl_preload_file_and_exit(const char *filename) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 94 | { |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 95 | char *token[2]; |
| 96 | parser_t *parser; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 97 | |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 98 | parser = config_open(filename); |
Denis Vlasenko | 084266e | 2008-07-26 23:08:31 +0000 | [diff] [blame] | 99 | while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) { // TODO: ';' is comment char too |
Denis Vlasenko | 5415c85 | 2008-07-21 23:05:26 +0000 | [diff] [blame] | 100 | // if (!token[1]) { |
| 101 | // bb_error_msg(WARN_BAD_LINE, filename, parser->lineno); |
| 102 | // } else { |
| 103 | { |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 104 | #if 0 |
| 105 | char *s = xasprintf("%s=%s", token[0], token[1]); |
| 106 | sysctl_write_setting(s); |
| 107 | free(s); |
| 108 | #else // PLAY_WITH_FIRE for -4 bytes? |
| 109 | sprintf(parser->line, "%s=%s", token[0], token[1]); // must have room by definition |
| 110 | sysctl_write_setting(parser->line); |
| 111 | #endif |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 112 | } |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 113 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 114 | if (ENABLE_FEATURE_CLEAN_UP) |
Denis Vlasenko | 4a717e0 | 2008-07-20 13:01:56 +0000 | [diff] [blame] | 115 | config_close(parser); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 116 | return 0; |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 117 | } /* end sysctl_preload_file_and_exit() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 118 | |
| 119 | /* |
| 120 | * Write a single sysctl setting |
| 121 | */ |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 122 | static int sysctl_write_setting(const char *setting) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 123 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 124 | int retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 125 | const char *name; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 126 | const char *value; |
| 127 | const char *equals; |
| 128 | char *tmpname, *outname, *cptr; |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 129 | int fd; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 130 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 131 | name = setting; |
| 132 | equals = strchr(setting, '='); |
| 133 | if (!equals) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 134 | bb_error_msg(ERR_NO_EQUALS, setting); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 135 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 136 | } |
| 137 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 138 | value = equals + 1; /* point to the value in name=value */ |
| 139 | if (name == equals || !*value) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 140 | bb_error_msg(ERR_MALFORMED_SETTING, setting); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 141 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 142 | } |
| 143 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 144 | tmpname = xasprintf("%s%.*s", PROC_SYS, (int)(equals - name), name); |
| 145 | outname = xstrdup(tmpname + strlen_PROC_SYS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 146 | |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame^] | 147 | sysctl_dots_to_slashes(tmpname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 148 | |
| 149 | while ((cptr = strchr(outname, '/')) != NULL) |
| 150 | *cptr = '.'; |
| 151 | |
Denis Vlasenko | 50f7f44 | 2007-04-11 23:20:53 +0000 | [diff] [blame] | 152 | fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666); |
| 153 | if (fd < 0) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 154 | switch (errno) { |
| 155 | case ENOENT: |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 156 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| 157 | bb_error_msg(ERR_INVALID_KEY, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 158 | break; |
| 159 | case EACCES: |
| 160 | bb_perror_msg(ERR_PERMISSION_DENIED, outname); |
| 161 | break; |
| 162 | default: |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 163 | bb_perror_msg(ERR_UNKNOWN_WRITING, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 164 | break; |
| 165 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 166 | retval = EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 167 | } else { |
Glenn L McGrath | ab82154 | 2003-12-26 02:19:34 +0000 | [diff] [blame] | 168 | dwrite_str(fd, value); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 169 | close(fd); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 170 | if (option_mask32 & FLAG_SHOW_KEYS) { |
| 171 | printf("%s = ", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 172 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 173 | puts(value); |
| 174 | retval = EXIT_SUCCESS; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 175 | } |
| 176 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 177 | free(tmpname); |
| 178 | free(outname); |
| 179 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 180 | } /* end sysctl_write_setting() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 181 | |
| 182 | /* |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 183 | * Read a sysctl setting |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 184 | */ |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 185 | static int sysctl_read_setting(const char *name) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 186 | { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 187 | int retval; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 188 | char *tmpname, *outname, *cptr; |
| 189 | char inbuf[1025]; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 190 | FILE *fp; |
| 191 | |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 192 | if (!*name) { |
| 193 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| 194 | bb_error_msg(ERR_INVALID_KEY, name); |
| 195 | return -1; |
| 196 | } |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 197 | |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 198 | tmpname = concat_path_file(PROC_SYS, name); |
| 199 | outname = xstrdup(tmpname + strlen_PROC_SYS); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 200 | |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame^] | 201 | sysctl_dots_to_slashes(tmpname); |
| 202 | |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 203 | while ((cptr = strchr(outname, '/')) != NULL) |
| 204 | *cptr = '.'; |
| 205 | |
Denis Vlasenko | 5415c85 | 2008-07-21 23:05:26 +0000 | [diff] [blame] | 206 | fp = fopen_for_read(tmpname); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 207 | if (fp == NULL) { |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 208 | switch (errno) { |
| 209 | case ENOENT: |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 210 | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| 211 | bb_error_msg(ERR_INVALID_KEY, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 212 | break; |
| 213 | case EACCES: |
| 214 | bb_error_msg(ERR_PERMISSION_DENIED, outname); |
| 215 | break; |
| 216 | default: |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 217 | bb_perror_msg(ERR_UNKNOWN_READING, outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 218 | break; |
| 219 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 220 | retval = EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 221 | } else { |
| 222 | while (fgets(inbuf, sizeof(inbuf) - 1, fp)) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 223 | if (option_mask32 & FLAG_SHOW_KEYS) { |
| 224 | printf("%s = ", outname); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 225 | } |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 226 | fputs(inbuf, stdout); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 227 | } |
| 228 | fclose(fp); |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 229 | retval = EXIT_SUCCESS; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 230 | } |
| 231 | |
| 232 | free(tmpname); |
| 233 | free(outname); |
| 234 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 235 | } /* end sysctl_read_setting() */ |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 236 | |
| 237 | /* |
Eric Andersen | c7bda1c | 2004-03-15 08:29:22 +0000 | [diff] [blame] | 238 | * Display all the sysctl settings |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 239 | */ |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 240 | static int sysctl_display_all(const char *path) |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 241 | { |
| 242 | int retval = 0; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 243 | DIR *dp; |
| 244 | struct dirent *de; |
| 245 | char *tmpdir; |
| 246 | struct stat ts; |
| 247 | |
Denis Vlasenko | 51742f4 | 2007-04-12 00:32:05 +0000 | [diff] [blame] | 248 | dp = opendir(path); |
| 249 | if (!dp) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 250 | return EXIT_FAILURE; |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 251 | } |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 252 | while ((de = readdir(dp)) != NULL) { |
| 253 | tmpdir = concat_subpath_file(path, de->d_name); |
| 254 | if (tmpdir == NULL) |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 255 | continue; /* . or .. */ |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 256 | if (stat(tmpdir, &ts) != 0) { |
| 257 | bb_perror_msg(tmpdir); |
| 258 | } else if (S_ISDIR(ts.st_mode)) { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 259 | retval |= sysctl_display_all(tmpdir); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 260 | } else { |
Denis Vlasenko | 64309f8 | 2007-11-29 06:40:28 +0000 | [diff] [blame] | 261 | retval |= sysctl_read_setting(tmpdir + strlen_PROC_SYS); |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 262 | } |
| 263 | free(tmpdir); |
| 264 | } /* end while */ |
| 265 | closedir(dp); |
Eric Andersen | b905028 | 2003-12-24 06:02:11 +0000 | [diff] [blame] | 266 | |
| 267 | return retval; |
Denis Vlasenko | 5a28a25 | 2007-10-29 19:22:13 +0000 | [diff] [blame] | 268 | } /* end sysctl_display_all() */ |
Denis Vlasenko | 58cc52a | 2008-10-15 08:22:55 +0000 | [diff] [blame^] | 269 | |
| 270 | static void sysctl_dots_to_slashes(char *name) |
| 271 | { |
| 272 | char *cptr = name; |
| 273 | |
| 274 | /* Example from bug 3894: |
| 275 | * net.ipv4.conf.eth0.100.mc_forwarding -> |
| 276 | * net/ipv4/conf/eth0.100/mc_forwarding */ |
| 277 | while (*cptr != '\0') { |
| 278 | if (*cptr == '.') { |
| 279 | *cptr = '\0'; |
| 280 | if (access(name, F_OK) == 0) |
| 281 | *cptr = '/'; |
| 282 | else |
| 283 | *cptr = '.'; |
| 284 | } |
| 285 | cptr++; |
| 286 | } |
| 287 | } /* end sysctl_dots_to_slashes() */ |