From: Nick Porter Date: Thu, 20 May 2021 17:45:00 +0000 (+0100) Subject: v4: Convert %{Foreach} to new xlat API (#4091) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=69a2a53a5fa991fb8ca4d3ec023d14f230ec6227;p=thirdparty%2Ffreeradius-server.git v4: Convert %{Foreach} to new xlat API (#4091) * Convert %{Foreach...} to new xlat api * Allow virtual attributes to use new xlat API --- diff --git a/src/lib/unlang/foreach.c b/src/lib/unlang/foreach.c index 886f9063dcd..2bf55564862 100644 --- a/src/lib/unlang/foreach.c +++ b/src/lib/unlang/foreach.c @@ -29,6 +29,7 @@ RCSID("$Id$") #include "foreach_priv.h" #include "return_priv.h" #include "unlang_priv.h" +#include "xlat_priv.h" static char const * const xlat_foreach_names[] = {"Foreach-Variable-0", "Foreach-Variable-1", @@ -59,9 +60,9 @@ typedef struct { #endif } unlang_frame_state_foreach_t; -static ssize_t unlang_foreach_xlat(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen, - void const *mod_inst, UNUSED void const *xlat_inst, - request_t *request, UNUSED char const *fmt); +static xlat_action_t unlang_foreach_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, + UNUSED void const *xlat_inst, void *xlat_thread_inst, + UNUSED fr_value_box_list_t *in); #define FOREACH_REQUEST_DATA (void *)unlang_foreach_xlat @@ -196,16 +197,21 @@ static unlang_action_t unlang_break(rlm_rcode_t *p_result, request_t *request, u * * @ingroup xlat_functions */ -static ssize_t unlang_foreach_xlat(TALLOC_CTX *ctx, char **out, UNUSED size_t outlen, - void const *mod_inst, UNUSED void const *xlat_inst, - request_t *request, UNUSED char const *fmt) +static xlat_action_t unlang_foreach_xlat(TALLOC_CTX *ctx, fr_dcursor_t *out, request_t *request, + void const *xlat_inst, UNUSED void *xlat_thread_inst, + UNUSED fr_value_box_list_t *in) { - fr_pair_t **pvp; + fr_pair_t **pvp; + int const *inst = xlat_inst; + fr_value_box_t *vb; - pvp = (fr_pair_t **) request_data_reference(request, FOREACH_REQUEST_DATA, *(int const *) mod_inst); - if (!pvp || !*pvp) return 0; + pvp = (fr_pair_t **) request_data_reference(request, FOREACH_REQUEST_DATA, *inst); + if (!pvp || !*pvp) return XLAT_ACTION_FAIL; - return fr_value_box_aprint(ctx, out, &(*pvp)->data, NULL); + MEM(vb = fr_value_box_alloc_null(ctx)); + fr_value_box_copy(ctx, vb, &(*pvp)->data); + fr_dcursor_append(out, vb); + return XLAT_ACTION_DONE; } void unlang_foreach_init(void) @@ -215,8 +221,9 @@ void unlang_foreach_init(void) for (i = 0; i < NUM_ELEMENTS(xlat_foreach_names); i++) { xlat_t *x; - x = xlat_register_legacy(&xlat_foreach_inst[i], xlat_foreach_names[i], - unlang_foreach_xlat, NULL, NULL, 0, 0); + x = xlat_register(NULL, xlat_foreach_names[i], + unlang_foreach_xlat, true); + x->uctx = &xlat_foreach_inst[i]; fr_assert(x); xlat_internal(x); } diff --git a/src/lib/unlang/xlat_eval.c b/src/lib/unlang/xlat_eval.c index 23fe8405967..284cdbd9914 100644 --- a/src/lib/unlang/xlat_eval.c +++ b/src/lib/unlang/xlat_eval.c @@ -1311,17 +1311,21 @@ xlat_action_t xlat_frame_eval(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_exp_t con node->fmt); xlat_debug_log_expansion(request, node, NULL); - MEM(value = fr_value_box_alloc_null(ctx)); - slen = node->call.func->func.sync(value, &str, node->call.func->buf_len, node->call.func->mod_inst, + if (node->call.func->type == XLAT_FUNC_NORMAL) { + node->call.func->func.async(ctx, out, request, node->call.func->uctx, NULL, NULL); + } else { + MEM(value = fr_value_box_alloc_null(ctx)); + slen = node->call.func->func.sync(value, &str, node->call.func->buf_len, node->call.func->mod_inst, NULL, request, NULL); - if (slen < 0) { - talloc_free(value); - goto fail; - } - if (slen == 0) continue; + if (slen < 0) { + talloc_free(value); + goto fail; + } + if (slen == 0) continue; - fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false); - fr_dcursor_append(out, value); + fr_value_box_bstrdup_buffer_shallow(NULL, value, NULL, str, false); + fr_dcursor_append(out, value); + } fr_dcursor_next(out); xlat_debug_log_result(request, fr_dcursor_current(out)); @@ -1507,6 +1511,37 @@ static char *xlat_sync_eval(TALLOC_CTX *ctx, request_t *request, xlat_exp_t cons case XLAT_VIRTUAL: XLAT_DEBUG("xlat_sync_eval VIRTUAL"); + /* + * Temporary hack to use the new API + */ + if (node->call.func->type == XLAT_FUNC_NORMAL) { + fr_value_box_list_t result; + xlat_action_t action; + fr_dcursor_t out; + TALLOC_CTX *pool = talloc_new(NULL); + + fr_value_box_list_init (&result); + fr_dcursor_init(&out, &result); + + action = node->call.func->func.async(pool, &out, request, node->call.func->uctx, NULL, NULL); + if (action == XLAT_ACTION_FAIL) { + talloc_free(pool); + return NULL; + } + if (!fr_dlist_empty(&result)) { + str = fr_value_box_list_aprint(ctx, &result, NULL, &fr_value_escape_double); + if (!str) { + RPEDEBUG("Failed concatenating xlat result string"); + talloc_free(pool); + return NULL; + } + } else { + str = talloc_strdup(ctx, ""); + } + talloc_free(pool); /* Memory should be in new ctx */ + break; + } + if (node->call.func->buf_len > 0) { str = talloc_array(ctx, char, node->call.func->buf_len); str[0] = '\0'; /* Be sure the string is \0 terminated */