It is no longer required for each module that deals with a channel to call ast_module...
[asterisk/asterisk.git] / apps / app_exec.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (c) 2004 - 2005, Tilghman Lesher.  All rights reserved.
5  * Portions copyright (c) 2006, Philipp Dunkel.
6  *
7  * Tilghman Lesher <app_exec__v002@the-tilghman.com>
8  *
9  * This code is released by the author with no restrictions on usage.
10  *
11  * See http://www.asterisk.org for more information about
12  * the Asterisk project. Please do not directly contact
13  * any of the maintainers of this project for assistance;
14  * the project provides a web site, mailing lists and IRC
15  * channels for your use.
16  *
17  */
18
19 /*! \file
20  *
21  * \brief Exec application
22  *
23  * \author Tilghman Lesher <app_exec__v002@the-tilghman.com>
24  * \author Philipp Dunkel <philipp.dunkel@ebox.at>
25  *
26  * \ingroup applications
27  */
28
29 #include "asterisk.h"
30
31 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <string.h>
37
38 #include "asterisk/file.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/options.h"
41 #include "asterisk/channel.h"
42 #include "asterisk/pbx.h"
43 #include "asterisk/module.h"
44
45 /* Maximum length of any variable */
46 #define MAXRESULT       1024
47
48 /*! Note
49  *
50  * The key difference between these two apps is exit status.  In a
51  * nutshell, Exec tries to be transparent as possible, behaving
52  * in exactly the same way as if the application it calls was
53  * directly invoked from the dialplan.
54  *
55  * TryExec, on the other hand, provides a way to execute applications
56  * and catch any possible fatal error without actually fatally
57  * affecting the dialplan.
58  */
59
60 static char *app_exec = "Exec";
61 static char *exec_synopsis = "Executes dialplan application";
62 static char *exec_descrip =
63 "Usage: Exec(appname(arguments))\n"
64 "  Allows an arbitrary application to be invoked even when not\n"
65 "hardcoded into the dialplan.  If the underlying application\n"
66 "terminates the dialplan, or if the application cannot be found,\n"
67 "Exec will terminate the dialplan.\n"
68 "  To invoke external applications, see the application System.\n"
69 "  If you would like to catch any error instead, see TryExec.\n";
70
71 static char *app_tryexec = "TryExec";
72 static char *tryexec_synopsis = "Executes dialplan application, always returning";
73 static char *tryexec_descrip =
74 "Usage: TryExec(appname(arguments))\n"
75 "  Allows an arbitrary application to be invoked even when not\n"
76 "hardcoded into the dialplan. To invoke external applications\n"
77 "see the application System.  Always returns to the dialplan.\n"
78 "The channel variable TRYSTATUS will be set to:\n"
79 "    SUCCESS   if the application returned zero\n"
80 "    FAILED    if the application returned non-zero\n"
81 "    NOAPP     if the application was not found or was not specified\n";
82
83 static char *app_execif = "ExecIf";
84 static char *execif_synopsis = "Executes dialplan application, conditionally";
85 static char *execif_descrip = 
86 "Usage:  ExecIF (<expr>|<app>|<data>)\n"
87 "If <expr> is true, execute and return the result of <app>(<data>).\n"
88 "If <expr> is true, but <app> is not found, then the application\n"
89 "will return a non-zero value.\n";
90
91 static int exec_exec(struct ast_channel *chan, void *data)
92 {
93         int res=0;
94         struct ast_module_user *u;
95         char *s, *appname, *endargs, args[MAXRESULT] = "";
96         struct ast_app *app;
97
98         if (ast_strlen_zero(data))
99                 return 0;
100
101         u = ast_module_user_add(chan);
102         
103         s = ast_strdupa(data);
104         appname = strsep(&s, "(");
105         if (s) {
106                 endargs = strrchr(s, ')');
107                 if (endargs)
108                         *endargs = '\0';
109                 pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
110         }
111         if (appname) {
112                 app = pbx_findapp(appname);
113                 if (app) {
114                         res = pbx_exec(chan, app, args);
115                 } else {
116                         ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
117                         res = -1;
118                 }
119         }
120
121         ast_module_user_remove(u);
122
123         return res;
124 }
125
126 static int tryexec_exec(struct ast_channel *chan, void *data)
127 {
128         int res=0;
129         struct ast_module_user *u;
130         char *s, *appname, *endargs, args[MAXRESULT] = "";
131         struct ast_app *app;
132
133         if (ast_strlen_zero(data))
134                 return 0;
135
136         u = ast_module_user_add(chan);
137
138         s = ast_strdupa(data);
139         appname = strsep(&s, "(");
140         if (s) {
141                 endargs = strrchr(s, ')');
142                 if (endargs)
143                         *endargs = '\0';
144                 pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
145         }
146         if (appname) {
147                 app = pbx_findapp(appname);
148                 if (app) {
149                         res = pbx_exec(chan, app, args);
150                         pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
151                 } else {
152                         ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
153                         pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
154                 }
155         }
156
157         ast_module_user_remove(u);
158
159         return 0;
160 }
161
162 static int execif_exec(struct ast_channel *chan, void *data)
163 {
164         int res = 0;
165         struct ast_module_user *u;
166         char *myapp = NULL;
167         char *mydata = NULL;
168         char *expr = NULL;
169         struct ast_app *app = NULL;
170
171         u = ast_module_user_add(chan);
172
173         expr = ast_strdupa(data);
174
175         if ((myapp = strchr(expr,'|'))) {
176                 *myapp = '\0';
177                 myapp++;
178                 if ((mydata = strchr(myapp,'|'))) {
179                         *mydata = '\0';
180                         mydata++;
181                 } else
182                         mydata = "";
183
184                 if (pbx_checkcondition(expr)) { 
185                         if ((app = pbx_findapp(myapp))) {
186                                 res = pbx_exec(chan, app, mydata);
187                         } else {
188                                 ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
189                                 res = -1;
190                         }
191                 }
192         } else {
193                 ast_log(LOG_ERROR,"Invalid Syntax.\n");
194                 res = -1;
195         }
196                 
197         ast_module_user_remove(u);
198
199         return res;
200 }
201
202 static int unload_module(void)
203 {
204         int res;
205
206         res = ast_unregister_application(app_exec);
207         res |= ast_unregister_application(app_tryexec);
208         res |= ast_unregister_application(app_execif);
209
210         return res;
211 }
212
213 static int load_module(void)
214 {
215         int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
216         res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
217         res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
218         return res;
219 }
220
221 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");