use double-quotes instead of angle-brackets for non-system include files (bug #4058)
[asterisk/asterisk.git] / apps / app_while.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * While Loop and ExecIf Implementations
5  * 
6  * Copyright 2004 - 2005, Anthony Minessale <anthmct@yahoo.com>
7  *
8  * Anthony Minessale <anthmct@yahoo.com>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14
15 #include "asterisk/file.h"
16 #include "asterisk/logger.h"
17 #include "asterisk/channel.h"
18 #include "asterisk/utils.h"
19 #include "asterisk/config.h"
20 #include "asterisk/pbx.h"
21 #include "asterisk/module.h"
22 #include "asterisk/lock.h"
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <string.h>
26
27 #define ALL_DONE(u,ret) {LOCAL_USER_REMOVE(u); return ret;}
28
29
30 static char *exec_app = "ExecIf";
31 static char *exec_desc = "  ExecIF (<expr>|<app>|<data>)\n"
32 "If <expr> is true, execute and return the result of <app>(<data>).\n"
33 "If <expr> is true, but <app> is not found, then the application\n"
34 "will return a non-zero value.";
35 static char *exec_synopsis = "ExecIF (<expr>|<app>|<data>)";
36
37 static char *start_app = "While";
38 static char *start_desc = "  While(<expr>)\n"
39 "Start a While Loop.  Execution will return to this point when\n"
40 "EndWhile is called until expr is no longer true.\n";
41
42 static char *start_synopsis = "Start A While Loop";
43
44
45 static char *stop_app = "EndWhile";
46 static char *stop_desc = "  EndWhile()\n"
47 "Return to the previous called While\n\n";
48
49 static char *stop_synopsis = "End A While Loop";
50
51 static char *tdesc = "While Loops and Conditional Execution";
52
53
54
55 STANDARD_LOCAL_USER;
56
57 LOCAL_USER_DECL;
58
59 static int execif_exec(struct ast_channel *chan, void *data) {
60         int res=0;
61         struct localuser *u;
62         char *myapp = NULL;
63         char *mydata = NULL;
64         char *expr = NULL;
65         struct ast_app *app = NULL;
66
67         LOCAL_USER_ADD(u);
68         expr = ast_strdupa((char *) data);
69         if ((myapp = strchr(expr,'|'))) {
70                 *myapp = '\0';
71                 myapp++;
72                 if ((mydata = strchr(myapp,'|'))) {
73                         *mydata = '\0';
74                         mydata++;
75                 } else
76                         mydata = "";
77
78                 if (ast_true(expr)) { 
79                         if ((app = pbx_findapp(myapp))) {
80                                 res = pbx_exec(chan, app, mydata, 1);
81                         } else {
82                                 ast_log(LOG_WARNING, "Count not find application! (%s)\n", myapp);
83                                 res = -1;
84                         }
85                 }
86         } else {
87                 ast_log(LOG_ERROR,"Invalid Syntax.\n");
88                 res = -1;
89         }
90                 
91         ALL_DONE(u,res);
92 }
93
94 #define VAR_SIZE 64
95
96
97 static char *get_index(struct ast_channel *chan, const char *prefix, int index) {
98         char varname[VAR_SIZE];
99
100         snprintf(varname, VAR_SIZE, "%s_%d", prefix, index);
101         return pbx_builtin_getvar_helper(chan, varname);
102 }
103
104
105 static int _while_exec(struct ast_channel *chan, void *data, int end)
106 {
107         int res=0;
108         struct localuser *u;
109         char *while_pri = NULL;
110         char *goto_str = NULL, *my_name = NULL;
111         char *condition = NULL, *label = NULL;
112         char varname[VAR_SIZE], end_varname[VAR_SIZE];
113         const char *prefix = "WHILE";
114         size_t size=0;
115         int used_index_i = -1, x=0;
116         char used_index[VAR_SIZE] = "0", new_index[VAR_SIZE] = "0";
117         
118         if (!chan) {
119                 /* huh ? */
120                 return -1;
121         }
122
123         LOCAL_USER_ADD(u);
124
125         /* dont want run away loops if the chan isn't even up
126            this is up for debate since it slows things down a tad ......
127         */
128         if (ast_waitfordigit(chan,1) < 0)
129                 ALL_DONE(u,-1);
130
131
132         for (x=0;;x++) {
133                 if (get_index(chan, prefix, x)) {
134                         used_index_i = x;
135                 } else 
136                         break;
137         }
138         
139         snprintf(used_index, VAR_SIZE, "%d", used_index_i);
140         snprintf(new_index, VAR_SIZE, "%d", used_index_i + 1);
141         
142         if (!end) {
143                 condition = ast_strdupa((char *) data);
144         }
145
146         size = strlen(chan->context) + strlen(chan->exten) + 32;
147         my_name = alloca(size);
148         memset(my_name, 0, size);
149         snprintf(my_name, size, "%s_%s_%d", chan->context, chan->exten, chan->priority);
150         
151         if (!label || ast_strlen_zero(label)) {
152                 if (end) 
153                         label = used_index;
154                 else if (!(label = pbx_builtin_getvar_helper(chan, my_name))) {
155                         label = new_index;
156                         pbx_builtin_setvar_helper(chan, my_name, label);
157                 }
158                 
159         }
160         
161         snprintf(varname, VAR_SIZE, "%s_%s", prefix, label);
162         while_pri = pbx_builtin_getvar_helper(chan, varname);
163         
164         if ((while_pri = pbx_builtin_getvar_helper(chan, varname)) && !end) {
165                 snprintf(end_varname,VAR_SIZE,"END_%s",varname);
166         }
167         
168
169         if (!end && !ast_true(condition)) {
170                 /* Condition Met (clean up helper vars) */
171                 pbx_builtin_setvar_helper(chan, varname, NULL);
172                 pbx_builtin_setvar_helper(chan, my_name, NULL);
173         snprintf(end_varname,VAR_SIZE,"END_%s",varname);
174                 if ((goto_str=pbx_builtin_getvar_helper(chan, end_varname))) {
175                         pbx_builtin_setvar_helper(chan, end_varname, NULL);
176                         ast_parseable_goto(chan, goto_str);
177                 }
178                 ALL_DONE(u,res);
179         }
180
181         if (!end && !while_pri) {
182                 size = strlen(chan->context) + strlen(chan->exten) + 32;
183                 goto_str = alloca(size);
184                 memset(goto_str, 0, size);
185                 snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority);
186                 pbx_builtin_setvar_helper(chan, varname, goto_str);
187         } 
188
189         else if (end && while_pri) {
190                 /* END of loop */
191                 snprintf(end_varname, VAR_SIZE, "END_%s", varname);
192                 if (! pbx_builtin_getvar_helper(chan, end_varname)) {
193                         size = strlen(chan->context) + strlen(chan->exten) + 32;
194                         goto_str = alloca(size);
195                         memset(goto_str, 0, size);
196                         snprintf(goto_str, size, "%s|%s|%d", chan->context, chan->exten, chan->priority+1);
197                         pbx_builtin_setvar_helper(chan, end_varname, goto_str);
198                 }
199                 ast_parseable_goto(chan, while_pri);
200         }
201         
202
203
204
205         ALL_DONE(u, res);
206 }
207
208 static int while_start_exec(struct ast_channel *chan, void *data) {
209         return _while_exec(chan, data, 0);
210 }
211
212 static int while_end_exec(struct ast_channel *chan, void *data) {
213         return _while_exec(chan, data, 1);
214 }
215
216
217 int unload_module(void)
218 {
219         STANDARD_HANGUP_LOCALUSERS;
220         ast_unregister_application(start_app);
221         ast_unregister_application(exec_app);
222         return ast_unregister_application(stop_app);
223 }
224
225 int load_module(void)
226 {
227         ast_register_application(start_app, while_start_exec, start_synopsis, start_desc);
228         ast_register_application(exec_app, execif_exec, exec_synopsis, exec_desc);
229         return ast_register_application(stop_app, while_end_exec, stop_synopsis, stop_desc);
230 }
231
232 char *description(void)
233 {
234         return tdesc;
235 }
236
237 int usecount(void)
238 {
239         int res;
240         STANDARD_USECOUNT(res);
241         return res;
242 }
243
244 char *key()
245 {
246         return ASTERISK_GPL_KEY;
247 }
248