r23792: convert Samba4 to GPLv3
[kai/samba-autobuild/.git] / source4 / lib / registry / tools / regshell.c
index 3fd9dab2688c63288ec30d3b9246f1a06b52b5bd..f431c81bf8dc19fb8f6a4dc9987aff6808d55095 100644 (file)
@@ -6,7 +6,7 @@
 
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
-#include "dynconfig.h"
-#include "registry.h"
+#include "lib/registry/registry.h"
 #include "lib/cmdline/popt_common.h"
+#include "lib/events/events.h"
 #include "system/time.h"
+#include "lib/smbreadline/smbreadline.h"
+#include "librpc/gen_ndr/ndr_security.h"
 
 /* 
  * ck/cd - change key
  * mkkey/mkdir - make key
  * ch - change hive
  * info - show key info
+ * save - save hive
+ * print - print value
  * help
  * exit
  */
 
-static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_info(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 {
+       struct security_descriptor *sec_desc = NULL;
        time_t last_mod;
+       WERROR error;
+       
        printf("Name: %s\n", cur->name);
        printf("Full path: %s\n", cur->path);
        printf("Key Class: %s\n", cur->class_name);
        last_mod = nt_time_to_unix(cur->last_mod);
        printf("Time Last Modified: %s\n", ctime(&last_mod));
-       /* FIXME: Security info */
+
+       error = reg_get_sec_desc(mem_ctx, cur, &sec_desc);
+       if (!W_ERROR_IS_OK(error)) {
+               printf("Error getting security descriptor\n");
+       } else {
+               ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor, "Security", sec_desc);
+       }
+       talloc_free(sec_desc);
        return cur;
 }
 
-static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_predef(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
+{
+       struct registry_key *ret = NULL;
+       if (argc < 2) {
+               fprintf(stderr, "Usage: predef predefined-key-name\n");
+       } else if (!ctx) {
+               fprintf(stderr, "No full registry loaded, no predefined keys defined\n");
+       } else {
+               WERROR error = reg_get_predefined_key_by_name(ctx, argv[1], &ret);
+
+               if (!W_ERROR_IS_OK(error)) {
+                       fprintf(stderr, "Error opening predefined key %s: %s\n", argv[1], win_errstr(error));
+                       ret = NULL;
+               }
+       }
+       return ret;
+}
+
+static struct registry_key *cmd_pwd(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 {
        printf("%s\n", cur->path);
        return cur;
 }
 
-static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_set(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 {
-       /* FIXME */
-       return NULL;
+       struct registry_value val;
+       WERROR error;
+
+       if (argc < 4) {
+               fprintf(stderr, "Usage: set value-name type value\n");
+               return cur;
+       } 
+
+       if (!reg_string_to_val(mem_ctx, argv[2], argv[3], &val.data_type, &val.data)) {
+               fprintf(stderr, "Unable to interpret data\n");
+               return cur;
+       }
+
+       error = reg_val_set(cur, argv[1], val.data_type, val.data);
+       if (!W_ERROR_IS_OK(error)) {
+               fprintf(stderr, "Error setting value: %s\n", win_errstr(error));
+               return NULL;
+       }
+       return cur;
 }
 
-static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 { 
        struct registry_key *new = NULL;
        WERROR error;
@@ -80,7 +128,27 @@ static struct registry_key *cmd_ck(TALLOC_CTX *mem_ctx, struct registry_key *cur
        return new;
 }
 
-static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_print(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
+{
+       struct registry_value *value;
+       WERROR error;
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: print <valuename>");
+               return NULL;
+       }
+       
+       error = reg_key_get_value_by_name(mem_ctx, cur, argv[1], &value);
+       if (!W_ERROR_IS_OK(error)) {
+               fprintf(stderr, "No such value '%s'\n", argv[1]);
+               return NULL;
+       }
+
+       printf("%s\n%s\n", str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
+       return NULL;
+}
+
+static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 {
        int i;
        WERROR error;
@@ -95,12 +163,12 @@ static struct registry_key *cmd_ls(TALLOC_CTX *mem_ctx, struct registry_key *cur
        }
 
        for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, cur, i, &value)); i++) {
-               printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value));
+               printf("V \"%s\" %s %s\n", value->name, str_regtype(value->data_type), reg_val_data_string(mem_ctx, value->data_type, &value->data));
        }
        
        return NULL; 
 }
-static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 { 
        struct registry_key *tmp;
        if(argc < 2) {
@@ -113,25 +181,17 @@ static struct registry_key *cmd_mkkey(TALLOC_CTX *mem_ctx, struct registry_key *
                return NULL;
        }
 
-       fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], cur->path);
-       
        return NULL; 
 }
 
