*: tweak error messages
authorDenis Vlasenko <vda.linux@googlemail.com>
Wed, 24 Dec 2008 03:11:43 +0000 (03:11 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Wed, 24 Dec 2008 03:11:43 +0000 (03:11 -0000)
sysctl: shrink; support recursing if name is a directory:
 "sysctl net.ipv4.conf". Patch by xmaks AT email.cz

   text    data     bss     dec     hex filename
 793659     504    7492  801655   c3b77 busybox_old
 793576     504    7492  801572   c3b24 busybox_unstripped

e2fsprogs/old_e2fsprogs/e2fsck.c
modutils/modprobe.c
procps/sysctl.c

index 741536c1c58a702d8535f7e98c6c73c1f0b4aee7..b927a9f650985ce22b14c1b31c203b4501f625af 100644 (file)
@@ -12632,7 +12632,7 @@ static void check_mount(e2fsck_t ctx)
        retval = ext2fs_check_if_mounted(ctx->filesystem_name,
                                         &ctx->mount_flags);
        if (retval) {
-               bb_error_msg(_("while determining whether %s is mounted."),
+               bb_error_msg(_("while determining whether %s is mounted"),
                        ctx->filesystem_name);
                return;
        }
@@ -12653,7 +12653,7 @@ static void check_mount(e2fsck_t ctx)
 
        printf(_("%s is mounted.  "), ctx->filesystem_name);
        if (!ctx->interactive)
-               bb_error_msg_and_die(_("Cannot continue, aborting."));
+               bb_error_msg_and_die(_("cannot continue, aborting"));
        printf(_("\n\n\007\007\007\007WARNING!!!  "
               "Running e2fsck on a mounted filesystem may cause\n"
               "SEVERE filesystem damage.\007\007\007\n\n"));
@@ -13060,7 +13060,7 @@ static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
                case 'a':
                        if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
                        conflict_opt:
-                               bb_error_msg_and_die(_("Only one the options -p/-a, -n or -y may be specified."));
+                               bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
                        }
                        ctx->options |= E2F_OPT_PREEN;
                        break;
@@ -13405,7 +13405,7 @@ restart:
 #ifdef ENABLE_COMPRESSION
        /* FIXME - do we support this at all? */
        if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
-               bb_error_msg(_("Warning: compression support is experimental."));
+               bb_error_msg(_("warning: compression support is experimental"));
 #endif
 #ifndef ENABLE_HTREE
        if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
index 40a1e66270aece074b46c77badd1992795afc354..ad39be059c523a9293fdc60fd7ae46bdd6bff8f0 100644 (file)
@@ -193,7 +193,7 @@ error:
        if (ENABLE_FEATURE_CLEAN_UP)
                RELEASE_CONFIG_BUFFER(modname);
        if (rc > 0 && !(option_mask32 & INSMOD_OPT_SILENT))
-               bb_error_msg("Failed to %sload module %s: %s.",
+               bb_error_msg("failed to %sload module %s: %s",
                             (option_mask32 & MODPROBE_OPT_REMOVE) ? "un" : "",
                             module, moderror(rc));
        return rc;
@@ -270,7 +270,7 @@ int modprobe_main(int argc UNUSED_PARAM, char **argv)
                            check_blacklist(conf, conf->probename)) {
                                rc = do_modprobe(conf, conf->probename);
                                if (rc < 0 && !(opt & INSMOD_OPT_SILENT))
-                                       bb_error_msg("Module %s not found.", arg);
+                                       bb_error_msg("module %s not found", arg);
                        }
                } else {
                        /* Probe all aliases */
index 860c8406211a930446393d5f5f25f97cb71d2253..23fb16e9eaada9d396bd9f9eb0be719f4f4b80fc 100644 (file)
 
 #include "libbb.h"
 
-static int sysctl_read_setting(const char *setting);
-static int sysctl_write_setting(const char *setting);
+static int sysctl_act_on_setting(char *setting);
 static int sysctl_display_all(const char *path);
-static int sysctl_preload_file_and_exit(const char *filename);
+static int sysctl_handle_preload_file(const char *filename);
 static void sysctl_dots_to_slashes(char *name);
 
-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 };
-
-static const char msg_unknown_key[] ALIGN1 =
-       "error: '%s' is an unknown key";
-
 static void dwrite_str(int fd, const char *buf)
 {
        write(fd, buf, strlen(buf));
@@ -52,212 +44,209 @@ int sysctl_main(int argc UNUSED_PARAM, char **argv)
        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);
