more ast_copy_string conversions
[asterisk/asterisk.git] / apps / app_math.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * simple math application
5  * 
6  * Copyright (C) 2004 - 2005, Andy Powell 
7  *
8  * Updated by Mark Spencer <markster@digium.com>
9  *
10  */
11
12 #include <stdlib.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <string.h>
16 #include <stdlib.h>
17 #include <stdio.h>
18 #include <sys/time.h>
19 #include <sys/stat.h>
20 #include <sys/types.h>
21 #include <time.h>
22 #include <dirent.h>
23 #include <ctype.h>
24 #include <sys/file.h>
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #include "asterisk/lock.h"
31 #include "asterisk/file.h"
32 #include "asterisk/logger.h"
33 #include "asterisk/channel.h"
34 #include "asterisk/pbx.h"
35 #include "asterisk/options.h"
36 #include "asterisk/config.h"
37 #include "asterisk/say.h"
38 #include "asterisk/module.h"
39 #include "asterisk/app.h"
40 #include "asterisk/manager.h"
41 #include "asterisk/localtime.h"
42 #include "asterisk/cli.h"
43 #include "asterisk/utils.h"
44 #include "asterisk/module.h"
45 #include "asterisk/translate.h"
46
47 static char *tdesc = "Basic Math Functions";
48
49 static char *app_math = "Math";
50
51 static char *math_synopsis = "Performs Mathematical Functions";
52
53 static char *math_descrip =
54 "Math(returnvar,<number1><op><number 2>\n\n"
55 "Perform floating point calculation on number 1 to number 2 and \n"
56 "store the result in returnvar.  Valid ops are: \n"
57 "    +,-,/,*,%,<,>,>=,<=,==\n"
58 "and behave as their C equivalents.  Always returns 0.\n";
59
60 #define ADDFUNCTION 0
61 #define DIVIDEFUNCTION 1
62 #define MULTIPLYFUNCTION 2
63 #define SUBTRACTFUNCTION 3
64 #define MODULUSFUNCTION 4
65
66 #define GTFUNCTION 5
67 #define LTFUNCTION 6
68 #define GTEFUNCTION 7
69 #define LTEFUNCTION 8
70 #define EQFUNCTION 9
71
72 STANDARD_LOCAL_USER;
73
74 LOCAL_USER_DECL;
75
76 static int math_exec(struct ast_channel *chan, void *data) 
77 {
78         float fnum1;
79         float fnum2;
80         float ftmp = 0;
81         char *op;
82         int iaction=-1;
83         static int deprecation_warning = 0;
84
85         /* dunno, big calulations :D */
86         char user_result[30];
87
88         char *s;
89         char *mvar, *mvalue1, *mvalue2=NULL;
90                 
91         struct localuser *u;
92
93         if (!deprecation_warning) {
94                 ast_log(LOG_WARNING, "Math() is deprecated, please use Set(var=${MATH(...)} instead.\n");
95                 deprecation_warning = 1;
96         }
97
98         if (!data) {
99                 ast_log(LOG_WARNING, "No parameters passed. !\n");
100                 return -1;
101         }
102
103         LOCAL_USER_ADD(u);
104                 
105         s = ast_strdupa((void *) data);
106
107         mvar = strsep(&s, "|");
108         mvalue1 = strsep(&s, "|");
109         
110         if ((op = strchr(mvalue1, '+'))) {
111                 iaction = ADDFUNCTION;
112                 *op = '\0';
113         } else if ((op = strchr(mvalue1, '-'))) {
114                 iaction = SUBTRACTFUNCTION;
115                 *op = '\0';
116         } else if ((op = strchr(mvalue1, '*'))) {
117                 iaction = MULTIPLYFUNCTION;
118                 *op = '\0';
119         } else if ((op = strchr(mvalue1, '/'))) {
120                 iaction = DIVIDEFUNCTION;
121                 *op = '\0';
122         } else if ((op = strchr(mvalue1, '>'))) {
123                 iaction = GTFUNCTION;
124                 *op = '\0';
125                 if (*(op+1) == '=') {
126                         op++;
127                         *op = '\0';
128                         iaction = GTEFUNCTION;
129                 }
130         } else if ((op = strchr(mvalue1, '<'))) {
131                 iaction = LTFUNCTION;
132                 *op = '\0';
133                 if (*(op+1) == '=') {
134                         op++;
135                         *op = '\0';
136                         iaction = LTEFUNCTION;
137                 }
138         } else if ((op = strchr(mvalue1, '='))) {
139                 iaction = GTFUNCTION;
140                 *op = '\0';
141                 if (*(op+1) == '=') {
142                         op++;
143                         *op = '\0';
144                         iaction = EQFUNCTION;
145                 } else
146                         op = NULL;
147         } 
148         
149         if (op) 
150                 mvalue2 = op + 1;
151                 
152         if (!mvar || !mvalue1 || !mvalue2) {
153                 ast_log(LOG_WARNING, "Supply all the parameters - just this once, please\n");
154                 LOCAL_USER_REMOVE(u);
155                 return -1;
156         }
157
158         if (!strcmp(mvar,"")) {
159                 ast_log(LOG_WARNING, "No return variable set.\n");
160                 LOCAL_USER_REMOVE(u);
161                 return -1;
162         }
163
164         if (sscanf(mvalue1, "%f", &fnum1) != 1) {
165                 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
166                 LOCAL_USER_REMOVE(u);
167                 return -1;
168         }
169
170         if (sscanf(mvalue2, "%f", &fnum2) != 1) {
171                 ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
172                 LOCAL_USER_REMOVE(u);
173                 return -1;
174         }
175
176         switch (iaction) {
177         case ADDFUNCTION :
178                 ftmp = fnum1 + fnum2;
179                 break;
180         case DIVIDEFUNCTION :
181                 if (fnum2 <=0)
182                         ftmp = 0; /* can't do a divide by 0 */
183                 else
184                         ftmp = (fnum1 / fnum2);
185                 break;
186         case MULTIPLYFUNCTION :
187                 ftmp = (fnum1 * fnum2);
188                 break;
189         case SUBTRACTFUNCTION :
190                 ftmp = (fnum1 - fnum2);
191                 break;
192         case MODULUSFUNCTION : {
193                 int inum1 = fnum1;
194                 int inum2 = fnum2;
195                         
196                 ftmp = (inum1 % inum2);
197                 
198                 break;
199                 }
200         case GTFUNCTION :
201                 if (fnum1 > fnum2)
202                         strcpy(user_result, "TRUE");
203                 else
204                         strcpy(user_result, "FALSE");
205                 break;
206         case LTFUNCTION :
207                 if (fnum1 < fnum2)
208                         strcpy(user_result, "TRUE");
209                 else
210                         strcpy(user_result, "FALSE");
211                 break;
212         case GTEFUNCTION :
213                 if (fnum1 >= fnum2)
214                         strcpy(user_result, "TRUE");
215                 else
216                         strcpy(user_result, "FALSE");
217                 break;
218         case LTEFUNCTION :
219                 if (fnum1 <= fnum2)
220                         strcpy(user_result, "TRUE");
221                 else
222                         strcpy(user_result, "FALSE");
223                 break;                                  
224         case EQFUNCTION :
225                 if (fnum1 == fnum2)
226                         strcpy(user_result, "TRUE");
227                 else
228                         strcpy(user_result, "FALSE");
229                 break;
230         default :
231                 ast_log(LOG_WARNING, "Something happened that neither of us should be proud of %d\n", iaction);
232                 LOCAL_USER_REMOVE(u);
233                 return -1;
234         }
235
236         if (iaction < GTFUNCTION || iaction > EQFUNCTION) 
237                 snprintf(user_result,sizeof(user_result),"%f",ftmp);
238                 
239         pbx_builtin_setvar_helper(chan, mvar, user_result);     
240         
241         LOCAL_USER_REMOVE(u);
242         return 0;
243 }
244
245 int unload_module(void)
246 {
247         int res;
248         STANDARD_HANGUP_LOCALUSERS;
249
250         res  = ast_unregister_application(app_math);
251         return res;
252 }
253
254 int load_module(void)
255 {
256         int res;
257         res = ast_register_application(app_math, math_exec, math_synopsis, math_descrip);
258         return res;
259 }
260
261 char *description(void)
262 {
263         return tdesc;
264 }
265
266 int usecount(void)
267 {
268         int res;
269         STANDARD_USECOUNT(res);
270         return res;
271 }
272
273 char *key()
274 {
275         return ASTERISK_GPL_KEY;
276 }
277
278 /* Fading everything to black and blue... */