39 #include <sys/types.h> 107 #define MAX_DB_FIELD 256 117 #define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \ 118 const char stmt##_sql[] = sql; 144 static
int init_stmt(sqlite3_stmt **stmt, const
char *sql,
size_t len)
147 if (sqlite3_prepare(
astdb, sql, len, stmt,
NULL) != SQLITE_OK) {
163 if (sqlite3_finalize(*stmt) != SQLITE_OK) {
181 clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
183 clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
184 clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
187 clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
194 return init_stmt(&get_stmt, get_stmt_sql,
sizeof(get_stmt_sql))
195 ||
init_stmt(&del_stmt, del_stmt_sql,
sizeof(del_stmt_sql))
196 ||
init_stmt(&deltree_stmt, deltree_stmt_sql,
sizeof(deltree_stmt_sql))
197 ||
init_stmt(&deltree_all_stmt, deltree_all_stmt_sql,
sizeof(deltree_all_stmt_sql))
198 ||
init_stmt(&gettree_stmt, gettree_stmt_sql,
sizeof(gettree_stmt_sql))
199 ||
init_stmt(&gettree_all_stmt, gettree_all_stmt_sql,
sizeof(gettree_all_stmt_sql))
200 ||
init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql,
sizeof(gettree_prefix_stmt_sql))
201 ||
init_stmt(&showkey_stmt, showkey_stmt_sql,
sizeof(showkey_stmt_sql))
202 ||
init_stmt(&put_stmt, put_stmt_sql,
sizeof(put_stmt_sql));
223 if (!create_astdb_stmt) {
224 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql,
sizeof(create_astdb_stmt_sql));
228 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
232 sqlite3_reset(create_astdb_stmt);
242 struct stat dont_care;
248 strcat(dbname,
".sqlite3");
258 ast_log(
LOG_ERROR,
"*** and re-run 'make menuselect' and select astdb2sqlite3\n");
259 ast_log(
LOG_ERROR,
"*** in the Utilities section, then 'make && make install'.\n");
260 ast_log(
LOG_ERROR,
"*** It is also imperative that the user under which\n");
261 ast_log(
LOG_ERROR,
"*** Asterisk runs have write permission to the directory\n");
270 if (sqlite3_open(dbname, &
astdb) != SQLITE_OK) {
272 sqlite3_close(
astdb);
298 static int db_execute_sql(
const char *sql,
int (*callback)(
void *,
int,
char **,
char **),
void *arg)
303 if (sqlite3_exec(
astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
305 sqlite3_free(errmsg);
333 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
334 ast_log(
LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
338 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
341 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
344 }
else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
347 }
else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
352 sqlite3_reset(put_stmt);
373 static int db_get_common(
const char *family,
const char *key,
char **buffer,
int bufferlen)
375 const unsigned char *
result;
380 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
381 ast_log(
LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
385 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
388 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
391 }
else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
392 ast_debug(1,
"Unable to find key '%s' in family '%s'\n", key, family);
394 }
else if (!(result = sqlite3_column_text(get_stmt, 0))) {
398 const char *
value = (
const char *) result;
400 if (bufferlen == -1) {
406 sqlite3_reset(get_stmt);
435 if (strlen(family) + strlen(key) + 2 >
sizeof(fullkey) - 1) {
436 ast_log(
LOG_WARNING,
"Family and key length must be less than %zu bytes\n",
sizeof(fullkey) - 3);
440 fullkey_len = snprintf(fullkey,
sizeof(fullkey),
"/%s/%s", family, key);
443 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
446 }
else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
447 ast_debug(1,
"Unable to find key '%s' in family '%s'\n", key, family);
450 sqlite3_reset(del_stmt);
459 sqlite3_stmt *stmt = deltree_stmt;
466 snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, keytree);
469 snprintf(prefix,
sizeof(prefix),
"/%s", family);
473 stmt = deltree_all_stmt;
477 if (!
ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
480 }
else if (sqlite3_step(stmt) != SQLITE_DONE) {
484 res = sqlite3_changes(
astdb);
496 while (sqlite3_step(stmt) == SQLITE_ROW) {
498 size_t key_len, value_len;
500 key = (
const char *) sqlite3_column_text(stmt, 0);
501 value = (
const char *) sqlite3_column_text(stmt, 1);
503 if (!key || !value) {
507 key_len = strlen(key);
508 value_len = strlen(value);
510 cur =
ast_malloc(
sizeof(*cur) + key_len + value_len + 2);
516 cur->key = cur->data + value_len + 1;
517 memcpy(cur->data, value, value_len + 1);
518 memcpy(cur->key, key, key_len + 1);
534 sqlite3_stmt *stmt = gettree_stmt;
541 res = snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, keytree);
544 res = snprintf(prefix,
sizeof(prefix),
"/%s", family);
547 if (res >=
sizeof(prefix)) {
553 stmt = gettree_all_stmt;
557 if (res && (sqlite3_bind_text(stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK)) {
577 res = snprintf(prefix,
sizeof(prefix),
"/%s/%s", family, key_prefix);
578 if (res >=
sizeof(prefix)) {
584 if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, res, SQLITE_STATIC) != SQLITE_OK) {
586 sqlite3_reset(gettree_prefix_stmt);
592 sqlite3_reset(gettree_prefix_stmt);
616 "Usage: database put <family> <key> <value>\n" 617 " Adds or updates an entry in the Asterisk database for\n" 618 " a given family, key, and value.\n";
628 ast_cli(a->
fd,
"Failed to update entry\n");
630 ast_cli(a->
fd,
"Updated database successfully\n");
644 "Usage: database get <family> <key>\n" 645 " Retrieves an entry in the Asterisk database for a given\n" 646 " family and key.\n";
656 ast_cli(a->
fd,
"Database entry not found.\n");
671 "Usage: database del <family> <key>\n" 672 " Deletes an entry in the Asterisk database for a given\n" 673 " family and key.\n";
683 ast_cli(a->
fd,
"Database entry does not exist.\n");
685 ast_cli(a->
fd,
"Database entry removed.\n");
696 e->
command =
"database deltree";
698 "Usage: database deltree <family> [keytree]\n" 699 " OR: database deltree <family>[/keytree]\n" 700 " Deletes a family or specific keytree within a family\n" 701 " in the Asterisk database. The two arguments may be\n" 702 " separated by either a space or a slash.\n";
715 if (num_deleted < 0) {
716 ast_cli(a->
fd,
"Database unavailable.\n");
717 }
else if (num_deleted == 0) {
718 ast_cli(a->
fd,
"Database entries do not exist.\n");
720 ast_cli(a->
fd,
"%d database entries removed.\n",num_deleted);
729 sqlite3_stmt *stmt = gettree_stmt;
735 "Usage: database show [family [keytree]]\n" 736 " OR: database show [family[/keytree]]\n" 737 " Shows Asterisk database contents, optionally restricted\n" 738 " to a given family, or family and keytree. The two arguments\n" 739 " may be separated either by a space or by a slash.\n";
747 snprintf(prefix,
sizeof(prefix),
"/%s/%s", a->
argv[2], a->
argv[3]);
748 }
else if (a->
argc == 3) {
750 snprintf(prefix,
sizeof(prefix),
"/%s", a->
argv[2]);
751 }
else if (a->
argc == 2) {
754 stmt = gettree_all_stmt;
761 if (!
ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, -1, SQLITE_STATIC) != SQLITE_OK)) {
768 while (sqlite3_step(stmt) == SQLITE_ROW) {
769 const char *key_s, *value_s;
770 if (!(key_s = (
const char *) sqlite3_column_text(stmt, 0))) {
774 if (!(value_s = (
const char *) sqlite3_column_text(stmt, 1))) {
779 ast_cli(a->
fd,
"%-50s: %-25s\n", key_s, value_s);
785 ast_cli(a->
fd,
"%d results found.\n", counter);
795 e->
command =
"database showkey";
797 "Usage: database showkey <keytree>\n" 798 " Shows Asterisk database contents, restricted to a given key.\n";
809 if (!
ast_strlen_zero(a->
argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->
argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
811 sqlite3_reset(showkey_stmt);
816 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
817 const char *key_s, *value_s;
818 if (!(key_s = (
const char *) sqlite3_column_text(showkey_stmt, 0))) {
821 if (!(value_s = (
const char *) sqlite3_column_text(showkey_stmt, 1))) {
825 ast_cli(a->
fd,
"%-50s: %-25s\n", key_s, value_s);
827 sqlite3_reset(showkey_stmt);
830 ast_cli(a->
fd,
"%d results found.\n", counter);
839 for (x = 0; x <
columns; x++) {
840 ast_cli(a->
fd,
"%-5s: %-50s\n", colnames[x], values[x]);
854 "Usage: database query \"<SQL Statement>\"\n" 855 " Run a user-specified SQL query on the database. Be careful.\n";
928 snprintf(idText,
sizeof(idText) ,
"ActionID: %s\r\n",
id);
930 res =
ast_db_get(family, key, tmp,
sizeof(tmp));
942 family, key, tmp, idText);
992 if (num_deleted < 0) {
994 }
else if (num_deleted == 0) {
1076 if (sqlite3_close(
astdb) == SQLITE_OK) {
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
static struct ast_cli_entry cli_database[]
#define AST_CLI_DEFINE(fn, txt,...)
static void astdb_atexit(void)
void astman_append(struct mansession *s, const char *fmt,...)
Asterisk main include file. File version handling, generic pbx functions.
const char * ast_config_AST_DB
const char * ast_config_AST_SBIN_DIR
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
static int manager_dbdel(struct mansession *s, const struct message *m)
static int ast_db_commit_transaction(void)
Convenient Signal Processing routines.
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
descriptor for a cli entry.
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
#define ast_cond_wait(cond, mutex)
#define ast_cond_init(cond, attr)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
#define ast_mutex_lock(a)
#define ast_strdup(str)
A wrapper for strdup()
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int init_statements(void)
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
void ast_cli(int fd, const char *fmt,...)
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
#define ast_cond_signal(cond)
static ast_mutex_t dblock
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
pthread_cond_t ast_cond_t
#define ast_strlen_zero(foo)
#define ast_pthread_create_background(a, b, c, d)
static pthread_t syncthread
#define EVENT_FLAG_SYSTEM
#define ast_debug(level,...)
Log a DEBUG message.
struct ast_db_entry * next
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
struct sla_ringing_trunk * last
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
In case you didn't read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
#define ast_malloc(len)
A wrapper for malloc()
#define DELETE(a, b, c, d)
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
static int display_results(void *arg, int columns, char **values, char **colnames)
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
static void clean_statements(void)
static void * db_sync_thread(void *data)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
struct ast_db_entry * ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
Get a list of values with the given key prefix.
static struct columns columns
static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
static struct ast_str * dbname
#define DEFINE_SQL_STATEMENT(stmt, sql)
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
Prototypes for public functions only of internal interest,.
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int manager_dbget(struct mansession *s, const struct message *m)
static int ast_db_rollback_transaction(void)
static int convert_bdb_to_sqlite3(void)
static int manager_dbput(struct mansession *s, const struct message *m)
static char * handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define EVENT_FLAG_REPORTING
static int manager_dbdeltree(struct mansession *s, const struct message *m)
static int db_create_astdb(void)
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
#define EXISTS(a, b, c, d)
int ast_db_get_allocated(const char *family, const char *key, char **out)
Get key value specified by family/key as a heap allocated string.
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
static int ast_db_begin_transaction(void)
Persistant data storage (akin to *doze registry)
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
#define AST_MUTEX_DEFINE_STATIC(mutex)
static void db_sync(void)
#define ast_mutex_unlock(a)
static char prefix[MAX_PREFIX]
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.