<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/18722">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">res_cliexec: Add dialplan exec CLI command.<br><br>Adds a CLI command similar to "dialplan eval function" except for<br>applications: "dialplan exec application", useful for quickly<br>testing certain application behavior directly from the CLI<br>without writing any dialplan.<br><br>ASTERISK-30062 #close<br><br>Change-Id: I42e9fa9b60746c21450d40f99a026d48d2486dde<br>---<br>A doc/CHANGES-staging/res_cliexec.txt<br>A res/res_cliexec.c<br>2 files changed, 166 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/22/18722/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/res_cliexec.txt b/doc/CHANGES-staging/res_cliexec.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..2b1fe76</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/res_cliexec.txt</span><br><span>@@ -0,0 +1,6 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: res_cliexec</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A new CLI command, dialplan exec application, has</span><br><span style="color: hsl(120, 100%, 40%);">+been added which allows dialplan applications to be</span><br><span style="color: hsl(120, 100%, 40%);">+executed at the CLI, useful for some quick testing</span><br><span style="color: hsl(120, 100%, 40%);">+without needing to write dialplan.</span><br><span>diff --git a/res/res_cliexec.c b/res/res_cliexec.c</span><br><span>new file mode 100644</span><br><span>index 0000000..b1e13f9</span><br><span>--- /dev/null</span><br><span>+++ b/res/res_cliexec.c</span><br><span>@@ -0,0 +1,160 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * Asterisk -- An open source telephony toolkit.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Copyright (C) 2022, Naveen Albert</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See http://www.asterisk.org for more information about</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Asterisk project. Please do not directly contact</span><br><span style="color: hsl(120, 100%, 40%);">+ * any of the maintainers of this project for assistance;</span><br><span style="color: hsl(120, 100%, 40%);">+ * the project provides a web site, mailing lists and IRC</span><br><span style="color: hsl(120, 100%, 40%);">+ * channels for your use.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the GNU General Public License Version 2. See the LICENSE file</span><br><span style="color: hsl(120, 100%, 40%);">+ * at the top of the source tree.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \file</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Naveen Albert <asterisk@phreaknet.org></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Execute dialplan applications from the CLI</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*** MODULEINFO</span><br><span style="color: hsl(120, 100%, 40%);">+ <defaultenabled>no</defaultenabled></span><br><span style="color: hsl(120, 100%, 40%);">+ <support_level>extended</support_level></span><br><span style="color: hsl(120, 100%, 40%);">+ ***/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/channel.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/pbx.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/module.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/cli.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/frame.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/format_cache.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct ast_channel_tech mock_channel_tech = {</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int cli_chan = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief CLI support for executing application */</span><br><span style="color: hsl(120, 100%, 40%);">+static char *handle_exec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_channel *c = NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);</span><br><span style="color: hsl(120, 100%, 40%);">+ char *app_name, *app_args;</span><br><span style="color: hsl(120, 100%, 40%);">+ int ret = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_app *app;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ e->command = "dialplan exec application";</span><br><span style="color: hsl(120, 100%, 40%);">+ e->usage =</span><br><span style="color: hsl(120, 100%, 40%);">+ "Usage: dialplan exec application <appname> [<args>]\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " Execute a single dialplan application call for\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " testing. A mock channel is used to execute\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " the application, so it may not make\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " sense to use all applications, and only\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " global variables should be used.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ " The ulaw, alaw, and h264 codecs are available.\n";</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ case CLI_GENERATE:</span><br><span style="color: hsl(120, 100%, 40%);">+ return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (a->argc != e->args + 1 && a->argc != e->args + 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SHOWUSAGE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ app_name = (char *) a->argv[3];</span><br><span style="color: hsl(120, 100%, 40%);">+ app_args = a->argc == e->args + 2 ? (char *) a->argv[4] : NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!app_name) {</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ caps = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!caps) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not allocate an empty format capabilities structure\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Failed to append a ulaw format to capabilities for channel nativeformats\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_format_cap_append(caps, ast_format_alaw, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Failed to append an alaw format to capabilities for channel nativeformats\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_format_cap_append(caps, ast_format_h264, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Failed to append an h264 format to capabilities for channel nativeformats\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ c = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "CLIExec/%d", ++cli_chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!c) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Unable to allocate mock channel for application execution.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_tech_set(c, &mock_channel_tech);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_nativeformats_set(c, caps);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_set_writeformat(c, ast_format_slin);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_set_rawwriteformat(c, ast_format_slin);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_set_readformat(c, ast_format_slin);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_set_rawreadformat(c, ast_format_slin);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_unlock(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ app = pbx_findapp(app_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!app) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not find application (%s)\n", app_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_hangup(c);</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_FAILURE;</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *substituted_args = ast_str_create(16);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (substituted_args) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_substitute_variables(&substituted_args, 0, c, app_args);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Executing: %s(%s)\n", app_name, ast_str_buffer(substituted_args));</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = pbx_exec(c, app, ast_str_buffer(substituted_args));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(substituted_args);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_WARNING, "Could not substitute application argument variables for %s\n", app_name);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Executing: %s(%s)\n", app_name, app_args);</span><br><span style="color: hsl(120, 100%, 40%);">+ ret = pbx_exec(c, app, app_args);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_hangup(c); /* no need to unref separately */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return CLI_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_cli_entry cli_cliorig[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_CLI_DEFINE(handle_exec, "Execute a dialplan application"),</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int unload_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ return ast_cli_unregister_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int load_module(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int res;</span><br><span style="color: hsl(120, 100%, 40%);">+ res = ast_cli_register_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));</span><br><span style="color: hsl(120, 100%, 40%);">+ return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Simple dialplan execution from the CLI");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/18722">change 18722</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/18722"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I42e9fa9b60746c21450d40f99a026d48d2486dde </div>
<div style="display:none"> Gerrit-Change-Number: 18722 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>