s3:netlookup: make use of cli_credentials_init_anon()
[bbaumbach/samba-autobuild/.git] / source3 / utils / regedit.c
index 5b7885ca3e1878ebe410c4eaac085e492390e1ee..ce50f65799170af43bd09e898963f076508babd2 100644 (file)
@@ -18,7 +18,7 @@
  */
 
 #include "includes.h"
-#include "popt_common.h"
+#include "popt_common_cmdline.h"
 #include "lib/util/data_blob.h"
 #include "lib/registry/registry.h"
 #include "regedit.h"
@@ -157,11 +157,11 @@ static void add_reg_key(struct regedit *regedit, struct tree_node *node,
        if (subkey) {
                msg = "Enter name of new subkey";
        }
-       dialog_input(regedit, &name, "New Key", msg);
+       dialog_input(regedit, &name, "New Key", "%s", msg);
        if (name) {
                WERROR rv;
                struct registry_key *new_key;
-               struct tree_node *new_node;
+               struct tree_node *new_node = NULL;
                struct tree_node *list;
                struct tree_node *parent;
 
@@ -187,7 +187,8 @@ static void add_reg_key(struct regedit *regedit, struct tree_node *node,
                        } else {
                                /* Reopen the parent key to make sure the
                                   new subkey will be noticed. */
-                               tree_node_reopen_key(parent);
+                               tree_node_reopen_key(regedit->registry_context,
+                                                    parent);
                        }
 
                        list = tree_node_first(node);
@@ -197,6 +198,7 @@ static void add_reg_key(struct regedit *regedit, struct tree_node *node,
                                node = new_node;
                        }
                        tree_view_set_current_node(regedit->keys, node);
+                       load_values(regedit);
                } else {
                        msg = get_friendly_werror_msg(rv);
                        dialog_notice(regedit, DIA_ALERT, "New Key",
@@ -206,58 +208,25 @@ static void add_reg_key(struct regedit *regedit, struct tree_node *node,
        }
 }
 
-static WERROR next_depth_first(struct tree_node **node)
-{
-       WERROR rv = WERR_OK;
-
-       SMB_ASSERT(node != NULL && *node != NULL);
-
-       if (tree_node_has_children(*node)) {
-               /* 1. If the node has children, go to the first one. */
-               rv = tree_node_load_children(*node);
-               if (W_ERROR_IS_OK(rv)) {
-                       SMB_ASSERT((*node)->child_head != NULL);
-                       *node = (*node)->child_head;
-               }
-       } else if ((*node)->next) {
-               /* 2. If there's a node directly after this one, go there */
-               *node = (*node)->next;
-       } else {
-               /* 3. Otherwise, go up the hierarchy to find the next one */
-               do {
-                       *node = (*node)->parent;
-                       if (*node && (*node)->next) {
-                               *node = (*node)->next;
-                               break;
-                       }
-               } while (*node);
-       }
-
-       return rv;
-}
-
-static WERROR regedit_search_next(struct regedit *regedit)
-{
-       WERROR rv;
-       struct regedit_search_opts *opts = &regedit->active_search;
-
-       if (opts->search_recursive) {
-               rv = next_depth_first(&opts->node);
-               if (!W_ERROR_IS_OK(rv)) {
-                       return rv;
-               }
-       } else {
-               opts->node = opts->node->next;
-       }
-
-       return WERR_OK;
-}
-
-static WERROR regedit_search(struct regedit *regedit)
+enum search_flags {
+       SEARCH_NEXT = (1<<0),
+       SEARCH_PREV = (1<<1),
+       SEARCH_REPEAT = (1<<2)
+};
+static WERROR regedit_search(struct regedit *regedit, struct tree_node *node,
+                            struct value_item *vitem, unsigned flags)
 {
        struct regedit_search_opts *opts;
        struct tree_node *found;
+       struct value_item *found_value;
+       bool search_key, need_sync;
+       char *save_value_name;
        WERROR rv;
+       bool (*iterate)(struct tree_node **, bool, WERROR *);
+       struct value_item *(*find_item)(struct value_list *,
+                                       struct value_item *,
+                                       const char *,
+                                       regedit_search_match_fn_t);
 
        opts = &regedit->active_search;
 
@@ -267,25 +236,78 @@ static WERROR regedit_search(struct regedit *regedit)
 
        SMB_ASSERT(opts->search_key || opts->search_value);
 
-       for (found = NULL; opts->node && !found; ) {
-               if (opts->search_key &&
-                   opts->match(opts->node->name, opts->query)) {
-                       found = opts->node;
+       rv = WERR_OK;
+       found = NULL;
+       found_value = NULL;
+       save_value_name = NULL;
+       search_key = opts->search_key;
+       need_sync = false;
+       iterate = tree_node_next;
+       find_item = value_list_find_next_item;
+
+       if (flags & SEARCH_PREV) {
+               iterate = tree_node_prev;
+               find_item = value_list_find_prev_item;
+       }
+
+       if (opts->search_value) {
+               struct value_item *it;
+
+               it = value_list_get_current_item(regedit->vl);
+               if (it) {
+                       save_value_name = talloc_strdup(regedit,
+                                                       it->value_name);
+                       if (save_value_name == NULL) {
+                               return WERR_NOT_ENOUGH_MEMORY;
+                       }
+               }
+
+               if (vitem) {
+                       search_key = false;
                }
+       }
+
+       if (!vitem && (flags & SEARCH_REPEAT)) {
                if (opts->search_value) {
-                       /* TODO
-                       rv = regedit_search_value(regedit);
-                       if (W_ERROR_IS_OK(rv)) {
-                               found = opts->node;
-                       } else if (!W_ERROR_EQUAL(rv, WERR_NO_MORE_ITEMS)) {
-                               return rv;
+                       search_key = false;
+               } else if (!iterate(&node, opts->search_recursive, &rv)) {
+                       beep();
+                       return rv;
+               }
+       }
+
+       do {
+               if (search_key) {
+                       SMB_ASSERT(opts->search_key == true);
+                       if (opts->match(node->name, opts->query)) {
+                               found = node;
+                       } else if (opts->search_value) {
+                               search_key = false;
                        }
-                       */
                }
-               rv = regedit_search_next(regedit);
-               if (!W_ERROR_IS_OK(rv)) {
-                       return rv;
+               if (!search_key) {
+                       SMB_ASSERT(opts->search_value == true);
+                       if (!vitem) {
+                               rv = value_list_load_quick(regedit->vl,
+                                                          node->key);
+                               if (!W_ERROR_IS_OK(rv)) {
+                                       goto out;
+                               }
+                               need_sync = true;
+                       }
+                       found_value = find_item(regedit->vl, vitem, opts->query,
+                                               opts->match);
+                       if (found_value) {
+                               found = node;
+                       } else {
+                               vitem = NULL;
+                               search_key = opts->search_key;
+                       }
                }
+       } while (!found && iterate(&node, opts->search_recursive, &rv));
+
+       if (!W_ERROR_IS_OK(rv)) {
+               goto out;
        }
 
        if (found) {
@@ -296,14 +318,51 @@ static WERROR regedit_search(struct regedit *regedit)
                        print_path(regedit, found);
                }
                tree_view_set_current_node(regedit->keys, found);
-               load_values(regedit);
+               if (found_value) {
+                       if (need_sync) {
+                               value_list_sync(regedit->vl);
+                       }
+                       value_list_set_current_item(regedit->vl, found_value);
+                       regedit->tree_input = false;
+               } else {
+                       load_values(regedit);
+                       regedit->tree_input = true;
+               }
                tree_view_show(regedit->keys);
                value_list_show(regedit->vl);
+               print_heading(regedit);
        } else {
+               if (need_sync) {
+                       load_values(regedit);
+                       value_list_set_current_item_by_name(regedit->vl,
+                                                           save_value_name);
+               }
                beep();
        }
 
-       return WERR_OK;
+out:
+       talloc_free(save_value_name);
+
+       return rv;
+}
+
+static void regedit_search_repeat(struct regedit *regedit, unsigned flags)
+{
+       struct tree_node *node;
+       struct value_item *vitem;
+       struct regedit_search_opts *opts;
+
+       opts = &regedit->active_search;
+       if (opts->query == NULL) {
+               return;
+       }
+
+       node = tree_view_get_current_node(regedit->keys);
+       vitem = NULL;
+       if (opts->search_value && !regedit->tree_input) {
+               vitem = value_list_get_current_item(regedit->vl);
+       }
+       regedit_search(regedit, node, vitem, flags | SEARCH_REPEAT);
 }
 
 static void handle_tree_input(struct regedit *regedit, int c)
@@ -319,6 +378,22 @@ static void handle_tree_input(struct regedit *regedit, int c)
                tree_view_driver(regedit->keys, ML_CURSOR_UP);
                load_values(regedit);
                break;
+       case KEY_NPAGE:
+               tree_view_driver(regedit->keys, ML_CURSOR_PGDN);
+               load_values(regedit);
+               break;
+       case KEY_PPAGE:
+               tree_view_driver(regedit->keys, ML_CURSOR_PGUP);
+               load_values(regedit);
+               break;
+       case KEY_HOME:
+               tree_view_driver(regedit->keys, ML_CURSOR_HOME);
+               load_values(regedit);
+               break;
+       case KEY_END:
+               tree_view_driver(regedit->keys, ML_CURSOR_END);
+               load_values(regedit);
+               break;
        case '\n':
        case KEY_ENTER:
        case KEY_RIGHT:
@@ -377,7 +452,8 @@ static void handle_tree_input(struct regedit *regedit, int c)
 
                        rv = reg_key_del(node, parent->key, node->name);
                        if (W_ERROR_IS_OK(rv)) {
-                               tree_node_reopen_key(parent);
+                               tree_node_reopen_key(regedit->registry_context,
+                                                    parent);
                                tree_view_clear(regedit->keys);
                                pop = tree_node_pop(&node);
                                talloc_free(pop);
@@ -406,6 +482,8 @@ static void handle_value_input(struct regedit *regedit, int c)
 {
        struct value_item *vitem;
        bool binmode = false;
+       WERROR err;
+       int sel;
 
        switch (c) {
        case KEY_DOWN:
@@ -414,35 +492,69 @@ static void handle_value_input(struct regedit *regedit, int c)
        case KEY_UP:
                value_list_driver(regedit->vl, ML_CURSOR_UP);
                break;
+       case KEY_NPAGE:
+               value_list_driver(regedit->vl, ML_CURSOR_PGDN);
+               break;
+       case KEY_PPAGE:
+               value_list_driver(regedit->vl, ML_CURSOR_PGUP);
+               break;
+       case KEY_HOME:
+               value_list_driver(regedit->vl, ML_CURSOR_HOME);
+               break;
+       case KEY_END:
+               value_list_driver(regedit->vl, ML_CURSOR_END);
+               break;
        case 'b':
        case 'B':
                binmode = true;
-               /* Falthrough... */
+
+               FALL_THROUGH;
        case '\n':
        case KEY_ENTER:
                vitem = value_list_get_current_item(regedit->vl);
                if (vitem) {
                        struct tree_node *node;
+                       const char *name = NULL;
                        node = tree_view_get_current_node(regedit->keys);
-                       dialog_edit_value(regedit, node->key, vitem->type,
-                                         vitem, binmode);
-                       tree_node_reopen_key(node);
-                       value_list_load(regedit->vl, node->key);
+                       sel = dialog_edit_value(regedit, node->key, vitem->type,
+                                               vitem, binmode, &err, &name);
+                       if (!W_ERROR_IS_OK(err)) {
+                               const char *msg = get_friendly_werror_msg(err);
+                               dialog_notice(regedit, DIA_ALERT, "Error",
+                                             "Error editing value:\n%s", msg);
+                       } else if (sel == DIALOG_OK) {
+                               tree_node_reopen_key(regedit->registry_context,
+                                                    node);
+                               value_list_load(regedit->vl, node->key);
+                               value_list_set_current_item_by_name(regedit->vl,
+                                                                   name);
+                               talloc_free(discard_const(name));
+                       }
                }
                break;
        case 'n':
        case 'N': {
                int new_type;
-               int sel;
 
                sel = dialog_select_type(regedit, &new_type);
                if (sel == DIALOG_OK) {
                        struct tree_node *node;
+                       const char *name = NULL;
                        node = tree_view_get_current_node(regedit->keys);
-                       dialog_edit_value(regedit, node->key, new_type, NULL,
-                                         false);
-                       tree_node_reopen_key(node);
-                       value_list_load(regedit->vl, node->key);
+                       sel = dialog_edit_value(regedit, node->key, new_type,
+                                               NULL, false, &err, &name);
+                       if (!W_ERROR_IS_OK(err)) {
+                               const char *msg = get_friendly_werror_msg(err);
+                               dialog_notice(regedit, DIA_ALERT, "Error",
+                                             "Error creating value:\n%s", msg);
+                       } else if (sel == DIALOG_OK) {
+                               tree_node_reopen_key(regedit->registry_context,
+                                                    node);
+                               value_list_load(regedit->vl, node->key);
+                               value_list_set_current_item_by_name(regedit->vl,
+                                                                   name);
+                               talloc_free(discard_const(name));
+                       }
                }
                break;
        }
@@ -450,8 +562,6 @@ static void handle_value_input(struct regedit *regedit, int c)
        case 'D':
                vitem = value_list_get_current_item(regedit->vl);
                if (vitem) {
-                       int sel;
-
                        sel = dialog_notice(regedit, DIA_CONFIRM,
                                            "Delete Value",
                                             "Really delete value \"%s\"?",
@@ -461,7 +571,8 @@ static void handle_value_input(struct regedit *regedit, int c)
                                node = tree_view_get_current_node(regedit->keys);
                                reg_del_value(regedit, node->key,
                                              vitem->value_name);
-                               tree_node_reopen_key(node);
+                               tree_node_reopen_key(regedit->registry_context,
+                                                    node);
                                value_list_load(regedit->vl, node->key);
                        }
                }
@@ -510,30 +621,30 @@ static void handle_main_input(struct regedit *regedit, int c)
        case '/': {
                int rv;
                struct regedit_search_opts *opts;
+               struct tree_node *node;
 
                opts = &regedit->active_search;
-               if (opts->query) {
-                       talloc_free(discard_const(opts->query));
-               }
                rv = dialog_search_input(regedit, opts);
                if (rv == DIALOG_OK) {
                        SMB_ASSERT(opts->query != NULL);
-                       opts->match = find_substring;
-                       opts->node = regedit->keys->root;
-                       if (opts->search_nocase) {
-                               opts->match = find_substring_nocase;
+                       opts->match = find_substring_nocase;
+                       node = regedit->keys->root->child_head;
+                       if (opts->search_case) {
+                               opts->match = find_substring;
                        }
-                       if (opts->search_relative) {
-                               opts->node =
-                                    tree_view_get_current_node(regedit->keys);
+                       if (!opts->search_recursive) {
+                               node = tree_view_get_current_node(regedit->keys);
+                               node = tree_node_first(node);
                        }
-                       regedit_search(regedit);
+                       regedit_search(regedit, node, NULL, SEARCH_NEXT);
                }
                break;
        }
        case 'x':
+               regedit_search_repeat(regedit, SEARCH_NEXT);
+               break;
        case 'X':
-               regedit_search(regedit);
+               regedit_search_repeat(regedit, SEARCH_PREV);
                break;
        case '\t':
                regedit->tree_input = !regedit->tree_input;
@@ -570,6 +681,7 @@ int regedit_getch(void)
 static void regedit_panic_handler(const char *msg)
 {
        endwin();
+       smb_panic_log(msg);
        smb_panic_s3(msg);
 }
 
@@ -638,7 +750,7 @@ static void display_window(TALLOC_CTX *mem_ctx, struct registry_context *ctx)
                handle_main_input(regedit, key);
                update_panels();
                doupdate();
-       } while (key != 'q' || key == 'Q');
+       } while (key != 'q' && key != 'Q');
 
        endwin();
 }
@@ -655,7 +767,6 @@ int main(int argc, const char **argv)
        };
        int opt;
        poptContext pc;
-       struct user_auth_info *auth_info;
        TALLOC_CTX *frame;
        struct registry_context *ctx;
        WERROR rv;
@@ -666,27 +777,18 @@ int main(int argc, const char **argv)
        lp_set_cmdline("log level", "0");
 
        /* process options */
-       auth_info = user_auth_info_init(frame);
-       if (auth_info == NULL) {
-               exit(1);
-       }
-       popt_common_set_auth_info(auth_info);
        pc = poptGetContext("regedit", argc, argv, long_options, 0);
 
        while ((opt = poptGetNextOpt(pc)) != -1) {
                /* TODO */
        }
 
-       if (!lp_load_global(get_dyn_CONFIGFILE())) {
-               DEBUG(0, ("ERROR loading config file...\n"));
-               exit(1);
-       }
-
-       /* some simple tests */
-
        rv = reg_open_samba3(frame, &ctx);
        if (!W_ERROR_IS_OK(rv)) {
+               fprintf(stderr, "Unable to open registry: %s\n",
+                       win_errstr(rv));
                TALLOC_FREE(frame);
+               poptFreeContext(pc);
 
                return 1;
        }
@@ -694,6 +796,7 @@ int main(int argc, const char **argv)
        display_window(frame, ctx);
 
        TALLOC_FREE(frame);
+       poptFreeContext(pc);
 
        return 0;
 }