|
@@ -54,7 +54,8 @@
|
|
#define CONFIG_ENV_MAX_ENTRIES 512
|
|
#define CONFIG_ENV_MAX_ENTRIES 512
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-#include "search.h"
|
|
|
|
|
|
+#include <env_callback.h>
|
|
|
|
+#include <search.h>
|
|
|
|
|
|
/*
|
|
/*
|
|
* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
|
* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
|
|
@@ -274,6 +275,17 @@ static inline int _compare_and_overwrite_entry(ENTRY item, ACTION action,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* If there is a callback, call it */
|
|
|
|
+ if (htab->table[idx].entry.callback &&
|
|
|
|
+ htab->table[idx].entry.callback(item.key,
|
|
|
|
+ item.data, env_op_overwrite, flag)) {
|
|
|
|
+ debug("callback() rejected setting variable "
|
|
|
|
+ "%s, skipping it!\n", item.key);
|
|
|
|
+ __set_errno(EINVAL);
|
|
|
|
+ *retval = NULL;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
free(htab->table[idx].entry.data);
|
|
free(htab->table[idx].entry.data);
|
|
htab->table[idx].entry.data = strdup(item.data);
|
|
htab->table[idx].entry.data = strdup(item.data);
|
|
if (!htab->table[idx].entry.data) {
|
|
if (!htab->table[idx].entry.data) {
|
|
@@ -398,6 +410,9 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
|
|
|
|
|
++htab->filled;
|
|
++htab->filled;
|
|
|
|
|
|
|
|
+ /* This is a new entry, so look up a possible callback */
|
|
|
|
+ env_callback_init(&htab->table[idx].entry);
|
|
|
|
+
|
|
/* check for permission */
|
|
/* check for permission */
|
|
if (htab->change_ok != NULL && htab->change_ok(
|
|
if (htab->change_ok != NULL && htab->change_ok(
|
|
&htab->table[idx].entry, item.data, env_op_create, flag)) {
|
|
&htab->table[idx].entry, item.data, env_op_create, flag)) {
|
|
@@ -409,6 +424,18 @@ int hsearch_r(ENTRY item, ACTION action, ENTRY ** retval,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* If there is a callback, call it */
|
|
|
|
+ if (htab->table[idx].entry.callback &&
|
|
|
|
+ htab->table[idx].entry.callback(item.key, item.data,
|
|
|
|
+ env_op_create, flag)) {
|
|
|
|
+ debug("callback() rejected setting variable "
|
|
|
|
+ "%s, skipping it!\n", item.key);
|
|
|
|
+ _hdelete(item.key, htab, &htab->table[idx].entry, idx);
|
|
|
|
+ __set_errno(EINVAL);
|
|
|
|
+ *retval = NULL;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* return new entry */
|
|
/* return new entry */
|
|
*retval = &htab->table[idx].entry;
|
|
*retval = &htab->table[idx].entry;
|
|
return 1;
|
|
return 1;
|
|
@@ -437,6 +464,7 @@ static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
|
|
debug("hdelete: DELETING key \"%s\"\n", key);
|
|
debug("hdelete: DELETING key \"%s\"\n", key);
|
|
free((void *)ep->key);
|
|
free((void *)ep->key);
|
|
free(ep->data);
|
|
free(ep->data);
|
|
|
|
+ ep->callback = NULL;
|
|
htab->table[idx].used = -1;
|
|
htab->table[idx].used = -1;
|
|
|
|
|
|
--htab->filled;
|
|
--htab->filled;
|
|
@@ -466,6 +494,15 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ /* If there is a callback, call it */
|
|
|
|
+ if (htab->table[idx].entry.callback &&
|
|
|
|
+ htab->table[idx].entry.callback(key, NULL, env_op_delete, flag)) {
|
|
|
|
+ debug("callback() rejected deleting variable "
|
|
|
|
+ "%s, skipping it!\n", key);
|
|
|
|
+ __set_errno(EINVAL);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
_hdelete(key, htab, ep, idx);
|
|
_hdelete(key, htab, ep, idx);
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
@@ -838,11 +875,9 @@ int himport_r(struct hsearch_data *htab,
|
|
e.data = value;
|
|
e.data = value;
|
|
|
|
|
|
hsearch_r(e, ENTER, &rv, htab, flag);
|
|
hsearch_r(e, ENTER, &rv, htab, flag);
|
|
- if (rv == NULL) {
|
|
|
|
|
|
+ if (rv == NULL)
|
|
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
|
|
printf("himport_r: can't insert \"%s=%s\" into hash table\n",
|
|
name, value);
|
|
name, value);
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
|
|
debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
|
|
debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
|
|
htab, htab->filled, htab->size,
|
|
htab, htab->filled, htab->size,
|
|
@@ -873,3 +908,27 @@ int himport_r(struct hsearch_data *htab,
|
|
debug("INSERT: done\n");
|
|
debug("INSERT: done\n");
|
|
return 1; /* everything OK */
|
|
return 1; /* everything OK */
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * hwalk_r()
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Walk all of the entries in the hash, calling the callback for each one.
|
|
|
|
+ * this allows some generic operation to be performed on each element.
|
|
|
|
+ */
|
|
|
|
+int hwalk_r(struct hsearch_data *htab, int (*callback)(ENTRY *))
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+ int retval;
|
|
|
|
+
|
|
|
|
+ for (i = 1; i <= htab->size; ++i) {
|
|
|
|
+ if (htab->table[i].used > 0) {
|
|
|
|
+ retval = callback(&htab->table[i].entry);
|
|
|
|
+ if (retval)
|
|
|
|
+ return retval;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 0;
|
|
|
|
+}
|