diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-11-04 17:19:33 -0500 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2008-11-04 17:19:33 -0500 |
| commit | b3eec3cda6d609383d554d731c2da492046bd204 (patch) | |
| tree | c655793271ec20d8badd2aea71948f8a4aba5177 /src/format.c | |
| parent | 2cc6d75d32a5d7ae7f2f51fd67e66bb95826fa34 (diff) | |
- add a "link" function
Diffstat (limited to 'src/format.c')
| -rw-r--r-- | src/format.c | 181 |
1 files changed, 181 insertions, 0 deletions
diff --git a/src/format.c b/src/format.c index 2f78ccd..ace8382 100644 --- a/src/format.c +++ b/src/format.c @@ -2314,6 +2314,186 @@ format_collect(struct plugin_state *state, Slapi_PBlock *pb, Slapi_Entry *e, return ret; } +/* Evaluate all of the arguments, and concatentate sets of entries from each + * list, separating them with an optional separator, padding the lists with a + * specified value until all of the elements of all lists have been used. */ +static int +format_link(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, + struct format_ref_attr_list ***ref_attr_list, + struct format_ref_attr_list ***inref_attr_list) +{ + int ret, argc, i, *j, l, n_lists, n_done; + unsigned int **lengths, length, max_length; + char **argv, ***values, *buffer, *p; + struct berval bv, **choices; + Slapi_Value *value; + + ret = format_parse_args(state, args, &argc, &argv); + if (ret != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "link: error parsing arguments\n"); + return -EINVAL; + } + if (argc < 1) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "link: error parsing arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + if (((argc + 1) % 3) != 0) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "link: wrong number of arguments\n"); + format_free_parsed_args(argv); + return -EINVAL; + } + + /* Allocate space to store the information. */ + values = malloc(sizeof(char **) * ((argc + 1) / 3)); + lengths = malloc(sizeof(int *) * ((argc + 1) / 3)); + j = malloc(sizeof(int) * ((argc + 1) / 3)); + if ((values == NULL) || (lengths == NULL)) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "link: out of memory\n"); + format_free_parsed_args(argv); + free(values); + free(lengths); + free(j); + return -ENOMEM; + } + + /* Walk the list of the arguments, building a list of lists. */ + choices = NULL; + n_lists = 0; + for (i = 0; i < argc; i += 3) { + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "link: evaluating \"%s\"\n", argv[i]); + values[i / 3] = format_get_data_set(state, e, group, set, + argv[i], disallowed, + ref_attrs, inref_attrs, + ref_attr_list, + inref_attr_list, + &lengths[i / 3]); + if (values[i / 3] != NULL) { + n_lists++; + } + } + + /* If we got _no_ answers for anything, that's a NULL result. */ + if (n_lists == 0) { + format_free_parsed_args(argv); + free(values); + free(lengths); + free(j); + return -ENOENT; + } + + /* Walk the lists, building the output data items. */ + n_lists = (argc + 1) / 3; + for (i = 0; i < n_lists; i++) { + j[i] = 0; + } + n_done = 0; + length = 0; + max_length = 0; + buffer = NULL; + do { + /* Calculate how much space we need. */ + length = 0; + for (i = 0; i < n_lists; i++) { + if ((values[i] != NULL) && (values[i][j[i]] != NULL)) { + length += lengths[i][j[i]]; + } else { + length += strlen(argv[i * 3 + 1]); + } + if (i < (n_lists - 1)) { + length += strlen(argv[i * 3 + 2]); + } + } + /* Make sure the buffer is large enough. */ + if (length > max_length) { + free(buffer); + buffer = malloc(length); + if (buffer == NULL) { + format_free_bv_list(choices); + format_free_parsed_args(argv); + for (i = 0; i < n_lists; i += 3) { + format_free_data_set(values[i], + lengths[i]); + } + free(values); + free(lengths); + free(j); + return -ENOMEM; + } + max_length = length; + } + /* Build the output value. */ + p = buffer; + for (i = 0; i < n_lists; i++) { + if ((values[i] != NULL) && (values[i][j[i]] != NULL)) { + l = lengths[i][j[i]]; + memcpy(p, values[i][j[i]], l); + p += l; + (j[i])++; + } else { + l = strlen(argv[i * 3 + 1]); + memcpy(p, argv[i * 3 + 1], l); + p += l; + } + if (i < (n_lists - 1)) { + l = strlen(argv[i * 3 + 2]); + memcpy(p, argv[i * 3 + 2], l); + p += l; + } + } + /* Add it to the result list. */ + bv.bv_val = buffer; + bv.bv_len = length; + if ((p - buffer) != length) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "link: internal error\n"); + break; + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "link: \"%.*s\"\n", + bv.bv_len, bv.bv_val); + format_add_bv_list(&choices, &bv); + } + /* Figure out if we're done yet. */ + for (i = 0, n_done = 0; i < n_lists; i++) { + if ((values[i] == NULL) || (values[i][j[i]] == NULL)) { + n_done++; + } + } + } while (n_done != n_lists); + + if (choices != NULL) { + format_add_choice(outbuf_choices, outbuf, choices); + format_free_bv_list(choices); + ret = 0; + } else { + ret = -ENOENT; + } + + format_free_parsed_args(argv); + for (i = 0; i < argc; i += 3) { + format_free_data_set(values[i / 3], lengths[i / 3]); + } + free(buffer); + free(values); + free(lengths); + free(j); + + return ret; +} + /* Choose a formatting function by name. */ static void * format_lookup_fn(const char *fnname) @@ -2343,6 +2523,7 @@ format_lookup_fn(const char *fnname) {"regsub", format_regsub}, {"ifeq", format_ifeq}, {"collect", format_collect}, + {"link", format_link}, }; for (i = 0; i < sizeof(fns) / sizeof(fns[0]); i++) { if ((fns[i].name != NULL) && |
