finish const-ifying ast_func_read()
[asterisk/asterisk.git] / funcs / func_logic.c
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
25 #include "asterisk.h"
26
27 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33
34 #include "asterisk/module.h"
35 #include "asterisk/channel.h"
36 #include "asterisk/pbx.h"
37 #include "asterisk/logger.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/app.h"
40
41 static int isnull(struct ast_channel *chan, const char *cmd, char *data,
42                   char *buf, size_t len)
43 {
44         strcpy(buf, data && *data ? "0" : "1");
45
46         return 0;
47 }
48
49 static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf,
50                   size_t len)
51 {
52         strcpy(buf, data && *data ? "1" : "0");
53
54         return 0;
55 }
56
57 static int iftime(struct ast_channel *chan, const char *cmd, char *data, char *buf,
58                   size_t len)
59 {
60         struct ast_timing timing;
61         char *expr;
62         char *iftrue;
63         char *iffalse;
64
65         data = ast_strip_quoted(data, "\"", "\"");
66         expr = strsep(&data, "?");
67         iftrue = strsep(&data, ":");
68         iffalse = data;
69
70         if (ast_strlen_zero(expr) || !(iftrue || iffalse)) {
71                 ast_log(LOG_WARNING,
72                                 "Syntax IFTIME(<timespec>?[<true>][:<false>])\n");
73                 return -1;
74         }
75
76         if (!ast_build_timing(&timing, expr)) {
77                 ast_log(LOG_WARNING, "Invalid Time Spec.\n");
78                 return -1;
79         }
80
81         if (iftrue)
82                 iftrue = ast_strip_quoted(iftrue, "\"", "\"");
83         if (iffalse)
84                 iffalse = ast_strip_quoted(iffalse, "\"", "\"");
85
86         ast_copy_string(buf, ast_check_timing(&timing) ? iftrue : iffalse, len);
87
88         return 0;
89 }
90
91 static int acf_if(struct ast_channel *chan, const char *cmd, char *data, char *buf,
92                   size_t len)
93 {
94         char *expr;
95         char *iftrue;
96         char *iffalse;
97
98         data = ast_strip_quoted(data, "\"", "\"");
99         expr = strsep(&data, "?");
100         iftrue = strsep(&data, ":");
101         iffalse = data;
102
103         if (ast_strlen_zero(expr) || !(iftrue || iffalse)) {
104                 ast_log(LOG_WARNING, "Syntax IF(<expr>?[<true>][:<false>])\n");
105                 return -1;
106         }
107
108         expr = ast_strip(expr);
109         if (iftrue)
110                 iftrue = ast_strip_quoted(iftrue, "\"", "\"");
111         if (iffalse)
112                 iffalse = ast_strip_quoted(iffalse, "\"", "\"");
113
114         ast_copy_string(buf, pbx_checkcondition(expr) ? (S_OR(iftrue, "")) : (S_OR(iffalse, "")), len);
115
116         return 0;
117 }
118
119 static int set(struct ast_channel *chan, const char *cmd, char *data, char *buf,
120                size_t len)
121 {
122         char *varname;
123         char *val;
124
125         varname = strsep(&data, "=");
126         val = data;
127
128         if (ast_strlen_zero(varname) || !val) {
129                 ast_log(LOG_WARNING, "Syntax SET(<varname>=[<value>])\n");
130                 return -1;
131         }
132
133         varname = ast_strip(varname);
134         val = ast_strip(val);
135         pbx_builtin_setvar_helper(chan, varname, val);
136         ast_copy_string(buf, val, len);
137
138         return 0;
139 }
140
141 static struct ast_custom_function isnull_function = {
142         .name = "ISNULL",
143         .synopsis = "NULL Test: Returns 1 if NULL or 0 otherwise",
144         .syntax = "ISNULL(<data>)",
145         .read = isnull,
146 };
147
148 static struct ast_custom_function set_function = {
149         .name = "SET",
150         .synopsis = "SET assigns a value to a channel variable",
151         .syntax = "SET(<varname>=[<value>])",
152         .read = set,
153 };
154
155 static struct ast_custom_function exists_function = {
156         .name = "EXISTS",
157         .synopsis = "Existence Test: Returns 1 if exists, 0 otherwise",
158         .syntax = "EXISTS(<data>)",
159         .read = exists,
160 };
161
162 static struct ast_custom_function if_function = {
163         .name = "IF",
164         .synopsis =
165                 "Conditional: Returns the data following '?' if true else the data following ':'",
166         .syntax = "IF(<expr>?[<true>][:<false>])",
167         .read = acf_if,
168 };
169
170 static struct ast_custom_function if_time_function = {
171         .name = "IFTIME",
172         .synopsis =
173                 "Temporal Conditional: Returns the data following '?' if true else the data following ':'",
174         .syntax = "IFTIME(<timespec>?[<true>][:<false>])",
175         .read = iftime,
176 };
177
178 static int unload_module(void)
179 {
180         int res = 0;
181
182         res |= ast_custom_function_unregister(&isnull_function);
183         res |= ast_custom_function_unregister(&set_function);
184         res |= ast_custom_function_unregister(&exists_function);
185         res |= ast_custom_function_unregister(&if_function);
186         res |= ast_custom_function_unregister(&if_time_function);
187
188         return res;
189 }
190
191 static int load_module(void)
192 {
193         int res = 0;
194
195         res |= ast_custom_function_register(&isnull_function);
196         res |= ast_custom_function_register(&set_function);
197         res |= ast_custom_function_register(&exists_function);
198         res |= ast_custom_function_register(&if_function);
199         res |= ast_custom_function_register(&if_time_function);
200
201         return res;
202 }
203
204 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Logical dialplan functions");