summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorJelmer Vernooij <jelmer@samba.org>2004-09-08 13:44:45 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:58:35 -0500
commit93454ff3d8177fb71443808f01740dbbe7e46dd8 (patch)
tree6394eb6a72b7c318788b4636dd7995a9154322f9 /source4
parentec952cde0501b15c5e14a3c06333f97dc77dc1f0 (diff)
downloadsamba-93454ff3d8177fb71443808f01740dbbe7e46dd8.tar.gz
samba-93454ff3d8177fb71443808f01740dbbe7e46dd8.tar.bz2
samba-93454ff3d8177fb71443808f01740dbbe7e46dd8.zip
r2257: Tab completion support in regshell (complete command names and key names
in the current key) (This used to be commit 83f9f8eaa4825bb49e2b160a1a810080ecae4d39)
Diffstat (limited to 'source4')
-rw-r--r--source4/lib/registry/common/reg_objects.c10
-rw-r--r--source4/lib/registry/tools/regshell.c116
2 files changed, 125 insertions, 1 deletions
diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c
index d042c74e47..d911b4650b 100644
--- a/source4/lib/registry/common/reg_objects.c
+++ b/source4/lib/registry/common/reg_objects.c
@@ -103,6 +103,16 @@ char *reg_key_name( REG_KEY *key )
return key->name;
}
+char *reg_key_class( REG_KEY *key )
+{
+ return key->class_name;
+}
+
+NTTIME reg_key_last_modified( REG_KEY *key )
+{
+ return key->last_mod;
+}
+
REG_KEY *reg_key_dup(REG_KEY *key)
{
key->ref++;
diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c
index b843e91120..638ed70d5e 100644
--- a/source4/lib/registry/tools/regshell.c
+++ b/source4/lib/registry/tools/regshell.c
@@ -28,10 +28,23 @@
* rmkey/rmdir - remove key
* mkkey/mkdir - make key
* ch - change hive
+ * info - show key info
* help
* exit
*/
+static REG_KEY *cmd_info(REG_KEY *cur, int argc, char **argv)
+{
+ 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));
+ printf("Time Last Modified: %s\n", ctime(&last_mod));
+ /* FIXME: Security info */
+ return cur;
+}
+
static REG_KEY *cmd_pwd(REG_KEY *cur, int argc, char **argv)
{
printf("%s\n", reg_key_get_path_abs(cur));
@@ -180,6 +193,7 @@ struct {
} 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 },
{"mkkey", "mkdir", "Make new key", cmd_mkkey },
{"rmval", "rm", "Remove value", cmd_rmval },
@@ -224,6 +238,104 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
return k;
}
+#define MAX_COMPLETIONS 100
+
+static REG_KEY *current_key = NULL;
+
+static char **reg_complete_command(const char *text, int end)
+{
+ /* Complete command */
+ char **matches;
+ int i, len, samelen, count=1;
+
+ matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+ if (!matches) return NULL;
+ matches[0] = NULL;
+
+ len = strlen(text);
+ for (i=0;regshell_cmds[i].handle && count < MAX_COMPLETIONS-1;i++) {
+ if (strncmp(text, regshell_cmds[i].name, len) == 0) {
+ matches[count] = strdup(regshell_cmds[i].name);
+ if (!matches[count])
+ goto cleanup;
+ if (count == 1)
+ samelen = strlen(matches[count]);
+ else
+ while (strncmp(matches[count], matches[count-1], samelen) != 0)
+ samelen--;
+ count++;
+ }
+ }
+
+ switch (count) {
+ case 0: /* should never happen */
+ case 1:
+ goto cleanup;
+ case 2:
+ 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[count] = NULL;
+ return matches;
+
+cleanup:
+ while (i >= 0) {
+ free(matches[i]);
+ i--;
+ }
+ free(matches);
+ return NULL;
+}
+
+static char **reg_complete_key(const char *text, int end)
+{
+ REG_KEY *subkey;
+ int i, j = 0;
+ int len;
+ char **matches;
+ /* Complete argument */
+
+ matches = (char **)malloc(sizeof(matches[0])*MAX_COMPLETIONS);
+ if (!matches) return NULL;
+ matches[0] = NULL;
+
+ len = strlen(text);
+ for(i = 0; j < MAX_COMPLETIONS-1; i++) {
+ WERROR status = reg_key_get_subkey_by_index(current_key, i, &subkey);
+ if(W_ERROR_IS_OK(status)) {
+ if(!strncmp(text, reg_key_name(subkey), len)) {
+ matches[j] = strdup(reg_key_name(subkey));
+ j++;
+ }
+ 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));
+ return NULL;
+ }
+ }
+ matches[j] = NULL;
+ return matches;
+}
+
+static char **reg_completion(const char *text, int start, int end)
+{
+ smb_readline_ca_char(' ');
+
+ if (start == 0) {
+ return reg_complete_command(text, end);
+ } else {
+ return reg_complete_key(text, end);
+ }
+}
+
int main(int argc, char **argv)
{
int opt;
@@ -264,7 +376,9 @@ static REG_KEY *process_cmd(REG_KEY *k, char *line)
asprintf(&prompt, "%s> ", reg_key_get_path_abs(curkey));
- line = smb_readline(prompt, NULL, NULL);
+ current_key = curkey; /* No way to pass a void * pointer
+ via readline :-( */
+ line = smb_readline(prompt, NULL, reg_completion);
if(!line)
break;