summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-07-07 15:02:09 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-07-07 15:02:09 -0400
commit3e875d39e2a3d606f411abdfa13cfc7b585afa38 (patch)
treee19069e1b80ce5f3adad58856e85e87210687ffa /src
parent4a0ba6a0782d07fb6bcdd386a5c7ae5141a0c90b (diff)
downloadslapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.tar.gz
slapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.tar.xz
slapi-nis-3e875d39e2a3d606f411abdfa13cfc7b585afa38.zip
- teach "merge" to merge lists of values in addition to single values
- deref: return a list of values - referral: return a list of values - drop "echo" and "list" (the latter subsumed by "merge")
Diffstat (limited to 'src')
-rw-r--r--src/format.c670
1 files changed, 220 insertions, 450 deletions
diff --git a/src/format.c b/src/format.c
index f36ff81..c5fa1ab 100644
--- a/src/format.c
+++ b/src/format.c
@@ -64,6 +64,28 @@ static int format_expand(struct plugin_state *state,
char ***ref_attrs,
struct format_inref_attr ***inref_attrs);
+static char *
+xstrndup(const char *start, size_t length)
+{
+ char *ret, *end;
+ end = memchr(start, '\0', length);
+ if (end != NULL) {
+ length = end - start;
+ }
+ ret = malloc(length + 1);
+ if (ret != NULL) {
+ memcpy(ret, start, length);
+ ret[length] = '\0';
+ }
+ return ret;
+}
+
+static char *
+xstrndupp(const char *start, const char *end)
+{
+ return xstrndup(start, end - start);
+}
+
char **
format_dup_attr_list(char **attr_list)
{
@@ -450,46 +472,6 @@ format_parse_args(struct plugin_state *state, const char *args,
return 0;
}
-/* Echo the parameter text. */
-static int
-format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *group, const char *set,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len, struct format_choice **outbuf_choices,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs)
-{
- int ret, i, argc, len;
- char **argv;
- ret = format_parse_args(state, args, &argc, &argv);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "echo: error parsing arguments\n");
- return -EINVAL;
- }
- if (argc < 1) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "echo: requires at least one argument\n");
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- for (i = 0, ret = 0; i < argc; i++) {
- /* Get the length of this argument. */
- len = strlen(argv[i]);
- /* Check that we've got space for this argument. */
- if (ret + len > outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "echo: out of space\n");
- return -ENOBUFS;
- }
- /* Append the text of the argument. */
- memcpy(outbuf + ret, argv[i], len);
- ret += len;
- }
- format_free_parsed_args(argv);
- return ret;
-}
-
/* Choose the first value of the attribute in the entry. */
static int
format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
@@ -542,88 +524,9 @@ format_first(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
-/* Create a list of the values of the attributes which are passed as arguments,
- * joined by a separator given as the first argument. */
-static int
-format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *group, const char *set,
- const char *args, const char *disallowed,
- char *outbuf, int outbuf_len, struct format_choice **outbuf_choices,
- char ***ref_attrs, struct format_inref_attr ***inref_attrs)
-{
- int ret, i, j, slen, count, argc;
- Slapi_ValueSet *values;
- Slapi_Value *value;
- char **argv, *actual_attr;
- const struct berval *val;
- int disposition, buffer_flags;
- ret = format_parse_args(state, args, &argc, &argv);
- if (ret != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
- "list: error parsing arguments\n");
- return -EINVAL;
- }
- for (i = 1, ret = 0, count = 0; i < argc; i++) {
- /* Get the list of values for this attribute. */
- if (slapi_vattr_values_get(e, argv[i], &values, &disposition,
- &actual_attr, 0,
- &buffer_flags) != 0) {
- continue;
- }
- for (j = slapi_valueset_first_value(values, &value);
- j != -1;
- j = slapi_valueset_next_value(values, j, &value)) {
- /* Get the length of the value. */
- val = slapi_value_get_berval(value);
- /* Check if we have space for the value. */
- if (ret + val->bv_len > (unsigned int) outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "list: out of space\n");
- slapi_vattr_values_free(&values, &actual_attr,
- buffer_flags);
- format_free_parsed_args(argv);
- return -ENOBUFS;
- }
- /* If the value is empty, skip it. */
- if (val->bv_len == 0) {
- continue;
- }
- /* If we've already added values, add the separator. */
- if (count > 0) {
- /* Get the length of the separator. */
- slen = strlen(argv[0]);
- /* Check if we have space for the separator. */
- if ((ret + val->bv_len + slen) >
- (unsigned int) outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "list: out of space\n");
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- format_free_parsed_args(argv);
- return -ENOBUFS;
- }
- /* Copy in the separator. */
- memcpy(outbuf + ret, argv[0], slen);
- ret += slen;
- }
- /* Copy in the value. */
- memcpy(outbuf + ret, val->bv_val, val->bv_len);
- ret += val->bv_len;
- count++;
- }
- /* Free the value set for this attribute. */
- slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
- }
- format_free_parsed_args(argv);
- return ret;
-}
-
-/* Look up the entry matching a DN stored in the attribute named by the second
- * argument, pull out the values for the attribute named by the third
- * argument, and create a list separated by the first argument. */
+/* Look up the entries matching DNs stored in the attribute named by the first
+ * argument, pull out the values for the attribute named by the second
+ * argument, and return a list of those values. */
static int
format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *group, const char *set,
@@ -632,14 +535,14 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
- int i, j, slen, ret, count, argc;
+ int i, j, slen, ret, argc;
Slapi_Entry *ref;
Slapi_DN *refdn;
Slapi_ValueSet *ref_values, *values;
Slapi_Value *ref_value, *value;
int disposition, ref_disposition, buffer_flags, ref_buffer_flags;
char **argv, *attrs[3], *actual_attr, *actual_ref_attr;
- const char *sep, *cref;
+ const char *cref;
const struct berval *val;
char *ref_attr, *target_attr;
struct berval **choices;
@@ -649,52 +552,38 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"deref: error parsing arguments\n");
return -EINVAL;
}
+ if (argc != 2) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "deref: requires two arguments\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
if (outbuf_choices == NULL) {
- if (argc != 3) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "deref: requires 3 arguments\n");
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- sep = argv[0];
- ref_attr = argv[1];
- target_attr = argv[2];
- } else {
- if (argc != 2) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "deref: requires 2 arguments\n");
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- sep = NULL;
- ref_attr = argv[0];
- target_attr = argv[1];
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "deref: returns a list, but a list "
+ "would not be appropriate\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
}
+ ref_attr = argv[0];
+ target_attr = argv[1];
/* Note that the attribute in this entry refers to other entries. */
if (ref_attrs != NULL) {
backend_shr_add_strlist(ref_attrs, ref_attr);
}
- /* Get the names of the reference attribute. */
+ /* Get the values of the reference attribute from this entry. */
if (slapi_vattr_values_get(e, ref_attr, &ref_values,
&ref_disposition, &actual_ref_attr,
0, &ref_buffer_flags) != 0) {
- /* No references. */
+ /* No references means we're done. */
format_free_parsed_args(argv);
- if (outbuf_choices == NULL) {
- return 0;
- } else {
- return -ENOENT;
- }
+ return 0;
}
/* Retrieve these attributes from the referred-to entries. */
attrs[0] = ref_attr;
attrs[1] = target_attr;
attrs[2] = NULL;
/* Iterate through the names of the referred-to entries. */
- ret = 0;
- count = 0;
choices = NULL;
for (i = slapi_valueset_first_value(ref_values, &ref_value);
i != -1;
@@ -708,7 +597,7 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
if (refdn == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
- "deref: internal error reading "
+ "deref: internal error parsing name "
"\"%s\"\n", cref);
continue;
}
@@ -738,61 +627,13 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
for (j = slapi_valueset_first_value(values, &value);
j != -1;
j = slapi_valueset_next_value(values, j, &value)) {
- /* Get the length of the value. */
+ /* Get the value. */
val = slapi_value_get_berval(value);
- /* Check if there's space for the value. */
- if (ret + val->bv_len > (unsigned int) outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "deref: out of space\n");
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- slapi_entry_free(ref);
- slapi_vattr_values_free(&ref_values,
- &actual_ref_attr,
- ref_buffer_flags);
- format_free_parsed_args(argv);
- return -ENOBUFS;
- }
/* If the value is empty, skip it. */
if (val->bv_len == 0) {
continue;
}
- /* If we're keeping a list of choices, just add it to
- * the list of values we've retrieved and keep going. */
- if (outbuf_choices != NULL) {
- format_add_bv_list(&choices, val);
- continue;
- }
- /* If we need to, add the separator. */
- if (count > 0) {
- /* Get the length of the separator. */
- slen = strlen(sep);
- /* Check if there's space for the separator. */
- if ((ret + val->bv_len + slen) >
- (unsigned int) outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "deref: out of space\n");
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- slapi_entry_free(ref);
- slapi_vattr_values_free(&ref_values,
- &actual_ref_attr,
- ref_buffer_flags);
- format_free_parsed_args(argv);
- return -ENOBUFS;
- }
- /* Append the separator. */
- memcpy(outbuf + ret, sep, slen);
- ret += slen;
- }
- /* Append the value. */
- memcpy(outbuf + ret, val->bv_val, val->bv_len);
- ret += val->bv_len;
- count++;
+ format_add_bv_list(&choices, val);
}
slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
slapi_entry_free(ref);
@@ -801,54 +642,29 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
&actual_ref_attr,
ref_buffer_flags);
format_free_parsed_args(argv);
- if (outbuf_choices != NULL) {
- if (choices != NULL) {
- if (format_count_bv_list(choices) == 1) {
- /* Return this value directly. */
- if (choices[0]->bv_len >
- (unsigned int) outbuf_len) {
- ret = -ENOSPC;
- format_free_bv_list(choices);
- } else {
- memcpy(outbuf, choices[0]->bv_val,
- choices[0]->bv_len);
- ret = choices[0]->bv_len;
- format_free_bv_list(choices);
- }
- } else {
- /* Return the values we found. */
- format_add_choice(outbuf_choices, outbuf,
- choices);
- format_free_bv_list(choices);
- }
- } else {
- /* Return a no-result error. */
- ret = -ENOENT;
- }
+ /* Return any values we found. */
+ if (choices != NULL) {
+ format_add_choice(outbuf_choices, outbuf, choices);
+ format_free_bv_list(choices);
}
- return ret;
+ return 0;
}
-/* Look up entries in the map named by the second argument, which have this
- * entry's DN stored in the attribute named by the third argument, pull out the
- * values for the attribute named by the fourth argument, and create a list
- * separated by the first argument. */
+/* Look up entries in the set named by the first argument, which have this
+ * entry's DN stored in the attribute named by the second argument, pull out
+ * the values for the attribute named by the third argument, and return a list
+ * of those values. */
struct format_referred_cbdata {
struct plugin_state *state;
- char *attr, *separator;
- char *outbuf;
- int outbuf_len;
- struct format_choice **outbuf_choices;
+ char *attr;
struct berval **choices;
- int count;
- int ret;
};
static int
format_referred_entry_cb(Slapi_Entry *e, void *callback_data)
{
Slapi_ValueSet *values;
Slapi_Value *value;
- int i, disposition, buffer_flags, len, slen;
+ int i, disposition, buffer_flags;
char *actual_attr;
const struct berval *val;
struct format_referred_cbdata *cbdata;
@@ -866,7 +682,7 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data)
0, &buffer_flags) != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN,
cbdata->state->plugin_desc->spd_id,
- "referred: no values for \"%s\" in \"%s\"?\n",
+ "referred: no values for \"%s\" in \"%s\"\n",
cbdata->attr, slapi_entry_get_ndn(e));
return 0;
}
@@ -875,39 +691,19 @@ format_referred_entry_cb(Slapi_Entry *e, void *callback_data)
i = slapi_valueset_next_value(values, i, &value)) {
/* Pull up the value. */
val = slapi_value_get_berval(value);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- cbdata->state->plugin_desc->spd_id,
- "referred: got %d bytes of \"%.*s\"\n",
- val->bv_len, val->bv_len, val->bv_val);
- /* If we're keeping a list of choices, just add it to the list
- * of values we've retrieved and keep going. */
- if (cbdata->outbuf_choices != NULL) {
- format_add_bv_list(&cbdata->choices, val);
+ if (val->bv_len == 0) {
continue;
}
- /* Check if there's space for the value. */
- slen = strlen(cbdata->separator);
- if ((val->bv_len + (cbdata->count ? slen : 0)) >
- (unsigned int) cbdata->outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- cbdata->state->plugin_desc->spd_id,
- "referred: out of space\n");
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- cbdata->ret = -ENOBUFS;
- return -1;
- }
- /* Store the value. */
- if (cbdata->count > 0) {
- memcpy(cbdata->outbuf, cbdata->separator, slen);
- }
- memcpy(cbdata->outbuf + (cbdata->count ? slen : 0),
- val->bv_val, val->bv_len);
- len = val->bv_len + (cbdata->count ? slen : 0);
- cbdata->outbuf += len;
- cbdata->outbuf_len -= len;
- cbdata->count++;
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata->state->plugin_desc->spd_id,
+ "referred: got %d-byte value for \"%s\"\n",
+ val->bv_len, actual_attr);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata->state->plugin_desc->spd_id,
+ "referred: got \"%.*s\" for \"%s\"\n",
+ val->bv_len, val->bv_val, actual_attr);
+ /* Add it to the list of values we've retrieved. */
+ format_add_bv_list(&cbdata->choices, val);
}
slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
return 0;
@@ -922,7 +718,7 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
{
int i, ret, argc;
Slapi_PBlock *local_pb;
- char **argv, *attrs[2], *filter, *tndn, *sep, *attr, *other_attr;
+ char **argv, *attrs[2], *filter, *tndn, *attr, *other_attr;
char *other_set, *set_filter, **set_bases, *use_filter;
struct format_referred_cbdata cbdata;
@@ -932,35 +728,22 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
"referred: error parsing arguments\n");
return -EINVAL;
}
+ if (argc != 3) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referred: requires 3 arguments\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
+ }
if (outbuf_choices == NULL) {
- if (argc != 4) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "referred: requires 4 arguments\n");
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- sep = argv[0];
- other_set = argv[1];
- other_attr = argv[2];
- attr = argv[3];
- } else {
- if (argc != 3) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "referred: requires 3 arguments\n");
- format_free_parsed_args(argv);
- return -EINVAL;
- }
- sep = NULL;
- other_set = argv[0];
- other_attr = argv[1];
- attr = argv[2];
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referred: returns a list, but a list would "
+ "not be appropriate here\n");
+ format_free_parsed_args(argv);
+ return -EINVAL;
}
-
- /* Build the attribute list. */
- attrs[0] = attr;
- attrs[1] = NULL;
+ other_set = argv[0];
+ other_attr = argv[1];
+ attr = argv[2];
/* Set up to search for matches. */
local_pb = slapi_pblock_new();
@@ -972,15 +755,10 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
}
cbdata.state = state;
cbdata.attr = attr;
- cbdata.separator = sep;
- cbdata.outbuf = outbuf;
- cbdata.outbuf_len = outbuf_len;
- cbdata.outbuf_choices = outbuf_choices;
cbdata.choices = NULL;
- cbdata.count = 0;
- cbdata.ret = 0;
- /* Retrieve the map-specific paramters. */
+ /* Retrieve the set-specific paramaters to determine which entries to
+ * examine. */
set_filter = NULL;
set_bases = NULL;
backend_get_set_config(state, group, other_set,
@@ -990,6 +768,10 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
state->plugin_desc->spd_id,
"no search bases defined for \"%s\"/\"%s\"?\n",
group, other_set);
+ backend_free_set_config(set_bases, set_filter);
+ slapi_pblock_destroy(local_pb);
+ format_free_parsed_args(argv);
+ return 0;
}
/* Note that the attribute in this map refers to this entry. */
@@ -998,6 +780,8 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
other_set, other_attr);
}
+ /* Escape the current entry's DN in case it's necessary, and build a
+ * search filter. */
tndn = format_escape_for_filter(slapi_entry_get_ndn(e));
if (tndn == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -1008,30 +792,31 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
format_free_parsed_args(argv);
return -ENOMEM;
}
-
- /* Now just search through the entries used for the map. */
use_filter = set_filter ? set_filter : "(objectClass=*)";
+ filter = malloc(strlen(use_filter) + strlen(other_attr) +
+ strlen(tndn) + 7);
+ if (filter == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referred: out of memory\n");
+ backend_free_set_config(set_bases, set_filter);
+ slapi_pblock_destroy(local_pb);
+ format_free_parsed_args(argv);
+ return -ENOMEM;
+ }
+ sprintf(filter, "(&(%s=%s)%s)", other_attr, tndn, use_filter);
+ free(tndn);
+
+ /* Search through the entries used for the set. */
+ attrs[0] = attr;
+ attrs[1] = NULL;
for (i = 0; (set_bases != NULL) && (set_bases[i] != NULL); i++) {
- /* Build the search filter. */
- filter = malloc(strlen(use_filter) + strlen(other_attr) +
- strlen(tndn) + 7);
- if (filter == NULL) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "referred: out of memory\n");
- backend_free_set_config(set_bases, set_filter);
- slapi_pblock_destroy(local_pb);
- format_free_parsed_args(argv);
- return -ENOMEM;
- }
- sprintf(filter, "(&(%s=%s)%s)", other_attr, tndn, use_filter);
/* Set up the search. */
slapi_search_internal_set_pb(local_pb,
set_bases[i], LDAP_SCOPE_SUB,
filter, attrs, FALSE,
NULL, NULL,
state->plugin_identity, 0);
- /* Let the callback do the work. */
+ /* Let the callback do the work of saving a value. */
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
"searching under \"%s\" for \"%s\"\n",
@@ -1040,49 +825,23 @@ format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
NULL,
format_referred_entry_cb,
NULL);
- free(filter);
- /* If the callback left an error code for us, then stop. */
- if (cbdata.ret != 0) {
- break;
- }
}
- free(tndn);
+ free(filter);
- if (outbuf_choices != NULL) {
- if (cbdata.choices != NULL) {
- if (format_count_bv_list(cbdata.choices) == 1) {
- /* Return this value directly. */
- if (cbdata.choices[0]->bv_len >
- (unsigned int) outbuf_len) {
- cbdata.ret = -ENOSPC;
- format_free_bv_list(cbdata.choices);
- } else {
- memcpy(outbuf,
- cbdata.choices[0]->bv_val,
- cbdata.choices[0]->bv_len);
- cbdata.ret = cbdata.choices[0]->bv_len;
- format_free_bv_list(cbdata.choices);
- }
- } else {
- /* Return the values we found. */
- format_add_choice(outbuf_choices, outbuf,
- cbdata.choices);
- format_free_bv_list(cbdata.choices);
- }
- } else {
- /* Return a no-result error. */
- cbdata.ret = -ENOENT;
- }
+ /* Return any values we found. */
+ if (cbdata.choices != NULL) {
+ format_add_choice(outbuf_choices, outbuf, cbdata.choices);
+ format_free_bv_list(cbdata.choices);
}
backend_free_set_config(set_bases, set_filter);
slapi_pblock_destroy(local_pb);
format_free_parsed_args(argv);
- return cbdata.ret ? cbdata.ret : cbdata.outbuf - outbuf;
+ return 0;
}
-/* Evaluate each argument, after the first, in turn, and merge them, using the
- * first argument as a separator. */
+/* Evaluate each argument's list of results, after the first, in turn, and
+ * merge them, using the first argument as a separator. */
static int
format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *group, const char *set,
@@ -1091,9 +850,12 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
struct format_choice **outbuf_choices,
char ***ref_attrs, struct format_inref_attr ***inref_attrs)
{
- int ret, i, argc, len, slen, count;
- char **argv;
+ int ret, i, j, argc, len, slen, count;
+ unsigned int *lengths;
+ char **argv, **values;
+ const char *sep;
struct format_choice *these_choices;
+
ret = format_parse_args(state, args, &argc, &argv);
if (ret != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
@@ -1106,51 +868,59 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
format_free_parsed_args(argv);
return -EINVAL;
}
- slen = strlen(argv[0]);
+ sep = argv[0];
+ slen = strlen(sep);
for (i = 1, ret = 0, count = 0; i < argc; i++) {
/* Expand this argument. */
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"merge: expanding ->%s<-\n", argv[i]);
these_choices = NULL;
- len = format_expand(state, pb, e, group, set,
- argv[i], disallowed,
- outbuf + ret + (count ? slen : 0),
- outbuf_len - (ret + (count ? slen : 0)),
- &these_choices,
- ref_attrs, inref_attrs);
- if (len < 0) {
+ values = format_get_data_set(state, e, group, set,
+ argv[i], disallowed,
+ ref_attrs, inref_attrs,
+ &lengths);
+ if (values == NULL) {
slapi_log_error(SLAPI_LOG_PLUGIN,
state->plugin_desc->spd_id,
- "merge: error expanding ->%s<-: %s\n",
- argv[i], strerror(-len));
- format_free_parsed_args(argv);
- return len;
+ "merge: no values for ->%s<-\n",
+ argv[i]);
+ continue;
}
- /* If it didn't expand to anything, just keep going. */
- if (len == 0) {
- if (these_choices == NULL) {
- /* No choices, ignore this expression. */
+ for (j = 0; values[j] != NULL; j++) {
+ /* Check for a non-empty value. */
+ if (lengths[j] == 0) {
continue;
- } else {
- /* Make note of the choices, and accept a
- * zero-length value as a placeholder. */
- format_append_choice(outbuf_choices,
- these_choices);
}
+ /* Check if there's space for this value. */
+ if (ret + lengths[j] + (count ? slen : 0) >
+ (unsigned int) outbuf_len) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "merge: out of space\n");
+ format_free_data_set(values, lengths);
+ format_free_parsed_args(argv);
+ return -ENOBUFS;
+ }
+ /* Log this value. */
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "merge: got %d-byte value for ->%s<\n",
+ lengths[j], argv[i]);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "merge: got %.*s for ->%s<\n",
+ lengths[j], values[j], argv[i]);
+ /* If this isn't the first result, fill in the
+ * separator. Then fill in the value. */
+ if (count > 0) {
+ memcpy(outbuf + ret, sep, slen);
+ ret += slen;
+ }
+ memcpy(outbuf + ret, values[j], lengths[j]);
+ ret += lengths[j];
+ count++;
}
- /* Log this value. */
- slapi_log_error(SLAPI_LOG_PLUGIN,
- state->plugin_desc->spd_id,
- "merge: expanded ->%s<- to ->%.*s<-\n",
- argv[i], len,
- outbuf + ret + (count ? slen : 0));
- /* If we filled in a result, and we had more than one in there
- * already, fill in the separator. */
- if (count > 0) {
- memcpy(outbuf + ret, argv[0], slen);
- }
- ret += (len + (count ? slen : 0));
- count++;
+ format_free_data_set(values, lengths);
}
format_free_parsed_args(argv);
return ret;
@@ -1177,8 +947,7 @@ format_match_generic(struct plugin_state *state,
{
Slapi_ValueSet *values;
Slapi_Value *value;
- const char *cvalue;
- char *actual_attr, **argv, **matches, *plugin_id;
+ char *cvalue, *actual_attr, **argv, **matches, *plugin_id, *defaults[2];
int i, count, argc, disposition, buffer_flags;
int ret, len;
@@ -1210,9 +979,11 @@ format_match_generic(struct plugin_state *state,
for (i = slapi_valueset_first_value(values, &value);
i != -1;
i = slapi_valueset_next_value(values, i, &value)) {
- cvalue = slapi_value_get_string(value);
+ cvalue = xstrndup(slapi_value_get_string(value),
+ slapi_value_get_length(value));
matches[count] = match_fn(argv[1], cvalue,
argv + 2);
+ free(cvalue);
if (matches[count] != NULL) {
count++;
}
@@ -1226,48 +997,71 @@ format_match_generic(struct plugin_state *state,
switch (count) {
case 0:
/* No matches. */
+ free(matches);
if ((default_arg >= 0) && (argv[default_arg] != NULL)) {
/* Try to store the default. */
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
"%s: no matching values for "
"\"%s\", using default value \"%s\"\n",
fnname, argv[1], argv[default_arg]);
- len = strlen(argv[default_arg]);
- if (len > outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
- "%s: out of space\n", fnname);
- free(matches);
- format_free_parsed_args(argv);
- return -ENOBUFS;
+ if (outbuf_choices != NULL) {
+ /* Return the default value as a list. */
+ defaults[0] = argv[default_arg];
+ defaults[1] = NULL;
+ format_add_choice_str(outbuf_choices, outbuf,
+ defaults);
+ len = 0;
+ } else {
+ /* Store the default directly in the buffer. */
+ len = strlen(argv[default_arg]);
+ if (len > outbuf_len) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_id,
+ "%s: out of space\n",
+ fnname);
+ format_free_parsed_args(argv);
+ return -ENOBUFS;
+ }
+ memcpy(outbuf, argv[default_arg], len);
}
- memcpy(outbuf, argv[default_arg], len);
} else {
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
"%s: no matching values for "
"\"%s\", and no default value\n",
fnname, argv[1]);
- free(matches);
format_free_parsed_args(argv);
return -ENOENT;
}
break;
case 1:
/* Single result. */
- len = strlen(matches[0]);
- if (len > outbuf_len) {
- slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
- "%s: out of space\n", fnname);
- free(matches[0]);
- free(matches);
- format_free_parsed_args(argv);
- return -ENOBUFS;
+ if (outbuf_choices != NULL) {
+ /* Return the one match as a list. */
+ format_add_choice_str(outbuf_choices, outbuf, matches);
+ len = 0;
+ } else {
+ /* Store the one match directly in the buffer. */
+ len = strlen(matches[0]);
+ if (len > outbuf_len) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
+ "%s: out of space\n", fnname);
+ free(matches[0]);
+ free(matches);
+ format_free_parsed_args(argv);
+ return -ENOBUFS;
+ }
+ memcpy(outbuf, matches[0], len);
}
- memcpy(outbuf, matches[0], len);
break;
default:
- if (outbuf_choices == NULL) {
+ if (outbuf_choices != NULL) {
+ /* Record the set of matching values as choices at this
+ * location. */
+ format_add_choice_str(outbuf_choices, outbuf, matches);
+ len = 0;
+ } else {
/* Too many matches to store. */
- if (argv[default_arg] != NULL) {
+ if ((default_arg >= 0) && (argv[default_arg] != NULL)) {
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_id,
"%s: too many matching values "
"for \"%s\", using default "
@@ -1293,11 +1087,6 @@ format_match_generic(struct plugin_state *state,
"%s: too many matching values "
"for \"%s\", and no default "
"value\n", fnname, argv[1]);
- if (values != NULL) {
- slapi_vattr_values_free(&values,
- &actual_attr,
- buffer_flags);
- }
for (i = 0; i < count; i++) {
free(matches[i]);
}
@@ -1305,11 +1094,6 @@ format_match_generic(struct plugin_state *state,
format_free_parsed_args(argv);
return -ENOENT;
}
- } else {
- /* Record the set of matching values as choices at this
- * location. */
- format_add_choice_str(outbuf_choices, outbuf, matches);
- len = 0;
}
break;
}
@@ -1516,9 +1300,7 @@ format_lookup_fn(const char *fnname)
char ***ref_attrs,
struct format_inref_attr ***inref_attrs);
} fns[] = {
- {"echo", format_echo},
{"first", format_first},
- {"list", format_list},
{"deref", format_deref},
{"referred", format_referred},
{"merge", format_merge},
@@ -1612,6 +1394,9 @@ format_single(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
i = slapi_valueset_next_value(value_set, i,
&value)) {
val = slapi_value_get_berval(value);
+ if (val->bv_len == 0) {
+ continue;
+ }
d = format_check_disallowed(val,
disallowed);
if (d == NULL) {
@@ -1658,27 +1443,6 @@ format_find_closer(const char *pair, const char *pattern)
return NULL;
}
-static char *
-xstrndup(const char *start, size_t length)
-{
- char *ret, *end;
- end = memchr(start, '\0', length);
- if (end != NULL) {
- length = end - start;
- }
- ret = malloc(length + 1);
- if (ret != NULL) {
- memcpy(ret, start, length);
- ret[length] = '\0';
- }
- return ret;
-}
-static char *
-xstrndupp(const char *start, const char *end)
-{
- return xstrndup(start, end - start);
-}
-
/* Trim off prefixes or suffixes which match the given patterns, free the
* original, and return the result. */
static struct berval
@@ -2366,6 +2130,12 @@ format_get_data_set(struct plugin_state *state, Slapi_Entry *e,
"choice: %d at %d\n",
this_choice->values[i]->bv_len,
this_choice->offset - template);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "choice: %.*s at %d\n",
+ this_choice->values[i]->bv_len,
+ this_choice->values[i]->bv_val,
+ this_choice->offset - template);
}
combinations *= this_choice->n_values;
}