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 */
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 "db1-ast/include/db.h"
40 static pthread_mutex_t dblock = AST_MUTEX_INITIALIZER;
42 static int dbinit(void)
45 if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
46 ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
55 static inline int keymatch(const char *key, const char *prefix)
59 if (!strcasecmp(key, prefix))
61 if ((strlen(key) > strlen(prefix)) &&
62 !strncasecmp(key, prefix, strlen(prefix))) {
63 if (key[strlen(prefix)] == '/')
69 int ast_db_deltree(const char *family, const char *keytree)
79 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
81 snprintf(prefix, sizeof(prefix), "/%s", family);
87 ast_pthread_mutex_lock(&dblock);
91 memset(&key, 0, sizeof(key));
92 memset(&data, 0, sizeof(data));
94 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
97 keys[key.size - 1] = '\0';
100 if (keymatch(keys, prefix)) {
101 astdb->del(astdb, &key, 0);
104 astdb->sync(astdb, 0);
105 ast_pthread_mutex_unlock(&dblock);
109 int ast_db_put(const char *family, const char *keys, char *value)
115 ast_pthread_mutex_lock(&dblock);
117 ast_pthread_mutex_unlock(&dblock);
121 snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
122 memset(&key, 0, sizeof(key));
123 memset(&data, 0, sizeof(data));
125 key.size = strlen(fullkey) + 1;
127 data.size = strlen(value) + 1;
128 res = astdb->put(astdb, &key, &data, 0);
129 astdb->sync(astdb, 0);
130 ast_pthread_mutex_unlock(&dblock);
132 ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
136 int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
142 ast_pthread_mutex_lock(&dblock);
144 ast_pthread_mutex_unlock(&dblock);
148 snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
149 memset(&key, 0, sizeof(key));
150 memset(&data, 0, sizeof(data));
152 key.size = strlen(fullkey) + 1;
154 res = astdb->get(astdb, &key, &data, 0);
156 ast_pthread_mutex_unlock(&dblock);
158 /* Be sure to NULL terminate our data either way */
161 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
164 printf("Got value of size %d\n", data.size);
167 ((char *)data.data)[data.size - 1] = '\0';
168 strncpy(value, data.data, valuelen - 1);
169 value[valuelen - 1] = '\0';
171 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
178 int ast_db_del(const char *family, const char *keys)
184 ast_pthread_mutex_lock(&dblock);
186 ast_pthread_mutex_unlock(&dblock);
190 snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
191 memset(&key, 0, sizeof(key));
193 key.size = strlen(fullkey) + 1;
195 res = astdb->del(astdb, &key, 0);
196 astdb->sync(astdb, 0);
198 ast_pthread_mutex_unlock(&dblock);
201 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
205 static int database_put(int fd, int argc, char *argv[])
209 return RESULT_SHOWUSAGE;
210 res = ast_db_put(argv[2], argv[3], argv[4]);
212 ast_cli(fd, "Failed to update entry\n");
214 ast_cli(fd, "Updated database successfully\n");
215 return RESULT_SUCCESS;
218 static int database_get(int fd, int argc, char *argv[])
223 return RESULT_SHOWUSAGE;
224 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
226 ast_cli(fd, "Database entry not found.\n");
228 ast_cli(fd, "Value: %s\n", tmp);
229 return RESULT_SUCCESS;
232 static int database_del(int fd, int argc, char *argv[])
236 return RESULT_SHOWUSAGE;
237 res = ast_db_del(argv[2], argv[3]);
239 ast_cli(fd, "Database entry does not exist.\n");
241 ast_cli(fd, "Database entry removed.\n");
242 return RESULT_SUCCESS;
245 static int database_deltree(int fd, int argc, char *argv[])
248 if ((argc < 3) || (argc > 4))
249 return RESULT_SHOWUSAGE;
251 res = ast_db_deltree(argv[2], argv[3]);
253 res = ast_db_deltree(argv[2], NULL);
255 ast_cli(fd, "Database entries do not exist.\n");
257 ast_cli(fd, "Database entries removed.\n");
258 return RESULT_SUCCESS;
261 static int database_show(int fd, int argc, char *argv[])
270 /* Family and key tree */
271 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
272 } else if (argc == 3) {
274 snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
275 } else if (argc == 2) {
279 return RESULT_SHOWUSAGE;
280 ast_pthread_mutex_lock(&dblock);
282 ast_pthread_mutex_unlock(&dblock);
283 ast_cli(fd, "Database unavailable\n");
284 return RESULT_SUCCESS;
286 memset(&key, 0, sizeof(key));
287 memset(&data, 0, sizeof(data));
289 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
292 keys[key.size - 1] = '\0';
297 values[data.size - 1]='\0';
299 values = "<bad value>";
300 if (keymatch(keys, prefix)) {
301 ast_cli(fd, "%-50s: %-25s\n", keys, values);
304 ast_pthread_mutex_unlock(&dblock);
305 return RESULT_SUCCESS;
308 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
315 struct ast_db_entry *last = NULL;
316 struct ast_db_entry *cur, *ret=NULL;
318 if (family && strlen(family)) {
319 if (keytree && strlen(keytree))
320 /* Family and key tree */
321 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
324 snprintf(prefix, sizeof(prefix), "/%s", family);
327 ast_pthread_mutex_lock(&dblock);
329 ast_pthread_mutex_unlock(&dblock);
330 ast_log(LOG_WARNING, "Database unavailable\n");
333 memset(&key, 0, sizeof(key));
334 memset(&data, 0, sizeof(data));
336 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
339 keys[key.size - 1] = '\0';
344 values[data.size - 1]='\0';
346 values = "<bad value>";
347 if (keymatch(keys, prefix)) {
348 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
351 cur->key = cur->data + strlen(values) + 1;
352 strcpy(cur->data, values);
353 strcpy(cur->key, keys);
362 ast_pthread_mutex_unlock(&dblock);
366 void ast_db_freetree(struct ast_db_entry *dbe)
368 struct ast_db_entry *last;
376 static char database_show_usage[] =
377 "Usage: database show [family [keytree]]\n"
378 " Shows Asterisk database contents, optionally restricted\n"
379 "to a given family, or family and keytree.\n";
381 static char database_put_usage[] =
382 "Usage: database put <family> <key> <value>\n"
383 " Adds or updates an entry in the Asterisk database for\n"
384 "a given family, key, and value.\n";
386 static char database_get_usage[] =
387 "Usage: database get <family> <key>\n"
388 " Retrieves an entry in the Asterisk database for a given\n"
391 static char database_del_usage[] =
392 "Usage: database del <family> <key>\n"
393 " Deletes an entry in the Asterisk database for a given\n"
396 static char database_deltree_usage[] =
397 "Usage: database deltree <family> [keytree]\n"
398 " Deletes a family or specific keytree within a family\n"
399 "in the Asterisk database.\n";
401 struct ast_cli_entry cli_database_show =
402 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
404 struct ast_cli_entry cli_database_get =
405 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
407 struct ast_cli_entry cli_database_put =
408 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
410 struct ast_cli_entry cli_database_del =
411 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
413 struct ast_cli_entry cli_database_deltree =
414 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
419 ast_cli_register(&cli_database_show);
420 ast_cli_register(&cli_database_get);
421 ast_cli_register(&cli_database_put);
422 ast_cli_register(&cli_database_del);
423 ast_cli_register(&cli_database_deltree);