RETURN_OK(snprintf(data, COMMAND_OUTPUT_MAX, "%ld", size));
}
+/** Set or clear migration flags.
+ *
+ */
+static size_t command_migrate(command_result_t *result, command_file_ctx_t *cc,
+ UNUSED char *data, UNUSED size_t data_used, char *in, UNUSED size_t inlen)
+{
+ char *p;
+ bool *out;
+
+ fr_skip_whitespace(in);
+ p = in;
+
+ if (strncmp(p, "xlat_new_functions", sizeof("xlat_new_functions") - 1) == 0) {
+ p += sizeof("xlat_new_functions") - 1;
+ out = &cc->tmpl_rules.xlat.new_functions;
+
+ } else {
+ fr_strerror_const("Unknown migration flag");
+ RETURN_PARSE_ERROR(0);
+ }
+
+ fr_skip_whitespace(p);
+ if (*p != '=') {
+ fr_strerror_const("Missing '=' after flag");
+ RETURN_PARSE_ERROR(0);
+ }
+ p++;
+
+ fr_skip_whitespace(p);
+ if ((strcmp(p, "yes") == 0) || (strcmp(p, "true") == 0) || (strcmp(p, "1") == 0)) {
+ *out = true;
+
+ } else if ((strcmp(p, "no") == 0) || (strcmp(p, "false") == 0) || (strcmp(p, "0") == 0)) {
+ *out = false;
+
+ } else {
+ fr_strerror_const("Invalid value for flag");
+ RETURN_PARSE_ERROR(0);
+ }
+
+ RETURN_OK(0);
+}
+
/** Skip the test file if we're missing a particular feature
*
*/
.list_def = request_attr_request,
.allow_unresolved = cc->tmpl_rules.attr.allow_unresolved
},
+ .xlat = cc->tmpl_rules.xlat,
});
if (dec_len <= 0) {
fr_strerror_printf_push_head("ERROR offset %d", (int) -dec_len);
.usage = "max-buffer-size[ <intger>]",
.description = "Limit the maximum temporary buffer space available for any command which uses it"
}},
+ { L("migrate "), &(command_entry_t){
+ .func = command_migrate,
+ .usage = "migrate <flag>=<value>",
+ .description = "Set migration flag"
+ }},
{ L("need-feature "), &(command_entry_t){
.func = command_need_feature,
.usage = "need-feature <feature>",
return 0;
}
+static bool const func_chars[UINT8_MAX + 1] = {
+ SBUFF_CHAR_CLASS_ALPHA_NUM,
+ ['.'] = true, ['-'] = true, ['_'] = true,
+};
+
+
/** Parse an xlat function and its child argument
*
* Parses a function call string in the format
* Special characters, spaces, etc. cannot be
* module names.
*/
- static bool const func_chars[UINT8_MAX + 1] = {
- SBUFF_CHAR_CLASS_ALPHA_NUM,
- ['.'] = true, ['-'] = true, ['_'] = true,
- };
-
XLAT_DEBUG("FUNC-MONO <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
/*
* Special characters, spaces, etc. cannot be
* module names.
*/
- static bool const func_chars[UINT8_MAX + 1] = {
- SBUFF_CHAR_CLASS_ALPHA_NUM,
- ['.'] = true, ['-'] = true, ['_'] = true,
- };
-
XLAT_DEBUG("FUNC-ARGS <-- %pV", fr_box_strvalue_len(fr_sbuff_current(in), fr_sbuff_remaining(in)));
/*
if (slen == 0) TALLOC_FREE(node); /* Free the empty node */
if (xlat_tokenize_function_args(head, in, t_rules) < 0) goto error;
+ continue;
+ }
+
+ /*
+ * More migration hacks: allow %foo(...)
+ */
+ if (t_rules->xlat.new_functions && fr_sbuff_next_if_char(in, '%')) {
+ fr_sbuff_marker_t m_s;
+
+ fr_sbuff_marker(&m_s, in);
+ fr_sbuff_adv_past_allowed(in, SIZE_MAX, func_chars, NULL);
+
+ /*
+ * Special-case: %% is just %
+ */
+ if ((fr_sbuff_diff(in, &m_s) == 0) && fr_sbuff_next_if_char(in, '%')) {
+ goto one_letter;
+ }
+
+ if (fr_sbuff_diff(in, &m_s) == 1) {
+ if (!fr_sbuff_next_if_char(in, '(')) {
+ fr_strerror_const("Missing '('");
+ goto error;
+ }
+
+ if (!fr_sbuff_next_if_char(in, ')')) {
+ fr_strerror_const("Missing ')'");
+ goto error;
+ }
+
+ one_letter:
+ fr_sbuff_marker_release(&m_s);
+
+ XLAT_DEBUG("ONE-LETTER <-- %pV",
+ fr_box_strvalue_len(str, talloc_array_length(str) - 1));
+
+ if (slen == 0) {
+ talloc_free_children(node); /* re-use empty nodes */
+ } else {
+ node = xlat_exp_alloc_null(head);
+ }
+
+ xlat_exp_set_type(node, XLAT_ONE_LETTER);
+ xlat_exp_set_name(node, fr_sbuff_current(&m_s), 1);
+
+#ifdef STATIC_ANALYZER
+ if (!node->fmt) goto error;
+#endif
+
+ /*
+ * %% is pure. Everything else is not.
+ */
+ node->flags.pure = (node->fmt[0] == '%');
+
+ xlat_exp_insert_tail(head, node);
+ continue;
+ }
+
+ if (!fr_sbuff_next_if_char(in, '(')) {
+ fr_strerror_const("Missing '('");
+ goto error;
+ }
+
+ /*
+ * The next bit is not finished.
+ */
+ fr_assert(0);
+
continue;
}