Merged revisions 83589 via svnmerge from
[asterisk/asterisk.git] / res / res_clioriginate.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2005 - 2006, Digium, Inc.
5  *
6  * Russell Bryant <russell@digium.com>
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 Russell Bryant <russell@digium.com>
22  *
23  * \brief Originate calls via the CLI
24  * 
25  */
26
27 #include "asterisk.h"
28
29 ASTERISK_FILE_VERSION(__FILE__, "$Revision$");
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/logger.h"
38 #include "asterisk/module.h"
39 #include "asterisk/cli.h"
40 #include "asterisk/utils.h"
41 #include "asterisk/frame.h"
42
43 /*! The timeout for originated calls, in seconds */
44 #define TIMEOUT 30
45
46 static char orig_help[] = 
47 "  There are two ways to use this command. A call can be originated between a\n"
48 "channel and a specific application, or between a channel and an extension in\n"
49 "the dialplan. This is similar to call files or the manager originate action.\n"
50 "Calls originated with this command are given a timeout of 30 seconds.\n\n"
51
52 "Usage1: originate <tech/data> application <appname> [appdata]\n"
53 "  This will originate a call between the specified channel tech/data and the\n"
54 "given application. Arguments to the application are optional. If the given\n"
55 "arguments to the application include spaces, all of the arguments to the\n"
56 "application need to be placed in quotation marks.\n\n"
57
58 "Usage2: originate <tech/data> extension [exten@][context]\n"
59 "  This will originate a call between the specified channel tech/data and the\n"
60 "given extension. If no context is specified, the 'default' context will be\n"
61 "used. If no extension is given, the 's' extension will be used.\n";
62
63 static int handle_orig(int fd, int argc, char *argv[]);
64 static char *complete_orig(const char *line, const char *word, int pos, int state);
65
66 struct ast_cli_entry cli_cliorig[] = {
67         { { "originate", NULL },
68         handle_orig, "Originate a call",
69         orig_help, complete_orig },
70 };
71
72 /*!
73  * \brief orginate a call from the CLI
74  * \param fd file descriptor for cli
75  * \param chan channel to create type/data
76  * \param app application you want to run
77  * \param appdata data for application
78  * \retval RESULT_SUCCESS on success.
79  * \retval RESULT_SHOWUSAGE on failure.
80 */
81 static int orig_app(int fd, const char *chan, const char *app, const char *appdata)
82 {
83         char *chantech;
84         char *chandata;
85         int reason = 0;
86         
87         if (ast_strlen_zero(app))
88                 return RESULT_SHOWUSAGE;
89
90         chandata = ast_strdupa(chan);
91         
92         chantech = strsep(&chandata, "/");
93         if (!chandata) {
94                 ast_cli(fd, "*** No data provided after channel type! ***\n");
95                 return RESULT_SHOWUSAGE;
96         }
97
98         ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, app, appdata, &reason, 1, NULL, NULL, NULL, NULL, NULL);
99
100         return RESULT_SUCCESS;
101 }
102
103 /*!
104  * \brief orginate from extension
105  * \param fd file descriptor for cli
106  * \param chan channel to create type/data
107  * \param data contains exten\@context
108  * \retval RESULT_SUCCESS on success.
109  * \retval RESULT_SHOWUSAGE on failure.
110 */
111 static int orig_exten(int fd, const char *chan, const char *data)
112 {
113         char *chantech;
114         char *chandata;
115         char *exten = NULL;
116         char *context = NULL;
117         int reason = 0;
118
119         chandata = ast_strdupa(chan);
120         
121         chantech = strsep(&chandata, "/");
122         if (!chandata) {
123                 ast_cli(fd, "*** No data provided after channel type! ***\n");
124                 return RESULT_SHOWUSAGE;
125         }
126
127         if (!ast_strlen_zero(data)) {
128                 context = ast_strdupa(data);
129                 exten = strsep(&context, "@");
130         }
131
132         if (ast_strlen_zero(exten))
133                 exten = "s";
134         if (ast_strlen_zero(context))
135                 context = "default";
136         
137         ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 1, NULL, NULL, NULL, NULL, NULL);
138
139         return RESULT_SUCCESS;
140 }
141
142 /*!
143  * \brief handle for orgination app or exten.
144  * \param fd file descriptor
145  * \param argc no of arguements
146  * \param argv contains either application or extension arguements
147  * \retval RESULT_SUCCESS on success.
148  * \retval RESULT_SHOWUSAGE on failure.
149 */
150 static int handle_orig(int fd, int argc, char *argv[])
151 {
152         int res;
153
154         if (ast_strlen_zero(argv[1]) || ast_strlen_zero(argv[2]))
155                 return RESULT_SHOWUSAGE;
156
157         /* ugly, can be removed when CLI entries have ast_module pointers */
158         ast_module_ref(ast_module_info->self);
159
160         if (!strcasecmp("application", argv[2])) {
161                 res = orig_app(fd, argv[1], argv[3], argv[4]);  
162         } else if (!strcasecmp("extension", argv[2])) {
163                 res = orig_exten(fd, argv[1], argv[3]);
164         } else
165                 res = RESULT_SHOWUSAGE;
166
167         ast_module_unref(ast_module_info->self);
168
169         return res;
170 }
171
172 /*!
173  * \brief complete suggestions for orginate command
174  * \param line 
175  * \param word to be completed word
176  * \param pos position
177  * \param state
178  * \retval completed word
179  * \retval NULL on failure
180 */
181 static char *complete_orig(const char *line, const char *word, int pos, int state)
182 {
183         static char *choices[] = { "application", "extension", NULL };
184         char *ret;
185
186         if (pos != 2)
187                 return NULL;
188
189         /* ugly, can be removed when CLI entries have ast_module pointers */
190         ast_module_ref(ast_module_info->self);
191         ret = ast_cli_complete(word, choices, state);
192         ast_module_unref(ast_module_info->self);
193
194         return ret;
195 }
196
197 /*! \brief Unload orginate module */
198 static int unload_module(void)
199 {
200         ast_cli_unregister_multiple(cli_cliorig, sizeof(cli_cliorig) / sizeof(struct ast_cli_entry));
201         return 0;
202 }
203
204 /*! \brief Load orginate module */
205 static int load_module(void)
206 {
207         ast_cli_register_multiple(cli_cliorig, sizeof(cli_cliorig) / sizeof(struct ast_cli_entry));
208         return 0;
209 }
210
211 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call origination from the CLI");