merge new_loader_completion branch, including (at least):
[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_orig = { { "originate", NULL }, handle_orig, "Originate a call", orig_help, complete_orig };
67
68 static int orig_app(int fd, const char *chan, const char *app, const char *appdata)
69 {
70         char *chantech;
71         char *chandata;
72         int reason = 0;
73         
74         if (ast_strlen_zero(app))
75                 return RESULT_SHOWUSAGE;
76
77         chandata = ast_strdupa(chan);
78         
79         chantech = strsep(&chandata, "/");
80         if (!chandata) {
81                 ast_cli(fd, "*** No data provided after channel type! ***\n");
82                 return RESULT_SHOWUSAGE;
83         }
84
85         ast_pbx_outgoing_app(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, app, appdata, &reason, 1, NULL, NULL, NULL, NULL, NULL);
86
87         return RESULT_SUCCESS;
88 }
89
90 static int orig_exten(int fd, const char *chan, const char *data)
91 {
92         char *chantech;
93         char *chandata;
94         char *exten = NULL;
95         char *context = NULL;
96         int reason = 0;
97
98         chandata = ast_strdupa(chan);
99         
100         chantech = strsep(&chandata, "/");
101         if (!chandata) {
102                 ast_cli(fd, "*** No data provided after channel type! ***\n");
103                 return RESULT_SHOWUSAGE;
104         }
105
106         if (!ast_strlen_zero(data)) {
107                 context = ast_strdupa(data);
108                 exten = strsep(&context, "@");
109         }
110
111         if (ast_strlen_zero(exten))
112                 exten = "s";
113         if (ast_strlen_zero(context))
114                 context = "default";
115         
116         ast_pbx_outgoing_exten(chantech, AST_FORMAT_SLINEAR, chandata, TIMEOUT * 1000, context, exten, 1, &reason, 1, NULL, NULL, NULL, NULL, NULL);
117
118         return RESULT_SUCCESS;
119 }
120
121 static int handle_orig(int fd, int argc, char *argv[])
122 {
123         int res;
124
125         if (ast_strlen_zero(argv[1]) || ast_strlen_zero(argv[2]))
126                 return RESULT_SHOWUSAGE;
127
128         /* ugly, can be removed when CLI entries have ast_module pointers */
129         ast_module_ref(ast_module_info->self);
130
131         if (!strcasecmp("application", argv[2])) {
132                 res = orig_app(fd, argv[1], argv[3], argv[4]);  
133         } else if (!strcasecmp("extension", argv[2])) {
134                 res = orig_exten(fd, argv[1], argv[3]);
135         } else
136                 res = RESULT_SHOWUSAGE;
137
138         ast_module_unref(ast_module_info->self);
139
140         return res;
141 }
142
143 static char *complete_orig(const char *line, const char *word, int pos, int state)
144 {
145         static char *choices[] = { "application", "extension", NULL };
146         char *ret;
147
148         if (pos != 2)
149                 return NULL;
150
151         /* ugly, can be removed when CLI entries have ast_module pointers */
152         ast_module_ref(ast_module_info->self);
153         ret = ast_cli_complete(word, choices, state);
154         ast_module_unref(ast_module_info->self);
155
156         return ret;
157 }
158
159 static int unload_module(void)
160 {
161         return ast_cli_unregister(&cli_orig);
162 }
163
164 static int load_module(void)
165 {
166         return ast_cli_register(&cli_orig);
167 }
168
169 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Call origination from the CLI");