2 * Asterisk -- A telephony toolkit for Linux.
6 * Copyright (C) 1999, Mark Spencer
8 * Mark Spencer <markster@linux-support.net>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
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 */
26 #include <asterisk/channel.h>
27 #include <asterisk/file.h>
28 #include <asterisk/app.h>
29 #include <asterisk/dsp.h>
30 #include <asterisk/logger.h>
31 #include <asterisk/options.h>
32 #include <asterisk/astdb.h>
33 #include <asterisk/cli.h>
34 #include <asterisk/utils.h>
35 #include <asterisk/lock.h>
36 #include <asterisk/manager.h>
37 #include "db1-ast/include/db.h"
42 AST_MUTEX_DEFINE_STATIC(dblock);
44 static int dbinit(void)
47 if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
48 ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
57 static inline int keymatch(const char *key, const char *prefix)
59 int preflen = strlen(prefix);
62 if (!strcasecmp(key, prefix))
64 if ((strlen(key) > preflen) &&
65 !strncasecmp(key, prefix, preflen)) {
66 if (key[preflen] == '/')
72 static inline int subkeymatch(const char *key, const char *suffix)
74 int suffixlen = strlen(suffix);
76 const char *subkey = key + strlen(key) - suffixlen;
79 if (!strcasecmp(subkey, suffix))
85 int ast_db_deltree(const char *family, const char *keytree)
95 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
97 snprintf(prefix, sizeof(prefix), "/%s", family);
103 ast_mutex_lock(&dblock);
107 memset(&key, 0, sizeof(key));
108 memset(&data, 0, sizeof(data));
110 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
113 keys[key.size - 1] = '\0';
116 if (keymatch(keys, prefix)) {
117 astdb->del(astdb, &key, 0);
120 astdb->sync(astdb, 0);
121 ast_mutex_unlock(&dblock);
125 int ast_db_put(const char *family, const char *keys, char *value)
131 ast_mutex_lock(&dblock);
133 ast_mutex_unlock(&dblock);
137 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
138 memset(&key, 0, sizeof(key));
139 memset(&data, 0, sizeof(data));
141 key.size = fullkeylen + 1;
143 data.size = strlen(value) + 1;
144 res = astdb->put(astdb, &key, &data, 0);
145 astdb->sync(astdb, 0);
146 ast_mutex_unlock(&dblock);
148 ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
152 int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
154 char fullkey[256]="";
158 ast_mutex_lock(&dblock);
160 ast_mutex_unlock(&dblock);
164 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
165 memset(&key, 0, sizeof(key));
166 memset(&data, 0, sizeof(data));
167 memset(value, 0, valuelen);
169 key.size = fullkeylen + 1;
171 res = astdb->get(astdb, &key, &data, 0);
173 ast_mutex_unlock(&dblock);
175 /* Be sure to NULL terminate our data either way */
177 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
180 printf("Got value of size %d\n", data.size);
183 ((char *)data.data)[data.size - 1] = '\0';
184 /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */
185 strncpy(value, data.data, (valuelen > data.size) ? data.size : valuelen);
186 value[valuelen - 1] = '\0';
188 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
194 int ast_db_del(const char *family, const char *keys)
200 ast_mutex_lock(&dblock);
202 ast_mutex_unlock(&dblock);
206 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
207 memset(&key, 0, sizeof(key));
209 key.size = fullkeylen + 1;
211 res = astdb->del(astdb, &key, 0);
212 astdb->sync(astdb, 0);
214 ast_mutex_unlock(&dblock);
217 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
221 static int database_put(int fd, int argc, char *argv[])
225 return RESULT_SHOWUSAGE;
226 res = ast_db_put(argv[2], argv[3], argv[4]);
228 ast_cli(fd, "Failed to update entry\n");
230 ast_cli(fd, "Updated database successfully\n");
231 return RESULT_SUCCESS;
234 static int database_get(int fd, int argc, char *argv[])
239 return RESULT_SHOWUSAGE;
240 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
242 ast_cli(fd, "Database entry not found.\n");
244 ast_cli(fd, "Value: %s\n", tmp);
245 return RESULT_SUCCESS;
248 static int database_del(int fd, int argc, char *argv[])
252 return RESULT_SHOWUSAGE;
253 res = ast_db_del(argv[2], argv[3]);
255 ast_cli(fd, "Database entry does not exist.\n");
257 ast_cli(fd, "Database entry removed.\n");
258 return RESULT_SUCCESS;
261 static int database_deltree(int fd, int argc, char *argv[])
264 if ((argc < 3) || (argc > 4))
265 return RESULT_SHOWUSAGE;
267 res = ast_db_deltree(argv[2], argv[3]);
269 res = ast_db_deltree(argv[2], NULL);
271 ast_cli(fd, "Database entries do not exist.\n");
273 ast_cli(fd, "Database entries removed.\n");
274 return RESULT_SUCCESS;
277 static int database_show(int fd, int argc, char *argv[])
286 /* Family and key tree */
287 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
288 } else if (argc == 3) {
290 snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
291 } else if (argc == 2) {
295 return RESULT_SHOWUSAGE;
296 ast_mutex_lock(&dblock);
298 ast_mutex_unlock(&dblock);
299 ast_cli(fd, "Database unavailable\n");
300 return RESULT_SUCCESS;
302 memset(&key, 0, sizeof(key));
303 memset(&data, 0, sizeof(data));
305 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
308 keys[key.size - 1] = '\0';
313 values[data.size - 1]='\0';
315 values = "<bad value>";
316 if (keymatch(keys, prefix)) {
317 ast_cli(fd, "%-50s: %-25s\n", keys, values);
320 ast_mutex_unlock(&dblock);
321 return RESULT_SUCCESS;
324 static int database_showkey(int fd, int argc, char *argv[])
334 snprintf(suffix, sizeof(suffix), "/%s", argv[2]);
336 return RESULT_SHOWUSAGE;
337 ast_mutex_lock(&dblock);
339 ast_mutex_unlock(&dblock);
340 ast_cli(fd, "Database unavailable\n");
341 return RESULT_SUCCESS;
343 memset(&key, 0, sizeof(key));
344 memset(&data, 0, sizeof(data));
346 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
349 keys[key.size - 1] = '\0';
354 values[data.size - 1]='\0';
356 values = "<bad value>";
357 if (subkeymatch(keys, suffix)) {
358 ast_cli(fd, "%-50s: %-25s\n", keys, values);
361 ast_mutex_unlock(&dblock);
362 return RESULT_SUCCESS;
365 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
372 struct ast_db_entry *last = NULL;
373 struct ast_db_entry *cur, *ret=NULL;
375 if (family && !ast_strlen_zero(family)) {
376 if (keytree && !ast_strlen_zero(keytree))
377 /* Family and key tree */
378 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
381 snprintf(prefix, sizeof(prefix), "/%s", family);
384 ast_mutex_lock(&dblock);
386 ast_mutex_unlock(&dblock);
387 ast_log(LOG_WARNING, "Database unavailable\n");
390 memset(&key, 0, sizeof(key));
391 memset(&data, 0, sizeof(data));
393 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
396 keys[key.size - 1] = '\0';
401 values[data.size - 1]='\0';
403 values = "<bad value>";
404 if (keymatch(keys, prefix)) {
405 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
408 cur->key = cur->data + strlen(values) + 1;
409 strcpy(cur->data, values);
410 strcpy(cur->key, keys);
419 ast_mutex_unlock(&dblock);
423 void ast_db_freetree(struct ast_db_entry *dbe)
425 struct ast_db_entry *last;
433 static char database_show_usage[] =
434 "Usage: database show [family [keytree]]\n"
435 " Shows Asterisk database contents, optionally restricted\n"
436 "to a given family, or family and keytree.\n";
438 static char database_showkey_usage[] =
439 "Usage: database showkey <keytree>\n"
440 " Shows Asterisk database contents, restricted to a given key.\n";
442 static char database_put_usage[] =
443 "Usage: database put <family> <key> <value>\n"
444 " Adds or updates an entry in the Asterisk database for\n"
445 "a given family, key, and value.\n";
447 static char database_get_usage[] =
448 "Usage: database get <family> <key>\n"
449 " Retrieves an entry in the Asterisk database for a given\n"
452 static char database_del_usage[] =
453 "Usage: database del <family> <key>\n"
454 " Deletes an entry in the Asterisk database for a given\n"
457 static char database_deltree_usage[] =
458 "Usage: database deltree <family> [keytree]\n"
459 " Deletes a family or specific keytree within a family\n"
460 "in the Asterisk database.\n";
462 struct ast_cli_entry cli_database_show =
463 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
465 struct ast_cli_entry cli_database_showkey =
466 { { "database", "showkey", NULL }, database_showkey, "Shows database contents", database_showkey_usage };
468 struct ast_cli_entry cli_database_get =
469 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
471 struct ast_cli_entry cli_database_put =
472 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
474 struct ast_cli_entry cli_database_del =
475 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
477 struct ast_cli_entry cli_database_deltree =
478 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
480 static int manager_dbput(struct mansession *s, struct message *m)
482 char *family = astman_get_header(m, "Family");
483 char *key = astman_get_header(m, "Key");
484 char *val = astman_get_header(m, "Val");
487 if (!strlen(family)) {
488 astman_send_error(s, m, "No family specified");
492 astman_send_error(s, m, "No key specified");
496 astman_send_error(s, m, "No val specified");
500 res = ast_db_put(family, key, val);
502 astman_send_error(s, m, "Failed to update entry");
504 astman_send_ack(s, m, "Updated database successfully");
508 static int manager_dbget(struct mansession *s, struct message *m)
510 char *family = astman_get_header(m, "Family");
511 char *key = astman_get_header(m, "Key");
515 if (!strlen(family)) {
516 astman_send_error(s, m, "No family specified.");
520 astman_send_error(s, m, "No key specified.");
524 res = ast_db_get(family, key, tmp, sizeof(tmp));
526 astman_send_error(s, m, "Database entry not found");
528 astman_send_ack(s, m, "Result will follow");
529 ast_cli(s->fd, "Event: DBGetResponse\r\n"
541 ast_cli_register(&cli_database_show);
542 ast_cli_register(&cli_database_showkey);
543 ast_cli_register(&cli_database_get);
544 ast_cli_register(&cli_database_put);
545 ast_cli_register(&cli_database_del);
546 ast_cli_register(&cli_database_deltree);
547 ast_manager_register("DBGet", EVENT_FLAG_SYSTEM, manager_dbget, "Get DB Entry");
548 ast_manager_register("DBPut", EVENT_FLAG_SYSTEM, manager_dbput, "Put DB Entry");