Asterisk - The Open Source Telephony Project GIT-master-7e7a603
func_logic.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2006, Digium, Inc.
5 * Portions Copyright (C) 2005, Anthony Minessale II
6 *
7 * See http://www.asterisk.org for more information about
8 * the Asterisk project. Please do not directly contact
9 * any of the maintainers of this project for assistance;
10 * the project provides a web site, mailing lists and IRC
11 * channels for your use.
12 *
13 * This program is free software, distributed under the terms of
14 * the GNU General Public License Version 2. See the LICENSE file
15 * at the top of the source tree.
16 */
17
18/*! \file
19 *
20 * \brief Conditional logic dialplan functions
21 *
22 * \author Anthony Minessale II
23 *
24 * \ingroup functions
25 */
26
27/*** MODULEINFO
28 <support_level>core</support_level>
29 ***/
30
31#include "asterisk.h"
32
33#include "asterisk/module.h"
34#include "asterisk/channel.h"
35#include "asterisk/pbx.h"
36#include "asterisk/utils.h"
37#include "asterisk/app.h"
38
39/*** DOCUMENTATION
40 <function name="ISNULL" language="en_US">
41 <synopsis>
42 Check if a value is NULL.
43 </synopsis>
44 <syntax>
45 <parameter name="data" required="true" />
46 </syntax>
47 <description>
48 <para>Returns <literal>1</literal> if NULL or <literal>0</literal> otherwise.</para>
49 </description>
50 </function>
51 <function name="SET" language="en_US">
52 <synopsis>
53 SET assigns a value to a channel variable.
54 </synopsis>
55 <syntax argsep="=">
56 <parameter name="varname" required="true" />
57 <parameter name="value" />
58 </syntax>
59 <description>
60 </description>
61 </function>
62 <function name="EXISTS" language="en_US">
63 <synopsis>
64 Test the existence of a value.
65 </synopsis>
66 <syntax>
67 <parameter name="data" required="true" />
68 </syntax>
69 <description>
70 <para>Returns <literal>1</literal> if exists, <literal>0</literal> otherwise.</para>
71 </description>
72 </function>
73 <function name="IF" language="en_US">
74 <synopsis>
75 Check for an expression.
76 </synopsis>
77 <syntax argsep="?">
78 <parameter name="expression" required="true" />
79 <parameter name="retvalue" argsep=":" required="true">
80 <argument name="true" />
81 <argument name="false" />
82 </parameter>
83 </syntax>
84 <description>
85 <para>Returns the data following <literal>?</literal> if true, else the data following <literal>:</literal></para>
86 </description>
87 </function>
88 <function name="IFTIME" language="en_US">
89 <synopsis>
90 Temporal Conditional.
91 </synopsis>
92 <syntax argsep="?">
93 <parameter name="timespec" required="true" />
94 <parameter name="retvalue" required="true" argsep=":">
95 <argument name="true" />
96 <argument name="false" />
97 </parameter>
98 </syntax>
99 <description>
100 <para>Returns the data following <literal>?</literal> if true, else the data following <literal>:</literal></para>
101 </description>
102 </function>
103 <function name="IMPORT" language="en_US">
104 <synopsis>
105 Retrieve the value of a variable from another channel.
106 </synopsis>
107 <syntax>
108 <parameter name="channel" required="true" />
109 <parameter name="variable" required="true" />
110 </syntax>
111 <description>
112 </description>
113 </function>
114 <function name="DELETE" language="en_US">
115 <synopsis>
116 Deletes a specified channel variable.
117 </synopsis>
118 <syntax>
119 <parameter name="varname" required="true">
120 <para>Channel variable name</para>
121 </parameter>
122 </syntax>
123 <description>
124 <para>Delete the channel variable specified in <replaceable>varname</replaceable>.
125 Will succeed if the channel variable exists or not.</para>
126 </description>
127 <see-also>
128 <ref type="function">GLOBAL_DELETE</ref>
129 </see-also>
130 </function>
131 <function name="VARIABLE_EXISTS" language="en_US">
132 <synopsis>
133 Check if a dialplan variable exists or not.
134 </synopsis>
135 <syntax>
136 <parameter name="varname" required="true">
137 <para>Channel variable name</para>
138 </parameter>
139 </syntax>
140 <description>
141 <para>Returns <literal>1</literal> if channel variable exists or <literal>0</literal> otherwise.</para>
142 </description>
143 <see-also>
144 <ref type="function">GLOBAL_EXISTS</ref>
145 </see-also>
146 </function>
147 ***/
148
149static int isnull(struct ast_channel *chan, const char *cmd, char *data,
150 char *buf, size_t len)
151{
152 strcpy(buf, data && *data ? "0" : "1");
153
154 return 0;
155}
156
157static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf,
158 size_t len)
159{
160 strcpy(buf, data && *data ? "1" : "0");
161
162 return 0;
163}
164
165static int iftime(struct ast_channel *chan, const char *cmd, char *data, char *buf,
166 size_t len)
167{
168 struct ast_timing timing;
169 char *expr;
170 char *iftrue;
171 char *iffalse;
172
173 data = ast_strip_quoted(data, "\"", "\"");
174 expr = strsep(&data, "?");
175 iftrue = strsep(&data, ":");
176 iffalse = data;
177
178 if (ast_strlen_zero(expr) || !(iftrue || iffalse)) {
180 "Syntax IFTIME(<timespec>?[<true>][:<false>])\n");
181 return -1;
182 }
183
184 if (!ast_build_timing(&timing, expr)) {
185 ast_log(LOG_WARNING, "Invalid Time Spec.\n");
186 ast_destroy_timing(&timing);
187 return -1;
188 }
189
190 if (iftrue)
191 iftrue = ast_strip_quoted(iftrue, "\"", "\"");
192 if (iffalse)
193 iffalse = ast_strip_quoted(iffalse, "\"", "\"");
194
195 ast_copy_string(buf, ast_check_timing(&timing) ? S_OR(iftrue, "") : S_OR(iffalse, ""), len);
196 ast_destroy_timing(&timing);
197
198 return 0;
199}
200
201static int acf_if(struct ast_channel *chan, const char *cmd, char *data, char *buf,
202 size_t len)
203{
205 AST_APP_ARG(expr);
206 AST_APP_ARG(remainder);
207 );
209 AST_APP_ARG(iftrue);
210 AST_APP_ARG(iffalse);
211 );
212 args2.iftrue = args2.iffalse = NULL; /* you have to set these, because if there is nothing after the '?',
213 then args1.remainder will be NULL, not a pointer to a null string, and
214 then any garbage in args2.iffalse will not be cleared, and you'll crash.
215 -- and if you mod the ast_app_separate_args func instead, you'll really
216 mess things up badly, because the rest of everything depends on null args
217 for non-specified stuff. */
218
219 AST_NONSTANDARD_APP_ARGS(args1, data, '?');
220 AST_NONSTANDARD_APP_ARGS(args2, args1.remainder, ':');
221
222 if (ast_strlen_zero(args1.expr) || !(args2.iftrue || args2.iffalse)) {
223 ast_debug(1, "<expr>='%s', <true>='%s', and <false>='%s'\n", args1.expr, args2.iftrue, args2.iffalse);
224 return -1;
225 }
226
227 args1.expr = ast_strip(args1.expr);
228 if (args2.iftrue)
229 args2.iftrue = ast_strip(args2.iftrue);
230 if (args2.iffalse)
231 args2.iffalse = ast_strip(args2.iffalse);
232
233 ast_copy_string(buf, pbx_checkcondition(args1.expr) ? (S_OR(args2.iftrue, "")) : (S_OR(args2.iffalse, "")), len);
234
235 return 0;
236}
237
238static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf,
239 size_t len)
240{
241 char *varname;
242 char *val;
243
244 varname = strsep(&data, "=");
245 val = data;
246
247 if (ast_strlen_zero(varname) || !val) {
248 ast_log(LOG_WARNING, "Syntax SET(<varname>=[<value>])\n");
249 return -1;
250 }
251
252 varname = ast_strip(varname);
253 val = ast_strip(val);
254 pbx_builtin_setvar_helper(chan, varname, val);
256
257 return 0;
258}
259
260static int set2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
261{
262 if (len > -1) {
263 ast_str_make_space(str, len == 0 ? strlen(data) : len);
264 }
265 return set(chan, cmd, data, ast_str_buffer(*str), ast_str_size(*str));
266}
267
268static int import_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **str, ssize_t len)
269{
271 AST_APP_ARG(channel);
272 AST_APP_ARG(varname);
273 );
275 if (buf) {
276 *buf = '\0';
277 }
278
279 if (!ast_strlen_zero(args.varname)) {
280 struct ast_channel *chan2;
281
282 if ((chan2 = ast_channel_get_by_name(args.channel))) {
283 char *s = ast_alloca(strlen(args.varname) + 4);
284 sprintf(s, "${%s}", args.varname);
285 ast_channel_lock(chan2);
286 if (buf) {
288 } else {
290 }
291 ast_channel_unlock(chan2);
292 chan2 = ast_channel_unref(chan2);
293 }
294 }
295
296 return 0;
297}
298
299static int import_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
300{
301 return import_helper(chan, cmd, data, buf, NULL, len);
302}
303
304static int import_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
305{
306 return import_helper(chan, cmd, data, NULL, str, len);
307}
308
309static int delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
310{
312
313 return 0;
314}
315
316static int variable_exists_read(struct ast_channel *chan, const char *cmd, char *data,
317 char *buf, size_t len)
318{
319 const char *var = pbx_builtin_getvar_helper(chan, data);
320
321 strcpy(buf, var ? "1" : "0");
322
323 return 0;
324}
325
327 .name = "ISNULL",
328 .read = isnull,
329 .read_max = 2,
330};
331
333 .name = "SET",
334 .read = set,
335 .read2 = set2,
336};
337
339 .name = "EXISTS",
340 .read = exists,
341 .read_max = 2,
342};
343
345 .name = "IF",
346 .read = acf_if,
347};
348
350 .name = "IFTIME",
351 .read = iftime,
352};
353
355 .name = "IMPORT",
356 .read = import_read,
357 .read2 = import_read2,
358};
359
361 .name = "DELETE",
362 .write = delete_write,
363};
364
366 .name = "VARIABLE_EXISTS",
367 .read = variable_exists_read,
368};
369
370static int unload_module(void)
371{
372 int res = 0;
373
382
383 return res;
384}
385
386static int load_module(void)
387{
388 int res = 0;
389
398
399 return res;
400}
401
402AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Logical dialplan functions");
const char * str
Definition: app_jack.c:147
#define var
Definition: ast_expr2f.c:605
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
#define ast_channel_lock(chan)
Definition: channel.h:2922
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2958
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
#define ast_channel_unlock(chan)
Definition: channel.h:2923
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static int import_read2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
Definition: func_logic.c:304
static struct ast_custom_function exists_function
Definition: func_logic.c:338
static struct ast_custom_function variable_exists_function
Definition: func_logic.c:365
static struct ast_custom_function import_function
Definition: func_logic.c:354
static struct ast_custom_function set_function
Definition: func_logic.c:332
static int set2(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **str, ssize_t len)
Definition: func_logic.c:260
static int import_helper(struct ast_channel *chan, const char *cmd, char *data, char *buf, struct ast_str **str, ssize_t len)
Definition: func_logic.c:268
static struct ast_custom_function if_function
Definition: func_logic.c:344
static struct ast_custom_function delete_function
Definition: func_logic.c:360
static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:238
static struct ast_custom_function if_time_function
Definition: func_logic.c:349
static int variable_exists_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:316
static struct ast_custom_function isnull_function
Definition: func_logic.c:326
static int delete_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_logic.c:309
static int load_module(void)
Definition: func_logic.c:386
static int unload_module(void)
Definition: func_logic.c:370
static int iftime(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:165
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:157
static int isnull(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:149
static int acf_if(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:201
static int import_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:299
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the 'nonstandard' argument separation process for an application.
char * strsep(char **str, const char *delims)
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Core PBX routines and definitions.
int ast_build_timing(struct ast_timing *i, const char *info_in)
Construct a timing bitmap, for use in time-based conditionals.
Definition: extconf.c:3806
int ast_check_timing(const struct ast_timing *i)
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified.
Definition: extconf.c:4000
int ast_destroy_timing(struct ast_timing *i)
Deallocates memory structures associated with a timing bitmap.
Definition: pbx_timing.c:279
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1558
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:8282
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: ael_main.c:211
#define NULL
Definition: resample.c:96
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: utils.c:1818
#define ast_str_make_space(buf, new_len)
Definition: strings.h:828
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:742
Main Channel structure associated with a channel.
const char * data
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Support for dynamic strings.
Definition: strings.h:623
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
const char * args
Utility functions.