Fix missing arguments
[asterisk/asterisk.git] / pbx / pbx_realtime.c
1 /*
2  * Realtime PBX Module
3  *
4  * Copyright (C) 2004, Digium Inc.
5  *
6  * Written by Mark Spencer <markster@digium.com>
7  *
8  * This program is Free Software distributed under the terms of
9  * of the GNU General Public License.
10  */
11
12 #include <asterisk/file.h>
13 #include <asterisk/logger.h>
14 #include <asterisk/channel.h>
15 #include <asterisk/config.h>
16 #include <asterisk/options.h>
17 #include <asterisk/pbx.h>
18 #include <asterisk/module.h>
19 #include <asterisk/frame.h>
20 #include <asterisk/file.h>
21 #include <asterisk/cli.h>
22 #include <asterisk/lock.h>
23 #include <asterisk/md5.h>
24 #include <asterisk/linkedlists.h>
25 #include <asterisk/chanvars.h>
26 #include <asterisk/sched.h>
27 #include <asterisk/io.h>
28 #include <asterisk/utils.h>
29 #include <asterisk/crypto.h>
30 #include <asterisk/astdb.h>
31
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <errno.h>
36
37 #define MODE_MATCH 0
38 #define MODE_MATCHMORE 1
39 #define MODE_CANMATCH 2
40
41 static char *tdesc = "Realtime Switch";
42
43 /* Realtime switch looks up extensions in the supplied realtime table.
44
45         [context@][realtimetable][/options]
46
47         If the realtimetable is omitted it is assumed to be "extensions".  If no context is 
48         specified the context is assumed to be whatever is the container.
49
50         The realtime table should have entries for context,exten,priority,app,args
51         
52         The realtime table currently does not support patterns or callerid fields.
53
54 */
55
56
57 #define REALTIME_COMMON(mode) \
58         char *buf; \
59         char *opts; \
60         const char *cxt; \
61         char *table; \
62         int res=-1; \
63         struct ast_variable *var=NULL; \
64         buf = ast_strdupa(data); \
65         if (buf) { \
66                 opts = strchr(buf, '/'); \
67                 if (opts) { \
68                         *opts='\0'; \
69                         opts++; \
70                 } else \
71                         opts=""; \
72                 table = strchr(buf, '@'); \
73                 if (table) { \
74                         *table = '\0'; \
75                         table++;\
76                         cxt = buf; \
77                 } else cxt = NULL; \
78                 if (!cxt || ast_strlen_zero(cxt)) \
79                         cxt = context;\
80                 if (!table || ast_strlen_zero(table)) \
81                         table = "extensions"; \
82                 var = realtime_switch_common(table, cxt, exten, priority, mode); \
83         } else \
84                 res = -1; 
85
86 static struct ast_variable *realtime_switch_common(const char *table, const char *context, const char *exten, int priority, int mode)
87 {
88         struct ast_variable *var;
89         char pri[20];
90         snprintf(pri, sizeof(pri), "%d", priority);
91         printf("%s/%s/%s/%s exists\n", table, context, exten, pri);
92         var = ast_load_realtime(table, "context", context, "exten", exten, "priority", pri, NULL);
93         return var;
94 }
95
96 static int realtime_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
97 {
98         REALTIME_COMMON(MODE_MATCH);
99         if (var) ast_destroy_realtime(var);
100         if (var)
101                 res = 1;
102         return res > 0 ? res : 0;
103 }
104
105 static int realtime_canmatch(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
106 {
107         REALTIME_COMMON(MODE_CANMATCH);
108         if (var) ast_destroy_realtime(var);
109         if (var)
110                 res = 1;
111         return res > 0 ? res : 0;
112 }
113
114 static int realtime_exec(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, int newstack, const char *data)
115 {
116         char app[256];
117         char *appdata="";
118         struct ast_app *a;
119         struct ast_variable *v;
120         REALTIME_COMMON(MODE_MATCH);
121         if (var) {
122                 v = var;
123                 while(v) {
124                         if (!strcasecmp(v->name, "app"))
125                                 strncpy(app, v->value, sizeof(app) -1 );
126                         else if (!strcasecmp(v->name, "appdata"))
127                                 appdata = ast_strdupa(v->value);
128                         v = v->next;
129                 }
130                 ast_destroy_realtime(var);
131                 if (!ast_strlen_zero(app)) {
132                         a = pbx_findapp(app);
133                         if (a) {
134                                 res = pbx_exec(chan, a, appdata, newstack);
135                         } else
136                                 ast_log(LOG_NOTICE, "No such application '%s' for extension '%s' in context '%s'\n", app, exten, context);
137                 }
138         }
139         return res;
140 }
141
142 static int realtime_matchmore(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
143 {
144         REALTIME_COMMON(MODE_MATCHMORE);
145         if (var) ast_destroy_realtime(var);
146         return res > 0 ? res : 0;
147 }
148
149 static struct ast_switch realtime_switch =
150 {
151         name:                   "Realtime",
152         description:                    "Realtime Dialplan Switch",
153         exists:                 realtime_exists,
154         canmatch:               realtime_canmatch,
155         exec:                   realtime_exec,
156         matchmore:              realtime_matchmore,
157 };
158
159 char *description(void)
160 {
161         return tdesc;
162 }
163
164 int usecount(void)
165 {
166         return 1;
167 }
168
169 char *key()
170 {
171         return ASTERISK_GPL_KEY;
172 }
173
174 int unload_module(void)
175 {
176         ast_unregister_switch(&realtime_switch);
177         return 0;
178 }
179
180 int load_module(void)
181 {
182         ast_register_switch(&realtime_switch);
183         return 0;
184 }
185