Asterisk - The Open Source Telephony Project  21.4.1
res_cliexec.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2022, Naveen Albert
5  *
6  * Naveen Albert <asterisk@phreaknet.org>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*!
20  * \file
21  * \author Naveen Albert <asterisk@phreaknet.org>
22  *
23  * \brief Execute dialplan applications from the CLI
24  *
25  */
26 
27 /*** MODULEINFO
28  <defaultenabled>no</defaultenabled>
29  <support_level>extended</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include "asterisk/channel.h"
35 #include "asterisk/pbx.h"
36 #include "asterisk/module.h"
37 #include "asterisk/cli.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/frame.h"
40 #include "asterisk/format_cache.h"
41 
42 static const struct ast_channel_tech mock_channel_tech = {
43 };
44 
45 static int cli_chan = 0;
46 
47 /*! \brief CLI support for executing application */
48 static char *handle_exec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
49 {
50  struct ast_channel *c = NULL;
51  RAII_VAR(struct ast_format_cap *, caps, NULL, ao2_cleanup);
52  char *app_name, *app_args;
53  int ret = 0;
54  struct ast_app *app;
55 
56  switch (cmd) {
57  case CLI_INIT:
58  e->command = "dialplan exec application";
59  e->usage =
60  "Usage: dialplan exec application <appname> [<args>]\n"
61  " Execute a single dialplan application call for\n"
62  " testing. A mock channel is used to execute\n"
63  " the application, so it may not make\n"
64  " sense to use all applications, and only\n"
65  " global variables should be used.\n"
66  " The ulaw, alaw, and h264 codecs are available.\n";
67  return NULL;
68  case CLI_GENERATE:
69  return NULL;
70  }
71 
72  if (a->argc != e->args + 1 && a->argc != e->args + 2) {
73  return CLI_SHOWUSAGE;
74  }
75 
76  app_name = (char *) a->argv[3];
77  app_args = a->argc == e->args + 2 ? (char *) a->argv[4] : NULL;
78 
79  if (!app_name) {
80  return CLI_FAILURE;
81  }
82 
84  if (!caps) {
85  ast_log(LOG_WARNING, "Could not allocate an empty format capabilities structure\n");
86  return CLI_FAILURE;
87  }
88 
89  if (ast_format_cap_append(caps, ast_format_ulaw, 0)) {
90  ast_log(LOG_WARNING, "Failed to append a ulaw format to capabilities for channel nativeformats\n");
91  return CLI_FAILURE;
92  }
93 
94  if (ast_format_cap_append(caps, ast_format_alaw, 0)) {
95  ast_log(LOG_WARNING, "Failed to append an alaw format to capabilities for channel nativeformats\n");
96  return CLI_FAILURE;
97  }
98 
99  if (ast_format_cap_append(caps, ast_format_h264, 0)) {
100  ast_log(LOG_WARNING, "Failed to append an h264 format to capabilities for channel nativeformats\n");
101  return CLI_FAILURE;
102  }
103 
104  c = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, "CLIExec/%d", ++cli_chan);
105  if (!c) {
106  ast_cli(a->fd, "Unable to allocate mock channel for application execution.\n");
107  return CLI_FAILURE;
108  }
109  ast_channel_tech_set(c, &mock_channel_tech);
110  ast_channel_nativeformats_set(c, caps);
111  ast_channel_set_writeformat(c, ast_format_slin);
112  ast_channel_set_rawwriteformat(c, ast_format_slin);
113  ast_channel_set_readformat(c, ast_format_slin);
114  ast_channel_set_rawreadformat(c, ast_format_slin);
115  ast_channel_unlock(c);
116 
117  app = pbx_findapp(app_name);
118  if (!app) {
119  ast_log(LOG_WARNING, "Could not find application (%s)\n", app_name);
120  ast_hangup(c);
121  return CLI_FAILURE;
122  } else {
123  struct ast_str *substituted_args = ast_str_create(16);
124 
125  if (substituted_args) {
126  ast_str_substitute_variables(&substituted_args, 0, c, app_args);
127  ast_cli(a->fd, "Executing: %s(%s)\n", app_name, ast_str_buffer(substituted_args));
128  ret = pbx_exec(c, app, ast_str_buffer(substituted_args));
129  ast_free(substituted_args);
130  } else {
131  ast_log(LOG_WARNING, "Could not substitute application argument variables for %s\n", app_name);
132  ast_cli(a->fd, "Executing: %s(%s)\n", app_name, app_args);
133  ret = pbx_exec(c, app, app_args);
134  }
135  }
136 
137  ast_hangup(c); /* no need to unref separately */
138 
139  ast_cli(a->fd, "Return Value: %s (%d)\n", ret ? "Failure" : "Success", ret);
140 
141  return CLI_SUCCESS;
142 }
143 
144 static struct ast_cli_entry cli_cliorig[] = {
145  AST_CLI_DEFINE(handle_exec, "Execute a dialplan application"),
146 };
147 
148 static int unload_module(void)
149 {
150  return ast_cli_unregister_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
151 }
152 
153 static int load_module(void)
154 {
155  int res;
156  res = ast_cli_register_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
158 }
159 
160 AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "Simple dialplan execution from the CLI");
Main Channel structure associated with a channel.
Asterisk main include file. File version handling, generic pbx functions.
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx_app.c:471
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
descriptor for a cli entry.
Definition: cli.h:171
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:185
General Asterisk PBX channel definitions.
Asterisk internal frame definitions.
#define ast_format_cap_append(cap, format, framing)
Add format capability to capabilities structure.
Definition: format_cap.h:99
#define ast_format_cap_alloc(flags)
Allocate a new ast_format_cap structure.
Definition: format_cap.h:49
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Definition: channel.h:628
Core PBX routines and definitions.
Support for dynamic strings.
Definition: strings.h:623
Format capabilities structure, holds formats + preference order + etc.
Definition: format_cap.c:54
struct ast_format * ast_format_h264
Built-in cached h264 format.
Definition: format_cache.c:176
const char * app_name(struct ast_app *app)
Definition: pbx_app.c:463
char * command
Definition: cli.h:186
static char * handle_exec(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI support for executing application.
Definition: res_cliexec.c:48
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2541
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
const char * usage
Definition: cli.h:177
Standard Command Line Interface.
struct ast_format * ast_format_alaw
Built-in cached alaw format.
Definition: format_cache.c:91
ast_app: A registered application
Definition: pbx_app.c:45
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: ael_main.c:165
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Definition: channel.h:1258
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
Media Format Cache API.
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659