diff options
author | Nalin Dahyabhai <nalin@localhost.localdomain> | 2008-05-13 18:30:14 -0400 |
---|---|---|
committer | Nalin Dahyabhai <nalin@localhost.localdomain> | 2008-05-13 18:30:14 -0400 |
commit | d01a5adac69f1fde9d64a88938a22147d0cfc25e (patch) | |
tree | cf294e92a96d9a1eb301f2a749f0ccd046e5c3d0 | |
parent | 6aee466569e68cf0a8b4d3acb0f9f425714a3cbb (diff) | |
download | slapi-nis-d01a5adac69f1fde9d64a88938a22147d0cfc25e.tar.gz slapi-nis-d01a5adac69f1fde9d64a88938a22147d0cfc25e.tar.xz slapi-nis-d01a5adac69f1fde9d64a88938a22147d0cfc25e.zip |
- note that the key is specified as a format specifier
- recognize "function" syntax in format specifiers
-rw-r--r-- | src/backend.c | 87 | ||||
-rw-r--r-- | src/format.c | 121 | ||||
-rw-r--r-- | src/format.h | 4 |
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); |