char *command; //!< Name of the trigger.
xlat_exp_head_t *xlat; //!< xlat representation of the trigger args.
fr_value_box_list_t args; //!< Arguments to pass to the trigger exec.
+ fr_value_box_list_t out; //!< result of the xlap (which we ignore)
+ unlang_result_t result; //!< the result of expansion
fr_exec_state_t exec; //!< Used for asynchronous execution.
fr_time_delta_t timeout; //!< How long the trigger has to run.
MEM(trigger = talloc_zero(request, fr_trigger_t));
fr_value_box_list_init(&trigger->args);
+ fr_value_box_list_init(&trigger->out);
trigger->command = talloc_strdup(trigger, value);
trigger->timeout = fr_time_delta_from_sec(5); /* @todo - Should be configurable? */
- slen = xlat_tokenize_argv(trigger, &trigger->xlat,
- &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1),
- NULL, NULL, &(tmpl_rules_t) {
+ if (value[0] != '/') {
+ slen = unlang_xlat_push_string(trigger, &trigger->result, &trigger->out, request, value);
+ if (slen < 0) goto parse_error; /* can't be zero! */
+ } else {
+ slen = xlat_tokenize_argv(trigger, &trigger->xlat,
+ &FR_SBUFF_IN(trigger->command, talloc_array_length(trigger->command) - 1),
+ NULL, NULL, &(tmpl_rules_t) {
.attr = {
.dict_def = request->local_dict,
.list_def = request_attr_request,
.allow_unresolved = false,
},
- }, true);
- if (slen <= 0) {
- char *spaces, *text;
+ }, true);
+ if (slen <= 0) {
+ char *spaces, *text;
- fr_canonicalize_error(trigger, &spaces, &text, slen, trigger->command);
+ parse_error:
+ fr_canonicalize_error(trigger, &spaces, &text, slen, trigger->command);
- cf_log_err(cp, "Failed parsing trigger command");
- cf_log_err(cp, "%s", text);
- cf_log_perr(cp, "%s^", spaces);
+ cf_log_err(cp, "Failed parsing trigger command");
+ cf_log_err(cp, "%s", text);
+ cf_log_perr(cp, "%s^", spaces);
- talloc_free(request);
- talloc_free(spaces);
- talloc_free(text);
- return -1;
+ talloc_free(request);
+ talloc_free(spaces);
+ talloc_free(text);
+ return -1;
+ }
}
/*
}
}
- if (xlat_finalize(trigger->xlat, intp ? unlang_interpret_event_list(request) : main_loop_event_list()) < 0) {
- fr_strerror_const("Failed performing ephemeral instantiation for xlat");
- talloc_free(request);
- return -1;
- }
+ if (trigger->xlat) {
+ if (xlat_finalize(trigger->xlat, intp ? unlang_interpret_event_list(request) : main_loop_event_list()) < 0) {
+ fr_strerror_const("Failed performing ephemeral instantiation for xlat");
+ talloc_free(request);
+ return -1;
+ }
- if (unlang_function_push(request,
- trigger_run,
- trigger_resume,
- NULL, 0,
- UNLANG_TOP_FRAME,
- trigger) < 0) goto error;
+ if (unlang_function_push(request,
+ trigger_run,
+ trigger_resume,
+ NULL, 0,
+ UNLANG_TOP_FRAME,
+ trigger) < 0) goto error;
+ }
if (!intp) {
/*
return unlang_xlat_push_internal(ctx, p_result, out, request, NULL, node, UNLANG_TOP_FRAME);
}
+/** Tokenize a string,and push the resulting xlat onto the stack for evaluation
+ *
+ * @param[in] ctx To allocate value boxes and values in.
+ * @param[out] p_result If set, and execution succeeds, true will be written
+ * here. If execution fails, false will be written.
+ * @param[out] out Where to write the result of the expansion.
+ * @param[in] request to push xlat onto.
+ * @param[in] string to tokenize and evaluate.
+ * @return
+ * - 0 on success.
+ * - -1 on failure.
+ */
+int unlang_xlat_push_string(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out,
+ request_t *request, char const *string)
+{
+ fr_slen_t slen;
+ xlat_exp_head_t *xlat;
+ fr_event_list_t *el;
+
+ el = unlang_interpret_event_list(request);
+ if (!el) el = main_loop_event_list();
+
+ slen = xlat_tokenize(ctx, &xlat, &FR_SBUFF_IN(string, strlen(string)), NULL,
+ &(tmpl_rules_t) {
+ .attr = {
+ .dict_def = request->local_dict, /* we can use local attributes */
+ .list_def = request_attr_request,
+ },
+ .xlat = {
+ .runtime_el = el,
+ },
+ .at_runtime = true,
+ });
+ if (slen <= 0) {
+ return slen;
+ }
+
+ return unlang_xlat_push_internal(ctx, p_result, out, request, xlat, xlat_exp_head(xlat), UNLANG_TOP_FRAME);
+}
+
static unlang_action_t unlang_xlat_repeat(unlang_result_t *p_result, request_t *request, unlang_stack_frame_t *frame)
{
unlang_frame_state_xlat_t *state = talloc_get_type_abort(frame->state, unlang_frame_state_xlat_t);
request_t *request, xlat_exp_head_t const *head, bool top_frame)
CC_HINT(warn_unused_result);
+int unlang_xlat_push_string(TALLOC_CTX *ctx, unlang_result_t *p_result, fr_value_box_list_t *out,
+ request_t *request, char const *string)
+ CC_HINT(warn_unused_result);
+
int unlang_xlat_eval(TALLOC_CTX *ctx, fr_value_box_list_t *out,
request_t *request, xlat_exp_head_t const *head)
CC_HINT(warn_unused_result);