1cbbd9dc82a0034a5e9c1adea00b8f0bbda46dcf
[asterisk/asterisk.git] / apps / app_db.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Database access functions
5  *
6  * Copyright (C) 1999 - 2005, Digium, Inc.
7  * Copyright (C) 2003, Jefferson Noxon
8  *
9  * Mark Spencer <markster@digium.com>
10  * Jefferson Noxon <jeff@debian.org>
11  *
12  * This program is free software, distributed under the terms of
13  * the GNU General Public License
14  */
15
16 #include <stdlib.h>
17 #include <unistd.h>
18 #include <string.h>
19 #include <sys/types.h>
20
21 #include "asterisk.h"
22
23 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
24
25 #include "asterisk/options.h"
26 #include "asterisk/file.h"
27 #include "asterisk/logger.h"
28 #include "asterisk/channel.h"
29 #include "asterisk/pbx.h"
30 #include "asterisk/module.h"
31 #include "asterisk/astdb.h"
32 #include "asterisk/lock.h"
33
34 static char *tdesc = "Database access functions for Asterisk extension logic";
35
36 static char *g_descrip =
37         "  DBget(varname=family/key): Retrieves a value from the Asterisk\n"
38         "database and stores it in the given variable.  Always returns 0.  If the\n"
39         "requested key is not found, jumps to priority n+101 if available.\n";
40
41 static char *p_descrip =
42         "  DBput(family/key=value): Stores the given value in the Asterisk\n"
43         "database.  Always returns 0.\n";
44
45 static char *d_descrip =
46         "  DBdel(family/key): Deletes a key from the Asterisk database.  Always\n"
47         "returns 0.\n";
48
49 static char *dt_descrip =
50         "  DBdeltree(family[/keytree]): Deletes a family or keytree from the Asterisk\n"
51         "database.  Always returns 0.\n";
52
53 static char *g_app = "DBget";
54 static char *p_app = "DBput";
55 static char *d_app = "DBdel";
56 static char *dt_app = "DBdeltree";
57
58 static char *g_synopsis = "Retrieve a value from the database";
59 static char *p_synopsis = "Store a value in the database";
60 static char *d_synopsis = "Delete a key from the database";
61 static char *dt_synopsis = "Delete a family or keytree from the database";
62
63 STANDARD_LOCAL_USER;
64
65 LOCAL_USER_DECL;
66
67 static int deltree_exec(struct ast_channel *chan, void *data)
68 {
69         int arglen;
70         char *argv, *family, *keytree;
71
72         arglen = strlen(data);
73         argv = alloca(arglen + 1);
74         if (!argv) {    /* Why would this fail? */
75                 ast_log(LOG_DEBUG, "Memory allocation failed\n");
76                 return 0;
77         }
78         memcpy(argv, data, arglen + 1);
79
80         if (strchr(argv, '/')) {
81                 family = strsep(&argv, "/");
82                 keytree = strsep(&argv, "\0");
83                         if (!family || !keytree) {
84                                 ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
85                                 return 0;
86                         }
87                 if (!strlen(keytree))
88                         keytree = 0;
89         } else {
90                 family = argv;
91                 keytree = 0;
92         }
93
94         if (option_verbose > 2) {
95                 if (keytree)
96                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s, keytree=%s\n", family, keytree);
97                 else
98                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: family=%s\n", family);
99         }
100
101         if (ast_db_deltree(family, keytree)) {
102                 if (option_verbose > 2)
103                         ast_verbose(VERBOSE_PREFIX_3 "DBdeltree: Error deleting key from database.\n");
104         }
105
106         return 0;
107 }
108
109 static int del_exec(struct ast_channel *chan, void *data)
110 {
111         int arglen;
112         char *argv, *family, *key;
113
114         arglen = strlen(data);
115         argv = alloca(arglen + 1);
116         if (!argv) {    /* Why would this fail? */
117                 ast_log (LOG_DEBUG, "Memory allocation failed\n");
118                 return 0;
119         }
120         memcpy(argv, data, arglen + 1);
121
122         if (strchr(argv, '/')) {
123                 family = strsep(&argv, "/");
124                 key = strsep(&argv, "\0");
125                 if (!family || !key) {
126                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
127                         return 0;
128                 }
129                 if (option_verbose > 2)
130                         ast_verbose(VERBOSE_PREFIX_3 "DBdel: family=%s, key=%s\n", family, key);
131                 if (ast_db_del(family, key)) {
132                         if (option_verbose > 2)
133                                 ast_verbose(VERBOSE_PREFIX_3 "DBdel: Error deleting key from database.\n");
134                 }
135         } else {
136                 ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
137         }
138         return 0;
139 }
140
141 static int put_exec(struct ast_channel *chan, void *data)
142 {
143         int arglen;
144         char *argv, *value, *family, *key;
145         static int dep_warning = 0;
146
147         if (!dep_warning) {
148                 ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
149                 dep_warning = 1;
150         }
151         
152         arglen = strlen(data);
153         argv = alloca(arglen + 1);
154         if (!argv) {    /* Why would this fail? */
155                 ast_log(LOG_DEBUG, "Memory allocation failed\n");
156                 return 0;
157         }
158         memcpy(argv, data, arglen + 1);
159
160         if (strchr(argv, '/') && strchr(argv, '=')) {
161                 family = strsep(&argv, "/");
162                 key = strsep(&argv, "=");
163                 value = strsep(&argv, "\0");
164                 if (!value || !family || !key) {
165                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
166                         return 0;
167                 }
168                 if (option_verbose > 2)
169                         ast_verbose(VERBOSE_PREFIX_3 "DBput: family=%s, key=%s, value=%s\n", family, key, value);
170                 if (ast_db_put(family, key, value)) {
171                         if (option_verbose > 2)
172                                 ast_verbose(VERBOSE_PREFIX_3 "DBput: Error writing value to database.\n");
173                 }
174
175         } else  {
176                 ast_log (LOG_DEBUG, "Ignoring, no parameters\n");
177         }
178         return 0;
179 }
180
181 static int get_exec(struct ast_channel *chan, void *data)
182 {
183         int arglen;
184         char *argv, *varname, *family, *key;
185         char dbresult[256];
186         static int dep_warning = 0;
187
188         if (!dep_warning) {
189                 ast_log(LOG_WARNING, "This application has been deprecated, please use the ${DB(family/key)} function instead.\n");
190                 dep_warning = 1;
191         }
192         
193         arglen = strlen(data);
194         argv = alloca(arglen + 1);
195         if (!argv) {    /* Why would this fail? */
196                 ast_log(LOG_DEBUG, "Memory allocation failed\n");
197                 return 0;
198         }
199         memcpy(argv, data, arglen + 1);
200
201         if (strchr(argv, '=') && strchr(argv, '/')) {
202                 varname = strsep(&argv, "=");
203                 family = strsep(&argv, "/");
204                 key = strsep(&argv, "\0");
205                 if (!varname || !family || !key) {
206                         ast_log(LOG_DEBUG, "Ignoring; Syntax error in argument\n");
207                         return 0;
208                 }
209                 if (option_verbose > 2)
210                         ast_verbose(VERBOSE_PREFIX_3 "DBget: varname=%s, family=%s, key=%s\n", varname, family, key);
211                 if (!ast_db_get(family, key, dbresult, sizeof (dbresult) - 1)) {
212                         pbx_builtin_setvar_helper(chan, varname, dbresult);
213                         if (option_verbose > 2)
214                                 ast_verbose(VERBOSE_PREFIX_3 "DBget: set variable %s to %s\n", varname, dbresult);
215                 } else {
216                         if (option_verbose > 2)
217                         ast_verbose(VERBOSE_PREFIX_3 "DBget: Value not found in database.\n");
218                         /* Send the call to n+101 priority, where n is the current priority */
219                         if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
220                                 chan->priority += 100;
221                 }
222
223         } else {
224                 ast_log(LOG_DEBUG, "Ignoring, no parameters\n");
225         }
226         return 0;
227 }
228
229 int unload_module(void)
230 {
231         int retval;
232
233         STANDARD_HANGUP_LOCALUSERS;
234         retval = ast_unregister_application(dt_app);
235         retval |= ast_unregister_application(d_app);
236         retval |= ast_unregister_application(p_app);
237         retval |= ast_unregister_application(g_app);
238
239         return retval;
240 }
241
242 int load_module(void)
243 {
244         int retval;
245
246         retval = ast_register_application(g_app, get_exec, g_synopsis, g_descrip);
247         if (!retval)
248                 retval = ast_register_application(p_app, put_exec, p_synopsis, p_descrip);
249         if (!retval)
250                 retval = ast_register_application(d_app, del_exec, d_synopsis, d_descrip);
251         if (!retval)
252                 retval = ast_register_application(dt_app, deltree_exec, dt_synopsis, dt_descrip);
253         return retval;
254 }
255
256 char *description(void)
257 {
258         return tdesc;
259 }
260
261 int usecount(void)
262 {
263         int res;
264         STANDARD_USECOUNT(res);
265         return res;
266 }
267
268 char *key()
269 {
270         return ASTERISK_GPL_KEY;
271 }