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