sysctl: add -e: supress warnings about invalid key (Jeremy Kerr
No binary (build failed)
—
(log yok)
| @@ -3505,16 +3505,17 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when | |
| "Configure kernel parameters at runtime" \ | |
| "\n\nOptions:\n" \ | |
| " -n Disable printing of key names\n" \ | |
| + | " -e Don't warn about unknown keys\n" \ |
| " -w Change sysctl setting\n" \ | |
| " -p FILE Load sysctl settings from FILE (default /etc/sysctl.conf)\n" \ | |
| " -a Display all values\n" \ | |
| " -A Display all values in table form" | |
| #define sysctl_example_usage \ | |
| - | "sysctl [-n] variable...\n" \ |
| - | "sysctl [-n] -w variable=value...\n" \ |
| - | "sysctl [-n] -a\n" \ |
| - | "sysctl [-n] -p file (default /etc/sysctl.conf)\n" \ |
| - | "sysctl [-n] -A\n" |
| + | "sysctl [-n] [-e] variable...\n" \ |
| + | "sysctl [-n] [-e] -w variable=value...\n" \ |
| + | "sysctl [-n] [-e] -a\n" \ |
| + | "sysctl [-n] [-e] -p file (default /etc/sysctl.conf)\n" \ |
| + | "sysctl [-n] [-e] -A\n" |
| #define syslogd_trivial_usage \ | |
| "[OPTION]..." | |
| @@ -16,24 +16,16 @@ | |
| #include "libbb.h" | |
| - | /* |
| - | * Function Prototypes |
| - | */ |
| - | static int sysctl_read_setting(const char *setting, int output); |
| - | static int sysctl_write_setting(const char *setting, int output); |
| - | static int sysctl_preload_file(const char *filename, int output); |
| - | static int sysctl_display_all(const char *path, int output, int show_table); |
| + | static int sysctl_read_setting(const char *setting); |
| + | static int sysctl_write_setting(const char *setting); |
| + | static int sysctl_display_all(const char *path); |
| + | static int sysctl_preload_file_and_exit(const char *filename); |
| - | /* |
| - | * Globals... |
| - | */ |
| static const char ETC_SYSCTL_CONF[] ALIGN1 = "/etc/sysctl.conf"; | |
| static const char PROC_SYS[] ALIGN1 = "/proc/sys/"; | |
| enum { strlen_PROC_SYS = sizeof(PROC_SYS) - 1 }; | |
| /* error messages */ | |
| - | static const char ERR_UNKNOWN_PARAMETER[] ALIGN1 = |
| - | "error: unknown parameter '%s'"; |
| static const char ERR_MALFORMED_SETTING[] ALIGN1 = | |
| "error: malformed setting '%s'"; | |
| static const char ERR_NO_EQUALS[] ALIGN1 = | |
| @@ -46,8 +38,6 @@ static const char ERR_UNKNOWN_READING[] ALIGN1 = | |
| "error reading key '%s'"; | |
| static const char ERR_PERMISSION_DENIED[] ALIGN1 = | |
| "error: permission denied on key '%s'"; | |
| - | static const char ERR_PRELOAD_FILE[] ALIGN1 = |
| - | "error: cannot open preload file '%s'"; |
| static const char WARN_BAD_LINE[] ALIGN1 = | |
| "warning: %s(%d): invalid syntax, continuing"; | |
| @@ -57,66 +47,50 @@ static void dwrite_str(int fd, const char *buf) | |
| write(fd, buf, strlen(buf)); | |
| } | |
| - | /* |
| - | * sysctl_main()... |
| - | */ |
| + | enum { |
| + | FLAG_SHOW_KEYS = 1 << 0, |
| + | FLAG_SHOW_KEY_ERRORS = 1 << 1, |
| + | FLAG_TABLE_FORMAT = 1 << 2, /* not implemented */ |
| + | FLAG_SHOW_ALL = 1 << 3, |
| + | FLAG_PRELOAD_FILE = 1 << 4, |
| + | FLAG_WRITE = 1 << 5, |
| + | }; |
| + | |
| int sysctl_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int sysctl_main(int argc, char **argv) | |
| { | |
| - | int retval = 0; |
| - | int output = 1; |
| - | int write_mode = 0; |
| - | int switches_allowed = 1; |
| - | |
| - | if (argc < 2) |
| - | bb_show_usage(); |
| - | |
| - | argv++; |
| - | |
| - | for (; *argv /*&& **argv*/; argv++) { |
| - | if (switches_allowed && **argv == '-') { /* we have a switch */ |
| - | switch ((*argv)[1]) { |
| - | case 'n': |
| - | output = 0; |
| - | break; |
| - | case 'w': |
| - | write_mode = 1; |
| - | switches_allowed = 0; |
| - | break; |
| - | case 'p': |
| - | argv++; |
| - | return sysctl_preload_file(((*argv /*&& **argv*/) ? *argv : ETC_SYSCTL_CONF), |
| - | output); |
| - | case 'a': |
| - | case 'A': |
| - | return sysctl_display_all(PROC_SYS, output, |
| - | ((*argv)[1] == 'A')); |
| - | default: |
| - | bb_error_msg(ERR_UNKNOWN_PARAMETER, *argv); |
| - | /* fall through */ |
| - | //case 'h': |
| - | //case '?': |
| - | bb_show_usage(); |
| - | } |
| - | } else { |
| - | switches_allowed = 0; |
| - | if (write_mode) |
| - | retval |= sysctl_write_setting(*argv, output); |
| - | else |
| - | sysctl_read_setting(*argv, output); |
| - | } |
| + | int retval; |
| + | int opt; |
| + | |
| + | opt = getopt32(argv, "+neAapw"); /* '+' - stop on first non-option */ |
| + | argv += optind; |
| + | opt ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
| + | option_mask32 ^= (FLAG_SHOW_KEYS | FLAG_SHOW_KEY_ERRORS); |
| + | |
| + | if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) |
| + | return sysctl_display_all(PROC_SYS); |
| + | if (opt & FLAG_PRELOAD_FILE) |
| + | return sysctl_preload_file_and_exit(*argv ? *argv : ETC_SYSCTL_CONF); |
| + | |
| + | retval = 0; |
| + | while (*argv) { |
| + | if (opt & FLAG_WRITE) |
| + | retval |= sysctl_write_setting(*argv); |
| + | else |
| + | retval |= sysctl_read_setting(*argv); |
| + | argv++; |
| } | |
| + | |
| return retval; | |
| } /* end sysctl_main() */ | |
| /* | |
| - | * sysctl_preload_file |
| * preload the sysctl's from a conf file | |
| * - we parse the file and then reform it (strip out whitespace) | |
| */ | |
| #define PRELOAD_BUF 256 | |
| - | static int sysctl_preload_file(const char *filename, int output) |
| + | static int sysctl_preload_file_and_exit(const char *filename) |
| { | |
| int lineno; | |
| char oneline[PRELOAD_BUF]; | |
| @@ -124,10 +98,7 @@ static int sysctl_preload_file(const char *filename, int output) | |
| char *name, *value; | |
| FILE *fp; | |
| - | fp = fopen(filename, "r"); |
| - | if (fp == NULL) { |
| - | bb_error_msg_and_die(ERR_PRELOAD_FILE, filename); |
| - | } |
| + | fp = xfopen(filename, "r"); |
| lineno = 0; | |
| while (fgets(oneline, sizeof(oneline) - 1, fp)) { | |
| @@ -163,35 +134,36 @@ static int sysctl_preload_file(const char *filename, int output) | |
| /* safe because sizeof(oneline) == sizeof(buffer) */ | |
| sprintf(buffer, "%s=%s", name, value); | |
| - | sysctl_write_setting(buffer, output); |
| + | sysctl_write_setting(buffer); |
| } | |
| - | fclose(fp); |
| + | if (ENABLE_FEATURE_CLEAN_UP) |
| + | fclose(fp); |
| return 0; | |
| - | } /* end sysctl_preload_file() */ |
| + | } /* end sysctl_preload_file_and_exit() */ |
| /* | |
| * Write a single sysctl setting | |
| */ | |
| - | static int sysctl_write_setting(const char *setting, int output) |
| + | static int sysctl_write_setting(const char *setting) |
| { | |
| - | int retval = 0; |
| + | int retval; |
| const char *name; | |
| const char *value; | |
| const char *equals; | |
| char *tmpname, *outname, *cptr; | |
| - | int fd = -1; |
| + | int fd; |
| name = setting; | |
| equals = strchr(setting, '='); | |
| if (!equals) { | |
| bb_error_msg(ERR_NO_EQUALS, setting); | |
| - | return -1; |
| + | return EXIT_FAILURE; |
| } | |
| value = equals + 1; /* point to the value in name=value */ | |
| if (name == equals || !*value) { | |
| bb_error_msg(ERR_MALFORMED_SETTING, setting); | |
| - | return -2; |
| + | return EXIT_FAILURE; |
| } | |
| tmpname = xasprintf("%s%.*s", PROC_SYS, (int)(equals - name), name); | |
| @@ -207,7 +179,8 @@ static int sysctl_write_setting(const char *setting, int output) | |
| if (fd < 0) { | |
| switch (errno) { | |
| case ENOENT: | |
| - | bb_error_msg(ERR_INVALID_KEY, outname); |
| + | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| + | bb_error_msg(ERR_INVALID_KEY, outname); |
| break; | |
| case EACCES: | |
| bb_perror_msg(ERR_PERMISSION_DENIED, outname); | |
| @@ -216,16 +189,15 @@ static int sysctl_write_setting(const char *setting, int output) | |
| bb_perror_msg(ERR_UNKNOWN_WRITING, outname); | |
| break; | |
| } | |
| - | retval = -1; |
| + | retval = EXIT_FAILURE; |
| } else { | |
| dwrite_str(fd, value); | |
| close(fd); | |
| - | if (output) { |
| - | dwrite_str(STDOUT_FILENO, outname); |
| - | dwrite_str(STDOUT_FILENO, " = "); |
| + | if (option_mask32 & FLAG_SHOW_KEYS) { |
| + | printf("%s = ", outname); |
| } | |
| - | dwrite_str(STDOUT_FILENO, value); |
| - | dwrite_str(STDOUT_FILENO, "\n"); |
| + | puts(value); |
| + | retval = EXIT_SUCCESS; |
| } | |
| free(tmpname); | |
| @@ -236,18 +208,19 @@ static int sysctl_write_setting(const char *setting, int output) | |
| /* | |
| * Read a sysctl setting | |
| */ | |
| - | static int sysctl_read_setting(const char *setting, int output) |
| + | static int sysctl_read_setting(const char *name) |
| { | |
| - | int retval = 0; |
| + | int retval; |
| char *tmpname, *outname, *cptr; | |
| char inbuf[1025]; | |
| - | const char *name; |
| FILE *fp; | |
| - | if (!*setting) |
| - | bb_error_msg(ERR_INVALID_KEY, setting); |
| + | if (!*name) { |
| + | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| + | bb_error_msg(ERR_INVALID_KEY, name); |
| + | return -1; |
| + | } |
| - | name = setting; |
| tmpname = concat_path_file(PROC_SYS, name); | |
| outname = xstrdup(tmpname + strlen_PROC_SYS); | |
| @@ -260,7 +233,8 @@ static int sysctl_read_setting(const char *setting, int output) | |
| if (fp == NULL) { | |
| switch (errno) { | |
| case ENOENT: | |
| - | bb_error_msg(ERR_INVALID_KEY, outname); |
| + | if (option_mask32 & FLAG_SHOW_KEY_ERRORS) |
| + | bb_error_msg(ERR_INVALID_KEY, outname); |
| break; | |
| case EACCES: | |
| bb_error_msg(ERR_PERMISSION_DENIED, outname); | |
| @@ -269,16 +243,16 @@ static int sysctl_read_setting(const char *setting, int output) | |
| bb_perror_msg(ERR_UNKNOWN_READING, outname); | |
| break; | |
| } | |
| - | retval = -1; |
| + | retval = EXIT_FAILURE; |
| } else { | |
| while (fgets(inbuf, sizeof(inbuf) - 1, fp)) { | |
| - | if (output) { |
| - | dwrite_str(STDOUT_FILENO, outname); |
| - | dwrite_str(STDOUT_FILENO, " = "); |
| + | if (option_mask32 & FLAG_SHOW_KEYS) { |
| + | printf("%s = ", outname); |
| } | |
| - | dwrite_str(STDOUT_FILENO, inbuf); |
| + | fputs(inbuf, stdout); |
| } | |
| fclose(fp); | |
| + | retval = EXIT_SUCCESS; |
| } | |
| free(tmpname); | |
| @@ -289,7 +263,7 @@ static int sysctl_read_setting(const char *setting, int output) | |
| /* | |
| * Display all the sysctl settings | |
| */ | |
| - | static int sysctl_display_all(const char *path, int output, int show_table) |
| + | static int sysctl_display_all(const char *path) |
| { | |
| int retval = 0; | |
| DIR *dp; | |
| @@ -299,18 +273,18 @@ static int sysctl_display_all(const char *path, int output, int show_table) | |
| dp = opendir(path); | |
| if (!dp) { | |
| - | return -1; |
| + | return EXIT_FAILURE; |
| } | |
| while ((de = readdir(dp)) != NULL) { | |
| tmpdir = concat_subpath_file(path, de->d_name); | |
| if (tmpdir == NULL) | |
| - | continue; |
| + | continue; /* . or .. */ |
| if (stat(tmpdir, &ts) != 0) { | |
| bb_perror_msg(tmpdir); | |
| } else if (S_ISDIR(ts.st_mode)) { | |
| - | sysctl_display_all(tmpdir, output, show_table); |
| + | retval |= sysctl_display_all(tmpdir); |
| } else { | |
| - | retval |= sysctl_read_setting(tmpdir + strlen_PROC_SYS, output); |
| + | retval |= sysctl_read_setting(tmpdir + strlen_PROC_SYS); |
| } | |
| free(tmpdir); | |
| } /* end while */ | |