diff options
Diffstat (limited to 'src/format.c')
| -rw-r--r-- | src/format.c | 158 |
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) && |
