summaryrefslogtreecommitdiff
path: root/procps/sysctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'procps/sysctl.c')
-rw-r--r--procps/sysctl.c168
1 files changed, 71 insertions, 97 deletions
diff --git a/procps/sysctl.c b/procps/sysctl.c
index a129480..3a0af02 100644
--- a/procps/sysctl.c
+++ b/procps/sysctl.c
@@ -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 */