summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/registry/TODO4
-rw-r--r--source4/lib/registry/common/reg_interface.c65
-rw-r--r--source4/lib/registry/common/reg_objects.c2
-rw-r--r--source4/lib/registry/reg_backend_dir/reg_backend_dir.c63
-rw-r--r--source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c25
-rw-r--r--source4/lib/registry/tools/regdiff.c12
-rw-r--r--source4/lib/registry/tools/regpatch.c148
-rw-r--r--source4/librpc/idl/winreg.idl15
-rw-r--r--source4/rpc_server/winreg/rpc_winreg.c13
9 files changed, 169 insertions, 178 deletions
diff --git a/source4/lib/registry/TODO b/source4/lib/registry/TODO
index 26fb8d217d..ac467d0078 100644
--- a/source4/lib/registry/TODO
+++ b/source4/lib/registry/TODO
@@ -3,7 +3,6 @@
- use memory pools?
- get rid of all the nasty memory leaks..
- security stuff
-- finish 'regpatch'
- clean up code
- rpc_server
@@ -22,6 +21,3 @@ reg_backend_ldb:
reg_backend_wine.c:
- implement
-
-regpatch.c:
- - test/finish
diff --git a/source4/lib/registry/common/reg_interface.c b/source4/lib/registry/common/reg_interface.c
index dc49dab4c1..d40a855f89 100644
--- a/source4/lib/registry/common/reg_interface.c
+++ b/source4/lib/registry/common/reg_interface.c
@@ -187,6 +187,8 @@ REG_VAL *reg_key_get_value_by_index(REG_KEY *key, int idx)
int reg_key_num_subkeys(REG_KEY *key)
{
+ if(!key) return 0;
+
if(!key->handle->functions->num_subkeys) {
if(!key->cache_subkeys)
key->handle->functions->fetch_subkeys(key, &key->cache_subkeys_count, &key->cache_subkeys);
@@ -306,8 +308,12 @@ REG_VAL *reg_key_get_value_by_name(REG_KEY *key, const char *name)
BOOL reg_key_del(REG_KEY *key)
{
- if(key->handle->functions->del_key)
- return key->handle->functions->del_key(key);
+ if(key->handle->functions->del_key) {
+ if(key->handle->functions->del_key(key)) {
+ free_cached_keys(key);
+ return True;
+ }
+ }
return False;
}
@@ -349,17 +355,53 @@ BOOL reg_val_del(REG_VAL *val)
return False;
}
- return val->handle->functions->del_value(val);
+ if(val->handle->functions->del_value(val)) {
+ free_cached_values(val->parent);
+ return True;
+ }
+ return False;
+}
+
+BOOL reg_key_add_name_recursive(REG_KEY *parent, const char *path)
+{
+ REG_KEY *cur, *prevcur = parent;
+ char *begin = (char *)path, *end;
+
+ while(1) {
+ end = strchr(begin, '\\');
+ if(end) *end = '\0';
+ cur = reg_key_get_subkey_by_name(prevcur, begin);
+ if(!cur) {
+ if(!reg_key_add_name(prevcur, begin)) { printf("foo\n"); return False; }
+ cur = reg_key_get_subkey_by_name(prevcur, begin);
+ if(!cur) {
+ DEBUG(0, ("Can't find key after adding it : %s\n", begin));
+ return False;
+ }
+ }
+
+ if(!end) break;
+ *end = '\\';
+ begin = end+1;
+ prevcur = cur;
+ }
+ return True;
}
BOOL reg_key_add_name(REG_KEY *parent, const char *name)
{
+ if (!parent) return False;
+
if (!parent->handle->functions->add_key) {
DEBUG(1, ("Backend '%s' doesn't support method add_key\n", parent->handle->functions->name));
return False;
}
- return parent->handle->functions->add_key(parent, name);
+ if(parent->handle->functions->add_key(parent, name)) {
+ free_cached_keys(parent);
+ return True;
+ }
+ return False;
}
BOOL reg_val_update(REG_VAL *val, int type, void *data, int len)
@@ -377,6 +419,7 @@ BOOL reg_val_update(REG_VAL *val, int type, void *data, int len)
new = val->handle->functions->add_value(val->parent, val->name, type, data, len);
memcpy(val, new, sizeof(REG_VAL));
+ free_cached_values(val->parent);
return True;
}
@@ -419,5 +462,19 @@ REG_VAL *reg_key_add_value(REG_KEY *key, const char *name, int type, void *value
ret = key->handle->functions->add_value(key, name, type, value, vallen);
ret->parent = key;
ret->handle = key->handle;
+ free_cached_values(key);
return ret;
}
+
+void free_cached_values(REG_KEY *key)
+{
+ free(key->cache_values); key->cache_values = NULL;
+ key->cache_values_count = 0;
+}
+
+
+void free_cached_keys(REG_KEY *key)
+{
+ free(key->cache_subkeys); key->cache_subkeys = NULL;
+ key->cache_subkeys_count = 0;
+}
diff --git a/source4/lib/registry/common/reg_objects.c b/source4/lib/registry/common/reg_objects.c
index 911dc15c8e..8de0065da0 100644
--- a/source4/lib/registry/common/reg_objects.c
+++ b/source4/lib/registry/common/reg_objects.c
@@ -161,7 +161,7 @@ char *reg_val_get_path(REG_VAL *v)
return NULL;
}
-char *reg_key_get_path(REG_KEY *k)
+const char *reg_key_get_path(REG_KEY *k)
{
SMB_REG_ASSERT(k);
return k->path;
diff --git a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
index baed39b4eb..5fec782e95 100644
--- a/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
+++ b/source4/lib/registry/reg_backend_dir/reg_backend_dir.c
@@ -21,27 +21,11 @@
#include "includes.h"
#include "lib/registry/common/registry.h"
-static DIR *reg_dir_dir(REG_HANDLE *h, const char *base, const char *name)
-{
- char *path = NULL;
- DIR *d;
- asprintf(&path, "%s/%s/%s", h->location, base, name);
- path = reg_path_win2unix(path);
-
- d = opendir(path);
- if(!d) {
- printf("Unable to open '%s'\n", path);
- return NULL;
- }
- SAFE_FREE(path);
- return d;
-}
-
static BOOL reg_dir_add_key(REG_KEY *parent, const char *name)
{
char *path;
int ret;
- asprintf(&path, "%s/%s/%s", parent->handle->location, reg_key_get_path(parent), name);
+ asprintf(&path, "%s%s\\%s", parent->handle->location, reg_key_get_path(parent), name);
path = reg_path_win2unix(path);
ret = mkdir(path, 0700);
free(path);
@@ -50,13 +34,7 @@ static BOOL reg_dir_add_key(REG_KEY *parent, const char *name)
static BOOL reg_dir_del_key(REG_KEY *k)
{
- char *path;
- int ret;
- asprintf(&path, "%s/%s", k->handle->location, reg_key_get_path(k));
- path = reg_path_win2unix(path);
- ret = rmdir(path);
- free(path);
- return (ret == 0);
+ return (rmdir((char *)k->backend_data) == 0);
}
static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name)
@@ -67,32 +45,41 @@ static REG_KEY *reg_dir_open_key(REG_HANDLE *h, const char *name)
DEBUG(0, ("NULL pointer passed as directory name!"));
return NULL;
}
- fullpath = reg_path_win2unix(strdup(name));
- d = reg_dir_dir(h, "", fullpath);
- free(fullpath);
+ asprintf(&fullpath, "%s%s", h->location, name);
+ fullpath = reg_path_win2unix(fullpath);
- if(d) return reg_key_new_abs(name, h, d);
- return NULL;
+ d = opendir(fullpath);
+ if(!d) {
+ DEBUG(3,("Unable to open '%s': %s\n", fullpath, strerror(errno)));
+ SAFE_FREE(fullpath);
+ return NULL;
+ }
+ closedir(d);
+
+ return reg_key_new_abs(name, h, fullpath);
}
static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
{
- DIR *d = (DIR *)k->backend_data;
struct dirent *e;
int max = 200;
+ char *fullpath = k->backend_data;
REG_KEY **ar;
- if(!d) return False;
- rewinddir(d);
+ DIR *d;
(*count) = 0;
ar = malloc(sizeof(REG_KEY *) * max);
+
+ d = opendir(fullpath);
+
+ if(!d) return False;
while((e = readdir(d))) {
if(e->d_type == DT_DIR &&
strcmp(e->d_name, ".") &&
strcmp(e->d_name, "..")) {
- char *fullpath = reg_path_win2unix(strdup(k->path));
- ar[(*count)] = reg_key_new_rel(e->d_name, k, reg_dir_dir(k->handle, fullpath, e->d_name));
- free(fullpath);
+ char *newfullpath;
+ asprintf(&newfullpath, "%s/%s", fullpath, e->d_name);
+ ar[(*count)] = reg_key_new_rel(e->d_name, k, newfullpath);
if(ar[(*count)])(*count)++;
if((*count) == max) {
@@ -101,6 +88,8 @@ static BOOL reg_dir_fetch_subkeys(REG_KEY *k, int *count, REG_KEY ***r)
}
}
}
+
+ closedir(d);
*r = ar;
return True;
@@ -113,7 +102,7 @@ static BOOL reg_dir_open(REG_HANDLE *h, const char *loc, BOOL try) {
static void dir_free(REG_KEY *k)
{
- closedir((DIR *)k->backend_data);
+ free(k->backend_data);
}
static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *data, int len)
@@ -132,7 +121,7 @@ static REG_VAL *reg_dir_add_value(REG_KEY *p, const char *name, int type, void *
static BOOL reg_dir_del_value(REG_VAL *v)
{
- char *fullpath = reg_path_win2unix(strdup(reg_val_get_path(v)));
+ /* FIXME*/
return False;
}
diff --git a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
index 7e8ad9bf48..796d957076 100644
--- a/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
+++ b/source4/lib/registry/reg_backend_rpc/reg_backend_rpc.c
@@ -230,9 +230,8 @@ static BOOL rpc_fetch_subkeys(REG_KEY *parent, int *count, REG_KEY ***subkeys)
static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
{
struct winreg_EnumValue r;
- struct winreg_EnumValueName name;
struct winreg_Uint8buf value;
- struct winreg_Uint16buf buf;
+ struct winreg_String valuename;
struct rpc_data *mydata = parent->handle->backend_data;
TALLOC_CTX *mem_ctx;
uint32 type, requested_len, returned_len;
@@ -241,6 +240,12 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
(*count) = 0;
+ /* Root */
+ if(parent->backend_data == parent->handle->backend_data) {
+ *values = ar;
+ return True;
+ }
+
if(!parent->backend_data) parent->backend_data = rpc_get_key_handle(parent->handle, reg_key_get_path(parent));
if(!parent->backend_data) return False;
@@ -248,16 +253,8 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
r.in.handle = parent->backend_data;
r.in.enum_index = 0;
- buf.max_len = 0x7fff;
- buf.offset = 0;
- buf.len = 0;
- buf.buffer = NULL;
-
- name.len = 0;
- name.max_len = buf.max_len *2;
- name.buf = &buf;
-
- r.in.name = r.out.name = &name;
+ init_winreg_String(&valuename, NULL);
+ r.in.name = r.out.name = &valuename;
type = 0;
r.in.type = r.out.type = &type;
@@ -280,7 +277,7 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
if(NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) {
r.in.enum_index++;
ar[(*count)] = reg_val_new(parent, NULL);
- ar[(*count)]->name = strdup((char *)name.buf);
+ ar[(*count)]->name = strdup(r.out.name->name);
ar[(*count)]->data_type = *r.out.type;
ar[(*count)]->data_len = value.len;
ar[(*count)]->data_blk = malloc(value.len);
@@ -292,6 +289,8 @@ static BOOL rpc_fetch_values(REG_KEY *parent, int *count, REG_VAL ***values)
talloc_destroy(mem_ctx);
+ *values = ar;
+
return True;
}
diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c
index 070516b798..5e2b97cb98 100644
--- a/source4/lib/registry/tools/regdiff.c
+++ b/source4/lib/registry/tools/regdiff.c
@@ -23,14 +23,22 @@
void writediff(REG_KEY *oldkey, REG_KEY *newkey, FILE *out)
{
- int i, numvals1, numvals2, numkeys2;
+ int i, numkeys1, numvals1, numvals2, numkeys2;
+
+ numkeys1 = reg_key_num_subkeys(oldkey);
+ for(i = 0; i < numkeys1; i++) {
+ REG_KEY *t1 = reg_key_get_subkey_by_index(oldkey, i);
+ if(!reg_key_get_subkey_by_name(newkey, reg_key_name(t1))) {
+ fprintf(out, "-%s\n", reg_key_get_path(t1)+1);
+ }
+ }
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));
+ fprintf(out, "\n[%s]\n", reg_key_get_path(t1)+1);
}
writediff(t2, t1, out);
}
diff --git a/source4/lib/registry/tools/regpatch.c b/source4/lib/registry/tools/regpatch.c
index f76da7ebf9..27f578e37f 100644
--- a/source4/lib/registry/tools/regpatch.c
+++ b/source4/lib/registry/tools/regpatch.c
@@ -172,7 +172,7 @@ static struct cmd_line *get_cmd_line(int fd)
while ((rc = read(fd, &ch, 1)) == 1 && ch != '\n') {
if (ch == '\r') continue; /* skip CR */
- if (i == cl->len) {
+ if (i == cl->len-1) {
/*
* Allocate some more memory
*/
@@ -193,6 +193,7 @@ static struct cmd_line *get_cmd_line(int fd)
return NULL;
}
+ cl->line[i] = '\0';
cl->line_len = i;
return cl;
@@ -276,9 +277,9 @@ 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;
+ if (!cl->line[0]) return NULL;
- p1 = strndup(cl->line, cl->line_len);
+ p1 = strdup(cl->line);
/* FIXME: Better return codes etc ... */
if (!p1) return NULL;
p2 = strchr(p1, '=');
@@ -380,7 +381,7 @@ static int regedit4_file_type(int fd)
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)));
+ DEBUG(0, ("Unable to get current offset: (%d) %s\n", cur_ofs, strerror(errno)));
exit(1); /* FIXME */
}
@@ -398,8 +399,7 @@ static int regedit4_file_type(int fd)
if (strcmp(desc, FMT_STRING_REGEDIT4) == 0) {
if (cur_ofs) {
lseek(fd, cur_ofs, SEEK_SET);
- }
- else {
+ } else {
skip_to_eol(fd);
}
return FMT_REGEDIT4;
@@ -420,6 +420,7 @@ static void strip_comment(struct cmd_line *cl)
for (i = 0; i < cl->line_len; i++) {
if (cl->line[i] == ';') {
+ cl->line[i] = '\0';
cl->line_len = i;
return;
}
@@ -427,41 +428,6 @@ static void strip_comment(struct cmd_line *cl)
}
/*
- * 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*
@@ -497,10 +463,9 @@ static CMD *regedit4_get_cmd(int fd)
}
strip_comment(cl); /* remove anything beyond a comment char */
- trim_trailing_spaces(cl);
- trim_leading_spaces(cl);
+ trim_string(cl->line, " \t", " \t");
- if (cl->line_len == 0) { /* An empty line */
+ if (!cl->line[0]) { /* An empty line */
free_cmd_line(cl);
}
else { /* Else, non-empty ... */
@@ -625,7 +590,7 @@ typedef struct command_file_s {
* Create a new command file structure
*/
-static CMD_FILE *cmd_file_create(char *file)
+static CMD_FILE *cmd_file_create(const char *file)
{
CMD_FILE *tmp;
struct stat sbuf;
@@ -637,7 +602,7 @@ static CMD_FILE *cmd_file_create(char *file)
*/
if (stat(file, &sbuf) < 0) { /* Not able to access file */
-
+ DEBUG(0,("Stat on %s failed\n", file));
return NULL;
}
@@ -650,6 +615,7 @@ static CMD_FILE *cmd_file_create(char *file)
tmp->name = strdup(file);
if ((tmp->fd = open(file, O_RDONLY, 666)) < 0) {
+ DEBUG(0,("Error opening %s\n", file));
free(tmp);
return NULL;
}
@@ -673,6 +639,7 @@ static CMD_FILE *cmd_file_create(char *file)
*/
free(tmp);
+ DEBUG(0,("Unknown type\n"));
return NULL;
}
@@ -711,49 +678,51 @@ int nt_apply_reg_command_file(REG_HANDLE *regf, const char *cmd_file_name)
*/
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;
+ 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_recursive(reg_get_root(regf), cmd->key)) {
+ tmp = reg_open_key(reg_get_root(regf), cmd->key);
+ } else {
+ DEBUG(0, ("Error adding new key '%s'\n", 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;
+ /*
+ * 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);
@@ -779,7 +748,7 @@ int main (int argc, char **argv)
};
pc = poptGetContext(argv[0], argc, (const char **) argv, long_options,0);
-
+
while((opt = poptGetNextOpt(pc)) != -1) {
}
@@ -797,12 +766,11 @@ int main (int argc, char **argv)
return 1;
}
- poptFreeContext(pc);
-
patch = poptGetArg(pc);
if(!patch) patch = "/dev/stdin";
+ poptFreeContext(pc);
nt_apply_reg_command_file(h, patch);
-
+
return 0;
}
diff --git a/source4/librpc/idl/winreg.idl b/source4/librpc/idl/winreg.idl
index 54cba24760..14f2bcfd5d 100644
--- a/source4/librpc/idl/winreg.idl
+++ b/source4/librpc/idl/winreg.idl
@@ -118,19 +118,6 @@
uint32 max_len;
uint32 offset;
uint32 len;
- uint16 buffer[len];
- } winreg_Uint16buf;
-
- typedef struct {
- uint16 len;
- uint16 max_len;
- winreg_Uint16buf *buf;
- } winreg_EnumValueName;
-
- typedef struct {
- uint32 max_len;
- uint32 offset;
- uint32 len;
uint8 buffer[len];
} winreg_Uint8buf;
@@ -139,7 +126,7 @@
WERROR winreg_EnumValue(
[in,ref] policy_handle *handle,
[in] uint32 enum_index,
- [in,out,ref] winreg_EnumValueName *name,
+ [in,out,ref] winreg_String *name,
[in,out] uint32 *type,
[in,out] winreg_Uint8buf *value,
[in,out] uint32 *requested_len,
diff --git a/source4/rpc_server/winreg/rpc_winreg.c b/source4/rpc_server/winreg/rpc_winreg.c
index 2dc6dcd741..2787c07847 100644
--- a/source4/rpc_server/winreg/rpc_winreg.c
+++ b/source4/rpc_server/winreg/rpc_winreg.c
@@ -22,10 +22,6 @@
#include "includes.h"
-REG_HANDLE *get_registry_handle() {
- return reg_open("nt4", "/home/aurelia/jelmer/NTUSER.dat", False);
-}
-
/*
winreg_OpenHKCR
*/
@@ -42,15 +38,6 @@ static NTSTATUS winreg_OpenHKCR(struct dcesrv_call_state *dce_call, TALLOC_CTX *
static NTSTATUS winreg_OpenHKCU(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct winreg_OpenHKCU *r)
{
- REG_KEY *hkcu = reg_open_key(get_registry_handle(), "\\HKEY_CURRENT_USER");
-
- if(!hkcu) {
- r->out.result = WERR_NO_MORE_ITEMS;
- return NT_STATUS_OK;
- }
-
- r->out.result = WERR_OK;
-
return NT_STATUS_NOT_IMPLEMENTED;
}