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));
151 memset(value, 0, valuelen);
153 key.size = strlen(fullkey) + 1;
155 res = astdb->get(astdb, &key, &data, 0);
157 ast_pthread_mutex_unlock(&dblock);
159 /* 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 /* Make sure that we don't write too much to the dst pointer or we don't read too much from the source pointer */
169 strncpy(value, data.data, (valuelen > data.size) ? data.size : valuelen);
171 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
177 int ast_db_del(const char *family, const char *keys)
183 ast_pthread_mutex_lock(&dblock);
185 ast_pthread_mutex_unlock(&dblock);
189 snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
190 memset(&key, 0, sizeof(key));
192 key.size = strlen(fullkey) + 1;
194 res = astdb->del(astdb, &key, 0);
195 astdb->sync(astdb, 0);
197 ast_pthread_mutex_unlock(&dblock);
200 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
204 static int database_put(int fd, int argc, char *argv[])
208 return RESULT_SHOWUSAGE;
209 res = ast_db_put(argv[2], argv[3], argv[4]);
211 ast_cli(fd, "Failed to update entry\n");
213 ast_cli(fd, "Updated database successfully\n");
214 return RESULT_SUCCESS;
217 static int database_get(int fd, int argc, char *argv[])
222 return RESULT_SHOWUSAGE;
223 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
225 ast_cli(fd, "Database entry not found.\n");
227 ast_cli(fd, "Value: %s\n", tmp);
228 return RESULT_SUCCESS;
231 static int database_del(int fd, int argc, char *argv[])
235 return RESULT_SHOWUSAGE;
236 res = ast_db_del(argv[2], argv[3]);
238 ast_cli(fd, "Database entry does not exist.\n");
240 ast_cli(fd, "Database entry removed.\n");
241 return RESULT_SUCCESS;
244 static int database_deltree(int fd, int argc, char *argv[])
247 if ((argc < 3) || (argc > 4))
248 return RESULT_SHOWUSAGE;
250 res = ast_db_deltree(argv[2], argv[3]);
252 res = ast_db_deltree(argv[2], NULL);
254 ast_cli(fd, "Database entries do not exist.\n");
256 ast_cli(fd, "Database entries removed.\n");
257 return RESULT_SUCCESS;
260 static int database_show(int fd, int argc, char *argv[])
269 /* Family and key tree */
270 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
271 } else if (argc == 3) {
273 snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
274 } else if (argc == 2) {
278 return RESULT_SHOWUSAGE;
279 ast_pthread_mutex_lock(&dblock);
281 ast_pthread_mutex_unlock(&dblock);
282 ast_cli(fd, "Database unavailable\n");
283 return RESULT_SUCCESS;
285 memset(&key, 0, sizeof(key));
286 memset(&data, 0, sizeof(data));
288 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
291 keys[key.size - 1] = '\0';
296 values[data.size - 1]='\0';
298 values = "<bad value>";
299 if (keymatch(keys, prefix)) {
300 ast_cli(fd, "%-50s: %-25s\n", keys, values);
303 ast_pthread_mutex_unlock(&dblock);
304 return RESULT_SUCCESS;
307 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
314 struct ast_db_entry *last = NULL;
315 struct ast_db_entry *cur, *ret=NULL;
317 if (family && strlen(family)) {
318 if (keytree && strlen(keytree))
319 /* Family and key tree */
320 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
323 snprintf(prefix, sizeof(prefix), "/%s", family);
326 ast_pthread_mutex_lock(&dblock);
328 ast_pthread_mutex_unlock(&dblock);
329 ast_log(LOG_WARNING, "Database unavailable\n");
332 memset(&key, 0, sizeof(key));
333 memset(&data, 0, sizeof(data));
335 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
338 keys[key.size - 1] = '\0';
343 values[data.size - 1]='\0';
345 values = "<bad value>";
346 if (keymatch(keys, prefix)) {
347 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
350 cur->key = cur->data + strlen(values) + 1;
351 strcpy(cur->data, values);
352 strcpy(cur->key, keys);
361 ast_pthread_mutex_unlock(&dblock);
365 void ast_db_freetree(struct ast_db_entry *dbe)
367 struct ast_db_entry *last;
375 static char database_show_usage[] =
376 "Usage: database show [family [keytree]]\n"
377 " Shows Asterisk database contents, optionally restricted\n"
378 "to a given family, or family and keytree.\n";
380 static char database_put_usage[] =
381 "Usage: database put <family> <key> <value>\n"
382 " Adds or updates an entry in the Asterisk database for\n"
383 "a given family, key, and value.\n";
385 static char database_get_usage[] =
386 "Usage: database get <family> <key>\n"
387 " Retrieves an entry in the Asterisk database for a given\n"
390 static char database_del_usage[] =
391 "Usage: database del <family> <key>\n"
392 " Deletes an entry in the Asterisk database for a given\n"
395 static char database_deltree_usage[] =
396 "Usage: database deltree <family> [keytree]\n"
397 " Deletes a family or specific keytree within a family\n"
398 "in the Asterisk database.\n";
400 struct ast_cli_entry cli_database_show =
401 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
403 struct ast_cli_entry cli_database_get =
404 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
406 struct ast_cli_entry cli_database_put =
407 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
409 struct ast_cli_entry cli_database_del =
410 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
412 struct ast_cli_entry cli_database_deltree =
413 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
418 ast_cli_register(&cli_database_show);
419 ast_cli_register(&cli_database_get);
420 ast_cli_register(&cli_database_put);
421 ast_cli_register(&cli_database_del);
422 ast_cli_register(&cli_database_deltree);