Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
db.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2005, Digium, Inc.
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief ASTdb Management
22 *
23 * \author Mark Spencer <markster@digium.com>
24 *
25 * \note DB3 is licensed under Sleepycat Public License and is thus incompatible
26 * with GPL. To avoid having to make another exception (and complicate
27 * licensing even further) we elect to use DB1 which is BSD licensed
28 */
29
30/*** MODULEINFO
31 <support_level>core</support_level>
32 ***/
33
34#include "asterisk.h"
35
36#include "asterisk/_private.h"
37#include "asterisk/paths.h" /* use ast_config_AST_DB */
38#include <sys/time.h>
39#include <sys/types.h>
40#include <sys/stat.h>
41#include <unistd.h>
42#include <signal.h>
43#include <dirent.h>
44#include <sqlite3.h>
45
46#include "asterisk/channel.h"
47#include "asterisk/file.h"
48#include "asterisk/app.h"
49#include "asterisk/dsp.h"
50#include "asterisk/astdb.h"
51#include "asterisk/cli.h"
52#include "asterisk/utils.h"
53#include "asterisk/manager.h"
54
55/*** DOCUMENTATION
56 <manager name="DBGet" language="en_US">
57 <since>
58 <version>1.2.0</version>
59 </since>
60 <synopsis>
61 Get DB Entry.
62 </synopsis>
63 <syntax>
64 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
65 <parameter name="Family" required="true" />
66 <parameter name="Key" required="true" />
67 </syntax>
68 <description>
69 </description>
70 </manager>
71 <manager name="DBGetTree" language="en_US">
72 <since>
73 <version>19.6.0</version>
74 <version>18.14.0</version>
75 <version>16.28.0</version>
76 </since>
77 <synopsis>
78 Get DB entries, optionally at a particular family/key
79 </synopsis>
80 <syntax>
81 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
82 <parameter name="Family" required="false" />
83 <parameter name="Key" required="false" />
84 </syntax>
85 <description>
86 </description>
87 </manager>
88 <manager name="DBPut" language="en_US">
89 <since>
90 <version>1.2.0</version>
91 </since>
92 <synopsis>
93 Put DB entry.
94 </synopsis>
95 <syntax>
96 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
97 <parameter name="Family" required="true" />
98 <parameter name="Key" required="true" />
99 <parameter name="Val" />
100 </syntax>
101 <description>
102 </description>
103 </manager>
104 <manager name="DBDel" language="en_US">
105 <since>
106 <version>1.6.0</version>
107 </since>
108 <synopsis>
109 Delete DB entry.
110 </synopsis>
111 <syntax>
112 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
113 <parameter name="Family" required="true" />
114 <parameter name="Key" required="true" />
115 </syntax>
116 <description>
117 </description>
118 </manager>
119 <manager name="DBDelTree" language="en_US">
120 <since>
121 <version>1.6.0</version>
122 </since>
123 <synopsis>
124 Delete DB Tree.
125 </synopsis>
126 <syntax>
127 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
128 <parameter name="Family" required="true" />
129 <parameter name="Key" />
130 </syntax>
131 <description>
132 </description>
133 </manager>
134 ***/
135
138static sqlite3 *astdb;
139static pthread_t syncthread;
140static int doexit;
141static int dosync;
142
143static void db_sync(void);
144
145#define DEFINE_SQL_STATEMENT(stmt,sql) static sqlite3_stmt *stmt; \
146 const char stmt##_sql[] = sql;
147
148DEFINE_SQL_STATEMENT(put_stmt, "INSERT OR REPLACE INTO astdb (key, value) VALUES (?, ?)")
149DEFINE_SQL_STATEMENT(get_stmt, "SELECT value FROM astdb WHERE key=?")
150DEFINE_SQL_STATEMENT(exists_stmt, "SELECT CAST(COUNT(1) AS INTEGER) AS 'exists' FROM astdb WHERE key=?")
151DEFINE_SQL_STATEMENT(del_stmt, "DELETE FROM astdb WHERE key=?")
152DEFINE_SQL_STATEMENT(deltree_stmt, "DELETE FROM astdb WHERE key || '/' LIKE ? || '/' || '%'")
153DEFINE_SQL_STATEMENT(deltree_all_stmt, "DELETE FROM astdb")
154DEFINE_SQL_STATEMENT(gettree_stmt, "SELECT key, value FROM astdb WHERE key || '/' LIKE ? || '/' || '%' ORDER BY key")
155DEFINE_SQL_STATEMENT(gettree_all_stmt, "SELECT key, value FROM astdb ORDER BY key")
156DEFINE_SQL_STATEMENT(showkey_stmt, "SELECT key, value FROM astdb WHERE key LIKE '%' || '/' || ? ORDER BY key")
157DEFINE_SQL_STATEMENT(create_astdb_stmt, "CREATE TABLE IF NOT EXISTS astdb(key TEXT, value TEXT, PRIMARY KEY(key))")
158
159/* This query begs an explanation:
160 *
161 * First, the parameter binding syntax used here is slightly different than the other
162 * queries in that we use a numbered parameter so that we can bind once and get the same
163 * value substituted multiple times within the executed query.
164 *
165 * Second, the key comparison is being used to find all keys that are lexicographically
166 * greater than the provided key, but less than the provided key with a high (but
167 * invalid) Unicode codepoint appended to it. This will give us all keys in the database
168 * that have 'key' as a prefix and performs much better than the equivalent "LIKE key ||
169 * '%'" operation.
170 */
171DEFINE_SQL_STATEMENT(gettree_prefix_stmt, "SELECT key, value FROM astdb WHERE key > ?1 AND key <= ?1 || X'ffff'")
172
173static int init_stmt(sqlite3_stmt **stmt, const char *sql, size_t len)
174{
176 if (sqlite3_prepare(astdb, sql, len, stmt, NULL) != SQLITE_OK) {
177 ast_log(LOG_WARNING, "Couldn't prepare statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
179 return -1;
180 }
182
183 return 0;
184}
185
186/*! \internal
187 * \brief Clean up the prepared SQLite3 statement
188 * \note dblock should already be locked prior to calling this method
189 */
190static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
191{
192 if (sqlite3_finalize(*stmt) != SQLITE_OK) {
193 ast_log(LOG_WARNING, "Couldn't finalize statement '%s': %s\n", sql, sqlite3_errmsg(astdb));
194 *stmt = NULL;
195 return -1;
196 }
197 *stmt = NULL;
198 return 0;
199}
200
201/*! \internal
202 * \brief Clean up all prepared SQLite3 statements
203 * \note dblock should already be locked prior to calling this method
204 */
205static void clean_statements(void)
206{
207 clean_stmt(&get_stmt, get_stmt_sql);
208 clean_stmt(&exists_stmt, exists_stmt_sql);
209 clean_stmt(&del_stmt, del_stmt_sql);
210 clean_stmt(&deltree_stmt, deltree_stmt_sql);
211 clean_stmt(&deltree_all_stmt, deltree_all_stmt_sql);
212 clean_stmt(&gettree_stmt, gettree_stmt_sql);
213 clean_stmt(&gettree_all_stmt, gettree_all_stmt_sql);
214 clean_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql);
215 clean_stmt(&showkey_stmt, showkey_stmt_sql);
216 clean_stmt(&put_stmt, put_stmt_sql);
217 clean_stmt(&create_astdb_stmt, create_astdb_stmt_sql);
218}
219
220static int init_statements(void)
221{
222 /* Don't initialize create_astdb_statement here as the astdb table needs to exist
223 * before these statements can be initialized */
224 return init_stmt(&get_stmt, get_stmt_sql, sizeof(get_stmt_sql))
225 || init_stmt(&exists_stmt, exists_stmt_sql, sizeof(exists_stmt_sql))
226 || init_stmt(&del_stmt, del_stmt_sql, sizeof(del_stmt_sql))
227 || init_stmt(&deltree_stmt, deltree_stmt_sql, sizeof(deltree_stmt_sql))
228 || init_stmt(&deltree_all_stmt, deltree_all_stmt_sql, sizeof(deltree_all_stmt_sql))
229 || init_stmt(&gettree_stmt, gettree_stmt_sql, sizeof(gettree_stmt_sql))
230 || init_stmt(&gettree_all_stmt, gettree_all_stmt_sql, sizeof(gettree_all_stmt_sql))
231 || init_stmt(&gettree_prefix_stmt, gettree_prefix_stmt_sql, sizeof(gettree_prefix_stmt_sql))
232 || init_stmt(&showkey_stmt, showkey_stmt_sql, sizeof(showkey_stmt_sql))
233 || init_stmt(&put_stmt, put_stmt_sql, sizeof(put_stmt_sql));
234}
235
236static int db_create_astdb(void)
237{
238 int res = 0;
239
240 if (!create_astdb_stmt) {
241 init_stmt(&create_astdb_stmt, create_astdb_stmt_sql, sizeof(create_astdb_stmt_sql));
242 }
243
245 if (sqlite3_step(create_astdb_stmt) != SQLITE_DONE) {
246 ast_log(LOG_WARNING, "Couldn't create astdb table: %s\n", sqlite3_errmsg(astdb));
247 res = -1;
248 }
249 sqlite3_reset(create_astdb_stmt);
250 db_sync();
252
253 return res;
254}
255
256static int db_open(void)
257{
258 struct stat dont_care;
259 char dbname[strlen(ast_config_AST_DB) + sizeof(".sqlite3")];
260
261 strcpy(dbname, ast_config_AST_DB);
262 strcat(dbname, ".sqlite3");
263
264 if (stat(dbname, &dont_care) && !stat(ast_config_AST_DB, &dont_care)) {
265 ast_log(LOG_ERROR, "When Asterisk 10.0.0 was released, the format of Asterisk's internal\n");
266 ast_log(LOG_ERROR, "database was changed from Berkeley DB to SQLite3. Part of that change\n");
267 ast_log(LOG_ERROR, "involved the creation of a conversion utility - astdb2sqlite3 - that\n");
268 ast_log(LOG_ERROR, "was shipped with Asterisk. This conversion utility performed a\n");
269 ast_log(LOG_ERROR, "one-time migration from the old format to the new one.\n");
270 ast_log(LOG_ERROR, "\n");
271 ast_log(LOG_ERROR, "Starting with Asterisk 23.0.0, astdb2sqlite3 no longer ships as part\n");
272 ast_log(LOG_ERROR, "of the Asterisk distribution. If you are upgrading from a version of\n");
273 ast_log(LOG_ERROR, "Asterisk that still uses the Berkeley DB implementation, you will need\n");
274 ast_log(LOG_ERROR, "to acquire astdb2sqlite3 from an earlier release of Asterisk.\n");
275 }
276
278 if (sqlite3_open(dbname, &astdb) != SQLITE_OK) {
279 ast_log(LOG_WARNING, "Unable to open Asterisk database '%s': %s\n", dbname, sqlite3_errmsg(astdb));
280 sqlite3_close(astdb);
282 return -1;
283 }
284
286
287 return 0;
288}
289
290static int db_init(void)
291{
292 if (astdb) {
293 return 0;
294 }
295
296 if (db_open() || db_create_astdb() || init_statements()) {
297 return -1;
298 }
299
300 return 0;
301}
302
303/* We purposely don't lock around the sqlite3 call because the transaction
304 * calls will be called with the database lock held. For any other use, make
305 * sure to take the dblock yourself. */
306static int db_execute_sql(const char *sql, int (*callback)(void *, int, char **, char **), void *arg)
307{
308 char *errmsg = NULL;
309 int res =0;
310
311 if (sqlite3_exec(astdb, sql, callback, arg, &errmsg) != SQLITE_OK) {
312 ast_log(LOG_WARNING, "Error executing SQL (%s): %s\n", sql, errmsg);
313 sqlite3_free(errmsg);
314 res = -1;
315 }
316
317 return res;
318}
319
321{
322 return db_execute_sql("BEGIN TRANSACTION", NULL, NULL);
323}
324
326{
327 return db_execute_sql("COMMIT", NULL, NULL);
328}
329
331{
332 return db_execute_sql("ROLLBACK", NULL, NULL);
333}
334
335int ast_db_put(const char *family, const char *key, const char *value)
336{
337 char *fullkey;
338 int fullkey_len;
339 int res = 0;
340
341 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
342 if (fullkey_len < 0) {
343 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
344 family, key);
345 return -1;
346 }
347
349 if (sqlite3_bind_text(put_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
350 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
351 res = -1;
352 } else if (sqlite3_bind_text(put_stmt, 2, value, -1, SQLITE_STATIC) != SQLITE_OK) {
353 ast_log(LOG_WARNING, "Couldn't bind value to stmt: %s\n", sqlite3_errmsg(astdb));
354 res = -1;
355 } else if (sqlite3_step(put_stmt) != SQLITE_DONE) {
356 ast_log(LOG_WARNING, "Couldn't execute statement: %s\n", sqlite3_errmsg(astdb));
357 res = -1;
358 }
359 sqlite3_reset(put_stmt);
360 db_sync();
362 ast_free(fullkey);
363
364 return res;
365}
366
367/*!
368 * \internal
369 * \brief Get key value specified by family/key.
370 *
371 * Gets the value associated with the specified \a family and \a key, and
372 * stores it, either into the fixed sized buffer specified by \a buffer
373 * and \a bufferlen, or as a heap allocated string if \a bufferlen is -1.
374 *
375 * \note If \a bufferlen is -1, \a buffer points to heap allocated memory
376 * and must be freed by calling ast_free().
377 *
378 * \retval -1 An error occurred
379 * \retval 0 Success
380 */
381static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
382{
383 const unsigned char *result;
384 char *fullkey;
385 int fullkey_len;
386 int res = 0;
387
388 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
389 if (fullkey_len < 0) {
390 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
391 family, key);
392 return -1;
393 }
394
396 if (sqlite3_bind_text(get_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
397 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
398 res = -1;
399 } else if (sqlite3_step(get_stmt) != SQLITE_ROW) {
400 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
401 res = -1;
402 } else if (!(result = sqlite3_column_text(get_stmt, 0))) {
403 ast_log(LOG_WARNING, "Couldn't get value\n");
404 res = -1;
405 } else {
406 const char *value = (const char *) result;
407
408 if (bufferlen == -1) {
409 *buffer = ast_strdup(value);
410 } else {
411 ast_copy_string(*buffer, value, bufferlen);
412 }
413 }
414 sqlite3_reset(get_stmt);
416 ast_free(fullkey);
417
418 return res;
419}
420
421int ast_db_get(const char *family, const char *key, char *value, int valuelen)
422{
424
425 /* Make sure we initialize */
426 value[0] = 0;
427
428 return db_get_common(family, key, &value, valuelen);
429}
430
431int ast_db_get_allocated(const char *family, const char *key, char **out)
432{
433 *out = NULL;
434
435 return db_get_common(family, key, out, -1);
436}
437
438int ast_db_exists(const char *family, const char *key)
439{
440 int result;
441 char *fullkey;
442 int fullkey_len;
443 int res = 0;
444
445 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
446 if (fullkey_len < 0) {
447 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
448 family, key);
449 return -1;
450 }
451
453 res = sqlite3_bind_text(exists_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC);
454 if (res != SQLITE_OK) {
455 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %d:%s\n", res, sqlite3_errmsg(astdb));
456 res = 0;
457 } else if (sqlite3_step(exists_stmt) != SQLITE_ROW) {
458 res = 0;
459 } else if (!(result = sqlite3_column_int(exists_stmt, 0))) {
460 res = 0;
461 } else {
462 res = result;
463 }
464 sqlite3_reset(exists_stmt);
466 ast_free(fullkey);
467
468 return res;
469}
470
471
472int ast_db_del(const char *family, const char *key)
473{
474 char *fullkey;
475 int fullkey_len;
476 int res = 0;
477
478 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
479 if (fullkey_len < 0) {
480 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
481 family, key);
482 return -1;
483 }
484
486 if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
487 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
488 res = -1;
489 } else if (sqlite3_step(del_stmt) != SQLITE_DONE) {
490 ast_debug(1, "Unable to find key '%s' in family '%s'\n", key, family);
491 res = -1;
492 }
493 sqlite3_reset(del_stmt);
494 db_sync();
496 ast_free(fullkey);
497
498 return res;
499}
500
501int ast_db_del2(const char *family, const char *key)
502{
503 char *fullkey;
504 char tmp[1];
505 int fullkey_len;
506 int mres, res = 0;
507
508 fullkey_len = ast_asprintf(&fullkey, "/%s/%s", family, key);
509 if (fullkey_len < 0) {
510 ast_log(LOG_WARNING, "Unable to allocate memory for family/key '/%s/%s'\n",
511 family, key);
512 return -1;
513 }
514
516 if (ast_db_get(family, key, tmp, sizeof(tmp))) {
517 ast_log(LOG_WARNING, "AstDB key %s does not exist\n", fullkey);
518 res = -1;
519 } else if (sqlite3_bind_text(del_stmt, 1, fullkey, fullkey_len, SQLITE_STATIC) != SQLITE_OK) {
520 ast_log(LOG_WARNING, "Couldn't bind key to stmt: %s\n", sqlite3_errmsg(astdb));
521 res = -1;
522 } else if ((mres = sqlite3_step(del_stmt) != SQLITE_DONE)) {
523 ast_log(LOG_WARNING, "AstDB error (%s): %s\n", fullkey, sqlite3_errstr(mres));
524 res = -1;
525 }
526 sqlite3_reset(del_stmt);
527 db_sync();
529 ast_free(fullkey);
530
531 return res;
532}
533
534static char *create_prefix(const char *family, const char *keytree,
535 int *prefix_len)
536{
537 char *prefix = NULL;
538 *prefix_len = 0;
539
540 if (!ast_strlen_zero(family)) {
541 if (!ast_strlen_zero(keytree)) {
542 /* Family and key tree */
543 *prefix_len = ast_asprintf(&prefix, "/%s/%s", family, keytree);
544 } else {
545 /* Family only */
546 *prefix_len = ast_asprintf(&prefix, "/%s", family);
547 }
548 if (*prefix_len < 0) {
549 ast_log(LOG_WARNING, "Unable to allocate memory for family/keytree '/%s%s%s'\n",
550 S_OR(family, ""), S_COR(keytree, "/", ""), S_OR(keytree, ""));
551 return NULL;
552 }
553 } else {
554 prefix = ast_strdup("");
555 }
556 return prefix;
557}
558
559int ast_db_deltree(const char *family, const char *keytree)
560{
561 sqlite3_stmt *stmt = deltree_stmt;
562 char *prefix = NULL;
563 int prefix_len = 0;
564 int res = 0;
565
566 if (ast_strlen_zero(family) && !ast_strlen_zero(keytree)) {
567 ast_log(LOG_WARNING, "Key tree '%s' specified without family\n", keytree);
568 return -1;
569 }
570
571 prefix = create_prefix(family, keytree, &prefix_len);
572 if (!prefix) {
573 return -1;
574 }
575 if (prefix_len == 0) {
576 stmt = deltree_all_stmt;
577 }
578
580 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
581 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
582 res = -1;
583 } else if (sqlite3_step(stmt) != SQLITE_DONE) {
584 ast_log(LOG_WARNING, "Couldn't execute stmt: %s\n", sqlite3_errmsg(astdb));
585 res = -1;
586 }
587 res = sqlite3_changes(astdb);
588 sqlite3_reset(stmt);
589 db_sync();
592
593 return res;
594}
595
596static struct ast_db_entry *db_gettree_common(sqlite3_stmt *stmt)
597{
598 struct ast_db_entry *head = NULL, *prev = NULL, *cur;
599
600 while (sqlite3_step(stmt) == SQLITE_ROW) {
601 const char *key, *value;
602 size_t key_len, value_len;
603
604 key = (const char *) sqlite3_column_text(stmt, 0);
605 value = (const char *) sqlite3_column_text(stmt, 1);
606
607 if (!key || !value) {
608 break;
609 }
610
611 key_len = strlen(key);
612 value_len = strlen(value);
613
614 cur = ast_malloc(sizeof(*cur) + key_len + value_len + 2);
615 if (!cur) {
616 break;
617 }
618
619 cur->next = NULL;
620 cur->key = cur->data + value_len + 1;
621 memcpy(cur->data, value, value_len + 1);
622 memcpy(cur->key, key, key_len + 1);
623
624 if (prev) {
625 prev->next = cur;
626 } else {
627 head = cur;
628 }
629 prev = cur;
630 }
631
632 return head;
633}
634
635struct ast_db_entry *ast_db_gettree(const char *family, const char *keytree)
636{
637 char *prefix = NULL;
638 int prefix_len = 0;
639 sqlite3_stmt *stmt = gettree_stmt;
640 struct ast_db_entry *ret;
641
642 prefix = create_prefix(family, keytree, &prefix_len);
643 if (!prefix) {
644 return NULL;
645 }
646 if (prefix_len == 0) {
647 stmt = gettree_all_stmt;
648 }
649
651 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
652 ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
653 sqlite3_reset(stmt);
656 return NULL;
657 }
658
659 ret = db_gettree_common(stmt);
660 sqlite3_reset(stmt);
663
664 return ret;
665}
666
667struct ast_db_entry *ast_db_gettree_by_prefix(const char *family, const char *key_prefix)
668{
669 char *prefix = NULL;
670 int prefix_len = 0;
671 struct ast_db_entry *ret;
672
673 prefix = create_prefix(family, key_prefix, &prefix_len);
674 if (!prefix) {
675 return NULL;
676 }
677
679 if (sqlite3_bind_text(gettree_prefix_stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK) {
680 ast_log(LOG_WARNING, "Could not bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
681 sqlite3_reset(gettree_prefix_stmt);
684 return NULL;
685 }
686
687 ret = db_gettree_common(gettree_prefix_stmt);
688 sqlite3_reset(gettree_prefix_stmt);
691
692 return ret;
693}
694
696{
697 struct ast_db_entry *last;
698 while (dbe) {
699 last = dbe;
700 dbe = dbe->next;
701 ast_free(last);
702 }
703}
704
705static char *handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
706{
707 int res;
708
709 switch (cmd) {
710 case CLI_INIT:
711 e->command = "database put";
712 e->usage =
713 "Usage: database put <family> <key> <value>\n"
714 " Adds or updates an entry in the Asterisk database for\n"
715 " a given family, key, and value.\n";
716 return NULL;
717 case CLI_GENERATE:
718 return NULL;
719 }
720
721 if (a->argc != 5)
722 return CLI_SHOWUSAGE;
723 res = ast_db_put(a->argv[2], a->argv[3], a->argv[4]);
724 if (res) {
725 ast_cli(a->fd, "Failed to update entry\n");
726 } else {
727 ast_cli(a->fd, "Updated database successfully\n");
728 }
729 return CLI_SUCCESS;
730}
731
732static char *handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
733{
734 int res;
735 char *tmp = NULL;
736
737 switch (cmd) {
738 case CLI_INIT:
739 e->command = "database get";
740 e->usage =
741 "Usage: database get <family> <key>\n"
742 " Retrieves an entry in the Asterisk database for a given\n"
743 " family and key.\n";
744 return NULL;
745 case CLI_GENERATE:
746 return NULL;
747 }
748
749 if (a->argc != 4)
750 return CLI_SHOWUSAGE;
751 res = ast_db_get_allocated(a->argv[2], a->argv[3], &tmp);
752 if (res) {
753 ast_cli(a->fd, "Database entry not found.\n");
754 } else {
755 ast_cli(a->fd, "Value: %s\n", tmp);
756 ast_free(tmp);
757 }
758
759 return CLI_SUCCESS;
760}
761
762static char *handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
763{
764 int res;
765
766 switch (cmd) {
767 case CLI_INIT:
768 e->command = "database del";
769 e->usage =
770 "Usage: database del <family> <key>\n"
771 " Deletes an entry in the Asterisk database for a given\n"
772 " family and key.\n";
773 return NULL;
774 case CLI_GENERATE:
775 return NULL;
776 }
777
778 if (a->argc != 4)
779 return CLI_SHOWUSAGE;
780 res = ast_db_del2(a->argv[2], a->argv[3]);
781 if (res) {
782 ast_cli(a->fd, "Database entry could not be removed.\n");
783 } else {
784 ast_cli(a->fd, "Database entry removed.\n");
785 }
786 return CLI_SUCCESS;
787}
788
789static char *handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
790{
791 int num_deleted;
792
793 switch (cmd) {
794 case CLI_INIT:
795 e->command = "database deltree";
796 e->usage =
797 "Usage: database deltree <family> [keytree]\n"
798 " OR: database deltree <family>[/keytree]\n"
799 " Deletes a family or specific keytree within a family\n"
800 " in the Asterisk database. The two arguments may be\n"
801 " separated by either a space or a slash.\n";
802 return NULL;
803 case CLI_GENERATE:
804 return NULL;
805 }
806
807 if ((a->argc < 3) || (a->argc > 4))
808 return CLI_SHOWUSAGE;
809 if (a->argc == 4) {
810 num_deleted = ast_db_deltree(a->argv[2], a->argv[3]);
811 } else {
812 num_deleted = ast_db_deltree(a->argv[2], NULL);
813 }
814 if (num_deleted < 0) {
815 ast_cli(a->fd, "Database unavailable.\n");
816 } else if (num_deleted == 0) {
817 ast_cli(a->fd, "Database entries do not exist.\n");
818 } else {
819 ast_cli(a->fd, "%d database entries removed.\n",num_deleted);
820 }
821 return CLI_SUCCESS;
822}
823
824static char *handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
825{
826 char *prefix = NULL;
827 int prefix_len = 0;
828 const char *family = a->argc > 2 ? a->argv[2] : "";
829 const char *keytree = a->argc > 3 ? a->argv[3] : "";
830 int counter = 0;
831 sqlite3_stmt *stmt = gettree_stmt;
832
833 switch (cmd) {
834 case CLI_INIT:
835 e->command = "database show";
836 e->usage =
837 "Usage: database show [family [keytree]]\n"
838 " OR: database show [family[/keytree]]\n"
839 " Shows Asterisk database contents, optionally restricted\n"
840 " to a given family, or family and keytree. The two arguments\n"
841 " may be separated either by a space or by a slash.\n";
842 return NULL;
843 case CLI_GENERATE:
844 return NULL;
845 }
846
847 if (a->argc > 4) {
848 return CLI_SHOWUSAGE;
849 }
850
851 prefix = create_prefix(family, keytree, &prefix_len);
852 if (!prefix) {
853 return NULL;
854 }
855 if (prefix_len == 0) {
856 stmt = gettree_all_stmt;
857 }
858
860 if (prefix_len && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
861 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
862 sqlite3_reset(stmt);
865 return NULL;
866 }
867
868 while (sqlite3_step(stmt) == SQLITE_ROW) {
869 const char *key_s, *value_s;
870 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
871 ast_log(LOG_WARNING, "Skipping invalid key!\n");
872 continue;
873 }
874 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
875 ast_log(LOG_WARNING, "Skipping invalid value!\n");
876 continue;
877 }
878 ++counter;
879 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
880 }
881
882 sqlite3_reset(stmt);
885
886 ast_cli(a->fd, "%d results found.\n", counter);
887 return CLI_SUCCESS;
888}
889
890static char *handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
891{
892 int counter = 0;
893
894 switch (cmd) {
895 case CLI_INIT:
896 e->command = "database showkey";
897 e->usage =
898 "Usage: database showkey <keytree>\n"
899 " Shows Asterisk database contents, restricted to a given key.\n";
900 return NULL;
901 case CLI_GENERATE:
902 return NULL;
903 }
904
905 if (a->argc != 3) {
906 return CLI_SHOWUSAGE;
907 }
908
910 if (!ast_strlen_zero(a->argv[2]) && (sqlite3_bind_text(showkey_stmt, 1, a->argv[2], -1, SQLITE_STATIC) != SQLITE_OK)) {
911 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", a->argv[2], sqlite3_errmsg(astdb));
912 sqlite3_reset(showkey_stmt);
914 return NULL;
915 }
916
917 while (sqlite3_step(showkey_stmt) == SQLITE_ROW) {
918 const char *key_s, *value_s;
919 if (!(key_s = (const char *) sqlite3_column_text(showkey_stmt, 0))) {
920 break;
921 }
922 if (!(value_s = (const char *) sqlite3_column_text(showkey_stmt, 1))) {
923 break;
924 }
925 ++counter;
926 ast_cli(a->fd, "%-50s: %-25s\n", key_s, value_s);
927 }
928 sqlite3_reset(showkey_stmt);
930
931 ast_cli(a->fd, "%d results found.\n", counter);
932 return CLI_SUCCESS;
933}
934
935static int display_results(void *arg, int columns, char **values, char **colnames)
936{
937 struct ast_cli_args *a = arg;
938 size_t x;
939
940 for (x = 0; x < columns; x++) {
941 ast_cli(a->fd, "%-5s: %-50s\n", colnames[x], values[x]);
942 }
943 ast_cli(a->fd, "\n");
944
945 return 0;
946}
947
948static char *handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
949{
950
951 switch (cmd) {
952 case CLI_INIT:
953 e->command = "database query";
954 e->usage =
955 "Usage: database query \"<SQL Statement>\"\n"
956 " Run a user-specified SQL query on the database. Be careful.\n";
957 return NULL;
958 case CLI_GENERATE:
959 return NULL;
960 }
961
962 if (a->argc != 3) {
963 return CLI_SHOWUSAGE;
964 }
965
967 db_execute_sql(a->argv[2], display_results, a);
968 db_sync(); /* Go ahead and sync the db in case they write */
970
971 return CLI_SUCCESS;
972}
973
974static struct ast_cli_entry cli_database[] = {
975 AST_CLI_DEFINE(handle_cli_database_show, "Shows database contents"),
976 AST_CLI_DEFINE(handle_cli_database_showkey, "Shows database contents"),
977 AST_CLI_DEFINE(handle_cli_database_get, "Gets database value"),
978 AST_CLI_DEFINE(handle_cli_database_put, "Adds/updates database value"),
979 AST_CLI_DEFINE(handle_cli_database_del, "Removes database key/value"),
980 AST_CLI_DEFINE(handle_cli_database_deltree, "Removes database keytree/values"),
981 AST_CLI_DEFINE(handle_cli_database_query, "Run a user-specified query on the astdb"),
982};
983
984static int manager_dbput(struct mansession *s, const struct message *m)
985{
986 const char *family = astman_get_header(m, "Family");
987 const char *key = astman_get_header(m, "Key");
988 const char *val = astman_get_header(m, "Val");
989 int res;
990
991 if (ast_strlen_zero(family)) {
992 astman_send_error(s, m, "No family specified");
993 return 0;
994 }
995 if (ast_strlen_zero(key)) {
996 astman_send_error(s, m, "No key specified");
997 return 0;
998 }
999
1000 res = ast_db_put(family, key, S_OR(val, ""));
1001 if (res) {
1002 astman_send_error(s, m, "Failed to update entry");
1003 } else {
1004 astman_send_ack(s, m, "Updated database successfully");
1005 }
1006 return 0;
1007}
1008
1009static int manager_dbget(struct mansession *s, const struct message *m)
1010{
1011 const char *id = astman_get_header(m,"ActionID");
1012 char idText[256];
1013 const char *family = astman_get_header(m, "Family");
1014 const char *key = astman_get_header(m, "Key");
1015 char *tmp = NULL;
1016 int res;
1017
1018 if (ast_strlen_zero(family)) {
1019 astman_send_error(s, m, "No family specified.");
1020 return 0;
1021 }
1022 if (ast_strlen_zero(key)) {
1023 astman_send_error(s, m, "No key specified.");
1024 return 0;
1025 }
1026
1027 idText[0] = '\0';
1028 if (!ast_strlen_zero(id))
1029 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1030
1031 res = ast_db_get_allocated(family, key, &tmp);
1032 if (res) {
1033 astman_send_error(s, m, "Database entry not found");
1034 } else {
1035 astman_send_listack(s, m, "Result will follow", "start");
1036
1037 astman_append(s, "Event: DBGetResponse\r\n"
1038 "Family: %s\r\n"
1039 "Key: %s\r\n"
1040 "Val: %s\r\n"
1041 "%s"
1042 "\r\n",
1043 family, key, tmp, idText);
1044 ast_free(tmp);
1045 astman_send_list_complete_start(s, m, "DBGetComplete", 1);
1047 }
1048 return 0;
1049}
1050
1051static int manager_db_tree_get(struct mansession *s, const struct message *m)
1052{
1053 char *prefix;
1054 int prefix_len = 0;
1055 char idText[256];
1056 const char *id = astman_get_header(m,"ActionID");
1057 const char *family = astman_get_header(m, "Family");
1058 const char *key = astman_get_header(m, "Key");
1059 sqlite3_stmt *stmt = gettree_stmt;
1060 int count = 0;
1061
1062 prefix = create_prefix(family, key, &prefix_len);
1063 if (!prefix) {
1064 astman_send_error(s, m, "Unable to allocate memory for Family/Key");
1065 return 0;
1066 }
1067 if (prefix_len == 0) {
1068 stmt = gettree_all_stmt;
1069 }
1070
1071 idText[0] = '\0';
1072 if (!ast_strlen_zero(id)) {
1073 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1074 }
1075
1077 if (!ast_strlen_zero(prefix) && (sqlite3_bind_text(stmt, 1, prefix, prefix_len, SQLITE_STATIC) != SQLITE_OK)) {
1078 ast_log(LOG_WARNING, "Couldn't bind %s to stmt: %s\n", prefix, sqlite3_errmsg(astdb));
1079 sqlite3_reset(stmt);
1082 astman_send_error(s, m, "Unable to search database");
1083 return 0;
1084 }
1085
1086 astman_send_listack(s, m, "Result will follow", "start");
1087
1088 while (sqlite3_step(stmt) == SQLITE_ROW) {
1089 const char *key_s, *value_s;
1090 if (!(key_s = (const char *) sqlite3_column_text(stmt, 0))) {
1091 ast_log(LOG_WARNING, "Skipping invalid key!\n");
1092 continue;
1093 }
1094 if (!(value_s = (const char *) sqlite3_column_text(stmt, 1))) {
1095 ast_log(LOG_WARNING, "Skipping invalid value!\n");
1096 continue;
1097 }
1098 astman_append(s, "Event: DBGetTreeResponse\r\n"
1099 "Key: %s\r\n"
1100 "Val: %s\r\n"
1101 "%s"
1102 "\r\n",
1103 key_s, value_s, idText);
1104 count++;
1105 }
1106
1107 sqlite3_reset(stmt);
1110
1111 astman_send_list_complete_start(s, m, "DBGetTreeComplete", count);
1113
1114 return 0;
1115}
1116
1117static int manager_dbdel(struct mansession *s, const struct message *m)
1118{
1119 const char *family = astman_get_header(m, "Family");
1120 const char *key = astman_get_header(m, "Key");
1121 int res;
1122
1123 if (ast_strlen_zero(family)) {
1124 astman_send_error(s, m, "No family specified.");
1125 return 0;
1126 }
1127
1128 if (ast_strlen_zero(key)) {
1129 astman_send_error(s, m, "No key specified.");
1130 return 0;
1131 }
1132
1133 res = ast_db_del2(family, key);
1134 if (res)
1135 astman_send_error(s, m, "Database entry could not be deleted");
1136 else
1137 astman_send_ack(s, m, "Key deleted successfully");
1138
1139 return 0;
1140}
1141
1142static int manager_dbdeltree(struct mansession *s, const struct message *m)
1143{
1144 const char *family = astman_get_header(m, "Family");
1145 const char *key = astman_get_header(m, "Key");
1146 int num_deleted;
1147
1148 if (ast_strlen_zero(family)) {
1149 astman_send_error(s, m, "No family specified.");
1150 return 0;
1151 }
1152
1153 if (!ast_strlen_zero(key)) {
1154 num_deleted = ast_db_deltree(family, key);
1155 } else {
1156 num_deleted = ast_db_deltree(family, NULL);
1157 }
1158
1159 if (num_deleted < 0) {
1160 astman_send_error(s, m, "Database unavailable");
1161 } else if (num_deleted == 0) {
1162 astman_send_error(s, m, "Database entry not found");
1163 } else {
1164 astman_send_ack(s, m, "Key tree deleted successfully");
1165 }
1166
1167 return 0;
1168}
1169
1170/*!
1171 * \internal
1172 * \brief Signal the astdb sync thread to do its thing.
1173 *
1174 * \note dblock is assumed to be held when calling this function.
1175 */
1176static void db_sync(void)
1177{
1178 dosync = 1;
1180}
1181
1182/*!
1183 * \internal
1184 * \brief astdb sync thread
1185 *
1186 * This thread is in charge of syncing astdb to disk after a change.
1187 * By pushing it off to this thread to take care of, this I/O bound operation
1188 * will not block other threads from performing other critical processing.
1189 * If changes happen rapidly, this thread will also ensure that the sync
1190 * operations are rate limited.
1191 */
1192static void *db_sync_thread(void *data)
1193{
1196 for (;;) {
1197 /* If dosync is set, db_sync() was called during sleep(1),
1198 * and the pending transaction should be committed.
1199 * Otherwise, block until db_sync() is called.
1200 */
1201 while (!dosync) {
1203 }
1204 dosync = 0;
1207 }
1208 if (doexit) {
1210 break;
1211 }
1214 sleep(1);
1216 }
1217
1218 return NULL;
1219}
1220
1221/*!
1222 * \internal
1223 * \brief Clean up resources on Asterisk shutdown
1224 */
1225static void astdb_atexit(void)
1226{
1228 ast_manager_unregister("DBGet");
1229 ast_manager_unregister("DBGetTree");
1230 ast_manager_unregister("DBPut");
1231 ast_manager_unregister("DBDel");
1232 ast_manager_unregister("DBDelTree");
1233
1234 /* Set doexit to 1 to kill thread. db_sync must be called with
1235 * mutex held. */
1237 doexit = 1;
1238 db_sync();
1240
1241 pthread_join(syncthread, NULL);
1244 if (sqlite3_close(astdb) == SQLITE_OK) {
1245 astdb = NULL;
1246 }
1248}
1249
1250int astdb_init(void)
1251{
1253
1254 if (db_init()) {
1255 return -1;
1256 }
1257
1259 return -1;
1260 }
1261
1269 return 0;
1270}
Prototypes for public functions only of internal interest,.
struct sla_ringing_trunk * last
Definition: app_sla.c:338
#define EXISTS(a, b, c, d)
#define COUNT(a, b)
#define DELETE(a, b, c, d)
Persistent data storage (akin to *doze registry)
Asterisk main include file. File version handling, generic pbx functions.
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: clicompat.c:13
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
#define ast_log
Definition: astobj2.c:42
static char * columns
static PGresult * result
Definition: cel_pgsql.c:84
General Asterisk PBX channel definitions.
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
static char * handle_cli_database_deltree(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:789
static int manager_dbdel(struct mansession *s, const struct message *m)
Definition: db.c:1117
static void db_sync(void)
Definition: db.c:1176
static int doexit
Definition: db.c:140
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:335
static void clean_statements(void)
Definition: db.c:205
static char * handle_cli_database_showkey(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:890
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.
Definition: db.c:667
static int manager_db_tree_get(struct mansession *s, const struct message *m)
Definition: db.c:1051
int ast_db_del2(const char *family, const char *key)
Same as ast_db_del, but with more stringent error checking.
Definition: db.c:501
static int manager_dbdeltree(struct mansession *s, const struct message *m)
Definition: db.c:1142
static struct ast_cli_entry cli_database[]
Definition: db.c:974
void ast_db_freetree(struct ast_db_entry *dbe)
Free structure created by ast_db_gettree()
Definition: db.c:695
static struct ast_db_entry * db_gettree_common(sqlite3_stmt *stmt)
Definition: db.c:596
static int manager_dbget(struct mansession *s, const struct message *m)
Definition: db.c:1009
static int db_init(void)
Definition: db.c:290
static char * handle_cli_database_query(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:948
int astdb_init(void)
Definition: db.c:1250
static sqlite3 * astdb
Definition: db.c:138
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.
Definition: db.c:431
static int manager_dbput(struct mansession *s, const struct message *m)
Definition: db.c:984
static int db_execute_sql(const char *sql, int(*callback)(void *, int, char **, char **), void *arg)
Definition: db.c:306
static int display_results(void *arg, int columns, char **values, char **colnames)
Definition: db.c:935
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: db.c:421
static int ast_db_begin_transaction(void)
Definition: db.c:320
static int db_create_astdb(void)
Definition: db.c:236
int ast_db_del(const char *family, const char *key)
Delete entry in astdb.
Definition: db.c:472
static int ast_db_commit_transaction(void)
Definition: db.c:325
static int db_open(void)
Definition: db.c:256
static ast_mutex_t dblock
Definition: db.c:136
#define DEFINE_SQL_STATEMENT(stmt, sql)
Definition: db.c:145
static void * db_sync_thread(void *data)
Definition: db.c:1192
static ast_cond_t dbcond
Definition: db.c:137
static char * handle_cli_database_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:824
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition: db.c:635
static char * create_prefix(const char *family, const char *keytree, int *prefix_len)
Definition: db.c:534
static int dosync
Definition: db.c:141
static pthread_t syncthread
Definition: db.c:139
static char * handle_cli_database_get(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:732
static void astdb_atexit(void)
Definition: db.c:1225
static int init_statements(void)
Definition: db.c:220
static char * handle_cli_database_del(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:762
static int db_get_common(const char *family, const char *key, char **buffer, int bufferlen)
Definition: db.c:381
static int clean_stmt(sqlite3_stmt **stmt, const char *sql)
Definition: db.c:190
static int ast_db_rollback_transaction(void)
Definition: db.c:330
int ast_db_deltree(const char *family, const char *keytree)
Delete one or more entries in astdb.
Definition: db.c:559
static char * handle_cli_database_put(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: db.c:705
int ast_db_exists(const char *family, const char *key)
Check if family/key exitsts.
Definition: db.c:438
Convenient Signal Processing routines.
Generic File Format Support. Should be included by clients of the file handling routines....
static int exists(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: func_logic.c:185
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager transaction to begin a list.
Definition: manager.c:2028
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1986
void astman_send_list_complete_start(struct mansession *s, const struct message *m, const char *event_name, int count)
Start the list complete event.
Definition: manager.c:2064
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
void astman_send_list_complete_end(struct mansession *s)
End the list complete event.
Definition: manager.c:2072
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:1907
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
static char prefix[MAX_PREFIX]
Definition: http.c:144
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_ERROR
#define LOG_WARNING
#define ast_cond_wait(cond, mutex)
Definition: lock.h:209
#define ast_cond_init(cond, attr)
Definition: lock.h:205
#define ast_mutex_unlock(a)
Definition: lock.h:194
pthread_cond_t ast_cond_t
Definition: lock.h:182
#define ast_mutex_lock(a)
Definition: lock.h:193
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:524
#define ast_cond_signal(cond)
Definition: lock.h:207
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_REPORTING
Definition: manager.h:84
#define ast_manager_register_xml_core(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:203
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DB
Definition: options.c:165
static char dbname[MAX_DB_OPTION_SIZE]
#define NULL
Definition: resample.c:96
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:87
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
descriptor for a cli entry.
Definition: cli.h:171
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Definition: astdb.h:31
struct ast_db_entry * next
Definition: astdb.h:32
char * key
Definition: astdb.h:33
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:327
Definition: ast_expr2.c:325
int value
Definition: syslog.c:37
@ KEY
Definition: test_db.c:41
static struct test_val a
FILE * out
Definition: utils/frame.c:33
Utility functions.
#define ast_assert(a)
Definition: utils.h:739
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
#define ARRAY_LEN(a)
Definition: utils.h:666