summaryrefslogtreecommitdiffstats
path: root/src/format.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/format.c')
-rw-r--r--src/format.c158
1 files changed, 158 insertions, 0 deletions
diff --git a/src/format.c b/src/format.c
index 42e79fb..3a96187 100644
--- a/src/format.c
+++ b/src/format.c
@@ -1,5 +1,6 @@
#include <sys/types.h>
#include <rpcsvc/yp.h>
+#include <fnmatch.h>
#include <stdlib.h>
#include "defaults.h"
#include "format.h"
@@ -414,6 +415,162 @@ format_merge(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e,
return ret;
}
+/* Look up the entry's values for the attribute named by the second argument,
+ * and use the callback to check if they match the first argument. If we find
+ * exactly one match, store it in the output buffer, otherwise store the text
+ * of the third argument if given, or return an error if no third argument was
+ * given. */
+static int
+format_match_generic(struct plugin_state *state,
+ Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *args, char *outbuf, int outbuf_len,
+ char ***visited_ndns,
+ const char *fnname,
+ PRBool (*match_fn)(const char *pattern, const char *value))
+{
+ Slapi_ValueSet *values;
+ Slapi_Value *value;
+ const char *cvalue, *matched;
+ char *actual_attr, **argv;
+ int i, count, argc, disposition, buffer_flags, ret, len;
+
+ ret = format_parse_args(state, args, &argc, &argv);
+ if (ret != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "%s: error parsing arguments\n", fnname);
+ return -1;
+ }
+ if (argc < 2) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "%s: requires at least 2 arguments\n", fnname);
+ format_free_parsed_args(argv);
+ return -1;
+ }
+ /* Walk the list of values for the attribute. */
+ matched = NULL;
+ count = 0;
+ values = NULL;
+ if (slapi_vattr_values_get(e, argv[1], &values,
+ &disposition, &actual_attr,
+ 0, &buffer_flags) == 0) {
+ for (i = slapi_valueset_first_value(values, &value);
+ i != -1;
+ i = slapi_valueset_next_value(values, i, &value)) {
+ cvalue = slapi_value_get_string(value);
+ if (match_fn(argv[0], cvalue)) {
+ count++;
+ if (count > 1) {
+ break;
+ }
+ matched = cvalue;
+ }
+ }
+ } else {
+ if (argv[2] != NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: no values found for "
+ "\"%s\", using default value \"%s\"\n",
+ fnname, argv[1], argv[2]);
+ count = 1;
+ matched = argv[2];
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: no values found for "
+ "\"%s\", and no default value\n",
+ fnname, argv[1]);
+ }
+ }
+ /* Make sure matched is either the single match, the default, or NULL
+ * if we had no default. */
+ switch (count) {
+ case 0:
+ /* No matches. */
+ if (argv[2] != NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: no matching values for "
+ "\"%s\", using default value \"%s\"\n",
+ fnname, argv[1], argv[2]);
+ matched = argv[2];
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: no matching values for "
+ "\"%s\", and no default value \"%s\"\n",
+ fnname, argv[1]);
+ if (values != NULL) {
+ slapi_vattr_values_free(&values, &actual_attr,
+ buffer_flags);
+ }
+ format_free_parsed_args(argv);
+ return -1;
+ }
+ break;
+ case 1:
+ /* No errors. */
+ break;
+ default:
+ /* Too many matches. */
+ if (argv[2] != NULL) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: too many matching values for "
+ "\"%s\", using default value \"%s\"\n",
+ fnname, argv[1], argv[2]);
+ matched = argv[2];
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ state->plugin_desc->spd_id,
+ "%s: too many matching values for "
+ "\"%s\", and no default value \"%s\"\n",
+ fnname, argv[1]);
+ if (values != NULL) {
+ slapi_vattr_values_free(&values, &actual_attr,
+ buffer_flags);
+ }
+ format_free_parsed_args(argv);
+ return -1;
+ }
+ break;
+ }
+ len = strlen(matched);
+ if (len > outbuf_len) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id,
+ "%s: out of space\n", fnname);
+ if (values != NULL) {
+ slapi_vattr_values_free(&values, &actual_attr,
+ buffer_flags);
+ }
+ format_free_parsed_args(argv);
+ return -1;
+ }
+ memcpy(outbuf, matched, len);
+ if (values != NULL) {
+ slapi_vattr_values_free(&values, &actual_attr, buffer_flags);
+ }
+ format_free_parsed_args(argv);
+ return len;
+}
+
+/* Check for glob-style matched values. */
+static PRBool
+format_match_cb(const char *pattern, const char *value)
+{
+ return fnmatch(pattern, value, 0) == 0;
+}
+static int
+format_match(struct plugin_state *state,
+ Slapi_PBlock *pb, Slapi_Entry *e,
+ const char *args, char *outbuf, int outbuf_len,
+ char ***visited_ndns)
+{
+ return format_match_generic(state, pb, e, args,
+ outbuf, outbuf_len, visited_ndns,
+ "format_match", format_match_cb);
+}
+
/* Choose a formatting function by name. */
static void *
format_lookup_fn(const char *fnname)
@@ -431,6 +588,7 @@ format_lookup_fn(const char *fnname)
{"list", format_list},
{"deref", format_deref},
{"merge", format_merge},
+ {"match", format_match},
};
for (i = 0; i < sizeof(fns) / sizeof(fns[0]); i++) {
if ((fns[i].name != NULL) &&