Add Q.SIG option to zapata.conf
[asterisk/asterisk.git] / db.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Channel Management
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 /* DB3 is licensed under Sleepycat Public License and is thus incompatible
15    with GPL.  To avoid having to make another exception (and complicate 
16    licensing even further) we elect to use DB1 which is BSD licensed */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sys/time.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <dirent.h>
26
27 #include "asterisk/channel.h"
28 #include "asterisk/file.h"
29 #include "asterisk/app.h"
30 #include "asterisk/dsp.h"
31 #include "asterisk/logger.h"
32 #include "asterisk/options.h"
33 #include "asterisk/astdb.h"
34 #include "asterisk/cli.h"
35 #include "asterisk/utils.h"
36 #include "asterisk/lock.h"
37 #include "asterisk/manager.h"
38 #include "db1-ast/include/db.h"
39 #include "asterisk.h"
40 #include "astconf.h"
41
42 static DB *astdb;
43 AST_MUTEX_DEFINE_STATIC(dblock);
44
45 static int dbinit(void) 
46 {
47         if (!astdb) {
48                 if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
49                         ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
50                 }
51         }
52         if (astdb)
53                 return 0;
54         return -1;
55 }
56
57
58 static inline int keymatch(const char *key, const char *prefix)
59 {
60         int preflen = strlen(prefix);
61         if (!preflen)
62                 return 1;
63         if (!strcasecmp(key, prefix))
64                 return 1;
65         if ((strlen(key) > preflen) &&
66                 !strncasecmp(key, prefix, preflen)) {
67                 if (key[preflen] == '/')
68                         return 1;
69         }
70         return 0;
71 }
72
73 static inline int subkeymatch(const char *key, const char *suffix)
74 {
75         int suffixlen = strlen(suffix);
76         if (suffixlen) {
77                 const char *subkey = key + strlen(key) - suffixlen;
78                 if (subkey < key)
79                         return 0;
80                 if (!strcasecmp(subkey, suffix))
81                         return 1;
82         }
83         return 0;
84 }
85
86 int ast_db_deltree(const char *family, const char *keytree)
87 {
88         char prefix[256];
89         DBT key, data;
90         char *keys;
91         int res;
92         int pass;
93         
94         if (family) {
95                 if (keytree)
96                         snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
97                 else
98                         snprintf(prefix, sizeof(prefix), "/%s", family);
99         } else if (keytree)
100                 return -1;
101         else
102                 prefix[0] = '\0';
103         
104         ast_mutex_lock(&dblock);
105         if (dbinit()) 
106                 return -1;
107         
108         memset(&key, 0, sizeof(key));
109         memset(&data, 0, sizeof(data));
110         pass = 0;
111         while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
112                 if (key.size) {
113                         keys = key.data;
114                         keys[key.size - 1] = '\0';
115                 } else
116                         keys = "<bad key>";
117                 if (keymatch(keys, prefix)) {
118                         astdb->del(astdb, &key, 0);
119                 }
120         }
121         astdb->sync(astdb, 0);
122         ast_mutex_unlock(&dblock);
123         return 0;
124 }
125
126 int ast_db_put(const char *family, const char *keys, char *value)
127 {
128         char fullkey[256];
129         DBT key, data;
130         int res, fullkeylen;
131
132         ast_mutex_lock(&dblock);
133         if (dbinit()) {
134                 ast_mutex_unlock(&dblock);
135                 return -1;
136         }
137
138         fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
139         memset(&key, 0, sizeof(key));
140         memset(&data, 0, sizeof(data));
141         key.data = fullkey;
142         key.size = fullkeylen + 1;
143         data.data = value;
144         data.size = strlen(value) + 1;
145         res = astdb->put(astdb, &key, &data, 0);
146         astdb->sync(astdb, 0);
147         ast_mutex_unlock(&dblock);
148         if (res)
149                 ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
150         return res;
151 }
152
153 int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
154 {
155         char fullkey[256]="";
156         DBT key, data;
157         int res, fullkeylen;
158
159         ast_mutex_lock(&dblock);
160         if (dbinit()) {
161                 ast_mutex_unlock(&dblock);
162                 return -1;
163         }
164
165         fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
166         memset(&key, 0, sizeof(key));
167         memset(&data, 0, sizeof(data));
168         memset(value, 0, valuelen);
169         key.data = fullkey;
170         key.size = fullkeylen + 1;
171         
172         res = astdb->get(astdb, &key, &data, 0);
173         
174         ast_mutex_unlock(&dblock);
175
176         /* Be sure to NULL terminate our data either way */
177         if (res) {
178                 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
179         } else {
180 #if 0
181                 printf("Got value of size %d\n", data.size);
182 #endif
183                 if (data.size) {
184                         ((char *)data.data)[data.size - 1] = '\0';
185                         /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */
186                         strncpy(value, data.data, (valuelen > data.size) ? data.size : valuelen);
187                         value[valuelen - 1] = '\0';
188                 } else {
189                         ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
190                 }
191         }
192         return res;
193 }
194
195 int ast_db_del(const char *family, const char *keys)
196 {
197         char fullkey[256];
198         DBT key;
199         int res, fullkeylen;
200
201         ast_mutex_lock(&dblock);
202         if (dbinit()) {
203                 ast_mutex_unlock(&dblock);
204                 return -1;
205         }
206         
207         fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
208         memset(&key, 0, sizeof(key));
209         key.data = fullkey;
210         key.size = fullkeylen + 1;
211         
212         res = astdb->del(astdb, &key, 0);
213         astdb->sync(astdb, 0);
214         
215         ast_mutex_unlock(&dblock);
216
217         if (res) 
218                 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
219         return res;
220 }
221
222 static int database_put(int fd, int argc, char *argv[])
223 {
224         int res;
225         if (argc != 5)
226                 return RESULT_SHOWUSAGE;
227         res = ast_db_put(argv[2], argv[3], argv[4]);
228         if (res) 
229                 ast_cli(fd, "Failed to update entry\n");
230         else
231                 ast_cli(fd, "Updated database successfully\n");
232         return RESULT_SUCCESS;
233 }
234
235 static int database_get(int fd, int argc, char *argv[])
236 {
237         int res;
238         char tmp[256];
239         if (argc != 4)
240                 return RESULT_SHOWUSAGE;
241         res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
242         if (res) 
243                 ast_cli(fd, "Database entry not found.\n");
244         else
245                 ast_cli(fd, "Value: %s\n", tmp);
246         return RESULT_SUCCESS;
247 }
248
249 static int database_del(int fd, int argc, char *argv[])
250 {
251         int res;
252         if (argc != 4)
253                 return RESULT_SHOWUSAGE;
254         res = ast_db_del(argv[2], argv[3]);
255         if (res) 
256                 ast_cli(fd, "Database entry does not exist.\n");
257         else
258                 ast_cli(fd, "Database entry removed.\n");
259         return RESULT_SUCCESS;
260 }
261
262 static int database_deltree(int fd, int argc, char *argv[])
263 {
264         int res;
265         if ((argc < 3) || (argc > 4))
266                 return RESULT_SHOWUSAGE;
267         if (argc == 4)
268                 res = ast_db_deltree(argv[2], argv[3]);
269         else
270                 res = ast_db_deltree(argv[2], NULL);
271         if (res) 
272                 ast_cli(fd, "Database entries do not exist.\n");
273         else
274                 ast_cli(fd, "Database entries removed.\n");
275         return RESULT_SUCCESS;
276 }
277
278 static int database_show(int fd, int argc, char *argv[])
279 {
280         char prefix[256];
281         DBT key, data;
282         char *keys, *values;
283         int res;
284         int pass;
285
286         if (argc == 4) {
287                 /* Family and key tree */
288                 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
289         } else if (argc == 3) {
290                 /* Family only */
291                 snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
292         } else if (argc == 2) {
293                 /* Neither */
294                 prefix[0] = '\0';
295         } else
296                 return RESULT_SHOWUSAGE;
297         ast_mutex_lock(&dblock);
298         if (dbinit()) {
299                 ast_mutex_unlock(&dblock);
300                 ast_cli(fd, "Database unavailable\n");
301                 return RESULT_SUCCESS;  
302         }
303         memset(&key, 0, sizeof(key));
304         memset(&data, 0, sizeof(data));
305         pass = 0;
306         while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
307                 if (key.size) {
308                         keys = key.data;
309                         keys[key.size - 1] = '\0';
310                 } else
311                         keys = "<bad key>";
312                 if (data.size) {
313                         values = data.data;
314                         values[data.size - 1]='\0';
315                 } else
316                         values = "<bad value>";
317                 if (keymatch(keys, prefix)) {
318                                 ast_cli(fd, "%-50s: %-25s\n", keys, values);
319                 }
320         }
321         ast_mutex_unlock(&dblock);
322         return RESULT_SUCCESS;  
323 }
324
325 static int database_showkey(int fd, int argc, char *argv[])
326 {
327         char suffix[256];
328         DBT key, data;
329         char *keys, *values;
330         int res;
331         int pass;
332
333         if (argc == 3) {
334                 /* Key only */
335                 snprintf(suffix, sizeof(suffix), "/%s", argv[2]);
336         } else
337                 return RESULT_SHOWUSAGE;
338         ast_mutex_lock(&dblock);
339         if (dbinit()) {
340                 ast_mutex_unlock(&dblock);
341                 ast_cli(fd, "Database unavailable\n");
342                 return RESULT_SUCCESS;  
343         }
344         memset(&key, 0, sizeof(key));
345         memset(&data, 0, sizeof(data));
346         pass = 0;
347         while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
348                 if (key.size) {
349                         keys = key.data;
350                         keys[key.size - 1] = '\0';
351                 } else
352                         keys = "<bad key>";
353                 if (data.size) {
354                         values = data.data;
355                         values[data.size - 1]='\0';
356                 } else
357                         values = "<bad value>";
358                 if (subkeymatch(keys, suffix)) {
359                                 ast_cli(fd, "%-50s: %-25s\n", keys, values);
360                 }
361         }
362         ast_mutex_unlock(&dblock);
363         return RESULT_SUCCESS;  
364 }
365
366 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
367 {
368         char prefix[256];
369         DBT key, data;
370         char *keys, *values;
371         int res;
372         int pass;
373         struct ast_db_entry *last = NULL;
374         struct ast_db_entry *cur, *ret=NULL;
375
376         if (family && !ast_strlen_zero(family)) {
377                 if (keytree && !ast_strlen_zero(keytree))
378                         /* Family and key tree */
379                         snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
380                 else
381                         /* Family only */
382                         snprintf(prefix, sizeof(prefix), "/%s", family);
383         } else
384                 prefix[0] = '\0';
385         ast_mutex_lock(&dblock);
386         if (dbinit()) {
387                 ast_mutex_unlock(&dblock);
388                 ast_log(LOG_WARNING, "Database unavailable\n");
389                 return NULL;    
390         }
391         memset(&key, 0, sizeof(key));
392         memset(&data, 0, sizeof(data));
393         pass = 0;
394         while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
395                 if (key.size) {
396                         keys = key.data;
397                         keys[key.size - 1] = '\0';
398                 } else
399                         keys = "<bad key>";
400                 if (data.size) {
401                         values = data.data;
402                         values[data.size - 1]='\0';
403                 } else
404                         values = "<bad value>";
405                 if (keymatch(keys, prefix)) {
406                                 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
407                                 if (cur) {
408                                         cur->next = NULL;
409                                         cur->key = cur->data + strlen(values) + 1;
410                                         strcpy(cur->data, values);
411                                         strcpy(cur->key, keys);
412                                         if (last)
413                                                 last->next = cur;
414                                         else
415                                                 ret = cur;
416                                         last = cur;
417                                 }
418                 }
419         }
420         ast_mutex_unlock(&dblock);
421         return ret;     
422 }
423
424 void ast_db_freetree(struct ast_db_entry *dbe)
425 {
426         struct ast_db_entry *last;
427         while(dbe) {
428                 last = dbe;
429                 dbe = dbe->next;
430                 free(last);
431         }
432 }
433
434 static char database_show_usage[] =
435 "Usage: database show [family [keytree]]\n"
436 "       Shows Asterisk database contents, optionally restricted\n"
437 "to a given family, or family and keytree.\n";
438
439 static char database_showkey_usage[] =
440 "Usage: database showkey <keytree>\n"
441 "       Shows Asterisk database contents, restricted to a given key.\n";
442
443 static char database_put_usage[] =
444 "Usage: database put <family> <key> <value>\n"
445 "       Adds or updates an entry in the Asterisk database for\n"
446 "a given family, key, and value.\n";
447
448 static char database_get_usage[] =
449 "Usage: database get <family> <key>\n"
450 "       Retrieves an entry in the Asterisk database for a given\n"
451 "family and key.\n";
452
453 static char database_del_usage[] =
454 "Usage: database del <family> <key>\n"
455 "       Deletes an entry in the Asterisk database for a given\n"
456 "family and key.\n";
457
458 static char database_deltree_usage[] =
459 "Usage: database deltree <family> [keytree]\n"
460 "       Deletes a family or specific keytree within a family\n"
461 "in the Asterisk database.\n";
462
463 struct ast_cli_entry cli_database_show =
464 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
465
466 struct ast_cli_entry cli_database_showkey =
467 { { "database", "showkey", NULL }, database_showkey, "Shows database contents", database_showkey_usage };
468
469 struct ast_cli_entry cli_database_get =
470 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
471
472 struct ast_cli_entry cli_database_put =
473 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
474
475 struct ast_cli_entry cli_database_del =
476 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
477
478 struct ast_cli_entry cli_database_deltree =
479 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
480
481 static int manager_dbput(struct mansession *s, struct message *m)
482 {
483         char *family = astman_get_header(m, "Family");
484         char *key = astman_get_header(m, "Key");
485         char *val = astman_get_header(m, "Val");
486         int res;
487
488         if (!strlen(family)) {
489                 astman_send_error(s, m, "No family specified");
490                 return 0;
491         }
492         if (!strlen(key)) {
493                 astman_send_error(s, m, "No key specified");
494                 return 0;
495         }
496         if (!strlen(val)) {
497                 astman_send_error(s, m, "No val specified");
498                 return 0;
499         }
500
501         res = ast_db_put(family, key, val);
502         if (res)
503                 astman_send_error(s, m, "Failed to update entry");
504         else 
505                 astman_send_ack(s, m, "Updated database successfully");
506         return 0;
507 }
508
509 static int manager_dbget(struct mansession *s, struct message *m)
510 {
511         char *family = astman_get_header(m, "Family");
512         char *key = astman_get_header(m, "Key");
513         char tmp[256];
514         int res;
515
516         if (!strlen(family)) {
517                 astman_send_error(s, m, "No family specified.");
518                 return 0;
519         }
520         if (!strlen(key)) {
521                 astman_send_error(s, m, "No key specified.");
522                 return 0;
523         }
524
525         res = ast_db_get(family, key, tmp, sizeof(tmp));
526         if (res)
527                 astman_send_error(s, m, "Database entry not found");
528         else {
529                 astman_send_ack(s, m, "Result will follow");
530                 ast_cli(s->fd, "Event: DBGetResponse\r\n"
531                                 "Family: %s\r\n"
532                                 "Key: %s\r\n"
533                                 "Val: %s\r\n\r\n",
534                                 family, key, tmp);
535         }
536         return 0;
537 }
538
539 int astdb_init(void)
540 {
541         dbinit();
542         ast_cli_register(&cli_database_show);
543         ast_cli_register(&cli_database_showkey);
544         ast_cli_register(&cli_database_get);
545         ast_cli_register(&cli_database_put);
546         ast_cli_register(&cli_database_del);
547         ast_cli_register(&cli_database_deltree);
548         ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
549         ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");
550         return 0;
551 }