00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <stdio.h>
00019 #include <stdlib.h>
00020 #include <string.h>
00021 #include <sys/time.h>
00022 #include <signal.h>
00023 #include <errno.h>
00024 #include <unistd.h>
00025 #include <dirent.h>
00026 #include <asterisk/channel.h>
00027 #include <asterisk/file.h>
00028 #include <asterisk/app.h>
00029 #include <asterisk/dsp.h>
00030 #include <asterisk/logger.h>
00031 #include <asterisk/options.h>
00032 #include <asterisk/astdb.h>
00033 #include <asterisk/cli.h>
00034 #include <asterisk/utils.h>
00035 #include <asterisk/lock.h>
00036 #include "db1-ast/include/db.h"
00037 #include "asterisk.h"
00038 #include "astconf.h"
00039
00040 static DB *astdb;
00041 AST_MUTEX_DEFINE_STATIC(dblock);
00042
00043 static int dbinit(void)
00044 {
00045 if (!astdb) {
00046 if (!(astdb = dbopen((char *)ast_config_AST_DB, O_CREAT | O_RDWR, 0664, DB_BTREE, NULL))) {
00047 ast_log(LOG_WARNING, "Unable to open Asterisk database\n");
00048 }
00049 }
00050 if (astdb)
00051 return 0;
00052 return -1;
00053 }
00054
00055
00056 static inline int keymatch(const char *key, const char *prefix)
00057 {
00058 int preflen = strlen(prefix);
00059 if (!preflen)
00060 return 1;
00061 if (!strcasecmp(key, prefix))
00062 return 1;
00063 if ((strlen(key) > preflen) &&
00064 !strncasecmp(key, prefix, preflen)) {
00065 if (key[preflen] == '/')
00066 return 1;
00067 }
00068 return 0;
00069 }
00070
00071 int ast_db_deltree(const char *family, const char *keytree)
00072 {
00073 char prefix[256];
00074 DBT key, data;
00075 char *keys;
00076 int res;
00077 int pass;
00078
00079 if (family) {
00080 if (keytree)
00081 snprintf(prefix, sizeof(prefix), "/%s/%s", family, keytree);
00082 else
00083 snprintf(prefix, sizeof(prefix), "/%s", family);
00084 } else if (keytree)
00085 return -1;
00086 else
00087 prefix[0] = '\0';
00088
00089 ast_mutex_lock(&dblock);
00090 if (dbinit())
00091 return -1;
00092
00093 memset(&key, 0, sizeof(key));
00094 memset(&data, 0, sizeof(data));
00095 pass = 0;
00096 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00097 if (key.size) {
00098 keys = key.data;
00099 keys[key.size - 1] = '\0';
00100 } else
00101 keys = "<bad key>";
00102 if (keymatch(keys, prefix)) {
00103 astdb->del(astdb, &key, 0);
00104 }
00105 }
00106 astdb->sync(astdb, 0);
00107 ast_mutex_unlock(&dblock);
00108 return 0;
00109 }
00110
00111 int ast_db_put(const char *family, const char *keys, char *value)
00112 {
00113 char fullkey[256];
00114 DBT key, data;
00115 int res, fullkeylen;
00116
00117 ast_mutex_lock(&dblock);
00118 if (dbinit()) {
00119 ast_mutex_unlock(&dblock);
00120 return -1;
00121 }
00122
00123 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00124 memset(&key, 0, sizeof(key));
00125 memset(&data, 0, sizeof(data));
00126 key.data = fullkey;
00127 key.size = fullkeylen + 1;
00128 data.data = value;
00129 data.size = strlen(value) + 1;
00130 res = astdb->put(astdb, &key, &data, 0);
00131 astdb->sync(astdb, 0);
00132 ast_mutex_unlock(&dblock);
00133 if (res)
00134 ast_log(LOG_WARNING, "Unable to put value '%s' for key '%s' in family '%s'\n", value, keys, family);
00135 return res;
00136 }
00137
00138 int ast_db_get(const char *family, const char *keys, char *value, int valuelen)
00139 {
00140 char fullkey[256]="";
00141 DBT key, data;
00142 int res, fullkeylen;
00143
00144 ast_mutex_lock(&dblock);
00145 if (dbinit()) {
00146 ast_mutex_unlock(&dblock);
00147 return -1;
00148 }
00149
00150 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00151 memset(&key, 0, sizeof(key));
00152 memset(&data, 0, sizeof(data));
00153 memset(value, 0, valuelen);
00154 key.data = fullkey;
00155 key.size = fullkeylen + 1;
00156
00157 res = astdb->get(astdb, &key, &data, 0);
00158
00159 ast_mutex_unlock(&dblock);
00160
00161
00162 if (res) {
00163 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
00164 } else {
00165 #if 0
00166 printf("Got value of size %d\n", data.size);
00167 #endif
00168 if (data.size) {
00169 ((char *)data.data)[data.size - 1] = '\0';
00170
00171 strncpy(value, data.data, (valuelen > data.size) ? data.size : valuelen);
00172 value[valuelen - 1] = '\0';
00173 } else {
00174 ast_log(LOG_NOTICE, "Strange, empty value for /%s/%s\n", family, keys);
00175 }
00176 }
00177 return res;
00178 }
00179
00180 int ast_db_del(const char *family, const char *keys)
00181 {
00182 char fullkey[256];
00183 DBT key;
00184 int res, fullkeylen;
00185
00186 ast_mutex_lock(&dblock);
00187 if (dbinit()) {
00188 ast_mutex_unlock(&dblock);
00189 return -1;
00190 }
00191
00192 fullkeylen = snprintf(fullkey, sizeof(fullkey), "/%s/%s", family, keys);
00193 memset(&key, 0, sizeof(key));
00194 key.data = fullkey;
00195 key.size = fullkeylen + 1;
00196
00197 res = astdb->del(astdb, &key, 0);
00198 astdb->sync(astdb, 0);
00199
00200 ast_mutex_unlock(&dblock);
00201
00202 if (res)
00203 ast_log(LOG_DEBUG, "Unable to find key '%s' in family '%s'\n", keys, family);
00204 return res;
00205 }
00206
00207 static int database_put(int fd, int argc, char *argv[])
00208 {
00209 int res;
00210 if (argc != 5)
00211 return RESULT_SHOWUSAGE;
00212 res = ast_db_put(argv[2], argv[3], argv[4]);
00213 if (res)
00214 ast_cli(fd, "Failed to update entry\n");
00215 else
00216 ast_cli(fd, "Updated database successfully\n");
00217 return RESULT_SUCCESS;
00218 }
00219
00220 static int database_get(int fd, int argc, char *argv[])
00221 {
00222 int res;
00223 char tmp[256];
00224 if (argc != 4)
00225 return RESULT_SHOWUSAGE;
00226 res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
00227 if (res)
00228 ast_cli(fd, "Database entry not found.\n");
00229 else
00230 ast_cli(fd, "Value: %s\n", tmp);
00231 return RESULT_SUCCESS;
00232 }
00233
00234 static int database_del(int fd, int argc, char *argv[])
00235 {
00236 int res;
00237 if (argc != 4)
00238 return RESULT_SHOWUSAGE;
00239 res = ast_db_del(argv[2], argv[3]);
00240 if (res)
00241 ast_cli(fd, "Database entry does not exist.\n");
00242 else
00243 ast_cli(fd, "Database entry removed.\n");
00244 return RESULT_SUCCESS;
00245 }
00246
00247 static int database_deltree(int fd, int argc, char *argv[])
00248 {
00249 int res;
00250 if ((argc < 3) || (argc > 4))
00251 return RESULT_SHOWUSAGE;
00252 if (argc == 4)
00253 res = ast_db_deltree(argv[2], argv[3]);
00254 else
00255 res = ast_db_deltree(argv[2], NULL);
00256 if (res)
00257 ast_cli(fd, "Database entries do not exist.\n");
00258 else
00259 ast_cli(fd, "Database entries removed.\n");
00260 return RESULT_SUCCESS;
00261 }
00262
00263 static int database_show(int fd, int argc, char *argv[])
00264 {
00265 char prefix[256];
00266 DBT key, data;
00267 char *keys, *values;
00268 int res;
00269 int pass;
00270
00271 if (argc == 4) {
00272
00273 snprintf(prefix, sizeof(prefix), "/%s/%s", argv[2], argv[3]);
00274 } else if (argc == 3) {
00275
00276 snprintf(prefix, sizeof(prefix), "/%s", argv[2]);
00277 } else if (argc == 2) {
00278
00279 prefix[0] = '\0';
00280 } else
00281 return RESULT_SHOWUSAGE;
00282 ast_mutex_lock(&dblock);
00283 if (dbinit()) {
00284 ast_mutex_unlock(&dblock);
00285 ast_cli(fd, "Database unavailable\n");
00286 return RESULT_SUCCESS;
00287 }
00288 memset(&key, 0, sizeof(key));
00289 memset(&data, 0, sizeof(data));
00290 pass = 0;
00291 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00292 if (key.size) {
00293 keys = key.data;
00294 keys[key.size - 1] = '\0';
00295 } else
00296 keys = "<bad key>";
00297 if (data.size) {
00298 values = data.data;
00299 values[data.size - 1]='\0';
00300 } else
00301 values = "<bad value>";
00302 if (keymatch(keys, prefix)) {
00303 ast_cli(fd, "%-50s: %-25s\n", keys, values);
00304 }
00305 }
00306 ast_mutex_unlock(&dblock);
00307 return RESULT_SUCCESS;
00308 }
00309
00310 struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
00311 {
00312 char prefix[256];
00313 DBT key, data;
00314 char *keys, *values;
00315 int res;
00316 int pass;
00317 struct ast_db_entry *last = NULL;
00318 struct ast_db_entry *cur, *ret=NULL;
00319
00320 if (family && !ast_strlen_zero(family)) {
00321 if (keytree && !ast_strlen_zero(keytree))
00322
00323 snprintf(prefix, sizeof(prefix), "/%s/%s", family, prefix);
00324 else
00325
00326 snprintf(prefix, sizeof(prefix), "/%s", family);
00327 } else
00328 prefix[0] = '\0';
00329 ast_mutex_lock(&dblock);
00330 if (dbinit()) {
00331 ast_mutex_unlock(&dblock);
00332 ast_log(LOG_WARNING, "Database unavailable\n");
00333 return NULL;
00334 }
00335 memset(&key, 0, sizeof(key));
00336 memset(&data, 0, sizeof(data));
00337 pass = 0;
00338 while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00339 if (key.size) {
00340 keys = key.data;
00341 keys[key.size - 1] = '\0';
00342 } else
00343 keys = "<bad key>";
00344 if (data.size) {
00345 values = data.data;
00346 values[data.size - 1]='\0';
00347 } else
00348 values = "<bad value>";
00349 if (keymatch(keys, prefix)) {
00350 cur = malloc(sizeof(struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
00351 if (cur) {
00352 cur->next = NULL;
00353 cur->key = cur->data + strlen(values) + 1;
00354 strcpy(cur->data, values);
00355 strcpy(cur->key, keys);
00356 if (last)
00357 last->next = cur;
00358 else
00359 ret = cur;
00360 last = cur;
00361 }
00362 }
00363 }
00364 ast_mutex_unlock(&dblock);
00365 return ret;
00366 }
00367
00368 void ast_db_freetree(struct ast_db_entry *dbe)
00369 {
00370 struct ast_db_entry *last;
00371 while(dbe) {
00372 last = dbe;
00373 dbe = dbe->next;
00374 free(last);
00375 }
00376 }
00377
00378 static char database_show_usage[] =
00379 "Usage: database show [family [keytree]]\n"
00380 " Shows Asterisk database contents, optionally restricted\n"
00381 "to a given family, or family and keytree.\n";
00382
00383 static char database_put_usage[] =
00384 "Usage: database put <family> <key> <value>\n"
00385 " Adds or updates an entry in the Asterisk database for\n"
00386 "a given family, key, and value.\n";
00387
00388 static char database_get_usage[] =
00389 "Usage: database get <family> <key>\n"
00390 " Retrieves an entry in the Asterisk database for a given\n"
00391 "family and key.\n";
00392
00393 static char database_del_usage[] =
00394 "Usage: database del <family> <key>\n"
00395 " Deletes an entry in the Asterisk database for a given\n"
00396 "family and key.\n";
00397
00398 static char database_deltree_usage[] =
00399 "Usage: database deltree <family> [keytree]\n"
00400 " Deletes a family or specific keytree within a family\n"
00401 "in the Asterisk database.\n";
00402
00403 struct ast_cli_entry cli_database_show =
00404 { { "database", "show", NULL }, database_show, "Shows database contents", database_show_usage };
00405
00406 struct ast_cli_entry cli_database_get =
00407 { { "database", "get", NULL }, database_get, "Gets database value", database_get_usage };
00408
00409 struct ast_cli_entry cli_database_put =
00410 { { "database", "put", NULL }, database_put, "Adds/updates database value", database_put_usage };
00411
00412 struct ast_cli_entry cli_database_del =
00413 { { "database", "del", NULL }, database_del, "Removes database key/value", database_del_usage };
00414
00415 struct ast_cli_entry cli_database_deltree =
00416 { { "database", "deltree", NULL }, database_deltree, "Removes database keytree/values", database_deltree_usage };
00417
00418 int astdb_init(void)
00419 {
00420 dbinit();
00421 ast_cli_register(&cli_database_show);
00422 ast_cli_register(&cli_database_get);
00423 ast_cli_register(&cli_database_put);
00424 ast_cli_register(&cli_database_del);
00425 ast_cli_register(&cli_database_deltree);
00426 return 0;
00427 }