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 <pthread.h>
00021
#include <string.h>
00022
#include <sys/time.h>
00023
#include <signal.h>
00024
#include <errno.h>
00025
#include <unistd.h>
00026
#include <dirent.h>
00027
#include <asterisk/channel.h>
00028
#include <asterisk/file.h>
00029
#include <asterisk/app.h>
00030
#include <asterisk/dsp.h>
00031
#include <asterisk/logger.h>
00032
#include <asterisk/options.h>
00033
#include <asterisk/astdb.h>
00034
#include <asterisk/cli.h>
00035
#include <asterisk/utils.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 strcpy(prefix,
"");
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 }
else {
00173
ast_log(
LOG_NOTICE,
"Strange, empty value for /%s/%s\n", family, keys);
00174 }
00175 }
00176
return res;
00177 }
00178
00179 int ast_db_del(
const char *family,
const char *keys)
00180 {
00181
char fullkey[256];
00182 DBT
key;
00183
int res, fullkeylen;
00184
00185
ast_mutex_lock(&dblock);
00186
if (dbinit()) {
00187
ast_mutex_unlock(&dblock);
00188
return -1;
00189 }
00190
00191 fullkeylen = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, keys);
00192 memset(&
key, 0,
sizeof(
key));
00193
key.data = fullkey;
00194
key.size = fullkeylen + 1;
00195
00196 res = astdb->del(astdb, &
key, 0);
00197 astdb->sync(astdb, 0);
00198
00199
ast_mutex_unlock(&dblock);
00200
00201
if (res)
00202
ast_log(
LOG_DEBUG,
"Unable to find key '%s' in family '%s'\n", keys, family);
00203
return res;
00204 }
00205
00206
static int database_put(
int fd,
int argc,
char *argv[])
00207 {
00208
int res;
00209
if (argc != 5)
00210
return RESULT_SHOWUSAGE;
00211 res =
ast_db_put(argv[2], argv[3], argv[4]);
00212
if (res)
00213
ast_cli(fd,
"Failed to update entry\n");
00214
else
00215
ast_cli(fd,
"Updated database successfully\n");
00216
return RESULT_SUCCESS;
00217 }
00218
00219
static int database_get(
int fd,
int argc,
char *argv[])
00220 {
00221
int res;
00222
char tmp[256];
00223
if (argc != 4)
00224
return RESULT_SHOWUSAGE;
00225 res =
ast_db_get(argv[2], argv[3], tmp,
sizeof(tmp));
00226
if (res)
00227
ast_cli(fd,
"Database entry not found.\n");
00228
else
00229
ast_cli(fd,
"Value: %s\n", tmp);
00230
return RESULT_SUCCESS;
00231 }
00232
00233
static int database_del(
int fd,
int argc,
char *argv[])
00234 {
00235
int res;
00236
if (argc != 4)
00237
return RESULT_SHOWUSAGE;
00238 res =
ast_db_del(argv[2], argv[3]);
00239
if (res)
00240
ast_cli(fd,
"Database entry does not exist.\n");
00241
else
00242
ast_cli(fd,
"Database entry removed.\n");
00243
return RESULT_SUCCESS;
00244 }
00245
00246
static int database_deltree(
int fd,
int argc,
char *argv[])
00247 {
00248
int res;
00249
if ((argc < 3) || (argc > 4))
00250
return RESULT_SHOWUSAGE;
00251
if (argc == 4)
00252 res =
ast_db_deltree(argv[2], argv[3]);
00253
else
00254 res =
ast_db_deltree(argv[2], NULL);
00255
if (res)
00256
ast_cli(fd,
"Database entries do not exist.\n");
00257
else
00258
ast_cli(fd,
"Database entries removed.\n");
00259
return RESULT_SUCCESS;
00260 }
00261
00262
static int database_show(
int fd,
int argc,
char *argv[])
00263 {
00264
char prefix[256];
00265 DBT
key, data;
00266
char *keys, *values;
00267
int res;
00268
int pass;
00269
00270
if (argc == 4) {
00271
00272 snprintf(prefix,
sizeof(prefix),
"/%s/%s", argv[2], argv[3]);
00273 }
else if (argc == 3) {
00274
00275 snprintf(prefix,
sizeof(prefix),
"/%s", argv[2]);
00276 }
else if (argc == 2) {
00277
00278 strcpy(prefix,
"");
00279 }
else
00280
return RESULT_SHOWUSAGE;
00281
ast_mutex_lock(&dblock);
00282
if (dbinit()) {
00283
ast_mutex_unlock(&dblock);
00284
ast_cli(fd,
"Database unavailable\n");
00285
return RESULT_SUCCESS;
00286 }
00287 memset(&key, 0,
sizeof(key));
00288 memset(&data, 0,
sizeof(data));
00289 pass = 0;
00290
while(!(res = astdb->seq(astdb, &key, &data, pass++ ? R_NEXT : R_FIRST))) {
00291
if (
key.size) {
00292 keys =
key.data;
00293 keys[
key.size - 1] =
'\0';
00294 }
else
00295 keys =
"<bad key>";
00296
if (data.size) {
00297 values = data.data;
00298 values[data.size - 1]=
'\0';
00299 }
else
00300 values =
"<bad value>";
00301
if (keymatch(keys, prefix)) {
00302
ast_cli(fd,
"%-50s: %-25s\n", keys, values);
00303 }
00304 }
00305
ast_mutex_unlock(&dblock);
00306
return RESULT_SUCCESS;
00307 }
00308
00309 struct ast_db_entry *
ast_db_gettree(
const char *family,
const char *keytree)
00310 {
00311
char prefix[256];
00312 DBT
key, data;
00313
char *keys, *values;
00314
int res;
00315
int pass;
00316
struct ast_db_entry *last = NULL;
00317
struct ast_db_entry *cur, *ret=NULL;
00318
00319
if (family && !ast_strlen_zero(family)) {
00320
if (keytree && !ast_strlen_zero(keytree))
00321
00322 snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, prefix);
00323
else
00324
00325 snprintf(prefix,
sizeof(prefix),
"/%s", family);
00326 }
else
00327 strcpy(prefix,
"");
00328
ast_mutex_lock(&dblock);
00329
if (dbinit()) {
00330
ast_mutex_unlock(&dblock);
00331
ast_log(
LOG_WARNING,
"Database unavailable\n");
00332
return NULL;
00333 }
00334 memset(&
key, 0,
sizeof(
key));
00335 memset(&data, 0,
sizeof(data));
00336 pass = 0;
00337
while(!(res = astdb->seq(astdb, &
key, &data, pass++ ? R_NEXT : R_FIRST))) {
00338
if (
key.size) {
00339 keys =
key.data;
00340 keys[
key.size - 1] =
'\0';
00341 }
else
00342 keys =
"<bad key>";
00343
if (data.size) {
00344 values = data.data;
00345 values[data.size - 1]=
'\0';
00346 }
else
00347 values =
"<bad value>";
00348
if (keymatch(keys, prefix)) {
00349 cur =
malloc(
sizeof(
struct ast_db_entry) + strlen(keys) + strlen(values) + 2);
00350
if (cur) {
00351 cur->next = NULL;
00352 cur->key = cur->data + strlen(values) + 1;
00353 strcpy(cur->data, values);
00354 strcpy(cur->key, keys);
00355
if (last)
00356 last->next = cur;
00357
else
00358 ret = cur;
00359 last = cur;
00360 }
00361 }
00362 }
00363
ast_mutex_unlock(&dblock);
00364
return ret;
00365 }
00366
00367 void ast_db_freetree(
struct ast_db_entry *dbe)
00368 {
00369
struct ast_db_entry *last;
00370
while(dbe) {
00371 last = dbe;
00372 dbe = dbe->
next;
00373
free(last);
00374 }
00375 }
00376
00377
static char database_show_usage[] =
00378
"Usage: database show [family [keytree]]\n"
00379
" Shows Asterisk database contents, optionally restricted\n"
00380
"to a given family, or family and keytree.\n";
00381
00382
static char database_put_usage[] =
00383
"Usage: database put <family> <key> <value>\n"
00384
" Adds or updates an entry in the Asterisk database for\n"
00385
"a given family, key, and value.\n";
00386
00387
static char database_get_usage[] =
00388
"Usage: database get <family> <key>\n"
00389
" Retrieves an entry in the Asterisk database for a given\n"
00390
"family and key.\n";
00391
00392
static char database_del_usage[] =
00393
"Usage: database del <family> <key>\n"
00394
" Deletes an entry in the Asterisk database for a given\n"
00395
"family and key.\n";
00396
00397
static char database_deltree_usage[] =
00398
"Usage: database deltree <family> [keytree]\n"
00399
" Deletes a family or specific keytree within a family\n"
00400
"in the Asterisk database.\n";
00401
00402 struct ast_cli_entry cli_database_show =
00403 { {
"database",
"show", NULL }, database_show,
"Shows database contents", database_show_usage };
00404
00405 struct ast_cli_entry cli_database_get =
00406 { {
"database",
"get", NULL }, database_get,
"Gets database value", database_get_usage };
00407
00408 struct ast_cli_entry cli_database_put =
00409 { {
"database",
"put", NULL }, database_put,
"Adds/updates database value", database_put_usage };
00410
00411 struct ast_cli_entry cli_database_del =
00412 { {
"database",
"del", NULL }, database_del,
"Removes database key/value", database_del_usage };
00413
00414 struct ast_cli_entry cli_database_deltree =
00415 { {
"database",
"deltree", NULL }, database_deltree,
"Removes database keytree/values", database_deltree_usage };
00416
00417 int astdb_init(
void)
00418 {
00419 dbinit();
00420
ast_cli_register(&
cli_database_show);
00421
ast_cli_register(&
cli_database_get);
00422
ast_cli_register(&
cli_database_put);
00423
ast_cli_register(&
cli_database_del);
00424
ast_cli_register(&
cli_database_deltree);
00425
return 0;
00426 }