#include <linux/security.h>
 #include "common.h"
 
-static struct tomoyo_profile tomoyo_default_profile = {
-       .learning = &tomoyo_default_profile.preference,
-       .permissive = &tomoyo_default_profile.preference,
-       .enforcing = &tomoyo_default_profile.preference,
-       .preference.enforcing_verbose = true,
-       .preference.learning_max_entry = 2048,
-       .preference.learning_verbose = false,
-       .preference.permissive_verbose = true
-};
-
 /* Profile version. Currently only 20090903 is defined. */
 static unsigned int tomoyo_profile_version;
 
        [TOMOYO_MAX_MAC_INDEX + TOMOYO_MAC_CATEGORY_FILE] = "file",
 };
 
+/* String table for PREFERENCE keyword. */
+static const char * const tomoyo_pref_keywords[TOMOYO_MAX_PREF] = {
+       [TOMOYO_PREF_MAX_LEARNING_ENTRY] = "max_learning_entry",
+};
+
 /* Permit policy management by non-root user? */
 static bool tomoyo_manage_by_non_root;
 
  *
  * @value: Bool value.
  */
+/*
 static const char *tomoyo_yesno(const unsigned int value)
 {
        return value ? "yes" : "no";
 }
+*/
 
+/**
+ * tomoyo_addprintf - strncat()-like-snprintf().
+ *
+ * @buffer: Buffer to write to. Must be '\0'-terminated.
+ * @len:    Size of @buffer.
+ * @fmt:    The printf()'s format string, followed by parameters.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_addprintf(char *buffer, int len, const char *fmt, ...)
 {
        va_list args;
        ptr = tomoyo_profile_ptr[profile];
        if (!ptr && tomoyo_memory_ok(entry)) {
                ptr = entry;
-               ptr->learning = &tomoyo_default_profile.preference;
-               ptr->permissive = &tomoyo_default_profile.preference;
-               ptr->enforcing = &tomoyo_default_profile.preference;
                ptr->default_config = TOMOYO_CONFIG_DISABLED;
                memset(ptr->config, TOMOYO_CONFIG_USE_DEFAULT,
                       sizeof(ptr->config));
+               ptr->pref[TOMOYO_PREF_MAX_LEARNING_ENTRY] = 2048;
                mb(); /* Avoid out-of-order execution. */
                tomoyo_profile_ptr[profile] = ptr;
                entry = NULL;
  */
 struct tomoyo_profile *tomoyo_profile(const u8 profile)
 {
+       static struct tomoyo_profile tomoyo_null_profile;
        struct tomoyo_profile *ptr = tomoyo_profile_ptr[profile];
-       if (!tomoyo_policy_loaded)
-               return &tomoyo_default_profile;
-       BUG_ON(!ptr);
+       if (!ptr)
+               ptr = &tomoyo_null_profile;
        return ptr;
 }
 
+/**
+ * tomoyo_find_yesno - Find values for specified keyword.
+ *
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns 1 if "@find=yes" was found, 0 if "@find=no" was found, -1 otherwise.
+ */
+/*
 static s8 tomoyo_find_yesno(const char *string, const char *find)
 {
        const char *cp = strstr(string, find);
        }
        return -1;
 }
+*/
 
-static void tomoyo_set_bool(bool *b, const char *string, const char *find)
-{
-       switch (tomoyo_find_yesno(string, find)) {
-       case 1:
-               *b = true;
-               break;
-       case 0:
-               *b = false;
-               break;
-       }
-}
-
+/**
+ * tomoyo_set_uint - Set value for specified preference.
+ *
+ * @i:      Pointer to "unsigned int".
+ * @string: String to check.
+ * @find:   Name of keyword.
+ *
+ * Returns nothing.
+ */
 static void tomoyo_set_uint(unsigned int *i, const char *string,
                            const char *find)
 {
                sscanf(cp + strlen(find), "=%u", i);
 }
 
