Fri Jul 24 00:40:56 2009

Asterisk developer's documentation


func_logic.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, Digium, Inc.
00005  * Portions Copyright (C) 2005, Anthony Minessale II
00006  *
00007  * See http://www.asterisk.org for more information about
00008  * the Asterisk project. Please do not directly contact
00009  * any of the maintainers of this project for assistance;
00010  * the project provides a web site, mailing lists and IRC
00011  * channels for your use.
00012  *
00013  * This program is free software, distributed under the terms of
00014  * the GNU General Public License Version 2. See the LICENSE file
00015  * at the top of the source tree.
00016  */
00017 
00018 /*! \file
00019  * 
00020  * \brief Conditional logic dialplan functions
00021  * 
00022  * \author Anthony Minessale II
00023  *
00024  * \ingroup functions
00025  */
00026 
00027 #include "asterisk.h"
00028 
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 168549 $")
00030 
00031 #include "asterisk/module.h"
00032 #include "asterisk/channel.h"
00033 #include "asterisk/pbx.h"
00034 #include "asterisk/utils.h"
00035 #include "asterisk/app.h"
00036 
00037 static int isnull(struct ast_channel *chan, const char *cmd, char *data,
00038         char *buf, size_t len)
00039 {
00040    strcpy(buf, data && *data ? "0" : "1");
00041 
00042    return 0;
00043 }
00044 
00045 static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf,
00046         size_t len)
00047 {
00048    strcpy(buf, data && *data ? "1" : "0");
00049 
00050    return 0;
00051 }
00052 
00053 static int iftime(struct ast_channel *chan, const char *cmd, char *data, char *buf,
00054         size_t len)
00055 {
00056    struct ast_timing timing;
00057    char *expr;
00058    char *iftrue;
00059    char *iffalse;
00060 
00061    data = ast_strip_quoted(data, "\"", "\"");
00062    expr = strsep(&data, "?");
00063    iftrue = strsep(&data, ":");
00064    iffalse = data;
00065 
00066    if (ast_strlen_zero(expr) || !(iftrue || iffalse)) {
00067       ast_log(LOG_WARNING,
00068             "Syntax IFTIME(<timespec>?[<true>][:<false>])\n");
00069       return -1;
00070    }
00071 
00072    if (!ast_build_timing(&timing, expr)) {
00073       ast_log(LOG_WARNING, "Invalid Time Spec.\n");
00074       return -1;
00075    }
00076 
00077    if (iftrue)
00078       iftrue = ast_strip_quoted(iftrue, "\"", "\"");
00079    if (iffalse)
00080       iffalse = ast_strip_quoted(iffalse, "\"", "\"");
00081 
00082    ast_copy_string(buf, ast_check_timing(&timing) ? S_OR(iftrue, "") : S_OR(iffalse, ""), len);
00083 
00084    return 0;
00085 }
00086 
00087 static int acf_if(struct ast_channel *chan, const char *cmd, char *data, char *buf,
00088         size_t len)
00089 {
00090    AST_DECLARE_APP_ARGS(args1,
00091       AST_APP_ARG(expr);
00092       AST_APP_ARG(remainder);
00093    );
00094    AST_DECLARE_APP_ARGS(args2,
00095       AST_APP_ARG(iftrue);
00096       AST_APP_ARG(iffalse);
00097    );
00098    args2.iftrue = args2.iffalse = NULL; /* you have to set these, because if there is nothing after the '?',
00099                                  then args1.remainder will be NULL, not a pointer to a null string, and
00100                                  then any garbage in args2.iffalse will not be cleared, and you'll crash.
00101                                   -- and if you mod the ast_app_separate_args func instead, you'll really
00102                                  mess things up badly, because the rest of everything depends on null args
00103                                  for non-specified stuff. */
00104    
00105    AST_NONSTANDARD_APP_ARGS(args1, data, '?');
00106    AST_NONSTANDARD_APP_ARGS(args2, args1.remainder, ':');
00107 
00108    if (ast_strlen_zero(args1.expr) || !(args2.iftrue || args2.iffalse)) {
00109       ast_log(LOG_WARNING, "Syntax IF(<expr>?[<true>][:<false>])  (expr must be non-null, and either <true> or <false> must be non-null)\n");
00110       ast_log(LOG_WARNING, "      In this case, <expr>='%s', <true>='%s', and <false>='%s'\n", args1.expr, args2.iftrue, args2.iffalse);
00111       return -1;
00112    }
00113 
00114    args1.expr = ast_strip(args1.expr);
00115    if (args2.iftrue)
00116       args2.iftrue = ast_strip(args2.iftrue);
00117    if (args2.iffalse)
00118       args2.iffalse = ast_strip(args2.iffalse);
00119 
00120    ast_copy_string(buf, pbx_checkcondition(args1.expr) ? (S_OR(args2.iftrue, "")) : (S_OR(args2.iffalse, "")), len);
00121 
00122    return 0;
00123 }
00124 
00125 static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf,
00126           size_t len)
00127 {
00128    char *varname;
00129    char *val;
00130 
00131    varname = strsep(&data, "=");
00132    val = data;
00133 
00134    if (ast_strlen_zero(varname) || !val) {
00135       ast_log(LOG_WARNING, "Syntax SET(<varname>=[<value>])\n");
00136       return -1;
00137    }
00138 
00139    varname = ast_strip(varname);
00140    val = ast_strip(val);
00141    pbx_builtin_setvar_helper(chan, varname, val);
00142    ast_copy_string(buf, val, len);
00143 
00144    return 0;
00145 }
00146 
00147 static int acf_import(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
00148 {
00149    AST_DECLARE_APP_ARGS(args,
00150       AST_APP_ARG(channel);
00151       AST_APP_ARG(varname);
00152    );
00153    AST_STANDARD_APP_ARGS(args, data);
00154    buf[0] = 0;
00155    if (!ast_strlen_zero(args.varname)) {
00156       struct ast_channel *chan2 = ast_get_channel_by_name_locked(args.channel);
00157       if (chan2) {
00158          char *s = alloca(strlen(args.varname) + 4);
00159          if (s) {
00160             sprintf(s, "${%s}", args.varname);
00161             pbx_substitute_variables_helper(chan2, s, buf, len);
00162          }
00163          ast_channel_unlock(chan2);
00164       }
00165    }
00166    return 0;
00167 }
00168 
00169 static struct ast_custom_function isnull_function = {
00170    .name = "ISNULL",
00171    .synopsis = "NULL Test: Returns 1 if NULL or 0 otherwise",
00172    .syntax = "ISNULL(<data>)",
00173    .read = isnull,
00174 };
00175 
00176 static struct ast_custom_function set_function = {
00177    .name = "SET",
00178    .synopsis = "SET assigns a value to a channel variable",
00179    .syntax = "SET(<varname>=[<value>])",
00180    .read = set,
00181 };
00182 
00183 static struct ast_custom_function exists_function = {
00184    .name = "EXISTS",
00185    .synopsis = "Existence Test: Returns 1 if exists, 0 otherwise",
00186    .syntax = "EXISTS(<data>)",
00187    .read = exists,
00188 };
00189 
00190 static struct ast_custom_function if_function = {
00191    .name = "IF",
00192    .synopsis =
00193       "Conditional: Returns the data following '?' if true, else the data following ':'",
00194    .syntax = "IF(<expr>?[<true>][:<false>])",
00195    .read = acf_if,
00196 };
00197 
00198 static struct ast_custom_function if_time_function = {
00199    .name = "IFTIME",
00200    .synopsis =
00201       "Temporal Conditional: Returns the data following '?' if true, else the data following ':'",
00202    .syntax = "IFTIME(<timespec>?[<true>][:<false>])",
00203    .read = iftime,
00204 };
00205 
00206 static struct ast_custom_function import_function = {
00207    .name = "IMPORT",
00208    .synopsis =
00209       "Retrieve the value of a variable from another channel\n",
00210    .syntax = "IMPORT(channel,variable)",
00211    .read = acf_import,
00212 };
00213 
00214 static int unload_module(void)
00215 {
00216    int res = 0;
00217 
00218    res |= ast_custom_function_unregister(&isnull_function);
00219    res |= ast_custom_function_unregister(&set_function);
00220    res |= ast_custom_function_unregister(&exists_function);
00221    res |= ast_custom_function_unregister(&if_function);
00222    res |= ast_custom_function_unregister(&if_time_function);
00223    res |= ast_custom_function_unregister(&import_function);
00224 
00225    return res;
00226 }
00227 
00228 static int load_module(void)
00229 {
00230    int res = 0;
00231 
00232    res |= ast_custom_function_register(&isnull_function);
00233    res |= ast_custom_function_register(&set_function);
00234    res |= ast_custom_function_register(&exists_function);
00235    res |= ast_custom_function_register(&if_function);
00236    res |= ast_custom_function_register(&if_time_function);
00237    res |= ast_custom_function_register(&import_function);
00238 
00239    return res;
00240 }
00241 
00242 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Logical dialplan functions");

Generated on Fri Jul 24 00:40:56 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7