+       option_mask32 = opt;
 
-       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);
+       if (opt & FLAG_PRELOAD_FILE) {
+               option_mask32 |= FLAG_WRITE;
+               /* xchdir("/proc/sys") is inside */
+               return sysctl_handle_preload_file(*argv ? *argv : "/etc/sysctl.conf");
+       }
+       xchdir("/proc/sys");
+       /* xchroot(".") - if you are paranoid */
+       if (opt & (FLAG_TABLE_FORMAT | FLAG_SHOW_ALL)) {
+               return sysctl_display_all(".");
+       }
 
        retval = 0;
        while (*argv) {
-               if (opt & FLAG_WRITE)
-                       retval |= sysctl_write_setting(*argv);
-               else
-                       retval |= sysctl_read_setting(*argv);
+               sysctl_dots_to_slashes(*argv);
+               retval |= sysctl_display_all(*argv);
                argv++;
        }
 
        return retval;
-} /* end sysctl_main() */
+}
 
 /* Set sysctl's from a conf file. Format example:
  * # Controls IP packet forwarding
  * net.ipv4.ip_forward = 0
  */
-static int sysctl_preload_file_and_exit(const char *filename)
+static int sysctl_handle_preload_file(const char *filename)
 {
        char *token[2];
        parser_t *parser;
 
        parser = config_open(filename);
+       /* Must do it _after_ config_open(): */
+       xchdir("/proc/sys");
+       /* xchroot(".") - if you are paranoid */
+
 // TODO: ';' is comment char too
        while (config_read(parser, token, 2, 2, "# \t=", PARSE_NORMAL)) {
-#if 0
-               char *s = xasprintf("%s=%s", token[0], token[1]);
-               sysctl_write_setting(s);
-               free(s);
-#else /* Save ~4 bytes by using parser internals */
-               sprintf(parser->line, "%s=%s", token[0], token[1]); // must have room by definition
-               sysctl_write_setting(parser->line);
-#endif
+               /* Save ~4 bytes by using parser internals */
+               /* parser->line is big enough for sprintf */
+               sprintf(parser->line, "%s=%s", token[0], token[1]);
+               sysctl_dots_to_slashes(parser->line);
+               sysctl_display_all(parser->line);
        }
        if (ENABLE_FEATURE_CLEAN_UP)
                config_close(parser);
        return 0;
-} /* end sysctl_preload_file_and_exit() */
+}
 
