summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-04 18:46:26 -0400
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2008-06-04 18:46:26 -0400
commit3e79d871c80cbec3ed306a17ce39f3d95f81c07d (patch)
tree3797a7242d3a2b08b7ea4be7f0e49f99b6ec20e7
parente095d84d1c2a58dc20aecfd7215daa7a5084cea4 (diff)
downloadslapi-nis-3e79d871c80cbec3ed306a17ce39f3d95f81c07d.tar.gz
slapi-nis-3e79d871c80cbec3ed306a17ce39f3d95f81c07d.tar.xz
slapi-nis-3e79d871c80cbec3ed306a17ce39f3d95f81c07d.zip
- add a "referred" function
- make formatting functions take the domain and map name now
-rw-r--r--src/format.c208
-rw-r--r--src/format.h1
2 files changed, 195 insertions, 14 deletions
diff --git a/src/format.c b/src/format.c
index 2daef85..66a8940 100644
--- a/src/format.c
+++ b/src/format.c
@@ -39,6 +39,7 @@
#include <rpcsvc/yp.h>
+#include "backend.h"
#include "defaults.h"
#include "format.h"
#include "plugin.h"
@@ -47,7 +48,7 @@
#define MAX_BUFFER_SIZE 0x100000
static int format_expand(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
- const char *fmt,
+ const char *domain, const char *map, const char *fmt,
char *outbuf, int outbuf_len,
char ***visited_ndns, bool_t contains_literals);
@@ -133,6 +134,7 @@ format_parse_args(struct plugin_state *state, const char *args,
/* Echo the parameter text. */
static int
format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
@@ -172,6 +174,7 @@ format_echo(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
* 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 *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
@@ -250,6 +253,7 @@ format_list(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
* argument, and create a list separated by the first argument. */
static int
format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
@@ -299,8 +303,8 @@ 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 \"%s\"",
- cref);
+ "deref: internal error reading "
+ "\"%s\"\n", cref);
continue;
}
ref = NULL;
@@ -386,10 +390,176 @@ format_deref(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
+/* Look up entries in the map named by the second argument, which have the
+ * 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. */
+struct format_referred_cbdata {
+ struct plugin_state *state;
+ char *attr, *separator;
+ char *outbuf;
+ int outbuf_len;
+ int count;
+ int ret;
+};
+static int
+format_referred_entry_cb(Slapi_Entry *e, void *callback_data)
+{
+ Slapi_ValueSet *values;
+ Slapi_Value *value;
+ int i, j, disposition, buffer_flags, len, slen;
+ char *actual_attr;
+ const char *cvalue;
+ struct format_referred_cbdata *cbdata = callback_data;
+
+ /* Iterate through the values for the specified attribute. */
+ if (slapi_vattr_values_get(e, cbdata->attr, &values,
+ &disposition, &actual_attr,
+ 0, &buffer_flags) != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ cbdata->state->plugin_desc->spd_id,
+ "referred: no values for \"%s\" in \"%s\"?\n",
+ cbdata->attr, slapi_entry_get_ndn(e));
+ return 0;
+ }
+ for (i = slapi_valueset_first_value(values, &value);
+ i != -1;
+ i = slapi_valueset_next_value(values, i, &value)) {
+ /* Pull up the value. */
+ cvalue = slapi_value_get_string(value);
+ if (cvalue == NULL) {
+ continue;
+ }
+ len = strlen(cvalue);
+ if (len == 0) {
+ continue;
+ }
+ slen = strlen(cbdata->separator);
+ /* Check if there's space for the value. */
+ if (len + (cbdata->count ? slen : 0) > 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),
+ cvalue, len);
+ cbdata->outbuf += (len + (cbdata->count ? slen : 0));
+ cbdata->outbuf_len -= (len + (cbdata->count ? slen : 0));
+ cbdata->count++;
+ }
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
+ return 0;
+}
+static int
+format_referred(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
+ const char *args, char *outbuf, int outbuf_len,
+ char ***visited_ndns)
+{
+ int i, j, len, slen, ret, count, argc;
+ Slapi_Entry *ref;
+ Slapi_DN *refdn;
+ Slapi_ValueSet *ref_values, *values;
+ Slapi_Value *ref_value, *value;
+ Slapi_PBlock *local_pb;
+ int disposition, ref_disposition, buffer_flags, ref_buffer_flags;
+ char **argv, *attrs[2], *actual_attr, *actual_ref_attr, *filter;
+ const char *sep, *cvalue, *cref, *map_filter, **map_bases;
+ struct format_referred_cbdata cbdata;
+
+ ret = format_parse_args(state, args, &argc, &argv);
+ if (ret != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referred: error parsing arguments\n");
+ return -EINVAL;
+ }
+ 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;
+ }
+
+ /* Build the attribute list. */
+ attrs[0] = argv[3];
+ attrs[1] = NULL;
+
+ /* Set up to search for matches. */
+ local_pb = slapi_pblock_new();
+ if (local_pb == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "referred: out of memory\n");
+ format_free_parsed_args(argv);
+ return -ENOMEM;
+ }
+ cbdata.state = state;
+ cbdata.attr = argv[3];
+ cbdata.separator = argv[0];
+ cbdata.outbuf = outbuf;
+ cbdata.outbuf_len = outbuf_len;
+ cbdata.count = 0;
+ cbdata.ret = 0;
+
+ /* Retrieve the map-specific paramters. */
+ map_filter = NULL;
+ map_bases = NULL;
+ backend_get_map_config(state, domain, map, &map_bases, &map_filter);
+ if (map_filter == NULL) {
+ map_filter = "(objectClass=*)";
+ }
+
+ /* Now just search through the entries used for the map. */
+ for (i = 0; (map_bases != NULL) && (map_bases[i] != NULL); i++) {
+ /* Build the search filter. */
+ filter = malloc(strlen(map_filter) + strlen(argv[2]) +
+ strlen(slapi_entry_get_ndn(e)) + 7);
+ if (filter == NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "referred: out of memory\n");
+ slapi_pblock_destroy(local_pb);
+ format_free_parsed_args(argv);
+ return -ENOMEM;
+ }
+ sprintf(filter, "(&(%s=%s)%s)", argv[2], slapi_entry_get_ndn(e),
+ map_filter);
+ /* Set up the search. */
+ slapi_search_internal_set_pb(local_pb,
+ map_bases[i], LDAP_SCOPE_SUB,
+ filter, attrs, FALSE,
+ NULL, NULL,
+ state->plugin_identity, 0);
+ /* Let the callback do the work. */
+ slapi_search_internal_callback_pb(local_pb, state,
+ NULL,
+ format_referred_entry_cb,
+ NULL);
+ free(filter);
+ /* If the callback left an error code for us, then stop. */
+ if (cbdata.ret != 0) {
+ break;
+ }
+ }
+
+ slapi_pblock_destroy(local_pb);
+ format_free_parsed_args(argv);
+ return cbdata.ret;
+}
+
/* Evaluate each argument, 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 *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
@@ -412,7 +582,7 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
/* Expand this argument. */
slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
"merge: expanding ->%s<-\n", argv[i]);
- len = format_expand(state, pb, e, argv[i],
+ len = format_expand(state, pb, e, domain, map, argv[i],
outbuf + ret + (count ? slen : 0),
outbuf_len - (ret + (count ? slen : 0)),
visited_ndns, TRUE);
@@ -454,6 +624,7 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
static int
format_match_generic(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, int min_args, int default_arg,
char *outbuf, int outbuf_len,
char ***visited_ndns,
@@ -603,10 +774,11 @@ format_match_cb(const char *pattern, const char *value, char **argv)
static int
format_match(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
- return format_match_generic(state, pb, e, args, 2, 2,
+ return format_match_generic(state, pb, e, domain, map, args, 2, 2,
outbuf, outbuf_len, visited_ndns,
"format_match", format_match_cb);
}
@@ -629,10 +801,11 @@ format_regmatch_cb(const char *pattern, const char *value, char **argv)
static int
format_regmatch(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
- return format_match_generic(state, pb, e, args, 2, 2,
+ return format_match_generic(state, pb, e, domain, map, args, 2, 2,
outbuf, outbuf_len, visited_ndns,
"format_regmatch", format_regmatch_cb);
}
@@ -748,10 +921,11 @@ format_regsub_cb(const char *pattern, const char *value, char **argv)
static int
format_regsub(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args, char *outbuf, int outbuf_len,
char ***visited_ndns)
{
- return format_match_generic(state, pb, e, args, 3, 3,
+ return format_match_generic(state, pb, e, domain, map, args, 3, 3,
outbuf, outbuf_len, visited_ndns,
"format_regsub", format_regsub_cb);
}
@@ -765,6 +939,7 @@ format_lookup_fn(const char *fnname)
const char *name;
int (*fct_ptr)(struct plugin_state *state,
Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *args,
char *outbuf, int outbuf_len,
char ***visited_ndns);
@@ -772,6 +947,7 @@ format_lookup_fn(const char *fnname)
{"echo", format_echo},
{"list", format_list},
{"deref", format_deref},
+ {"referred", format_referred},
{"merge", format_merge},
{"match", format_match},
{"regmatch", format_regmatch},
@@ -879,7 +1055,7 @@ xstrndupp(const char *start, const char *end)
* treat the entire input format specifier as an expression. */
static int
format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
- const char *fmt,
+ const char *domain, const char *map, const char *fmt,
char *outbuf, int outbuf_len,
char ***visited_ndns,
bool_t contains_literals)
@@ -892,7 +1068,8 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
const char *default_value, *alternate_value, *paramstart, *paramend;
size_t spn;
int (*formatfn)(struct plugin_state *state,
- Slapi_PBlock *pb, Slapi_Entry *e, const char *args,
+ Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map, const char *args,
char *outbuf, int outbuf_len, char ***visited_ndns);
spd_id = state->plugin_desc->spd_id;
@@ -951,6 +1128,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
/* Recursively expand the
* subexpression. */
exp_used = format_expand(state, pb, e,
+ domain, map,
tmp,
expr + j,
exp_size - j,
@@ -1058,9 +1236,9 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return -ENOSYS;
}
/* Call the "function". */
- exp_used = (*formatfn)(state, pb, e, tmp,
- expr + j,
- exp_size - j,
+ exp_used = (*formatfn)(state, pb, e,
+ domain, map, tmp,
+ expr + j, exp_size - j,
visited_ndns);
free(tmp);
if (exp_used < 0) {
@@ -1188,6 +1366,7 @@ format_expand(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
static char *
format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *fmt, char ***visited_ndns)
{
char *buf, *tmp, *ret, *spd_id;
@@ -1208,7 +1387,7 @@ format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return NULL;
}
- i = format_expand(state, pb, e, fmt, buf, buflen,
+ i = format_expand(state, pb, e, domain, map, fmt, buf, buflen,
visited_ndns, TRUE);
if ((i >= 0) && (i < buflen)) {
buf[i] = '\0';
@@ -1254,6 +1433,7 @@ format_format(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
char *
format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *domain, const char *map,
const char *fmt, char ***visited_ndns)
{
Slapi_PBlock *local_pb;
@@ -1275,7 +1455,7 @@ format_get_data(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
local_pb = NULL;
}
- ret = format_format(state, pb, e, fmt, ndn_list);
+ ret = format_format(state, pb, e, domain, map, fmt, ndn_list);
/* If we supplied a PBlock, clean it up. */
if (pb == local_pb) {
diff --git a/src/format.h b/src/format.h
index 8168e26..d59a3a8 100644
--- a/src/format.h
+++ b/src/format.h
@@ -28,5 +28,6 @@ void format_free_data(char *data);
void format_free_ndn_list(char **ndn_list);
char *format_get_data(struct plugin_state *state,
struct slapi_pblock *pb, struct slapi_entry *e,
+ const char *domain, const char *map,
const char *fmt, char ***visited_ndn_list);
#endif