there's no compilation, but the intended functionality is present.
call.c \
call_env.c \
caller.c \
+ catch.c \
compile.c \
condition.c \
detach.c \
switch.c \
timeout.c \
tmpl.c \
+ try.c \
transaction.c \
xlat.c \
xlat_alloc.c \
unlang_timeout_init();
unlang_limit_init();
unlang_transaction_init();
+ unlang_try_init();
+ unlang_catch_init();
instance_count++;
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file unlang/catch.c
+ * @brief Unlang "catch" keyword evaluation.
+ *
+ * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
+ */
+RCSID("$Id$")
+
+#include "unlang_priv.h"
+#include "catch_priv.h"
+
+static unlang_action_t cleanup(unlang_stack_frame_t *frame, unlang_t *unlang)
+{
+
+ /*
+ * Clean up this frame now, so that stats, etc. will be
+ * processed using the correct frame.
+ */
+ frame_cleanup(frame);
+
+ /*
+ * frame_next() will call cleanup *before* resetting the frame->instruction.
+ * but since the instruction is NULL, no duplicate cleanups will happen.
+ *
+ * frame_next() will then set frame->instruction = frame->next, and everything will be OK.
+ */
+ frame->instruction = NULL;
+ frame->next = unlang;
+ return UNLANG_ACTION_EXECUTE_NEXT;
+}
+
+static unlang_action_t catch_skip_to_next(UNUSED rlm_rcode_t *p_result, UNUSED request_t *request, unlang_stack_frame_t *frame)
+{
+ unlang_t *unlang;
+
+ fr_assert(frame->instruction->type == UNLANG_TYPE_CATCH);
+
+ for (unlang = frame->instruction->next;
+ unlang != NULL;
+ unlang = unlang->next) {
+ if (unlang->type == UNLANG_TYPE_CATCH) continue;
+
+ break;
+ }
+
+ return cleanup(frame, unlang);
+}
+
+static unlang_action_t unlang_catch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
+{
+#ifndef NDEBUG
+ unlang_catch_t const *c = unlang_generic_to_catch(frame->instruction);
+
+ fr_assert(c->catching[*p_result]);
+#endif
+
+ /*
+ * Skip over any "catch" statementa after this one.
+ */
+ frame_repeat(frame, catch_skip_to_next);
+
+ return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING);
+}
+
+
+/** Skip ahead to a particular "catch" instruction.
+ *
+ */
+unlang_action_t unlang_interpret_skip_to_catch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
+{
+ unlang_t *unlang;
+
+ fr_assert(frame->instruction->type == UNLANG_TYPE_TRY);
+
+ for (unlang = frame->instruction->next;
+ unlang != NULL;
+ unlang = unlang->next) {
+ unlang_catch_t const *c;
+
+ if (unlang->type != UNLANG_TYPE_CATCH) {
+ REDEBUG("Failed to 'catch' error %s",
+ fr_table_str_by_value(mod_rcode_table, *p_result, "<invalid>"));
+ return UNLANG_ACTION_CALCULATE_RESULT;
+ }
+
+ c = unlang_generic_to_catch(unlang);
+ if (c->catching[*p_result]) break;
+ }
+
+ fr_assert(unlang != NULL);
+
+ return cleanup(frame, unlang);
+}
+
+void unlang_catch_init(void)
+{
+ unlang_register(UNLANG_TYPE_CATCH,
+ &(unlang_op_t){
+ .name = "catch",
+ .interpret = unlang_catch,
+ .debug_braces = true
+ });
+}
--- /dev/null
+#pragma once
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * $Id$
+ *
+ * @file unlang/catch_priv.h
+ * @brief Declarations for the "catch" keyword
+ *
+ * @copyright 2006-2019 The FreeRADIUS server project
+ */
+#include "unlang_priv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ unlang_group_t group;
+
+ bool catching[RLM_MODULE_NUMCODES];
+} unlang_catch_t;
+
+unlang_action_t unlang_interpret_skip_to_catch(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame);
+
+/** Cast a group structure to the transaction keyword extension
+ *
+ */
+static inline unlang_catch_t *unlang_group_to_catch(unlang_group_t *g)
+{
+ return talloc_get_type_abort(g, unlang_catch_t);
+}
+
+/** Cast a generic structure to the catch keyword extension
+ *
+ */
+static inline unlang_catch_t const *unlang_generic_to_catch(unlang_t const *g)
+{
+ return talloc_get_type_abort_const(g, unlang_catch_t);
+}
+
+#ifdef __cplusplus
+}
+#endif
case UNLANG_TYPE_TIMEOUT:
case UNLANG_TYPE_LIMIT:
case UNLANG_TYPE_TRANSACTION:
+ case UNLANG_TYPE_TRY:
+ case UNLANG_TYPE_CATCH: /* @todo - print out things we catch, too */
g = unlang_generic_to_group(c);
DEBUG("%.*s%s {", depth, unlang_spaces, c->debug_name);
unlang_dump(g->children, depth + 1);
},
};
-
/** Push a configuration section onto the request stack for later interpretation.
*
*/
--- /dev/null
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+/**
+ * $Id$
+ *
+ * @file unlang/try.c
+ * @brief Unlang "try" keyword evaluation.
+ *
+ * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
+ */
+RCSID("$Id$")
+
+#include "unlang_priv.h"
+#include "catch_priv.h"
+
+static unlang_action_t unlang_try(rlm_rcode_t *p_result, request_t *request, unlang_stack_frame_t *frame)
+{
+ /*
+ * When this frame finishes, jump ahead to the appropriate "catch".
+ *
+ * All of the magic is done in the compile phase.
+ */
+ frame_repeat(frame, unlang_interpret_skip_to_catch);
+
+ return unlang_interpret_push_children(p_result, request, frame->result, UNLANG_NEXT_SIBLING);
+}
+
+void unlang_try_init(void)
+{
+ unlang_register(UNLANG_TYPE_TRY,
+ &(unlang_op_t){
+ .name = "try",
+ .interpret = unlang_try,
+ .debug_braces = true
+ });
+}
--- /dev/null
+#pragma once
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * $Id$
+ *
+ * @file unlang/try_priv.h
+ * @brief Declarations for unlang trys
+ *
+ * @copyright 2023 Network RADIUS SAS (legal@networkradius.com)
+ */
+#include "unlang_priv.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ unlang_group_t group;
+} unlang_try_t;
+
+#ifdef __cplusplus
+}
+#endif
UNLANG_TYPE_TIMEOUT, //!< time-based timeouts.
UNLANG_TYPE_LIMIT, //!< limit number of requests in a section
UNLANG_TYPE_TRANSACTION, //!< transactions for editing lists
+ UNLANG_TYPE_TRY, //!< try / catch blocks
+ UNLANG_TYPE_CATCH, //!< catch a previous try
UNLANG_TYPE_POLICY, //!< Policy section.
UNLANG_TYPE_XLAT, //!< Represents one level of an xlat expansion.
UNLANG_TYPE_TMPL, //!< asynchronously expand a tmpl_t
void unlang_limit_init(void);
+void unlang_try_init(void);
+
+void unlang_catch_init(void);
+
/** @} */
#ifdef __cplusplus