summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/backend.c87
-rw-r--r--src/format.c121
-rw-r--r--src/format.h4
3 files changed, 149 insertions, 63 deletions
diff --git a/src/backend.c b/src/backend.c
index 4fda175..bb4d38d 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -21,7 +21,7 @@
/* The data we ask the map cache to keep, for us, for each map. */
struct backend_map_data {
struct plugin_state *state;
- char *domain, *map, **bases, *filter, *key_attr, *value_fmt;
+ char *domain, *map, **bases, *filter, *key_fmt, *value_fmt;
};
static char **
@@ -70,7 +70,7 @@ backend_free_map_data(void *data)
free(map_data->map);
free(map_data->bases);
free(map_data->filter);
- free(map_data->key_attr);
+ free(map_data->key_fmt);
free(map_data->value_fmt);
free(map_data);
}
@@ -89,13 +89,13 @@ backend_copy_cb_data(const struct backend_map_data *data)
ret->map = strdup(data->map);
ret->bases = backend_dup_strlist(data->bases);
ret->filter = strdup(data->filter);
- ret->key_attr = strdup(data->key_attr);
+ ret->key_fmt = strdup(data->key_fmt);
ret->value_fmt = strdup(data->value_fmt);
if ((ret->domain == NULL) ||
(ret->map == NULL) ||
(ret->bases == NULL) ||
(ret->filter == NULL) ||
- (ret->key_attr == NULL) ||
+ (ret->key_fmt == NULL) ||
(ret->value_fmt == NULL)) {
backend_free_map_data(ret);
return NULL;
@@ -114,8 +114,10 @@ backend_map_entry_cb(Slapi_Entry *e, void *callback_data)
data = callback_data;
/* Pull out the key and value for the entry. */
visited_dn_list = NULL;
- key = format_get_data(NULL, e, data->key_attr, &visited_dn_list);
- value = format_get_data(NULL, e, data->value_fmt, &visited_dn_list);
+ key = format_get_data(data->state, NULL, e,
+ data->key_fmt, &visited_dn_list);
+ value = format_get_data(data->state, NULL, e,
+ data->value_fmt, &visited_dn_list);
/* Pull out the NDN of this entry. */
dn = slapi_entry_get_ndn(e);
/* If we actually generated a value, then set it for all keys. */
@@ -259,7 +261,7 @@ backend_map_config_entry(struct plugin_state *state, Slapi_Entry *e,
cb_data.state = state;
cb_data.domain = (char *) domain;
cb_data.map = (char *) map;
- cb_data.key_attr = use_key_attribute;
+ cb_data.key_fmt = use_key_attribute;
cb_data.value_fmt = use_value_attribute;
cb_data.filter = use_entry_filter;
cb_data.bases = base;
@@ -418,6 +420,7 @@ backend_entry_matches_map(struct backend_map_data *map_data, Slapi_Entry *e)
* map. */
struct backend_add_entry_cbdata {
+ struct plugin_state *state;
Slapi_PBlock *pb;
Slapi_Entry *e;
char *dn;
@@ -451,10 +454,10 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data,
/* Pull out the key and value. */
visited_dn_list = NULL;
- key = format_get_data(cbdata->pb, cbdata->e, map_data->key_attr,
- &visited_dn_list);
- value = format_get_data(cbdata->pb, cbdata->e, map_data->value_fmt,
- &visited_dn_list);
+ key = format_get_data(cbdata->state, cbdata->pb, cbdata->e,
+ map_data->key_fmt, &visited_dn_list);
+ value = format_get_data(cbdata->state, cbdata->pb, cbdata->e,
+ map_data->value_fmt, &visited_dn_list);
/* If we actually generated a value, then set it for all keys. */
if ((key != NULL) && (value != NULL)) {
@@ -491,19 +494,20 @@ backend_add_entry_cb(const char *domain, const char *map, void *backend_data,
static int
backend_add_cb(Slapi_PBlock *pb)
{
- struct plugin_state *state;
struct backend_add_entry_cbdata cbdata;
- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
slapi_pblock_get(pb, SLAPI_ADD_TARGET, &cbdata.dn);
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &cbdata.e);
cbdata.pb = pb;
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id,
"added \"%s\"\n", cbdata.dn);
/* Add map entries which corresponded to this directory server
* entry. */
- if (!map_data_foreach_map(state, NULL, backend_add_entry_cb, &cbdata)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ if (!map_data_foreach_map(cbdata.state, NULL,
+ backend_add_entry_cb, &cbdata)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata.state->plugin_desc->spd_id,
"error adding map entries corresponding to "
"\"%s\"\n", cbdata.dn);
}
@@ -512,6 +516,7 @@ backend_add_cb(Slapi_PBlock *pb)
}
struct backend_modify_entry_cbdata {
+ struct plugin_state *state;
Slapi_PBlock *pb;
LDAPMod **mods;
Slapi_Entry *e;
@@ -544,9 +549,9 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data,
} else {
/* Pull out the key and value. */
visited_dn_list = NULL;
- key = format_get_data(cbdata->pb, cbdata->e,
- map_data->key_attr, &visited_dn_list);
- value = format_get_data(cbdata->pb, cbdata->e,
+ key = format_get_data(cbdata->state, cbdata->pb, cbdata->e,
+ map_data->key_fmt, &visited_dn_list);
+ value = format_get_data(cbdata->state, cbdata->pb, cbdata->e,
map_data->value_fmt, &visited_dn_list);
/* If we actually generated a value, then set it for all keys.
* */
@@ -596,20 +601,20 @@ backend_modify_entry_cb(const char *domain, const char *map, void *backend_data,
static int
backend_modify_cb(Slapi_PBlock *pb)
{
- struct plugin_state *state;
struct backend_modify_entry_cbdata cbdata;
- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
slapi_pblock_get(pb, SLAPI_MODIFY_TARGET, &cbdata.dn);
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &cbdata.mods);
slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e);
cbdata.pb = pb;
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id,
"modified \"%s\"\n", cbdata.dn);
/* Modify map entries which corresponded to this directory server
* entry. */
- if (!map_data_foreach_map(state, NULL,
+ if (!map_data_foreach_map(cbdata.state, NULL,
backend_modify_entry_cb, &cbdata)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata.state->plugin_desc->spd_id,
"error modifying map entries corresponding to "
"\"%s\"\n", cbdata.dn);
}
@@ -619,6 +624,7 @@ backend_modify_cb(Slapi_PBlock *pb)
}
struct backend_modrdn_entry_cbdata {
+ struct plugin_state *state;
Slapi_PBlock *pb;
Slapi_Entry *e_pre, *e_post;
char *dn_pre, *dn_post;
@@ -642,16 +648,16 @@ backend_modrdn_entry_cb(const char *domain, const char *map, void *backend_data,
matched_post = backend_entry_matches_map(map_data, cbdata->e_post);
/* Pull out the key and value for the old entry. */
- key_pre = format_get_data(cbdata->pb, cbdata->e_pre,
- map_data->key_attr, NULL);
- value_pre = format_get_data(cbdata->pb, cbdata->e_pre,
+ key_pre = format_get_data(cbdata->state, cbdata->pb, cbdata->e_pre,
+ map_data->key_fmt, NULL);
+ value_pre = format_get_data(cbdata->state, cbdata->pb, cbdata->e_pre,
map_data->value_fmt, NULL);
/* Pull out the key and value for the new entry. */
visited_dn_list = NULL;
- key_post = format_get_data(cbdata->pb, cbdata->e_post,
- map_data->key_attr, &visited_dn_list);
- value_post = format_get_data(cbdata->pb, cbdata->e_post,
+ key_post = format_get_data(cbdata->state, cbdata->pb, cbdata->e_post,
+ map_data->key_fmt, &visited_dn_list);
+ value_post = format_get_data(cbdata->state, cbdata->pb, cbdata->e_post,
map_data->value_fmt, &visited_dn_list);
/* Now decide what to set, or unset, in this map. */
@@ -747,22 +753,22 @@ backend_modrdn_entry_cb(const char *domain, const char *map, void *backend_data,
static int
backend_modrdn_cb(Slapi_PBlock *pb)
{
- struct plugin_state *state;
struct backend_modrdn_entry_cbdata cbdata;
- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &cbdata.e_pre);
slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &cbdata.e_post);
cbdata.dn_pre = slapi_entry_get_ndn(cbdata.e_pre);
cbdata.dn_post = slapi_entry_get_ndn(cbdata.e_post);
cbdata.pb = pb;
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id,
"renamed \"%s\" to \"%s\"\n",
cbdata.dn_pre, cbdata.dn_post);
/* Modify map entries which corresponded to this directory server
* entry. */
- if (!map_data_foreach_map(state, NULL,
+ if (!map_data_foreach_map(cbdata.state, NULL,
backend_modrdn_entry_cb, &cbdata)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata.state->plugin_desc->spd_id,
"error renaming map entries corresponding to "
"\"%s\"\n", cbdata.dn_post);
}
@@ -775,6 +781,7 @@ backend_modrdn_cb(Slapi_PBlock *pb)
* map. */
struct backend_delete_entry_cbdata {
+ struct plugin_state *state;
Slapi_PBlock *pb;
char *dn;
};
@@ -802,18 +809,18 @@ backend_delete_entry_cb(const char *domain, const char *map, void *backend_data,
static int
backend_delete_cb(Slapi_PBlock *pb)
{
- struct plugin_state *state;
struct backend_delete_entry_cbdata cbdata;
- slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &cbdata.state);
slapi_pblock_get(pb, SLAPI_DELETE_TARGET, &cbdata.dn);
cbdata.pb = pb;
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN, cbdata.state->plugin_desc->spd_id,
"deleted \"%s\"\n", cbdata.dn);
/* Remove map entries which corresponded to this directory server
* entry. */
- if (!map_data_foreach_map(state, NULL,
+ if (!map_data_foreach_map(cbdata.state, NULL,
backend_delete_entry_cb, &cbdata)) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata.state->plugin_desc->spd_id,
"error removing map entries corresponding to "
"\"%s\"\n", cbdata.dn);
}
diff --git a/src/format.c b/src/format.c
index c2e78ef..b6cc37d 100644
--- a/src/format.c
+++ b/src/format.c
@@ -3,6 +3,7 @@
#include <stdlib.h>
#include "defaults.h"
#include "format.h"
+#include "plugin.h"
void
format_free_data(char *data)
@@ -20,6 +21,8 @@ format_free_ndn_list(char **ndn_list)
}
}
+/* Retrieve a single value for an attribute. If there are no values, or more
+ * than one, fail. */
static char *
format_single(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr,
char ***visited_ndns)
@@ -39,6 +42,7 @@ format_single(Slapi_PBlock *pb, Slapi_Entry *e, const char *attr,
return ret;
}
+/* Find the matching closing marker. */
static const char *
format_find_closer(const char *pair, const char *pattern)
{
@@ -62,7 +66,7 @@ format_find_closer(const char *pair, const char *pattern)
* we visit (other than e) to the list of visited NDNs. Unless it's a literal,
* treat the entire input format specifier as an expression. */
static int
-format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
+format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *fmt,
char *outbuf, int outbuf_len,
char ***visited_ndns,
@@ -71,24 +75,25 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
int i, j;
int exp_len, level;
const char *fmtstart, *fmtend, *match, *attribute;
- char *tmp;
+ char *tmp, *fnname, *spd_id;
char exp[outbuf_len * 2];
- const char *default_value, *alternate_value;
+ const char *default_value, *alternate_value, *paramstart, *paramend;
size_t spn;
- slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
+ spd_id = state->plugin_desc->spd_id;
+ slapi_log_error(SLAPI_LOG_PLUGIN, spd_id,
"expanding %s\"%s\"%s\n",
- literal ? "" : "%{", fmt, literal ? "" : "%{");
+ literal ? "" : "%{", fmt, literal ? "" : "}");
- /* First, expand any subexpressions. */
+ /* First, expand any subexpressions and call any "functions". */
level = 0;
i = 0;
j = 0;
while (fmt[i] != '\0') {
switch (fmt[i]) {
case '%':
- /* This might be a subexpression, or an escaped
- * character. */
+ /* This might be a subexpression, a "function" call, or
+ * an escaped character. */
switch (fmt[i + 1]) {
case '%':
/* It's just an escaped "%". */
@@ -102,8 +107,10 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
/* Find the end of the subexpression. */
match = format_find_closer("{}", fmtstart + 1);
if (match == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
- "expansion failed: no closing brace (2)\n");
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion failed: "
+ "no closing brace\n");
return -1;
} else {
/* Mark the first character after the
@@ -112,8 +119,11 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
/* Make a copy of the subexpression. */
tmp = malloc(fmtend - fmtstart);
if (tmp == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
- "expansion out of memory\n");
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion "
+ "failed: out "
+ "of memory\n");
return -1;
}
memcpy(tmp, fmtstart + 2,
@@ -121,7 +131,7 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
tmp[fmtend - fmtstart - 3] = '\0';
/* Recursively expand the
* subexpression. */
- exp_len = format_expand(pb, e,
+ exp_len = format_expand(state, pb, e,
tmp,
exp + j,
sizeof(exp) - j,
@@ -130,9 +140,14 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
free(tmp);
if ((exp_len < 0) ||
(exp_len + j >= (int) sizeof(exp))) {
- /* We'd be out of space, FAIL. */
- slapi_log_error(SLAPI_LOG_PLUGIN, "nis-plugin",
- "expansion too big\n");
+ /* We'd be out of space,
+ * FAIL. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion "
+ "failed: result"
+ " would be too "
+ "big\n");
return -1;
} else {
/* It fit, so keep going. */
@@ -142,6 +157,63 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
}
continue;
break;
+ default:
+ /* Assume it's a "function" call. Pick out the
+ * name of the function. */
+ paramstart = strchr(fmt + i, '{');
+ if (paramstart == NULL) {
+ /* No start? Bad format. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion failed: "
+ "bad function "
+ "invocation\n");
+ return -1;
+ }
+ paramend = strchr(paramstart + 1, '}');
+ if (paramend == NULL) {
+ /* No matching end? Bad format. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion failed: "
+ "bad function "
+ "invocation\n");
+ return -1;
+ }
+ fnname = malloc(paramstart - (fmt + i));
+ if (fnname == NULL) {
+ /* Out of memory, FAIL. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion failed: "
+ "out of memory\n");
+ return -1;
+ }
+ memcpy(fnname, fmt + i + 1,
+ paramstart - (fmt + i + 1));
+ fnname[paramstart - (fmt + i + 1)] = '\0';
+ /* Isolate the parameter string. */
+ tmp = malloc(paramend - paramstart);
+ if (tmp == NULL) {
+ /* Out of memory, FAIL. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ spd_id,
+ "expansion failed: "
+ "out of memory\n");
+ free(fnname);
+ return -1;
+ }
+ memcpy(tmp, paramstart + 1,
+ paramend - (paramstart + 1));
+ tmp[paramend - paramstart] = '\0';
+ slapi_log_error(SLAPI_LOG_PLUGIN, spd_id,
+ "calling \"%s\"(\"%s\")\n",
+ fnname, tmp);
+ free(fnname);
+ free(tmp);
+ i = (paramend - fmt) + 1;
+ continue;
+ break;
}
break;
default:
@@ -261,15 +333,16 @@ format_expand(Slapi_PBlock *pb, Slapi_Entry *e,
}
static char *
-format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
- char ***visited_ndns)
+format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *fmt, char ***visited_ndns)
{
char buf[YPMAXRECORD], *tmp;
const char *match, *fmtstart, *fmtend;
unsigned int i, j;
int exp_len;
- i = format_expand(pb, e, fmt, buf, sizeof(buf), visited_ndns, TRUE);
+ i = format_expand(state, pb, e, fmt, buf, sizeof(buf),
+ visited_ndns, TRUE);
if (i < sizeof(buf)) {
buf[i] = '\0';
return strdup(buf);
@@ -279,12 +352,13 @@ format_format(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
}
char *
-format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
- char ***visited_ndns)
+format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *fmt, char ***visited_ndns)
{
Slapi_PBlock *local_pb;
char ***ndn_list, **local_ndn_list, *ret;
+ /* Supply an NDN list if the caller didn't. */
if (visited_ndns != NULL) {
ndn_list = visited_ndns;
} else {
@@ -292,6 +366,7 @@ format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
local_ndn_list = NULL;
}
+ /* Supply a PBlock if the caller didn't. */
if (pb == NULL) {
local_pb = slapi_pblock_new();
pb = local_pb;
@@ -299,11 +374,13 @@ format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
local_pb = NULL;
}
- ret = format_format(pb, e, fmt, ndn_list);
+ ret = format_format(state, pb, e, fmt, ndn_list);
+ /* If we supplied a PBlock, clean it up. */
if (pb == local_pb) {
slapi_pblock_destroy(local_pb);
}
+ /* If we supplied an NDN list, clean it up. */
if (ndn_list == &local_ndn_list) {
format_free_ndn_list(local_ndn_list);
}
diff --git a/src/format.h b/src/format.h
index 1269d0b..796eebb 100644
--- a/src/format.h
+++ b/src/format.h
@@ -1,5 +1,7 @@
#include <dirsrv/slapi-plugin.h>
+struct plugin_state;
void format_free_data(char *data);
void format_free_ndn_list(char **ndn_list);
-char *format_get_data(Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
+char *format_get_data(struct plugin_state *state,
+ Slapi_PBlock *pb, Slapi_Entry *e, const char *fmt,
char ***visited_ndn_list);