Applications no longer need to call ast_module_user_add and ast_module_user_remove...
[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         char *s, *appname, *endargs, args[MAXRESULT] = "";
95         struct ast_app *app;
96
97         if (ast_strlen_zero(data))
98                 return 0;
99         
100         s = ast_strdupa(data);
101         appname = strsep(&s, "(");
102         if (s) {
103                 endargs = strrchr(s, ')');
104                 if (endargs)
105                         *endargs = '\0';
106                 pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
107         }
108         if (appname) {
109                 app = pbx_findapp(appname);
110                 if (app) {
111                         res = pbx_exec(chan, app, args);
112                 } else {
113                         ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
114                         res = -1;
115                 }
116         }
117
118         return res;
119 }
120
121 static int tryexec_exec(struct ast_channel *chan, void *data)
122 {
123         int res = 0;
124         char *s, *appname, *endargs, args[MAXRESULT] = "";
125         struct ast_app *app;
126
127         if (ast_strlen_zero(data))
128                 return 0;
129
130         s = ast_strdupa(data);
131         appname = strsep(&s, "(");
132         if (s) {
133                 endargs = strrchr(s, ')');
134                 if (endargs)
135                         *endargs = '\0';
136                 pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
137         }
138         if (appname) {
139                 app = pbx_findapp(appname);
140                 if (app) {
141                         res = pbx_exec(chan, app, args);
142                         pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
143                 } else {
144                         ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
145                         pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
146                 }
147         }
148
149         return 0;
150 }
151
152 static int execif_exec(struct ast_channel *chan, void *data)
153 {
154         int res = 0;
155         char *myapp = NULL;
156         char *mydata = NULL;
157         char *expr = NULL;
158         struct ast_app *app = NULL;
159
160         expr = ast_strdupa(data);
161
162         if ((myapp = strchr(expr,'|'))) {
163                 *myapp = '\0';
164                 myapp++;
165                 if ((mydata = strchr(myapp,'|'))) {
166                         *mydata = '\0';
167                         mydata++;
168                 } else
169                         mydata = "";
170
171                 if (pbx_checkcondition(expr)) { 
172                         if ((app = pbx_findapp(myapp))) {
173                                 res = pbx_exec(chan, app, mydata);
174                         } else {
175                                 ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
176                                 res = -1;
177                         }
178                 }
179         } else {
180                 ast_log(LOG_ERROR,"Invalid Syntax.\n");
181                 res = -1;
182         }
183
184         return res;
185 }
186
187 static int unload_module(void)
188 {
189         int res;
190
191         res = ast_unregister_application(app_exec);
192         res |= ast_unregister_application(app_tryexec);
193         res |= ast_unregister_application(app_execif);
194
195         return res;
196 }
197
198 static int load_module(void)
199 {
200         int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
201         res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
202         res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
203         return res;
204 }
205
206 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");