-static int sysctl_write_setting(const char *setting)
+static int sysctl_act_on_setting(char *setting)
 {
-       int retval;
-       const char *name;
-       const char *value;
-       const char *equals;
-       char *tmpname, *outname, *cptr;
-       int fd;
+       int fd, retval = EXIT_SUCCESS;
+       char *cptr, *outname, *value;
 
-       name = setting;
-       equals = strchr(setting, '=');
-       if (!equals) {
-               bb_error_msg("error: '%s' must be of the form name=value", setting);
-               return EXIT_FAILURE;
-       }
+       outname = xstrdup(setting);
 
-       value = equals + 1;     /* point to the value in name=value */
-       if (name == equals || !*value) {
-               bb_error_msg("error: malformed setting '%s'", setting);
-               return EXIT_FAILURE;
+       cptr = outname;
+       while (*cptr) {
+               if (*cptr == '/')
+                       *cptr = '.';
+               cptr++;
        }
 
-       tmpname = xasprintf("%s%.*s", PROC_SYS, (int)(equals - name), name);
-       outname = xstrdup(tmpname + strlen_PROC_SYS);
-
-       sysctl_dots_to_slashes(tmpname);
-
-       while ((cptr = strchr(outname, '/')) != NULL)
-               *cptr = '.';
+       if (option_mask32 & FLAG_WRITE) {
+               cptr = strchr(setting, '=');
+               if (cptr == NULL) {
+                       bb_error_msg("error: '%s' must be of the form name=value",
+                               outname);
+                       retval = EXIT_FAILURE;
+                       goto end;
+               }
+               value = cptr + 1;       /* point to the value in name=value */
+               if (setting == cptr || !*value) {
+                       bb_error_msg("error: malformed setting '%s'", outname);
+                       retval = EXIT_FAILURE;
+                       goto end;
+               }
+               *cptr = '\0';
+               fd = open(setting, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+       } else {
+               fd = open(setting, O_RDONLY);
+       }
 
-       fd = open(tmpname, O_WRONLY | O_CREAT | O_TRUNC, 0666);
        if (fd < 0) {
                switch (errno) {
                case ENOENT:
                        if (option_mask32 & FLAG_SHOW_KEY_ERRORS)
-                               bb_error_msg(msg_unknown_key, outname);
+                               bb_error_msg("error: '%s' is an unknown key", outname);
                        break;
                default:
-                       bb_perror_msg("error setting key '%s'", outname);
+                       bb_perror_msg("error %sing key '%s'",
+                                       option_mask32 & FLAG_WRITE ?
+                                               "sett" : "read",
+                                       outname);
                        break;
                }
                retval = EXIT_FAILURE;
-       } else {
+               goto end;
+       }
+
+       if (option_mask32 & FLAG_WRITE) {
                dwrite_str(fd, value);
                close(fd);
-               if (option_mask32 & FLAG_SHOW_KEYS) {
+               if (option_mask32 & FLAG_SHOW_KEYS)
                        printf("%s = ", outname);
-               }
                puts(value);
-               retval = EXIT_SUCCESS;
-       }
-
-       free(tmpname);
-       free(outname);
-       return retval;
-} /* end sysctl_write_setting() */
-
-static int sysctl_read_setting(const char *name)
-{
-       int retval;
-       char *tmpname, *outname, *cptr;
-       char inbuf[1025];
-       FILE *fp;
-
-       if (!*name) {
-               if (option_mask32 & FLAG_SHOW_KEY_ERRORS)
-                       bb_error_msg(msg_unknown_key, name);
-               return -1;
-       }
-
-       tmpname = concat_path_file(PROC_SYS, name);
-       outname = xstrdup(tmpname + strlen_PROC_SYS);
-
-       sysctl_dots_to_slashes(tmpname);
-
-       while ((cptr = strchr(outname, '/')) != NULL)
-               *cptr = '.';
+       } else {
+               char c;
 
-       fp = fopen_for_read(tmpname);
-       if (fp == NULL) {
-               switch (errno) {
-               case ENOENT:
-                       if (option_mask32 & FLAG_SHOW_KEY_ERRORS)
-                               bb_error_msg(msg_unknown_key, outname);
-                       break;
-               default:
+               value = cptr = xmalloc_read(fd, NULL);
+               close(fd);
+               if (value == NULL) {
                        bb_perror_msg("error reading key '%s'", outname);
-                       break;
+                       goto end;
                }
-               retval = EXIT_FAILURE;
-       } else {
-               while (fgets(inbuf, sizeof(inbuf) - 1, fp)) {
-                       if (option_mask32 & FLAG_SHOW_KEYS) {
+
+               /* dev.cdrom.info and sunrpc.transports, for example,
+                * are multi-line. Try "sysctl sunrpc.transports"
+                */
+               while ((c = *cptr) != '\0') {
+                       if (option_mask32 & FLAG_SHOW_KEYS)
                                printf("%s = ", outname);
+                       while (1) {
+                               fputc(c, stdout);
+                               cptr++;
+                               if (c == '\n')
+                                       break;
+                               c = *cptr;
+                               if (c == '\0')
+                                       break;
                        }
-                       fputs(inbuf, stdout);
                }
-               fclose(fp);
-               retval = EXIT_SUCCESS;
+               free(value);
        }
-
-       free(tmpname);
+ end:
        free(outname);
        return retval;
-} /* end sysctl_read_setting() */
+}
 
 static int sysctl_display_all(const char *path)
 {
-       int retval = EXIT_SUCCESS;
-       DIR *dp;
-       struct dirent *de;
-       char *tmpdir;
-       struct stat ts;
-
-       dp = opendir(path);
-       if (!dp) {
-               return EXIT_FAILURE;
-       }
-       while ((de = readdir(dp)) != NULL) {
-               tmpdir = concat_subpath_file(path, de->d_name);
-               if (tmpdir == NULL)
-                       continue; /* . or .. */
-               if (stat(tmpdir, &ts) != 0) {
-                       bb_perror_msg(tmpdir);
-               } else if (S_ISDIR(ts.st_mode)) {
-                       retval |= sysctl_display_all(tmpdir);
-               } else {
-                       retval |= sysctl_read_setting(tmpdir + strlen_PROC_SYS);
+       DIR *dirp;
+       struct stat buf;
+       struct dirent *entry;
+       char *next;
+       int retval = 0;
+
+       stat(path, &buf);
+       if (S_ISDIR(buf.st_mode) && !(option_mask32 & FLAG_WRITE)) {
+               dirp = opendir(path);
+               if (dirp == NULL)
+                       return -1;
+               while ((entry = readdir(dirp)) != NULL) {
+                       next = concat_subpath_file(
+                               path, entry->d_name);
+                       if (next == NULL)
+                               continue; /* d_name is "." or ".." */
+                       /* if path was ".", drop "./" prefix: */
+                       retval |= sysctl_display_all((next[0] == '.' && next[1] == '/') ?
+                                           next + 2 : next);
+                       free(next);
                }
-               free(tmpdir);
-       } /* end while */
-       closedir(dp);
+               closedir(dirp);
+       } else {
+               char *name = xstrdup(path);
+               retval |= sysctl_act_on_setting(name);
+               free(name);
+       }
 
        return retval;
-} /* end sysctl_display_all() */
+}
 
 static void sysctl_dots_to_slashes(char *name)
 {
        char *cptr, *last_good, *end;
 
-       /* It can be good as-is! */
-       if (access(name, F_OK) == 0)
-               return;
-
-       /* Example from bug 3894:
+       /* Convert minimum number of '.' to '/' so that
+        * we end up with existing file's name.
+        *
+        * Example from bug 3894:
         * net.ipv4.conf.eth0.100.mc_forwarding ->
-        * net/ipv4/conf/eth0.100/mc_forwarding. NB:
-        * net/ipv4/conf/eth0/mc_forwarding *also exists*,
+        * net/ipv4/conf/eth0.100/mc_forwarding
+        * NB: net/ipv4/conf/eth0/mc_forwarding *also exists*,
         * therefore we must start from the end, and if
         * we replaced even one . -> /, start over again,
         * but never replace dots before the position
-        * where replacement occurred. */
-       end = name + strlen(name) - 1;
+        * where last replacement occurred.
+        */
+       end = name + strlen(name);
        last_good = name - 1;
+       *end = '.'; /* trick the loop in trying full name too */
+
  again:
        cptr = end;
        while (cptr > last_good) {
                if (*cptr == '.') {
                        *cptr = '\0';
+                       //bb_error_msg("trying:'%s'", name);
                        if (access(name, F_OK) == 0) {
                                *cptr = '/';
+                               *end = '\0'; /* prevent trailing '/' */
+                               //bb_error_msg("replaced:'%s'", name);
                                last_good = cptr;
                                goto again;
                        }
@@ -265,4 +254,5 @@ static void sysctl_dots_to_slashes(char *name)
                }
                cptr--;
        }
-} /* end sysctl_dots_to_slashes() */
+       *end = '\0';
+}