r23792: convert Samba4 to GPLv3
[kai/samba-autobuild/.git] / source4 / lib / registry / tools / regshell.c
index 638ed70d5eeced08769369ab4936b1f060c79140..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 "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 REG_KEY *cmd_info(REG_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;
-       printf("Name: %s\n", reg_key_name(cur));
-       printf("Full path: %s\n", reg_key_get_path(cur));
-       printf("Key Class: %s\n", reg_key_class(cur));
-       last_mod = nt_time_to_unix(reg_key_last_modified(cur));
+       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 REG_KEY *cmd_pwd(REG_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)
 {
-       printf("%s\n", reg_key_get_path_abs(cur));
+       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 REG_KEY *cmd_set(REG_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 REG_KEY *cmd_ck(REG_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)
 { 
-       REG_KEY *new = NULL;
+       struct registry_key *new = NULL;
        WERROR error;
        if(argc < 2) {
                new = cur;
        } else {
-               error = reg_open_key(cur, argv[1], &new);
+               error = reg_open_key(mem_ctx, cur, argv[1], &new);
                if(!W_ERROR_IS_OK(error)) {
                        DEBUG(0, ("Error opening specified key: %s\n", win_errstr(error)));
                        return NULL;
                }
        } 
 
-       printf("Current path is: %s\n", reg_key_get_path_abs(new));
+       printf("Current path is: %s\n", new->path);
        
        return new;
 }
 
-static REG_KEY *cmd_ls(REG_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;
-       REG_VAL *value;
-       REG_KEY *sub;
-       for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(cur, i, &sub)); i++) {
-               printf("K %s\n", reg_key_name(sub));
+       struct registry_value *value;
+       struct registry_key *sub;
+       for(i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(mem_ctx, cur, i, &sub)); i++) {
+               printf("K %s\n", sub->name);
        }
 
        if(!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) {
                DEBUG(0, ("Error occured while browsing thru keys: %s\n", win_errstr(error)));
        }
 
-       for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(cur, i, &value)); i++) {
-               printf("V \"%s\" %s %s\n", reg_val_name(value), str_regtype(reg_val_type(value)), reg_val_data_string(value));
+       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->data_type, &value->data));
        }
        
        return NULL; 
 }
-static REG_KEY *cmd_mkkey(REG_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)
 { 
-       REG_KEY *tmp;
+       struct registry_key *tmp;
        if(argc < 2) {
                fprintf(stderr, "Usage: mkkey <keyname>\n");
                return NULL;
        }
        
-       if(!W_ERROR_IS_OK(reg_key_add_name(cur, argv[1], 0, NULL, &tmp))) {
+       if(!W_ERROR_IS_OK(reg_key_add_name(mem_ctx, cur, argv[1], 0, NULL, &tmp))) {
                fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]);
                return NULL;
        }
 
-       fprintf(stderr, "Successfully added new subkey '%s' to '%s'\n", argv[1], reg_key_get_path_abs(cur));
-       
        return NULL; 
 }
 
-static REG_KEY *cmd_rmkey(REG_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)
 { 
-       REG_KEY *key;
        if(argc < 2) {
                fprintf(stderr, "Usage: rmkey <name>\n");
                return NULL;
        }
 
-       if(!W_ERROR_IS_OK(reg_open_key(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]);
@@ -136,20 +200,14 @@ static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv)
        return NULL; 
 }
 
-static REG_KEY *cmd_rmval(REG_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)
 { 
-       REG_VAL *val;
        if(argc < 2) {
                fprintf(stderr, "Usage: rmval <valuename>\n");
                return NULL;
        }
 
-       if(!W_ERROR_IS_OK(reg_key_get_value_by_name(cur, argv[1], &val))) {
-               fprintf(stderr, "No such value '%s'\n", argv[1]);
-               return NULL;
-       }
-
-       if(!W_ERROR_IS_OK(reg_val_del(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]);
@@ -158,43 +216,24 @@ static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv)
        return NULL; 
 }
 
-static REG_KEY *cmd_hive(REG_KEY *cur, int argc, char **argv)
-{
-       int i;
-       WERROR error = WERR_OK;
-       for(i = 0; W_ERROR_IS_OK(error); i++) {
-               REG_KEY *hive;
-               error = reg_get_hive(reg_key_handle(cur), i, &hive);
-               if(!W_ERROR_IS_OK(error)) break;
-
-               if(argc == 1) {
-                       printf("%s\n", reg_key_name(hive));
-               } else if(!strcmp(reg_key_name(hive), argv[1])) {
-                       return hive;
-               } 
-               reg_key_free(hive);
-       }
-       return NULL;
-}
-
-static REG_KEY *cmd_exit(REG_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 REG_KEY *cmd_help(REG_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;
-       REG_KEY *(*handle)(REG_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 },
@@ -202,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 REG_KEY *cmd_help(REG_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");
@@ -215,7 +255,7 @@ static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv)
        return NULL;
 } 
 
-static REG_KEY *process_cmd(REG_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;
@@ -229,7 +269,7 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
        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(k, argc, argv);
+                       return regshell_cmds[i].handle(mem_ctx, ctx, k, argc, argv);
                }
        }
 
@@ -240,15 +280,15 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
 
 #define MAX_COMPLETIONS 100
 
-static REG_KEY *current_key = NULL;
+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;
-       int i, len, samelen, count=1;
+       int i, len, samelen=0, count=1;
 
