diff options
author | Jelmer Vernooij <jelmer@samba.org> | 2004-04-04 16:24:08 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:50:33 -0500 |
commit | c424c2b857fe08587eb81a5c5e3625545119d1c2 (patch) | |
tree | 03505d09ccd72cdfd1218066d355e2d01d403bd0 /source4/lib/registry/tools | |
parent | 3855ee0164d1c8ff3c3c4ba8a5556d8cfb6546b3 (diff) | |
download | samba-c424c2b857fe08587eb81a5c5e3625545119d1c2.tar.gz samba-c424c2b857fe08587eb81a5c5e3625545119d1c2.tar.bz2 samba-c424c2b857fe08587eb81a5c5e3625545119d1c2.zip |
r20: Add the registry library. Still needs a lot of work,
see source/lib/registry/TODO for details.
(This used to be commit 7cab3a00d7b4b1d95a3bfa6b28f318b4aaa5d493)
Diffstat (limited to 'source4/lib/registry/tools')
-rw-r--r-- | source4/lib/registry/tools/regdiff.c | 148 | ||||
-rw-r--r-- | source4/lib/registry/tools/regpatch.c | 808 | ||||
-rw-r--r-- | source4/lib/registry/tools/regshell.c | 243 | ||||
-rw-r--r-- | source4/lib/registry/tools/regtree.c | 91 |
4 files changed, 1290 insertions, 0 deletions
diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c new file mode 100644 index 0000000000..070516b798 --- /dev/null +++ b/source4/lib/registry/tools/regdiff.c @@ -0,0 +1,148 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +#include "includes.h" + +void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out) +{ + int i, numvals1, numvals2, numkeys2; + + numkeys2 = reg_key_num_subkeys(newkey); + for(i = 0; i < numkeys2; i++) { + REG_KEY *t1 = reg_key_get_subkey_by_index(newkey, i); + REG_KEY *t2 = reg_key_get_subkey_by_name(oldkey, reg_key_name(t1)); + if(!t2) { + fprintf(out, "[%s]\n", reg_key_get_path(t1)); + } + writediff(t2, t1, out); + } + + numvals2 = reg_key_num_values(newkey); + for(i = 0; i < numvals2; i++) { + REG_VAL *t1 = reg_key_get_value_by_index(newkey, i); + REG_VAL *t2 = reg_key_get_value_by_name(oldkey, reg_val_name(t1)); + if(!t2 || reg_val_size(t2) != reg_val_size(t1) || memcmp(reg_val_data_blk(t1), reg_val_data_blk(t2), reg_val_size(t1))) { + fprintf(out, "\"%s\"=%s:%s\n", reg_val_name(t1), str_regtype(reg_val_type(t1)), reg_val_data_string(t1)); + } + } + + numvals1 = reg_key_num_values(oldkey); + for(i = 0; i < numvals1; i++) { + REG_VAL *t1 = reg_key_get_value_by_index(oldkey, i); + if(!reg_key_get_value_by_name(newkey, reg_val_name(t1))) { + fprintf(out, "\"%s\"=-\n", reg_val_name(t1)); + } + } +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + poptContext pc; + REG_KEY *root; + const char *backend1 = NULL, *backend2 = NULL; + const char *location2; + char *outputfile = NULL; + FILE *fd = stdout; + REG_HANDLE *h2; + REG_KEY *root1 = NULL, *root2; + int from_null = 0; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, NULL, 'b', "backend to use", NULL}, + {"output", 'o', POPT_ARG_STRING, &outputfile, 'o', "output file to use", NULL }, + {"null", 'n', POPT_ARG_NONE, &from_null, 'n', "Diff from NULL" }, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + switch(opt) { + case 'b': + if(!backend1 && !from_null) backend1 = poptGetOptArg(pc); + else if(!backend2) backend2 = poptGetOptArg(pc); + break; + } + } + setup_logging(argv[0], True); + + if(!from_null) { + REG_HANDLE *h1; + const char *location1; + location1 = poptGetArg(pc); + if(!location1) { + poptPrintUsage(pc, stderr, 0); + return 1; + } + + if(!backend1) backend1 = "dir"; + + h1 = reg_open(backend1, location1, True); + if(!h1) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location1, backend1); + return 1; + } + + root1 = reg_get_root(h1); + } + + location2 = poptGetArg(pc); + if(!location2) { + poptPrintUsage(pc, stderr, 0); + return 2; + } + + if(!backend2) backend2 = "dir"; + + h2 = reg_open(backend2, location2, True); + if(!h2) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location2, backend2); + return 1; + } + + root2 = reg_get_root(h2); + if(!root2) { + fprintf(stderr, "Can't open root key for '%s:%s'\n", backend2, location2); + return 1; + } + + poptFreeContext(pc); + + if(outputfile) { + fd = fopen(outputfile, "w+"); + if(!fd) { + fprintf(stderr, "Unable to open '%s'\n", outputfile); + return 1; + } + } + + fprintf(fd, "REGEDIT4\n\n"); + fprintf(fd, "; Generated using regdiff\n"); + + writediff(root1, root2, fd); + + fclose(fd); + + return 0; +} diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c new file mode 100644 index 0000000000..f76da7ebf9 --- /dev/null +++ b/source4/lib/registry/tools/regpatch.c @@ -0,0 +1,808 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) 2002, Richard Sharpe, rsharpe@richardsharpe.com + Copyright (C) 2004, Jelmer Vernooij, jelmer@samba.org + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +#include "includes.h" + +/* + * Routines to parse a REGEDIT4 file + * + * The file consists of: + * + * REGEDIT4 + * \[[-]key-path\]\n + * <value-spec>* + * + * Format: + * [cmd:]name=type:value + * + * cmd = a|d|c|add|delete|change|as|ds|cs + * + * There can be more than one key-path and value-spec. + * + * Since we want to support more than one type of file format, we + * construct a command-file structure that keeps info about the command file + */ + +#define FMT_UNREC -1 +#define FMT_REGEDIT4 0 +#define FMT_EDITREG1_1 1 + +#define FMT_STRING_REGEDIT4 "REGEDIT4" +#define FMT_STRING_EDITREG1_0 "EDITREG1.0" + +#define CMD_NONE 0 +#define CMD_ADD_KEY 1 +#define CMD_DEL_KEY 2 + +#define CMD_KEY 1 +#define CMD_VAL 2 + +#include <include/includes.h> + +typedef struct val_spec_list { + struct val_spec_list *next; + char *name; + int type; + char *val; /* Kept as a char string, really? */ +} VAL_SPEC_LIST; + +typedef struct command_s { + int cmd; + char *key; + int val_count; + VAL_SPEC_LIST *val_spec_list, *val_spec_last; +} CMD; + +typedef struct cmd_line { + int len, line_len; + char *line; +} CMD_LINE; + +static void free_val_spec_list(VAL_SPEC_LIST *vl) +{ + if (!vl) return; + if (vl->name) free(vl->name); + if (vl->val) free(vl->val); + free(vl); + +} + +/* + * Some routines to handle lines of info in the command files + */ +static void skip_to_eol(int fd) +{ + int rc; + char ch = 0; + + while ((rc = read(fd, &ch, 1)) == 1) { + if (ch == 0x0A) return; + } + if (rc < 0) { + DEBUG(0, ("Could not read file descriptor: %d, %s\n", + fd, strerror(errno))); + exit(1); + } +} + +static void free_cmd(CMD *cmd) +{ + if (!cmd) return; + + while (cmd->val_spec_list) { + VAL_SPEC_LIST *tmp; + + tmp = cmd->val_spec_list; + cmd->val_spec_list = tmp->next; + free(tmp); + } + + free(cmd); + +} + +static void free_cmd_line(CMD_LINE *cmd_line) +{ + if (cmd_line) { + if (cmd_line->line) free(cmd_line->line); + free(cmd_line); + } +} + +static void print_line(struct cmd_line *cl) +{ + char *pl; + + if (!cl) return; + + pl = smb_xmalloc(cl->line_len + 1); + + strncpy(pl, cl->line, cl->line_len); + pl[cl->line_len] = 0; + + fprintf(stdout, "%s\n", pl); + free(pl); +} + +#define INIT_ALLOC 10 + +/* + * Read a line from the input file. + * NULL returned when EOF and no chars read + * Otherwise we return a cmd_line * + * Exit if other errors + */ +static struct cmd_line *get_cmd_line(int fd) +{ + struct cmd_line *cl = (CMD_LINE *)smb_xmalloc(sizeof(CMD_LINE)); + int i = 0, rc; + unsigned char ch; + + cl->len = INIT_ALLOC; + + /* + * Allocate some space for the line. We extend later if needed. + */ + + cl->line = (char *)smb_xmalloc(INIT_ALLOC); + + /* + * Now read in the chars to EOL. Don't store the EOL in the + * line. What about CR? + */ + + while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') { + if (ch == '\r') continue; /* skip CR */ + if (i == cl->len) { + /* + * Allocate some more memory + */ + if ((cl->line = realloc(cl->line, cl->len + INIT_ALLOC)) == NULL) { + DEBUG(0, ("Unable to realloc space for line: %s\n", + strerror(errno))); + exit(1); + } + cl->len += INIT_ALLOC; + } + cl->line[i] = ch; + i++; + } + + /* read 0 and we were at loc'n 0, return NULL */ + if (rc == 0 && i == 0) { + free_cmd_line(cl); + return NULL; + } + + cl->line_len = i; + + return cl; + +} + +/* + * parse_value: parse out a value. We pull it apart as: + * + * <value> ::= <value-name>=<type>:<value-string> + * + * <value-name> ::= char-string-without-spaces | '"' char-string '"' + * + * If it parsed OK, return the <value-name> as a string, and the + * value type and value-string in parameters. + * + * The value name can be empty. There can only be one empty name in + * a list of values. A value of - removes the value entirely. + */ + +static char *parse_name(char *nstr) +{ + int len = 0, start = 0; + if (!nstr) return NULL; + + len = strlen(nstr); + + while (len && nstr[len - 1] == ' ') len--; + + nstr[len] = 0; /* Trim any spaces ... if there were none, doesn't matter */ + + /* + * Beginning and end should be '"' or neither should be so + */ + if ((nstr[0] == '"' && nstr[len - 1] != '"') || + (nstr[0] != '"' && nstr[len - 1] == '"')) + return NULL; + + if (nstr[0] == '"') { + start = 1; + len -= 2; + } + + return strndup(&nstr[start], len); +} + +static int parse_value_type(char *tstr) +{ + int len = strlen(tstr); + + while (len && tstr[len - 1] == ' ') len--; + tstr[len] = 0; + + if (strcmp(tstr, "REG_DWORD") == 0) + return REG_DWORD; + else if (strcmp(tstr, "dword") == 0) + return REG_DWORD; + else if (strcmp(tstr, "REG_EXPAND_SZ") == 0) + return REG_EXPAND_SZ; + else if (strcmp(tstr, "REG_BIN") == 0) + return REG_BINARY; + else if (strcmp(tstr, "REG_SZ") == 0) + return REG_SZ; + else if (strcmp(tstr, "REG_MULTI_SZ") == 0) + return REG_MULTI_SZ; + else if (strcmp(tstr, "-") == 0) + return REG_DELETE; + + return 0; +} + +static char *parse_val_str(char *vstr) +{ + + return strndup(vstr, strlen(vstr)); + +} + +static char *parse_value(struct cmd_line *cl, int *vtype, char **val) +{ + char *p1 = NULL, *p2 = NULL, *nstr = NULL, *tstr = NULL, *vstr = NULL; + + if (!cl || !vtype || !val) return NULL; + if (!cl->line_len) return NULL; + + p1 = strndup(cl->line, cl->line_len); + /* FIXME: Better return codes etc ... */ + if (!p1) return NULL; + p2 = strchr(p1, '='); + if (!p2) return NULL; + + *p2 = 0; p2++; /* Split into two strings at p2 */ + + /* Now, parse the name ... */ + + nstr = parse_name(p1); + if (!nstr) goto error; + + /* Now, split the remainder and parse on type and val ... */ + + tstr = p2; + while (*tstr == ' ') tstr++; /* Skip leading white space */ + p2 = strchr(p2, ':'); + + if (p2) { + *p2 = 0; p2++; /* split on the : */ + } + + *vtype = parse_value_type(tstr); + + if (!vtype) goto error; + + if (!p2 || !*p2) return nstr; + + /* Now, parse the value string. It should return a newly malloc'd string */ + + while (*p2 == ' ') p2++; /* Skip leading space */ + vstr = parse_val_str(p2); + + if (!vstr) goto error; + + *val = vstr; + + return nstr; + + error: + if (p1) free(p1); + if (nstr) free(nstr); + if (vstr) free(vstr); + return NULL; +} + +/* + * Parse out a key. Look for a correctly formatted key [...] + * and whether it is a delete or add? A delete is signalled + * by a - in front of the key. + * Assumes that there are no leading and trailing spaces + */ + +static char *parse_key(struct cmd_line *cl, int *cmd) +{ + int start = 1; + char *tmp; + + if (cl->line[0] != '[' || + cl->line[cl->line_len - 1] != ']') return NULL; + if (cl->line_len == 2) return NULL; + *cmd = CMD_ADD_KEY; + if (cl->line[1] == '-') { + if (cl->line_len == 3) return NULL; + start = 2; + *cmd = CMD_DEL_KEY; + } + tmp = smb_xmalloc(cl->line_len - 1 - start + 1); + strncpy(tmp, &cl->line[start], cl->line_len - 1 - start); + tmp[cl->line_len - 1 - start] = 0; + return tmp; +} + +/* + * Parse a line to determine if we have a key or a value + * We only check for key or val ... + */ + +static int parse_line(struct cmd_line *cl) +{ + + if (!cl || cl->len == 0) return 0; + + if (cl->line[0] == '[') /* No further checking for now */ + return CMD_KEY; + else + return CMD_VAL; +} + +/* + * We seek to offset 0, read in the required number of bytes, + * and compare to the correct value. + * We then seek back to the original location + */ +static int regedit4_file_type(int fd) +{ + int cur_ofs = 0; + char desc[9]; + + cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ + if (cur_ofs < 0) { + DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); + exit(1); /* FIXME */ + } + + if (cur_ofs) { + lseek(fd, 0, SEEK_SET); + } + + if (read(fd, desc, 8) < 8) { + DEBUG(0, ("Unable to read command file format\n")); + exit(2); /* FIXME */ + } + + desc[8] = 0; + + if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) { + if (cur_ofs) { + lseek(fd, cur_ofs, SEEK_SET); + } + else { + skip_to_eol(fd); + } + return FMT_REGEDIT4; + } + + return FMT_UNREC; +} + +/* + * Run though the data in the line and strip anything after a comment + * char. + */ +static void strip_comment(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = 0; i < cl->line_len; i++) { + if (cl->line[i] == ';') { + cl->line_len = i; + return; + } + } +} + +/* + * trim leading space + */ + +static void trim_leading_spaces(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = 0; i < cl->line_len; i++) { + if (cl->line[i] != ' '){ + if (i) memcpy(cl->line, &cl->line[i], cl->line_len - i); + return; + } + } +} + +/* + * trim trailing spaces + */ +static void trim_trailing_spaces(struct cmd_line *cl) +{ + int i; + + if (!cl) return; + + for (i = cl->line_len; i == 0; i--) { + if (cl->line[i-1] != ' ' && + cl->line[i-1] != '\t') { + cl->line_len = i; + } + } +} + +/* + * Get a command ... This consists of possibly multiple lines: + * [key] + * values* + * possibly Empty line + * + * value ::= <value-name>=<value-type>':'<value-string> + * <value-name> is some path, possibly enclosed in quotes ... + * We alctually look for the next key to terminate a previous key + * if <value-type> == '-', then it is a delete type. + */ +static CMD *regedit4_get_cmd(int fd) +{ + struct command_s *cmd = NULL; + struct cmd_line *cl = NULL; + struct val_spec_list *vl = NULL; + + cmd = (struct command_s *)smb_xmalloc(sizeof(struct command_s)); + + cmd->cmd = CMD_NONE; + cmd->key = NULL; + cmd->val_count = 0; + cmd->val_spec_list = cmd->val_spec_last = NULL; + while ((cl = get_cmd_line(fd))) { + + /* + * If it is an empty command line, and we already have a key + * then exit from here ... FIXME: Clean up the parser + */ + + if (cl->line_len == 0 && cmd->key) { + free_cmd_line(cl); + break; + } + + strip_comment(cl); /* remove anything beyond a comment char */ + trim_trailing_spaces(cl); + trim_leading_spaces(cl); + + if (cl->line_len == 0) { /* An empty line */ + free_cmd_line(cl); + } + else { /* Else, non-empty ... */ + /* + * Parse out the bits ... + */ + switch (parse_line(cl)) { + case CMD_KEY: + if ((cmd->key = parse_key(cl, &cmd->cmd)) == NULL) { + DEBUG(0, ("Error parsing key from line: ")); + print_line(cl); + DEBUG(0, ("\n")); + } + break; + + case CMD_VAL: + /* + * We need to add the value stuff to the list + * There could be a \ on the end which we need to + * handle at some time + */ + vl = (struct val_spec_list *)smb_xmalloc(sizeof(struct val_spec_list)); + vl->next = NULL; + vl->val = NULL; + vl->name = parse_value(cl, &vl->type, &vl->val); + if (!vl->name) goto error; + if (cmd->val_spec_list == NULL) { + cmd->val_spec_list = cmd->val_spec_last = vl; + } + else { + cmd->val_spec_last->next = vl; + cmd->val_spec_last = vl; + } + cmd->val_count++; + break; + + default: + DEBUG(0, ("Unrecognized line in command file: \n")); + print_line(cl); + break; + } + } + + } + if (!cmd->cmd) goto error; /* End of file ... */ + + return cmd; + + error: + if (vl) free(vl); + if (cmd) free_cmd(cmd); + return NULL; +} + +static int regedit4_exec_cmd(CMD *cmd) +{ + + return 0; +} + +static int editreg_1_0_file_type(int fd) +{ + int cur_ofs = 0; + char desc[11]; + + cur_ofs = lseek(fd, 0, SEEK_CUR); /* Get current offset */ + if (cur_ofs < 0) { + DEBUG(0, ("Unable to get current offset: %s\n", strerror(errno))); + exit(1); /* FIXME */ + } + + if (cur_ofs) { + lseek(fd, 0, SEEK_SET); + } + + if (read(fd, desc, 10) < 10) { + DEBUG(0, ("Unable to read command file format\n")); + exit(2); /* FIXME */ + } + + desc[10] = 0; + + if (strcmp(desc, FMT_STRING_EDITREG1_0) == 0) { + lseek(fd, cur_ofs, SEEK_SET); + return FMT_REGEDIT4; + } + + return FMT_UNREC; +} + +static CMD *editreg_1_0_get_cmd(int fd) +{ + return NULL; +} + +static int editreg_1_0_exec_cmd(CMD *cmd) +{ + + return -1; +} + +typedef struct command_ops_s { + int type; + int (*file_type)(int fd); + CMD *(*get_cmd)(int fd); + int (*exec_cmd)(CMD *cmd); +} CMD_OPS; + +CMD_OPS default_cmd_ops[] = { + {0, regedit4_file_type, regedit4_get_cmd, regedit4_exec_cmd}, + {1, editreg_1_0_file_type, editreg_1_0_get_cmd, editreg_1_0_exec_cmd}, + {-1, NULL, NULL, NULL} +}; + +typedef struct command_file_s { + char *name; + int type, fd; + CMD_OPS cmd_ops; +} CMD_FILE; + +/* + * Create a new command file structure + */ + +static CMD_FILE *cmd_file_create(char *file) +{ + CMD_FILE *tmp; + struct stat sbuf; + int i = 0; + + /* + * Let's check if the file exists ... + * No use creating the cmd_file structure if the file does not exist + */ + + if (stat(file, &sbuf) < 0) { /* Not able to access file */ + + return NULL; + } + + tmp = (CMD_FILE *)smb_xmalloc(sizeof(CMD_FILE)); + + /* + * Let's fill in some of the fields; + */ + + tmp->name = strdup(file); + + if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) { + free(tmp); + return NULL; + } + + /* + * Now, try to find the format by indexing through the table + */ + while (default_cmd_ops[i].type != -1) { + if ((tmp->type = default_cmd_ops[i].file_type(tmp->fd)) >= 0) { + tmp->cmd_ops = default_cmd_ops[i]; + return tmp; + } + i++; + } + + /* + * If we got here, return NULL, as we could not figure out the type + * of command file. + * + * What about errors? + */ + + free(tmp); + return NULL; +} + +/* + * Extract commands from the command file, and execute them. + * We pass a table of command callbacks for that + */ + +//FIXME + +/* + * Main code from here on ... + */ + +/* + * key print function here ... + */ + +/* + * Sec Desc print functions + */ + +char *str_type(unsigned char type); + +int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name) +{ + CMD *cmd; + int modified = 0; + CMD_FILE *cmd_file = NULL; + cmd_file = cmd_file_create(cmd_file_name); + + while ((cmd = cmd_file->cmd_ops.get_cmd(cmd_file->fd)) != NULL) { + + /* + * Now, apply the requests to the tree ... + */ + switch (cmd->cmd) { + case CMD_ADD_KEY: { + REG_KEY *tmp = NULL; + tmp = reg_open_key(reg_get_root(regf), cmd->key); + /* If we found it, apply the other bits, else create such a key */ + if (!tmp) { + if(reg_key_add_name(reg_get_root(regf), cmd->key)) { + tmp = reg_open_key(reg_get_root(regf), cmd->key); + } + modified = 1; + } + + while (cmd->val_count) { + VAL_SPEC_LIST *val = cmd->val_spec_list; + REG_VAL *reg_val = NULL; + + if (val->type == REG_DELETE) { + reg_val = reg_key_get_value_by_name( tmp, val->name); + reg_val_del(reg_val); + modified = 1; + } + else { + /* FIXME + reg_val = nt_add_reg_value(tmp, val->name, val->type, + val->val); */ + modified = 1; + } + + cmd->val_spec_list = val->next; + free_val_spec_list(val); + cmd->val_count--; + } + + break; + } + + case CMD_DEL_KEY: + /* + * Any value does not matter ... + * Find the key if it exists, and delete it ... + */ + + reg_key_del_recursive(reg_open_key(reg_get_root(regf), cmd->key)); + modified = 1; + break; + } + } + free_cmd(cmd); + + return modified; +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + poptContext pc; + REG_KEY *root; + const char *location; + const char *patch; + char *backend = "dir"; + REG_HANDLE *h; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 'b', "backend to use", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + setup_logging(argv[0], True); + + location = poptGetArg(pc); + if(!location) { + poptPrintUsage(pc, stderr, 0); + return 1; + } + + h = reg_open(backend, location, True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", location, backend); + return 1; + } + + poptFreeContext(pc); + + patch = poptGetArg(pc); + if(!patch) patch = "/dev/stdin"; + + nt_apply_reg_command_file(h, patch); + + return 0; +} diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c new file mode 100644 index 0000000000..9074d1c716 --- /dev/null +++ b/source4/lib/registry/tools/regshell.c @@ -0,0 +1,243 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +#include "includes.h" + +/* + * ck/cd - change key + * ls - list values/keys + * rmval/rm - remove value + * rmkey/rmdir - remove key + * mkkey/mkdir - make key + * help + * exit + */ + +static REG_KEY *cmd_set(REG_KEY *cur, int argc, char **argv) +{ + /* FIXME */ + return NULL; +} + +static REG_KEY *cmd_ck(REG_KEY *cur, int argc, char **argv) +{ + REG_KEY *new; + if(argc < 2) { + new = cur; + } else { + new = reg_open_key(cur, argv[1]); + } + + if(!new) new = cur; + + printf("Current path is: %s\n", reg_key_get_path(new)); + + return new; +} + +static REG_KEY *cmd_ls(REG_KEY *cur, int argc, char **argv) +{ + int i, num; + num = reg_key_num_subkeys(cur); + for(i = 0; i < num; i++) { + REG_KEY *sub = reg_key_get_subkey_by_index(cur, i); + printf("K %s\n", reg_key_name(sub)); + } + + num = reg_key_num_values(cur); + for(i = 0; i < num; i++) { + REG_VAL *sub = reg_key_get_value_by_index(cur, i); + printf("V %s %s %s\n", reg_val_name(sub), str_regtype(reg_val_type(sub)), reg_val_data_string(sub)); + } + + return NULL; +} +static REG_KEY *cmd_mkkey(REG_KEY *cur, int argc, char **argv) +{ + if(argc < 2) { + fprintf(stderr, "Usage: mkkey <keyname>\n"); + return NULL; + } + + if(!reg_key_add_name(cur, argv[1])) { + 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(cur)); + + return NULL; +} + +static REG_KEY *cmd_rmkey(REG_KEY *cur, int argc, char **argv) +{ + REG_KEY *key; + if(argc < 2) { + fprintf(stderr, "Usage: rmkey <name>\n"); + return NULL; + } + + key = reg_open_key(cur, argv[1]); + if(!key) { + fprintf(stderr, "No such subkey '%s'\n", argv[1]); + return NULL; + } + + if(!reg_key_del(key)) { + fprintf(stderr, "Error deleting '%s'\n", argv[1]); + } else { + fprintf(stderr, "Successfully deleted '%s'\n", argv[1]); + } + + return NULL; +} + +static REG_KEY *cmd_rmval(REG_KEY *cur, int argc, char **argv) +{ + REG_VAL *val; + if(argc < 2) { + fprintf(stderr, "Usage: rmval <valuename>\n"); + return NULL; + } + + val = reg_key_get_value_by_name(cur, argv[1]); + if(!val) { + fprintf(stderr, "No such value '%s'\n", argv[1]); + return NULL; + } + + if(!reg_val_del(val)) { + fprintf(stderr, "Error deleting value '%s'\n", argv[1]); + } else { + fprintf(stderr, "Successfully deleted value '%s'\n", argv[1]); + } + + return NULL; +} + +static REG_KEY *cmd_exit(REG_KEY *cur, int argc, char **argv) +{ + exit(0); + return NULL; +} + +static REG_KEY *cmd_help(REG_KEY *, int, char **); + +struct { + const char *name; + const char *alias; + const char *help; + REG_KEY *(*handle)(REG_KEY *, int argc, char **argv); +} regshell_cmds[] = { + {"ck", "cd", "Change current key", cmd_ck }, + {"list", "ls", "List values/keys in current key", cmd_ls }, + {"mkkey", "mkdir", "Make new key", cmd_mkkey }, + {"rmval", "rm", "Remove value", cmd_rmval }, + {"rmkey", "rmdir", "Remove key", cmd_rmkey }, + {"set", "update", "Update value", cmd_set }, + {"help", "?", "Help", cmd_help }, + {"exit", "quit", "Exit", cmd_exit }, + {NULL } +}; + +static REG_KEY *cmd_help(REG_KEY *cur, int argc, char **argv) +{ + int i; + printf("Available commands:\n"); + for(i = 0; regshell_cmds[i].name; i++) { + printf("%s - %s\n", regshell_cmds[i].name, regshell_cmds[i].help); + } + return NULL; +} + +REG_KEY *process_cmd(REG_KEY *k, char *line) +{ + int argc; + char **argv = NULL; + int ret, i; + + if ((ret = poptParseArgvString(line, &argc, (const char ***) &argv)) != 0) { + fprintf(stderr, "regshell: %s\n", poptStrerror(ret)); + return k; + } + + 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); + } + } + + fprintf(stderr, "No such command '%s'\n", argv[0]); + + return k; +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + char *backend = "dir"; + REG_KEY *curkey = NULL;; + poptContext pc; + REG_HANDLE *h; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + h = reg_open(backend, poptPeekArg(pc), True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + return 1; + } + poptFreeContext(pc); + + setup_logging("regtree", True); + + curkey = reg_get_root(h); + + if(!curkey) return 1; + + while(True) { + char *line, *prompt; + + asprintf(&prompt, "%s> ", reg_key_get_path(curkey)); + + line = smb_readline(prompt, NULL, NULL); + + if(!line) + break; + + if(line[0] != '\n') { + REG_KEY *new = process_cmd(curkey, line); + if(new)curkey = new; + } + } + + return 0; +} diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c new file mode 100644 index 0000000000..80cbccf48f --- /dev/null +++ b/source4/lib/registry/tools/regtree.c @@ -0,0 +1,91 @@ +/* + Unix SMB/CIFS implementation. + simple registry frontend + + Copyright (C) Jelmer Vernooij 2004 + + 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 + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + 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. +*/ + +#include "includes.h" + +void print_tree(int l, REG_KEY *p, int fullpath, int novals) +{ + int num_subkeys, i, num_values; + + for(i = 0; i < l; i++) putchar(' '); + if(fullpath) printf("%s\n", reg_key_get_path(p)); + else printf("%s\n", reg_key_name(p)); + + num_subkeys = reg_key_num_subkeys(p); + for(i = 0; i < num_subkeys; i++) { + REG_KEY *subkey = reg_key_get_subkey_by_index(p, i); + print_tree(l+1, subkey, fullpath, novals); + reg_key_free(subkey); + } + + if(!novals) { + num_values = reg_key_num_values(p); + for(i = 0; i < num_values; i++) { + int j; + char *desc; + REG_VAL *value = reg_key_get_value_by_index(p, i); + for(j = 0; j < l+1; j++) putchar(' '); + desc = reg_val_description(value); + printf("%s\n", desc); + free(desc); + reg_val_free(value); + } + } +} + +int main (int argc, char **argv) +{ + uint32 setparms, checkparms; + int opt; + char *backend = "dir"; + poptContext pc; + REG_KEY *root; + REG_HANDLE *h; + int fullpath = 0, no_values = 0; + struct poptOption long_options[] = { + POPT_AUTOHELP + {"backend", 'b', POPT_ARG_STRING, &backend, 0, "backend to use", NULL}, + {"fullpath", 'f', POPT_ARG_NONE, &fullpath, 0, "show full paths", NULL}, + {"no-values", 'V', POPT_ARG_NONE, &no_values, 0, "don't show values", NULL}, + POPT_TABLEEND + }; + + pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0); + + while((opt = poptGetNextOpt(pc)) != -1) { + } + + setup_logging("regtree", True); + + h = reg_open(backend, poptPeekArg(pc), True); + if(!h) { + fprintf(stderr, "Unable to open '%s' with backend '%s'\n", poptGetArg(pc), backend); + return 1; + } + poptFreeContext(pc); + + root = reg_get_root(h); + if(!root) return 1; + + print_tree(0, root, fullpath, no_values); + + return 0; +} |