From: Alan T. DeKok Date: Fri, 10 Apr 2020 12:44:34 +0000 (-0400) Subject: remove UNLANG_TYPE_XLAT_INLINE and replace with UNLANG_TYPE_TMPL X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2da6fbcf88c7d8994ccc359b6720fa6decc4096d;p=thirdparty%2Ffreeradius-server.git remove UNLANG_TYPE_XLAT_INLINE and replace with UNLANG_TYPE_TMPL which has the same functionality, but will also allow for async template expansions. --- diff --git a/src/lib/unlang/compile.c b/src/lib/unlang/compile.c index fac268e0219..b8a5dbea47d 100644 --- a/src/lib/unlang/compile.c +++ b/src/lib/unlang/compile.c @@ -2484,42 +2484,81 @@ static unlang_t *compile_detach(unlang_t *parent, unlang_compile_t *unlang_ctx, } #endif -static unlang_t *compile_xlat_inline(unlang_t *parent, - unlang_compile_t *unlang_ctx, CONF_PAIR const *cp) +static unlang_t *compile_tmpl(unlang_t *parent, + unlang_compile_t *unlang_ctx, CONF_PAIR *cp) { unlang_t *c; - unlang_xlat_inline_t *mx; + unlang_tmpl_t *ut; + ssize_t slen; + FR_TOKEN type; + char const *p = cf_pair_attr(cp); + size_t len; + vp_tmpl_t *vpt; - mx = talloc_zero(parent, unlang_xlat_inline_t); + ut = talloc_zero(parent, unlang_tmpl_t); - c = unlang_xlat_inline_to_generic(mx); + c = unlang_tmpl_to_generic(ut); c->parent = parent; c->next = NULL; - c->name = "expand"; + c->name = p; c->debug_name = c->name; - c->type = UNLANG_TYPE_XLAT_INLINE; + c->type = UNLANG_TYPE_TMPL; + + if (*p == '`') { + type = T_BACK_QUOTED_STRING; + p++; + len = strlen(p); + if (!len || (p[len - 1] != '`')) { + talloc_free(ut); + cf_log_err(cp, "String is missing trailing quotation character"); + return NULL; + } + + p = talloc_bstrndup(ut, p, len - 1); + len--; + + } else { + type = T_DOUBLE_QUOTED_STRING; + len = strlen(p); + } (void) compile_action_defaults(c, unlang_ctx); - mx->xlat_name = talloc_typed_strdup(mx, cf_pair_attr(cp)); - if (mx->xlat_name[0] == '%') { - ssize_t slen; + slen = tmpl_afrom_str(ut, &vpt, p, len, type, unlang_ctx->rules, true); + if (slen <= 0) { + char *spaces, *text; - slen = xlat_tokenize(mx, &mx->exp, mx->xlat_name, talloc_array_length(mx->xlat_name) - 1, unlang_ctx->rules); - if (slen < 0) { - cf_log_err(cp, "%s", fr_strerror()); - talloc_free(mx); - return NULL; + error: + fr_canonicalize_error(cp, &spaces, &text, slen, fr_strerror()); + + cf_log_err(cp, "Syntax error"); + cf_log_err(cp, "%s", p); + cf_log_err(cp, "%s^ %s", spaces, text); + + talloc_free(ut); + talloc_free(spaces); + talloc_free(text); + + return NULL; + } + + if (vpt->type == TMPL_TYPE_XLAT) { + xlat_exp_t *head; + + /* + * Re-write it to be a pre-parsed XLAT structure. + */ + slen = xlat_tokenize(vpt, &head, vpt->name, talloc_array_length(vpt->name) - 1, unlang_ctx->rules); + if (slen <= 0) { + p = vpt->name; + goto error; } - } else { - char *p; - mx->exec = true; - memmove(mx->xlat_name, mx->xlat_name + 1, strlen(mx->xlat_name)); /* including trailing NUL */ - p = strrchr(mx->xlat_name, '`'); - if (p) *p = '\0'; + vpt->type = TMPL_TYPE_XLAT_STRUCT; + vpt->tmpl_xlat = head; } + ut->tmpl = vpt; /* const issues */ return c; } @@ -3366,7 +3405,7 @@ static unlang_t *compile_item(unlang_t *parent, unlang_compile_t *unlang_ctx, CO */ if (((modrefname[0] == '%') && (modrefname[1] == '{')) || (modrefname[0] == '`')) { - return compile_xlat_inline(parent, unlang_ctx, cp); + return compile_tmpl(parent, unlang_ctx, cp); } } diff --git a/src/lib/unlang/tmpl.c b/src/lib/unlang/tmpl.c index cb6f5814cb0..f36e23bf3d3 100644 --- a/src/lib/unlang/tmpl.c +++ b/src/lib/unlang/tmpl.c @@ -41,9 +41,9 @@ void unlang_tmpl_push(fr_value_box_t **out, REQUEST *request, vp_tmpl_t const *t unlang_stack_frame_t *frame = &stack->frame[stack->depth]; unlang_frame_state_tmpl_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t); - unlang_t *instruction; + unlang_tmpl_t *ut; - static unlang_t const tmpl_instruction = { + static unlang_t tmpl_instruction = { .type = UNLANG_TYPE_TMPL, .name = "tmpl", .debug_name = "tmpl", @@ -61,14 +61,15 @@ void unlang_tmpl_push(fr_value_box_t **out, REQUEST *request, vp_tmpl_t const *t }; state->out = out; - state->tmpl = tmpl; - memcpy(&instruction, &tmpl_instruction, sizeof(instruction)); /* const issues */ + MEM(ut = talloc(state, unlang_tmpl_t)); + ut->self = tmpl_instruction; + ut->tmpl = tmpl; /* * Push a new tmpl frame onto the stack */ - unlang_interpret_push(request, instruction, RLM_MODULE_UNKNOWN, UNLANG_NEXT_STOP, false); + unlang_interpret_push(request, unlang_tmpl_to_generic(ut), RLM_MODULE_UNKNOWN, UNLANG_NEXT_STOP, false); } /** Wrapper to call a resumption function after a tmpl has been expanded @@ -98,17 +99,12 @@ rlm_rcode_t unlang_tmpl_yield(REQUEST *request, fr_unlang_tmpl_resume_t resume, unlang_stack_frame_t *frame = &stack->frame[stack->depth]; unlang_frame_state_tmpl_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t); - if (!tmpl_async_required(state->tmpl)) { - if (tmpl_aexpand_type(request, state->out, FR_TYPE_VALUE_BOX, request, state->tmpl, NULL, NULL) < 0) { - return RLM_MODULE_FAIL; - } - - return RLM_MODULE_OK; - } state->rctx = rctx; state->resume = resume; + frame->interpret = unlang_tmpl_resume; + /* * We set the repeatable flag here, so that the resume * function is always called going back up the stack. @@ -120,22 +116,36 @@ rlm_rcode_t unlang_tmpl_yield(REQUEST *request, fr_unlang_tmpl_resume_t resume, */ frame->interpret = unlang_tmpl_resume; repeatable_set(frame); - - /* - * Not implemented. - */ - return RLM_MODULE_FAIL; + return RLM_MODULE_YIELD; } static unlang_action_t unlang_tmpl(UNUSED REQUEST *request, rlm_rcode_t *presult) { -#if 0 unlang_stack_t *stack = request->stack; unlang_stack_frame_t *frame = &stack->frame[stack->depth]; unlang_frame_state_tmpl_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_tmpl_t); -#endif + unlang_tmpl_t *ut = unlang_generic_to_tmpl(frame->instruction); + if (!state->out) { + state->out = fr_value_box_alloc(state, FR_TYPE_STRING, NULL, false); + } + + if (!tmpl_async_required(ut->tmpl)) { + if (tmpl_aexpand_type(request, state->out, FR_TYPE_STRING, request, ut->tmpl, NULL, NULL) < 0) { + REDEBUG("Failed expanding %s - %s", ut->tmpl->name, fr_strerror()); + *presult = RLM_MODULE_FAIL; + } + + *presult = RLM_MODULE_OK; + return UNLANG_ACTION_CALCULATE_RESULT; + } + + REDEBUG("Async xlats are not implemented!"); + + /* + * Not implemented. + */ *presult = RLM_MODULE_FAIL; return UNLANG_ACTION_CALCULATE_RESULT; diff --git a/src/lib/unlang/tmpl_priv.h b/src/lib/unlang/tmpl_priv.h index 24b370afd0d..f6ad31b7cd6 100644 --- a/src/lib/unlang/tmpl_priv.h +++ b/src/lib/unlang/tmpl_priv.h @@ -34,7 +34,6 @@ extern "C" { * Represents a single tmpl */ typedef struct { - vp_tmpl_t const *tmpl; //!< the tmpl to expand fr_value_box_t **out; //!< where the expansion is stored void *rctx; //!< for resume / signal fr_unlang_tmpl_resume_t resume; //!< resumption handler diff --git a/src/lib/unlang/unlang_priv.h b/src/lib/unlang/unlang_priv.h index 07dc920772b..5db2356e8c5 100644 --- a/src/lib/unlang/unlang_priv.h +++ b/src/lib/unlang/unlang_priv.h @@ -78,7 +78,6 @@ typedef enum { UNLANG_TYPE_CALL, //!< call another virtual server #endif UNLANG_TYPE_POLICY, //!< Policy section. - UNLANG_TYPE_XLAT_INLINE, //!< xlat statement, inline in "unlang" UNLANG_TYPE_XLAT, //!< Represents one level of an xlat expansion. UNLANG_TYPE_TMPL, //!< asynchronously expand a vp_tmpl_t UNLANG_TYPE_MAX @@ -174,10 +173,8 @@ typedef struct { */ typedef struct { unlang_t self; - int exec; - char *xlat_name; - xlat_exp_t *exp; //!< First xlat node to execute. -} unlang_xlat_inline_t; + vp_tmpl_t const *tmpl; +} unlang_tmpl_t; /** State of a redundant operation * @@ -312,13 +309,13 @@ static inline unlang_t *unlang_group_to_generic(unlang_group_t *p) return (unlang_t *)p; } -static inline unlang_xlat_inline_t *unlang_generic_to_xlat_inline(unlang_t *p) +static inline unlang_tmpl_t *unlang_generic_to_tmpl(unlang_t *p) { - rad_assert(p->type == UNLANG_TYPE_XLAT_INLINE); - return talloc_get_type_abort(p, unlang_xlat_inline_t); + rad_assert(p->type == UNLANG_TYPE_TMPL); + return talloc_get_type_abort(p, unlang_tmpl_t); } -static inline unlang_t *unlang_xlat_inline_to_generic(unlang_xlat_inline_t *p) +static inline unlang_t *unlang_tmpl_to_generic(unlang_tmpl_t *p) { return (unlang_t *)p; } diff --git a/src/lib/unlang/xlat.c b/src/lib/unlang/xlat.c index ed7c8f863bf..8a6b4d46798 100644 --- a/src/lib/unlang/xlat.c +++ b/src/lib/unlang/xlat.c @@ -32,14 +32,6 @@ RCSID("$Id$") #include #include "unlang_priv.h" /* Fixme - Should create a proper semi-public interface for the interpret */ -/** Hold the result of an inline xlat expansion - * - */ -typedef struct { - fr_value_box_t *result; //!< Where to store the result of the - ///< xlat expansion. This is usually discarded. -} unlang_frame_state_xlat_inline_t; - /** State of an xlat expansion * * State of one level of nesting within an xlat expansion. @@ -392,32 +384,6 @@ xlat_action_t unlang_xlat_yield(REQUEST *request, return XLAT_ACTION_YIELD; } -/** Evaluates "naked" xlats in the config - * - */ -static unlang_action_t unlang_xlat_inline(REQUEST *request, UNUSED rlm_rcode_t *presult) -{ - unlang_stack_t *stack = request->stack; - unlang_stack_frame_t *frame = &stack->frame[stack->depth]; - unlang_t *instruction = frame->instruction; - unlang_xlat_inline_t *mx = unlang_generic_to_xlat_inline(instruction); - - if (!mx->exec) { - TALLOC_CTX *pool; - unlang_frame_state_xlat_inline_t *state; - - MEM(frame->state = state = talloc_zero(stack, unlang_frame_state_xlat_inline_t)); - MEM(pool = talloc_pool(frame->state, 1024)); /* Pool to absorb some allocs */ - - unlang_xlat_push(pool, &state->result, request, mx->exp, false); - return UNLANG_ACTION_PUSHED_CHILD; - } else { - RDEBUG2("`%s`", mx->xlat_name); - radius_exec_program(request, NULL, 0, NULL, request, mx->xlat_name, request->packet->vps, - false, true, fr_time_delta_from_sec(EXEC_TIMEOUT)); - return UNLANG_ACTION_EXECUTE_NEXT; - } -} /** Register xlat operation with the interpreter * @@ -433,12 +399,4 @@ void unlang_xlat_init(void) .frame_state_size = sizeof(unlang_frame_state_xlat_t), .frame_state_name = "unlang_frame_state_xlat_t", }); - - - unlang_register(UNLANG_TYPE_XLAT_INLINE, - &(unlang_op_t){ - .name = "xlat_inline", - .interpret = unlang_xlat_inline, - .debug_braces = false - }); }