#define CONFIG_ENV_MAX_ENTRIES 512
#endif
-#include "search.h"
+#include <env_callback.h>
+#include <env_flags.h>
+#include <search.h>
/*
* [Aho,Sethi,Ullman] Compilers: Principles, Techniques and Tools, 1986
* Instead the interface of all functions is extended to take an argument
* which describes the current status.
*/
+
typedef struct _ENTRY {
int used;
ENTRY entry;
} _ENTRY;
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+ int idx);
+
/*
* hcreate()
*/
&& strcmp(item.key, htab->table[idx].entry.key) == 0) {
/* Overwrite existing value? */
if ((action == ENTER) && (item.data != NULL)) {
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data,
+ env_op_overwrite, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ __set_errno(EPERM);
+ *retval = NULL;
+ 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);
htab->table[idx].entry.data = strdup(item.data);
if (!htab->table[idx].entry.data) {
++htab->filled;
+ /* This is a new entry, so look up a possible callback */
+ env_callback_init(&htab->table[idx].entry);
+ /* Also look for flags */
+ env_flags_init(&htab->table[idx].entry);
+
+ /* check for permission */
+ if (htab->change_ok != NULL && htab->change_ok(
+ &htab->table[idx].entry, item.data, env_op_create, flag)) {
+ debug("change_ok() rejected setting variable "
+ "%s, skipping it!\n", item.key);
+ _hdelete(item.key, htab, &htab->table[idx].entry, idx);
+ __set_errno(EPERM);
+ *retval = NULL;
+ 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 */
*retval = &htab->table[idx].entry;
return 1;
* do that.
*/
+static void _hdelete(const char *key, struct hsearch_data *htab, ENTRY *ep,
+ int idx)
+{
+ /* free used ENTRY */
+ debug("hdelete: DELETING key \"%s\"\n", key);
+ free((void *)ep->key);
+ free(ep->data);
+ ep->callback = NULL;
+ ep->flags = 0;
+ htab->table[idx].used = -1;
+
+ --htab->filled;
+}
+
int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
{
ENTRY e, *ep;
}
/* Check for permission */
- if (htab->apply != NULL &&
- htab->apply(ep->key, ep->data, NULL, flag)) {
+ if (htab->change_ok != NULL &&
+ htab->change_ok(ep, NULL, env_op_delete, flag)) {
+ debug("change_ok() rejected deleting variable "
+ "%s, skipping it!\n", key);
__set_errno(EPERM);
return 0;
}
- /* free used ENTRY */
- debug("hdelete: DELETING key \"%s\"\n", key);
- free((void *)ep->key);
- free(ep->data);
- htab->table[idx].used = -1;
+ /* 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;
+ }
- --htab->filled;
+ _hdelete(key, htab, ep, idx);
return 1;
}
return (strcmp(e1->key, e2->key));
}
-ssize_t hexport_r(struct hsearch_data *htab, const char sep,
+ssize_t hexport_r(struct hsearch_data *htab, const char sep, int flag,
char **resp, size_t size,
int argc, char * const argv[])
{
if ((argc > 0) && (found == 0))
continue;
+ if ((flag & H_HIDE_DOT) && ep->key[0] == '.')
+ continue;
+
list[n++] = ep;
totlen += strlen(ep->key) + 2;
e.key = name;
e.data = value;
- /* if there is an apply function, check what it has to say */
- if (htab->apply != NULL) {
- debug("searching before calling cb function"
- " for %s\n", name);
- /*
- * Search for variable in existing env, so to pass
- * its previous value to the apply callback
- */
- hsearch_r(e, FIND, &rv, htab, 0);
- debug("previous value was %s\n", rv ? rv->data : "");
- if (htab->apply(name, rv ? rv->data : NULL,
- value, flag)) {
- debug("callback function refused to set"
- " variable %s, skipping it!\n", name);
- continue;
- }
- }
-
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",
name, value);
- return 0;
- }
debug("INSERT: table %p, filled %d/%d rv %p ==> name=\"%s\" value=\"%s\"\n",
htab, htab->filled, htab->size,
debug("INSERT: done\n");
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;
+}