Wed Oct 28 11:45:25 2009

Asterisk developer's documentation


app_exec.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (c) 2004 - 2005, Tilghman Lesher.  All rights reserved.
00005  * Portions copyright (c) 2006, Philipp Dunkel.
00006  *
00007  * Tilghman Lesher <app_exec__v002@the-tilghman.com>
00008  *
00009  * This code is released by the author with no restrictions on usage.
00010  *
00011  * See http://www.asterisk.org for more information about
00012  * the Asterisk project. Please do not directly contact
00013  * any of the maintainers of this project for assistance;
00014  * the project provides a web site, mailing lists and IRC
00015  * channels for your use.
00016  *
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Exec application
00022  *
00023  * \author Tilghman Lesher <app_exec__v002@the-tilghman.com>
00024  * \author Philipp Dunkel <philipp.dunkel@ebox.at>
00025  *
00026  * \ingroup applications
00027  */
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 120905 $")
00032 
00033 #include "asterisk/file.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/module.h"
00037 #include "asterisk/app.h"
00038 
00039 /* Maximum length of any variable */
00040 #define MAXRESULT 1024
00041 
00042 /*! Note
00043  *
00044  * The key difference between these two apps is exit status.  In a
00045  * nutshell, Exec tries to be transparent as possible, behaving
00046  * in exactly the same way as if the application it calls was
00047  * directly invoked from the dialplan.
00048  *
00049  * TryExec, on the other hand, provides a way to execute applications
00050  * and catch any possible fatal error without actually fatally
00051  * affecting the dialplan.
00052  */
00053 
00054 static char *app_exec = "Exec";
00055 static char *exec_synopsis = "Executes dialplan application";
00056 static char *exec_descrip =
00057 "  Exec(appname(arguments)):\n"
00058 "Allows an arbitrary application to be invoked even when not\n"
00059 "hardcoded into the dialplan.  If the underlying application\n"
00060 "terminates the dialplan, or if the application cannot be found,\n"
00061 "Exec will terminate the dialplan.\n"
00062 "  To invoke external applications, see the application System.\n"
00063 "  If you would like to catch any error instead, see TryExec.\n";
00064 
00065 static char *app_tryexec = "TryExec";
00066 static char *tryexec_synopsis = "Executes dialplan application, always returning";
00067 static char *tryexec_descrip =
00068 "  TryExec(appname(arguments)):\n"
00069 "Allows an arbitrary application to be invoked even when not\n"
00070 "hardcoded into the dialplan. To invoke external applications\n"
00071 "see the application System.  Always returns to the dialplan.\n"
00072 "The channel variable TRYSTATUS will be set to one of:\n"
00073 "    SUCCESS   if the application returned zero\n"
00074 "    FAILED    if the application returned non-zero\n"
00075 "    NOAPP     if the application was not found or was not specified\n";
00076 
00077 static char *app_execif = "ExecIf";
00078 static char *execif_synopsis = "Executes dialplan application, conditionally";
00079 static char *execif_descrip =
00080 "  ExecIF (<expr>?<appiftrue>(<args>)[:<appiffalse>(<args>)])\n"
00081 "If <expr> is true, execute and return the result of <appiftrue>(<args>).\n"
00082 "If <expr> is true, but <appiftrue> is not found, then the application\n"
00083 "will return a non-zero value.\n";
00084 
00085 static int exec_exec(struct ast_channel *chan, void *data)
00086 {
00087    int res = 0;
00088    char *s, *appname, *endargs, args[MAXRESULT];
00089    struct ast_app *app;
00090 
00091    if (ast_strlen_zero(data))
00092       return 0;
00093 
00094    s = ast_strdupa(data);
00095    args[0] = 0;
00096    appname = strsep(&s, "(");
00097    if (s) {
00098       endargs = strrchr(s, ')');
00099       if (endargs)
00100          *endargs = '\0';
00101       pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
00102    }
00103    if (appname) {
00104       app = pbx_findapp(appname);
00105       if (app) {
00106          res = pbx_exec(chan, app, args);
00107       } else {
00108          ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
00109          res = -1;
00110       }
00111    }
00112 
00113    return res;
00114 }
00115 
00116 static int tryexec_exec(struct ast_channel *chan, void *data)
00117 {
00118    int res = 0;
00119    char *s, *appname, *endargs, args[MAXRESULT];
00120    struct ast_app *app;
00121 
00122    if (ast_strlen_zero(data))
00123       return 0;
00124 
00125    s = ast_strdupa(data);
00126    args[0] = 0;
00127    appname = strsep(&s, "(");
00128    if (s) {
00129       endargs = strrchr(s, ')');
00130       if (endargs)
00131          *endargs = '\0';
00132       pbx_substitute_variables_helper(chan, s, args, MAXRESULT - 1);
00133    }
00134    if (appname) {
00135       app = pbx_findapp(appname);
00136       if (app) {
00137          res = pbx_exec(chan, app, args);
00138          pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
00139       } else {
00140          ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
00141          pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
00142       }
00143    }
00144 
00145    return 0;
00146 }
00147 
00148 static int execif_exec(struct ast_channel *chan, void *data)
00149 {
00150    int res = 0;
00151    char *truedata = NULL, *falsedata = NULL, *end, *firstcomma, *firstquestion;
00152    struct ast_app *app = NULL;
00153    AST_DECLARE_APP_ARGS(expr,
00154       AST_APP_ARG(expr);
00155       AST_APP_ARG(remainder);
00156    );
00157    AST_DECLARE_APP_ARGS(apps,
00158       AST_APP_ARG(t);
00159       AST_APP_ARG(f);
00160    );
00161    char *parse = ast_strdupa(data);
00162 
00163    firstcomma = strchr(parse, ',');
00164    firstquestion = strchr(parse, '?');
00165 
00166    if ((firstcomma != NULL && firstquestion != NULL && firstcomma < firstquestion) || (firstquestion == NULL)) {
00167       /* Deprecated syntax */
00168       AST_DECLARE_APP_ARGS(depr,
00169          AST_APP_ARG(expr);
00170          AST_APP_ARG(appname);
00171          AST_APP_ARG(appargs);
00172       );
00173       AST_STANDARD_APP_ARGS(depr, parse);
00174 
00175       ast_log(LOG_WARNING, "Deprecated syntax found.  Please upgrade to using ExecIf(<expr>?%s(%s))\n", depr.appname, depr.appargs);
00176 
00177       /* Make the two syntaxes look the same */
00178       expr.expr = depr.expr;
00179       apps.t = depr.appname;
00180       apps.f = NULL;
00181       truedata = depr.appargs;
00182    } else {
00183       /* Preferred syntax */
00184 
00185       AST_NONSTANDARD_APP_ARGS(expr, parse, '?');
00186       if (ast_strlen_zero(expr.remainder)) {
00187          ast_log(LOG_ERROR, "Usage: ExecIf(<expr>?<appiftrue>(<args>)[:<appiffalse>(<args)])\n");
00188          return -1;
00189       }
00190 
00191       AST_NONSTANDARD_APP_ARGS(apps, expr.remainder, ':');
00192 
00193       if (apps.t && (truedata = strchr(apps.t, '('))) {
00194          *truedata++ = '\0';
00195          if ((end = strrchr(truedata, ')'))) {
00196             *end = '\0';
00197          }
00198       }
00199 
00200       if (apps.f && (falsedata = strchr(apps.f, '('))) {
00201          *falsedata++ = '\0';
00202          if ((end = strrchr(falsedata, ')'))) {
00203             *end = '\0';
00204          }
00205       }
00206    }
00207 
00208    if (pbx_checkcondition(expr.expr)) {
00209       if (!ast_strlen_zero(apps.t) && (app = pbx_findapp(apps.t))) {
00210          res = pbx_exec(chan, app, S_OR(truedata, ""));
00211       } else {
00212          ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.t);
00213          res = -1;
00214       }
00215    } else if (!ast_strlen_zero(apps.f)) {
00216       if ((app = pbx_findapp(apps.f))) {
00217          res = pbx_exec(chan, app, S_OR(falsedata, ""));
00218       } else {
00219          ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.f);
00220          res = -1;
00221       }
00222    }
00223 
00224    return res;
00225 }
00226 
00227 static int unload_module(void)
00228 {
00229    int res;
00230 
00231    res = ast_unregister_application(app_exec);
00232    res |= ast_unregister_application(app_tryexec);
00233    res |= ast_unregister_application(app_execif);
00234 
00235    return res;
00236 }
00237 
00238 static int load_module(void)
00239 {
00240    int res = ast_register_application(app_exec, exec_exec, exec_synopsis, exec_descrip);
00241    res |= ast_register_application(app_tryexec, tryexec_exec, tryexec_synopsis, tryexec_descrip);
00242    res |= ast_register_application(app_execif, execif_exec, execif_synopsis, execif_descrip);
00243    return res;
00244 }
00245 
00246 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");

Generated on Wed Oct 28 11:45:25 2009 for Asterisk - the Open Source PBX by  doxygen 1.5.6