-       matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+       matches = malloc_array_p(char *, MAX_COMPLETIONS);
        if (!matches) return NULL;
        matches[0] = NULL;
 
@@ -275,52 +315,76 @@ static char **reg_complete_command(const char *text, int end)
                matches[0] = strdup(matches[1]);
                break;
        default:
-               matches[0] = malloc(samelen+1);
-               if (!matches[0])
-                       goto cleanup;
-               strncpy(matches[0], matches[1], samelen);
-               matches[0][samelen] = 0;
+               matches[0] = strndup(matches[1], samelen);
        }
        matches[count] = NULL;
        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)
 {
-       REG_KEY *subkey;
-       int i, j = 0;
+       struct registry_key *base;
+       struct registry_key *subkey;
+       int i, j = 1;
+       int samelen = 0;
        int len;
        char **matches;
-       /* Complete argument */
+       const char *base_n = "";
+       TALLOC_CTX *mem_ctx;
+       WERROR status;
 
-       matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+       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);
        for(i = 0; j < MAX_COMPLETIONS-1; i++) {
-               WERROR status = reg_key_get_subkey_by_index(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, reg_key_name(subkey), len)) {
-                               matches[j] = strdup(reg_key_name(subkey));
+                       if(!strncmp(text, subkey->name, len)) {
+                               matches[j] = strdup(subkey->name);
                                j++;
+
+                               if (j == 1)
+                                       samelen = strlen(matches[j]);
+                               else
+                                       while (strncmp(matches[j], matches[j-1], samelen) != 0)
+                                               samelen--;
                        }
-                       reg_key_free(subkey);
                } else if(W_ERROR_EQUAL(status, WERR_NO_MORE_ITEMS)) {
                        break;
                } else {
                        printf("Error creating completion list: %s\n", win_errstr(status));
+                       talloc_free(mem_ctx);
                        return NULL;
                }
        }
+
+       if (j == 1) { /* No matches at all */
+               SAFE_FREE(matches);
+               talloc_free(mem_ctx);
+               return NULL;
+       }
+
+       if (j == 2) { /* Exact match */
+               asprintf(&matches[0], "%s%s", base_n, matches[1]);
+       } else {
+               asprintf(&matches[0], "%s%s", base_n, talloc_strndup(mem_ctx, matches[1], samelen));
+       }               
+       talloc_free(mem_ctx);
+
        matches[j] = NULL;
        return matches;
 }
@@ -330,51 +394,81 @@ 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);
        }
 }
 
  int main(int argc, char **argv)
 {
        int opt;
-       const char *backend = "dir";
-       const char *credentials = NULL;
-       REG_KEY *curkey = NULL;
+       const char *backend = NULL;
+       struct registry_key *curkey = NULL;
        poptContext pc;
        WERROR error;
-       REG_HANDLE *h;
+       TALLOC_CTX *mem_ctx = talloc_init("cmd");
+       const char *remote = NULL;
+       struct registry_context *h = NULL;
        struct poptOption long_options[] = {
                POPT_AUTOHELP
-               POPT_COMMON_SAMBA
                {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL},
-               {"credentials", 'c', POPT_ARG_STRING, &credentials, 0, "credentials", NULL},
-               POPT_TABLEEND
+               {"remote", 'R', POPT_ARG_STRING, &remote, 0, "connect to specified remote server", NULL},
+               POPT_COMMON_SAMBA
+               POPT_COMMON_CREDENTIALS
+               POPT_COMMON_VERSION
+               { NULL }
        };
-       
+
        pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
        
        while((opt = poptGetNextOpt(pc)) != -1) {
        }
 
-       error = reg_open(backend, poptPeekArg(pc), credentials, &h);
+       registry_init();
+
+       if (remote) {
+               error = reg_open_remote (&h, NULL, cmdline_credentials, remote, NULL); 
+       } else if (backend) {
+               error = reg_open_hive(NULL, backend, poptGetArg(pc), NULL, cmdline_credentials, &curkey);
+       } else {
+               error = reg_open_local(NULL, &h, NULL, cmdline_credentials);
+       }
+
        if(!W_ERROR_IS_OK(error)) {
-               fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend);
+               fprintf(stderr, "Unable to open registry\n");
                return 1;
        }
-       poptFreeContext(pc);
-
-    setup_logging("regtree", True);
 
-       error = reg_get_hive(h, 0, &curkey);
+       if (h) {
+               int i;
 
-       if(!W_ERROR_IS_OK(error)) return 1;
+               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);
+       
        while(True) {
                char *line, *prompt;
                
-               asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey));
+               if(curkey->hive->root->name) {
+                       asprintf(&prompt, "%s:%s> ", curkey->hive->root->name, curkey->path);
+               } else {
+                       asprintf(&prompt, "%s> ", curkey->path);
+               }
                
                current_key = curkey;           /* No way to pass a void * pointer 
                                                                           via readline :-( */
@@ -384,10 +478,11 @@ static char **reg_completion(const char *text, int start, int end)
                        break;
 
                if(line[0] != '\n') {
-                       REG_KEY *new = process_cmd(curkey, line);
+                       struct registry_key *new = process_cmd(mem_ctx, h, curkey, line);
                        if(new)curkey = new;
                }
        }
+       talloc_free(mem_ctx);
 
        return 0;
 }