2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2005 - 2006, Digium, Inc.
6 * Russell Bryant <russell@digium.com>
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.
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.
21 * \author Russell Bryant <russell@digium.com>
23 * \brief Originate calls via the CLI
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
31 #include "asterisk/channel.h"
32 #include "asterisk/pbx.h"
33 #include "asterisk/module.h"
34 #include "asterisk/cli.h"
35 #include "asterisk/utils.h"
36 #include "asterisk/frame.h"
38 /*! The timeout for originated calls, in seconds */
42 * \brief orginate a call from the CLI
43 * \param fd file descriptor for cli
44 * \param chan channel to create type/data
45 * \param app application you want to run
46 * \param appdata data for application
47 * \retval CLI_SUCCESS on success.
48 * \retval CLI_SHOWUSAGE on failure.
50 static char *orig_app(int fd, const char *chan, const char *app, const char *appdata)
56 if (ast_strlen_zero(app))
59 chandata = ast_strdupa(chan);
61 chantech = strsep(&chandata, "/");
63 ast_cli(fd, "*** No data provided after channel type! ***\n");
67 ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, app, appdata, &reason, 0, NULL, NULL, NULL, NULL, NULL);
73 * \brief orginate from extension
74 * \param fd file descriptor for cli
75 * \param chan channel to create type/data
76 * \param data contains exten\@context
77 * \retval CLI_SUCCESS on success.
78 * \retval CLI_SHOWUSAGE on failure.
80 static char *orig_exten(int fd, const char *chan, const char *data)
88 chandata = ast_strdupa(chan);
90 chantech = strsep(&chandata, "/");
92 ast_cli(fd, "*** No data provided after channel type! ***\n");
96 if (!ast_strlen_zero(data)) {
97 context = ast_strdupa(data);
98 exten = strsep(&context, "@");
101 if (ast_strlen_zero(exten))
103 if (ast_strlen_zero(context))
106 ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 0, NULL, NULL, NULL, NULL, NULL);
112 * \brief handle for orgination app or exten.
113 * \param e pointer to the CLI structure to initialize
114 * \param cmd operation to execute
115 * \param a structure that contains either application or extension arguments
116 * \retval CLI_SUCCESS on success.
117 * \retval CLI_SHOWUSAGE on failure.
119 static char *handle_orig(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
121 static char *choices[] = { "application", "extension", NULL };
125 e->command = "channel originate";
127 " There are two ways to use this command. A call can be originated between a\n"
128 "channel and a specific application, or between a channel and an extension in\n"
129 "the dialplan. This is similar to call files or the manager originate action.\n"
130 "Calls originated with this command are given a timeout of 30 seconds.\n\n"
132 "Usage1: channel originate <tech/data> application <appname> [appdata]\n"
133 " This will originate a call between the specified channel tech/data and the\n"
134 "given application. Arguments to the application are optional. If the given\n"
135 "arguments to the application include spaces, all of the arguments to the\n"
136 "application need to be placed in quotation marks.\n\n"
138 "Usage2: channel originate <tech/data> extension [exten@][context]\n"
139 " This will originate a call between the specified channel tech/data and the\n"
140 "given extension. If no context is specified, the 'default' context will be\n"
141 "used. If no extension is given, the 's' extension will be used.\n";
147 /* ugly, can be removed when CLI entries have ast_module pointers */
148 ast_module_ref(ast_module_info->self);
149 res = ast_cli_complete(a->word, choices, a->n);
150 ast_module_unref(ast_module_info->self);
155 if (ast_strlen_zero(a->argv[2]) || ast_strlen_zero(a->argv[3]))
156 return CLI_SHOWUSAGE;
158 /* ugly, can be removed when CLI entries have ast_module pointers */
159 ast_module_ref(ast_module_info->self);
161 if (!strcasecmp("application", a->argv[3])) {
162 res = orig_app(a->fd, a->argv[2], a->argv[4], a->argv[5]);
163 } else if (!strcasecmp("extension", a->argv[3])) {
164 res = orig_exten(a->fd, a->argv[2], a->argv[4]);
166 ast_log(LOG_WARNING, "else");
170 ast_module_unref(ast_module_info->self);
175 static char *handle_redirect(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
177 const char *name, *dest;
178 struct ast_channel *chan;
183 e->command = "channel redirect";
185 "Usage: channel redirect <channel> <[[context,]exten,]priority>\n"
186 " Redirect an active channel to a specified extension.\n";
187 /*! \todo It would be nice to be able to redirect 2 channels at the same
188 * time like you can with AMI redirect. However, it is not possible to acquire
189 * two channels without the potential for a deadlock with how ast_channel structs
190 * are managed today. Once ast_channel is a refcounted object, this command
191 * will be able to support that. */
194 return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
197 if (a->argc != e->args + 2) {
198 return CLI_SHOWUSAGE;
204 chan = ast_get_channel_by_name_locked(name);
206 ast_cli(a->fd, "Channel '%s' not found\n", name);
210 res = ast_async_parseable_goto(chan, dest);
212 ast_channel_unlock(chan);
215 ast_cli(a->fd, "Channel '%s' successfully redirected to %s\n", name, dest);
217 ast_cli(a->fd, "Channel '%s' failed to be redirected to %s\n", name, dest);
220 return res ? CLI_FAILURE : CLI_SUCCESS;
223 static struct ast_cli_entry cli_cliorig[] = {
224 AST_CLI_DEFINE(handle_orig, "Originate a call"),
225 AST_CLI_DEFINE(handle_redirect, "Redirect a call"),
228 static int unload_module(void)
230 return ast_cli_unregister_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
233 static int load_module(void)
236 res = ast_cli_register_multiple(cli_cliorig, ARRAY_LEN(cli_cliorig));
237 return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
240 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call origination and redirection from the CLI");