Wed Apr 6 11:29:38 2011

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: 251884 $")
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 /*** DOCUMENTATION
00040    <application name="Exec" language="en_US">
00041       <synopsis>
00042          Executes dialplan application.
00043       </synopsis>
00044       <syntax>
00045          <parameter name="appname" required="true" hasparams="true">
00046             <para>Application name and arguments of the dialplan application to execute.</para>
00047             <argument name="arguments" required="true" />
00048          </parameter>
00049       </syntax>
00050       <description>
00051          <para>Allows an arbitrary application to be invoked even when not
00052          hard coded into the dialplan.  If the underlying application
00053          terminates the dialplan, or if the application cannot be found,
00054          Exec will terminate the dialplan.</para>
00055          <para>To invoke external applications, see the application System.
00056          If you would like to catch any error instead, see TryExec.</para>
00057       </description>
00058    </application>
00059    <application name="TryExec" language="en_US">
00060       <synopsis>
00061          Executes dialplan application, always returning.
00062       </synopsis>
00063       <syntax>
00064          <parameter name="appname" required="true" hasparams="true">
00065             <argument name="arguments" required="true" />
00066          </parameter>
00067       </syntax>
00068       <description>
00069          <para>Allows an arbitrary application to be invoked even when not
00070          hard coded into the dialplan. To invoke external applications
00071          see the application System.  Always returns to the dialplan.
00072          The channel variable TRYSTATUS will be set to one of:
00073          </para>
00074          <variablelist>
00075             <variable name="TRYSTATUS">
00076                <value name="SUCCESS">
00077                   If the application returned zero.
00078                </value>
00079                <value name="FAILED">
00080                   If the application returned non-zero.
00081                </value>
00082                <value name="NOAPP">
00083                   If the application was not found or was not specified.
00084                </value>
00085             </variable>
00086          </variablelist>
00087       </description>
00088    </application>
00089    <application name="ExecIf" language="en_US">
00090       <synopsis>
00091          Executes dialplan application, conditionally.
00092       </synopsis>
00093       <syntax argsep="?">
00094          <parameter name="expression" required="true" />
00095          <parameter name="execapp" required="true" argsep=":">
00096             <argument name="appiftrue" required="true" hasparams="true">
00097                <argument name="args" required="true" />
00098             </argument>
00099             <argument name="appiffalse" required="false" hasparams="true">
00100                <argument name="args" required="true" />
00101             </argument>
00102          </parameter>
00103       </syntax>
00104       <description>
00105          <para>If <replaceable>expr</replaceable> is true, execute and return the
00106          result of <replaceable>appiftrue(args)</replaceable>.</para>
00107          <para>If <replaceable>expr</replaceable> is true, but <replaceable>appiftrue</replaceable> is not found,
00108          then the application will return a non-zero value.</para>
00109       </description>
00110    </application>
00111  ***/
00112 
00113 /* Maximum length of any variable */
00114 #define MAXRESULT 1024
00115 
00116 /*! Note
00117  *
00118  * The key difference between these two apps is exit status.  In a
00119  * nutshell, Exec tries to be transparent as possible, behaving
00120  * in exactly the same way as if the application it calls was
00121  * directly invoked from the dialplan.
00122  *
00123  * TryExec, on the other hand, provides a way to execute applications
00124  * and catch any possible fatal error without actually fatally
00125  * affecting the dialplan.
00126  */
00127 
00128 static const char app_exec[] = "Exec";
00129 static const char app_tryexec[] = "TryExec";
00130 static const char app_execif[] = "ExecIf";
00131 
00132 static int exec_exec(struct ast_channel *chan, const char *data)
00133 {
00134    int res = 0;
00135    char *s, *appname, *endargs;
00136    struct ast_app *app;
00137    struct ast_str *args = NULL;
00138 
00139    if (ast_strlen_zero(data))
00140       return 0;
00141 
00142    s = ast_strdupa(data);
00143    appname = strsep(&s, "(");
00144    if (s) {
00145       endargs = strrchr(s, ')');
00146       if (endargs)
00147          *endargs = '\0';
00148       if ((args = ast_str_create(16))) {
00149          ast_str_substitute_variables(&args, 0, chan, s);
00150       }
00151    }
00152    if (appname) {
00153       app = pbx_findapp(appname);
00154       if (app) {
00155          res = pbx_exec(chan, app, args ? ast_str_buffer(args) : NULL);
00156       } else {
00157          ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
00158          res = -1;
00159       }
00160    }
00161 
00162    ast_free(args);
00163    return res;
00164 }
00165 
00166 static int tryexec_exec(struct ast_channel *chan, const char *data)
00167 {
00168    int res = 0;
00169    char *s, *appname, *endargs;
00170    struct ast_app *app;
00171    struct ast_str *args = NULL;
00172 
00173    if (ast_strlen_zero(data))
00174       return 0;
00175 
00176    s = ast_strdupa(data);
00177    appname = strsep(&s, "(");
00178    if (s) {
00179       endargs = strrchr(s, ')');
00180       if (endargs)
00181          *endargs = '\0';
00182       if ((args = ast_str_create(16))) {
00183          ast_str_substitute_variables(&args, 0, chan, s);
00184       }
00185    }
00186    if (appname) {
00187       app = pbx_findapp(appname);
00188       if (app) {
00189          res = pbx_exec(chan, app, args ? ast_str_buffer(args) : NULL);
00190          pbx_builtin_setvar_helper(chan, "TRYSTATUS", res ? "FAILED" : "SUCCESS");
00191       } else {
00192          ast_log(LOG_WARNING, "Could not find application (%s)\n", appname);
00193          pbx_builtin_setvar_helper(chan, "TRYSTATUS", "NOAPP");
00194       }
00195    }
00196 
00197    ast_free(args);
00198    return 0;
00199 }
00200 
00201 static int execif_exec(struct ast_channel *chan, const char *data)
00202 {
00203    int res = 0;
00204    char *truedata = NULL, *falsedata = NULL, *end, *firstcomma, *firstquestion;
00205    struct ast_app *app = NULL;
00206    AST_DECLARE_APP_ARGS(expr,
00207       AST_APP_ARG(expr);
00208       AST_APP_ARG(remainder);
00209    );
00210    AST_DECLARE_APP_ARGS(apps,
00211       AST_APP_ARG(t);
00212       AST_APP_ARG(f);
00213    );
00214    char *parse = ast_strdupa(data);
00215 
00216    firstcomma = strchr(parse, ',');
00217    firstquestion = strchr(parse, '?');
00218 
00219    if ((firstcomma != NULL && firstquestion != NULL && firstcomma < firstquestion) || (firstquestion == NULL)) {
00220       /* Deprecated syntax */
00221       AST_DECLARE_APP_ARGS(depr,
00222          AST_APP_ARG(expr);
00223          AST_APP_ARG(appname);
00224          AST_APP_ARG(appargs);
00225       );
00226       AST_STANDARD_APP_ARGS(depr, parse);
00227 
00228       ast_log(LOG_WARNING, "Deprecated syntax found.  Please upgrade to using ExecIf(<expr>?%s(%s))\n", depr.appname, depr.appargs);
00229 
00230       /* Make the two syntaxes look the same */
00231       expr.expr = depr.expr;
00232       apps.t = depr.appname;
00233       apps.f = NULL;
00234       truedata = depr.appargs;
00235    } else {
00236       /* Preferred syntax */
00237 
00238       AST_NONSTANDARD_RAW_ARGS(expr, parse, '?');
00239       if (ast_strlen_zero(expr.remainder)) {
00240          ast_log(LOG_ERROR, "Usage: ExecIf(<expr>?<appiftrue>(<args>)[:<appiffalse>(<args)])\n");
00241          return -1;
00242       }
00243 
00244       AST_NONSTANDARD_RAW_ARGS(apps, expr.remainder, ':');
00245 
00246       if (apps.t && (truedata = strchr(apps.t, '('))) {
00247          *truedata++ = '\0';
00248          if ((end = strrchr(truedata, ')'))) {
00249             *end = '\0';
00250          }
00251       }
00252 
00253       if (apps.f && (falsedata = strchr(apps.f, '('))) {
00254          *falsedata++ = '\0';
00255          if ((end = strrchr(falsedata, ')'))) {
00256             *end = '\0';
00257          }
00258       }
00259    }
00260 
00261    if (pbx_checkcondition(expr.expr)) {
00262       if (!ast_strlen_zero(apps.t) && (app = pbx_findapp(apps.t))) {
00263          res = pbx_exec(chan, app, S_OR(truedata, ""));
00264       } else {
00265          ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.t);
00266          res = -1;
00267       }
00268    } else if (!ast_strlen_zero(apps.f)) {
00269       if ((app = pbx_findapp(apps.f))) {
00270          res = pbx_exec(chan, app, S_OR(falsedata, ""));
00271       } else {
00272          ast_log(LOG_WARNING, "Could not find application! (%s)\n", apps.f);
00273          res = -1;
00274       }
00275    }
00276 
00277    return res;
00278 }
00279 
00280 static int unload_module(void)
00281 {
00282    int res;
00283 
00284    res = ast_unregister_application(app_exec);
00285    res |= ast_unregister_application(app_tryexec);
00286    res |= ast_unregister_application(app_execif);
00287 
00288    return res;
00289 }
00290 
00291 static int load_module(void)
00292 {
00293    int res = ast_register_application_xml(app_exec, exec_exec);
00294    res |= ast_register_application_xml(app_tryexec, tryexec_exec);
00295    res |= ast_register_application_xml(app_execif, execif_exec);
00296    return res;
00297 }
00298 
00299 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Executes dialplan applications");

Generated on Wed Apr 6 11:29:38 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7