-static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 { 
-       struct registry_key *key;
        if(argc < 2) {
                fprintf(stderr, "Usage: rmkey <name>\n");
                return NULL;
        }
 
-       if(!W_ERROR_IS_OK(reg_open_key(mem_ctx, cur, argv[1], &key))) {
-               fprintf(stderr, "No such subkey '%s'\n", argv[1]);
-               return NULL;
-       }
-
-       if(!W_ERROR_IS_OK(reg_key_del(key))) {
+       if(!W_ERROR_IS_OK(reg_key_del(cur, argv[1]))) {
                fprintf(stderr, "Error deleting '%s'\n", argv[1]);
        } else {
                fprintf(stderr, "Successfully deleted '%s'\n", argv[1]);
@@ -140,20 +200,14 @@ static struct registry_key *cmd_rmkey(TALLOC_CTX *mem_ctx, struct registry_key *
        return NULL; 
 }
 
-static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 { 
-       struct registry_value *val;
        if(argc < 2) {
                fprintf(stderr, "Usage: rmval <valuename>\n");
                return NULL;
        }
 
-       if(!W_ERROR_IS_OK(reg_key_get_value_by_name(mem_ctx, cur, argv[1], &val))) {
-               fprintf(stderr, "No such value '%s'\n", argv[1]);
-               return NULL;
-       }
-
-       if(!W_ERROR_IS_OK(reg_del_value(val))) {
+       if(!W_ERROR_IS_OK(reg_del_value(cur, argv[1]))) {
                fprintf(stderr, "Error deleting value '%s'\n", argv[1]);
        } else {
                fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]);
@@ -162,46 +216,24 @@ static struct registry_key *cmd_rmval(TALLOC_CTX *mem_ctx, struct registry_key *
        return NULL; 
 }
 
-static struct registry_key *cmd_hive(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
-{
-       if (!cur->hive->reg_ctx) {
-               fprintf(stderr, "Only one hive loaded\n");
-               return cur;
-       }
-
-       if (argc == 1) {
-               printf("%s\n", cur->hive->root->name);
-       } else {
-               struct registry_key *newroot;
-               WERROR error = reg_get_hive_by_name(cur->hive->reg_ctx, argv[1], &newroot);
-               if (W_ERROR_IS_OK(error)) {
-                       return newroot;
-               } else {
-                       fprintf(stderr, "Can't switch to hive %s: %s\n", cur->hive->root->name, win_errstr(error));
-               }
-       }
-
-       return NULL;
-}
-
-static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_exit(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *cur, int argc, char **argv)
 {
        exit(0);
        return NULL; 
 }
 
-static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *, int, char **);
+static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int, char **);
 
-struct {
+static struct {
        const char *name;
        const char *alias;
        const char *help;
-       struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_key *, int argc, char **argv);
+       struct registry_key *(*handle)(TALLOC_CTX *mem_ctx, struct registry_context *ctx,struct registry_key *, int argc, char **argv);
 } regshell_cmds[] = {
        {"ck", "cd", "Change current key", cmd_ck },
-       {"ch", "hive", "Change current hive", cmd_hive },
        {"info", "i", "Show detailed information of a key", cmd_info },
        {"list", "ls", "List values/keys in current key", cmd_ls },
+       {"print", "p", "Print value", cmd_print },
        {"mkkey", "mkdir", "Make new key", cmd_mkkey },
        {"rmval", "rm", "Remove value", cmd_rmval },
        {"rmkey", "rmdir", "Remove key", cmd_rmkey },
@@ -209,10 +241,11 @@ struct {
        {"set", "update", "Update value", cmd_set },
        {"help", "?", "Help", cmd_help },
        {"exit", "quit", "Exit", cmd_exit },
+       {"predef", "predefined", "Go to predefined key", cmd_predef },
        {NULL }
 };
 
-static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *cur, int argc, char **argv)
+static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *cur, int argc, char **argv)
 {
        int i;
        printf("Available commands:\n");
@@ -222,7 +255,7 @@ static struct registry_key *cmd_help(TALLOC_CTX *mem_ctx, struct registry_key *c
        return NULL;
 } 
 
-static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key *k, char *line)
+static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_context *ctx, struct registry_key *k, char *line)
 {
        int argc;
        char **argv = NULL;
@@ -236,7 +269,7 @@ static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key
        for(i = 0; regshell_cmds[i].name; i++) {
                if(!strcmp(regshell_cmds[i].name, argv[0]) || 
                   (regshell_cmds[i].alias && !strcmp(regshell_cmds[i].alias, argv[0]))) {
-                       return regshell_cmds[i].handle(mem_ctx, k, argc, argv);
+                       return regshell_cmds[i].handle(mem_ctx, ctx, k, argc, argv);
                }
        }
 
@@ -249,7 +282,7 @@ static struct registry_key *process_cmd(TALLOC_CTX *mem_ctx, struct registry_key
 
 static struct registry_key *current_key = NULL;
 
-static char **reg_complete_command(const char *text, int end)
+static char **reg_complete_command(const char *text, int start, int end)
 {
        /* Complete command */
        char **matches;
@@ -288,31 +321,37 @@ static char **reg_complete_command(const char *text, int end)
        return matches;
 
 cleanup:
-       while (i >= 0) {
-               free(matches[i]);
-               i--;
+       count--;
+       while (count >= 0) {
+               free(matches[count]);
+               count--;
        }
        free(matches);
        return NULL;
 }
 
-static char **reg_complete_key(const char *text, int end)
+static char **reg_complete_key(const char *text, int start, int end)
 {
+       struct registry_key *base;
        struct registry_key *subkey;
        int i, j = 1;
        int samelen = 0;
        int len;
        char **matches;
+       const char *base_n = "";
        TALLOC_CTX *mem_ctx;
+       WERROR status;
 
        matches = malloc_array_p(char *, MAX_COMPLETIONS);
        if (!matches) return NULL;
        matches[0] = NULL;
+       mem_ctx = talloc_init("completion");
+
+       base = current_key;
 
        len = strlen(text);
-       mem_ctx = talloc_init("completion");
        for(i = 0; j < MAX_COMPLETIONS-1; i++) {
-               WERROR status = reg_key_get_subkey_by_index(mem_ctx, current_key, i, &subkey);
+               status = reg_key_get_subkey_by_index(mem_ctx, base, i, &subkey);
                if(W_ERROR_IS_OK(status)) {
                        if(!strncmp(text, subkey->name, len)) {
                                matches[j] = strdup(subkey->name);
@@ -328,22 +367,23 @@ static char **reg_complete_key(const char *text, int end)
                        break;
                } else {
                        printf("Error creating completion list: %s\n", win_errstr(status));
-                       talloc_destroy(mem_ctx);
+                       talloc_free(mem_ctx);
                        return NULL;
                }
        }
-       talloc_destroy(mem_ctx);
 
        if (j == 1) { /* No matches at all */
                SAFE_FREE(matches);
+               talloc_free(mem_ctx);
                return NULL;
        }
 
        if (j == 2) { /* Exact match */
-               matches[0] = strdup(matches[1]);
+               asprintf(&matches[0], "%s%s", base_n, matches[1]);
        } else {
-               matches[0] = strndup(matches[1], samelen);
+               asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen));
        }               
+       talloc_free(mem_ctx);
 
        matches[j] = NULL;
        return matches;
@@ -354,9 +394,9 @@ static char **reg_completion(const char *text, int start, int end)
        smb_readline_ca_char(' ');
 
        if (start == 0) {
-               return reg_complete_command(text, end);
+               return reg_complete_command(text, start, end);
        } else {
-               return reg_complete_key(text, end);
+               return reg_complete_key(text, start, end);
        }
 }
 
@@ -372,32 +412,27 @@ static char **reg_completion(const char *text, int start, int end)
        struct registry_context *h = NULL;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               POPT_COMMON_CREDENTIALS
                {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
                {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
-               POPT_TABLEEND
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CREDENTIALS
+               POPT_COMMON_VERSION
+               { NULL }
        };
 
-       regshell_init_subsystems;
-
-       if (!lp_load(dyn_CONFIGFILE,True,False,False)) {
-               fprintf(stderr, "Can't load %s - run testparm to debug it\n", dyn_CONFIGFILE);
-       }
-
-       
        pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
        
        while((opt = poptGetNextOpt(pc)) != -1) {
        }
 
-    setup_logging("regtree", True);
+       registry_init();
 
        if (remote) {
-               error = reg_open_remote (&h, cmdline_get_username(), cmdline_get_userpassword(), remote); 
+               error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL); 
        } else if (backend) {
-               error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, &curkey);
+               error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &curkey);
        } else {
-               error = reg_open_local(&h);
+               error = reg_open_local(NULL, &h, NULL, cmdline_credentials);
        }
 
        if(!W_ERROR_IS_OK(error)) {
@@ -406,8 +441,22 @@ static char **reg_completion(const char *text, int start, int end)
        }
 
        if (h) {
-               /*FIXME: What if HKEY_CLASSES_ROOT is not present ? */
-               reg_get_hive(h, HKEY_CLASSES_ROOT, &curkey);
+               int i;
+
+               for (i = 0; reg_predefined_keys[i].handle; i++) {
+                       WERROR err;
+                       err = reg_get_predefined_key(h, reg_predefined_keys[i].handle, &curkey);
+                       if (W_ERROR_IS_OK(err)) {
+                               break;
+                       } else {
+                               curkey = NULL;
+                       }
+               }
+       }
+
+       if (!curkey) {
+               fprintf(stderr, "Unable to access any of the predefined keys\n");
+               return -1;
        }
        
        poptFreeContext(pc);
@@ -429,11 +478,11 @@ static char **reg_completion(const char *text, int start, int end)
                        break;
 
                if(line[0] != '\n') {
-                       struct registry_key *new = process_cmd(mem_ctx, curkey, line);
+                       struct registry_key *new = process_cmd(mem_ctx, h, curkey, line);
                        if(new)curkey = new;
                }
        }
-       talloc_destroy(mem_ctx);
+       talloc_free(mem_ctx);
 
        return 0;
 }