-static void tomoyo_set_pref(const char *name, const char *value,
-                           const bool use_default,
-                           struct tomoyo_profile *profile)
-{
-       struct tomoyo_preference **pref;
-       bool *verbose;
-       if (!strcmp(name, "enforcing")) {
-               if (use_default) {
-                       pref = &profile->enforcing;
-                       goto set_default;
-               }
-               profile->enforcing = &profile->preference;
-               verbose = &profile->preference.enforcing_verbose;
-               goto set_verbose;
-       }
-       if (!strcmp(name, "permissive")) {
-               if (use_default) {
-                       pref = &profile->permissive;
-                       goto set_default;
-               }
-               profile->permissive = &profile->preference;
-               verbose = &profile->preference.permissive_verbose;
-               goto set_verbose;
-       }
-       if (!strcmp(name, "learning")) {
-               if (use_default) {
-                       pref = &profile->learning;
-                       goto set_default;
-               }
-               profile->learning = &profile->preference;
-               tomoyo_set_uint(&profile->preference.learning_max_entry, value,
-                            "max_entry");
-               verbose = &profile->preference.learning_verbose;
-               goto set_verbose;
-       }
-       return;
- set_default:
-       *pref = &tomoyo_default_profile.preference;
-       return;
- set_verbose:
-       tomoyo_set_bool(verbose, value, "verbose");
-}
-
+/**
+ * tomoyo_set_mode - Set mode for specified profile.
+ *
+ * @name:    Name of functionality.
+ * @value:   Mode for @name.
+ * @profile: Pointer to "struct tomoyo_profile".
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
 static int tomoyo_set_mode(char *name, const char *value,
-                          const bool use_default,
                           struct tomoyo_profile *profile)
 {
        u8 i;
        } else {
                return -EINVAL;
        }
-       if (use_default) {
+       if (strstr(value, "use_default")) {
                config = TOMOYO_CONFIG_USE_DEFAULT;
        } else {
                u8 mode;
 {
        char *data = head->write_buf;
        unsigned int i;
-       bool use_default = false;
        char *cp;
        struct tomoyo_profile *profile;
        if (sscanf(data, "PROFILE_VERSION=%u", &tomoyo_profile_version) == 1)
                return 0;
        i = simple_strtoul(data, &cp, 10);
-       if (data == cp) {
-               profile = &tomoyo_default_profile;
-       } else {
-               if (*cp != '-')
-                       return -EINVAL;
-               data = cp + 1;
-               profile = tomoyo_assign_profile(i);
-               if (!profile)
-                       return -EINVAL;
-       }
+       if (*cp != '-')
+               return -EINVAL;
+       data = cp + 1;
+       profile = tomoyo_assign_profile(i);
+       if (!profile)
+               return -EINVAL;
        cp = strchr(data, '=');
        if (!cp)
                return -EINVAL;
        *cp++ = '\0';
-       if (profile != &tomoyo_default_profile)
-               use_default = strstr(cp, "use_default") != NULL;
-       if (tomoyo_str_starts(&data, "PREFERENCE::")) {
-               tomoyo_set_pref(data, cp, use_default, profile);
-               return 0;
-       }
-       if (profile == &tomoyo_default_profile)
-               return -EINVAL;
        if (!strcmp(data, "COMMENT")) {
                static DEFINE_SPINLOCK(lock);
                const struct tomoyo_path_info *new_comment
                tomoyo_put_name(old_comment);
                return 0;
        }
-       return tomoyo_set_mode(data, cp, use_default, profile);
-}
-
-static void tomoyo_print_preference(struct tomoyo_io_buffer *head,
-                                   const int idx)
-{
-       struct tomoyo_preference *pref = &tomoyo_default_profile.preference;
-       const struct tomoyo_profile *profile = idx >= 0 ?
-               tomoyo_profile_ptr[idx] : NULL;
-       char buffer[16] = "";
-       if (profile) {
-               buffer[sizeof(buffer) - 1] = '\0';
-               snprintf(buffer, sizeof(buffer) - 1, "%u-", idx);
-       }
-       if (profile) {
-               pref = profile->learning;
-               if (pref == &tomoyo_default_profile.preference)
-                       goto skip1;
-       }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ "
-                        "verbose=%s max_entry=%u }\n",
-                        buffer, "learning",
-                        tomoyo_yesno(pref->learning_verbose),
-                        pref->learning_max_entry);
- skip1:
-       if (profile) {
-               pref = profile->permissive;
-               if (pref == &tomoyo_default_profile.preference)
-                       goto skip2;
-       }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-                        buffer, "permissive",
-                        tomoyo_yesno(pref->permissive_verbose));
- skip2:
-       if (profile) {
-               pref = profile->enforcing;
-               if (pref == &tomoyo_default_profile.preference)
-                       return;
+       if (!strcmp(data, "PREFERENCE")) {
+               for (i = 0; i < TOMOYO_MAX_PREF; i++)
+                       tomoyo_set_uint(&profile->pref[i], cp,
+                                       tomoyo_pref_keywords[i]);
+               return 0;
        }
-       tomoyo_io_printf(head, "%sPREFERENCE::%s={ verbose=%s }\n",
-                        buffer, "enforcing",
-                        tomoyo_yesno(pref->enforcing_verbose));
+       return tomoyo_set_mode(data, cp, profile);
 }
 
 static void tomoyo_print_config(struct tomoyo_io_buffer *head, const u8 config)
        switch (head->r.step) {
        case 0:
                tomoyo_io_printf(head, "PROFILE_VERSION=%s\n", "20090903");
-               tomoyo_print_preference(head, -1);
                head->r.step++;
                break;
        case 1:
                break;
        case 2:
                {
+                       u8 i;
                        const struct tomoyo_path_info *comment =
                                profile->comment;
                        tomoyo_io_printf(head, "%u-COMMENT=", index);
                        tomoyo_set_string(head, comment ? comment->name : "");
                        tomoyo_set_lf(head);
+                       tomoyo_io_printf(head, "%u-PREFERENCE={ ", index);
+                       for (i = 0; i < TOMOYO_MAX_PREF; i++)
+                               tomoyo_io_printf(head, "%s=%u ",
+                                                tomoyo_pref_keywords[i],
+                                                profile->pref[i]);
+                       tomoyo_set_string(head, "}\n");
                        head->r.step++;
                }
                break;
                }
                if (head->r.bit == TOMOYO_MAX_MAC_INDEX
                    + TOMOYO_MAX_MAC_CATEGORY_INDEX) {
-                       tomoyo_print_preference(head, index);
                        head->r.index++;
                        head->r.step = 1;
                }
 static void tomoyo_read_version(struct tomoyo_io_buffer *head)
 {
        if (!head->r.eof) {
-               tomoyo_io_printf(head, "2.3.0");
+               tomoyo_io_printf(head, "2.4.0");
                head->r.eof = true;
        }
 }