120#define DEFAULT_SINGLE_DB_CONNECTION 0
133 char readhandle[5][30];
134 char writehandle[5][30];
174#define DSN_BUCKETS 37
178static int dsn_hash(
const void *obj,
const int flags)
180 const struct dsn *object;
198static int dsn_cmp(
void *obj,
void *arg,
int flags)
200 const struct dsn *object_left = obj;
201 const struct dsn *object_right = arg;
202 const char *right_key = arg;
207 right_key = object_right->
name;
210 cmp = strcmp(object_left->
name, right_key);
213 cmp = strncmp(object_left->
name, right_key, strlen(right_key));
292 res = SQLGetConnectAttr(
connection->
con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
293 if (SQL_SUCCEEDED(res)) {
294 return dead == SQL_CD_TRUE ? 1 : 0;
305 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
385 obj = (*dsn)->connection;
415 (*dsn)->connection =
NULL;
427 }
else if (obj && *obj) {
477 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->
con, &stmt);
478 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
484 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
485 if (res == SQL_ERROR && !silent) {
487 SQLINTEGER nativeerror=0, numfields=0;
488 SQLSMALLINT diagbytes=0;
489 unsigned char state[10], diagnostic[256];
491 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
492 for (i = 0; i < numfields; i++) {
493 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1,
state, &nativeerror, diagnostic,
sizeof(diagnostic), &diagbytes);
496 ast_log(
LOG_WARNING,
"Oh, that was good. There are really %d diagnostics?\n", (
int)numfields);
505 SQLCloseCursor(stmt);
506 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
530 char *t, varname[15];
531 int i, dsn_num, bogus_chan = 0;
532 int transactional = 0;
539 SQLHSTMT stmt =
NULL;
543 const char *
status =
"FAILURE";
546 if (!
buf || !insertbuf) {
552 if (!strcmp(query->acf->name, cmd)) {
567 if (
args.argc < query->minargs) {
569 args.argc, cmd, query->minargs);
588 if (query->sql_insert) {
607 snprintf(varname,
sizeof(varname),
"%u",
args.argc);
609 for (i = 0; i <
args.argc; i++) {
610 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
616 for (i = 0; i <
values.argc; i++) {
617 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
625 if (query->sql_insert) {
635 for (i = 0; i <
args.argc; i++) {
636 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
640 for (i = 0; i <
values.argc; i++) {
641 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
653 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
657 ast_log(
LOG_WARNING,
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
670 if (!transactional) {
677 SQLRowCount(stmt, &rows);
678 SQLCloseCursor(stmt);
679 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
684 }
else if (query->sql_insert) {
685 if (!transactional) {
689 for (transactional = 0, dsn_num = 0; dsn_num < 5; dsn_num++) {
693 ast_log(
LOG_WARNING,
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
710 SQLRowCount(stmt, &rows);
711 SQLCloseCursor(stmt);
712 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
726 snprintf(varname,
sizeof(varname),
"%d", (
int)rows);
731 if (!transactional) {
746 char varname[15], rowcount[12] =
"-1";
748 int res, x, y, buflen = 0, escapecommas, rowlimit = 1, multirow = 0, dsn_num, bogus_chan = 0;
752 SQLHSTMT stmt =
NULL;
753 SQLSMALLINT colcount=0;
755 SQLSMALLINT collength;
759 const char *
status =
"FAILURE";
762 if (!sql || !colnames) {
773 if (!strcmp(query->acf->name, cmd)) {
789 if (
args.argc < query->minargs) {
791 args.argc, cmd, query->minargs);
808 snprintf(varname,
sizeof(varname),
"%u",
args.argc);
810 for (x = 0; x <
args.argc; x++) {
811 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
823 for (x = 0; x <
args.argc; x++) {
824 snprintf(varname,
sizeof(varname),
"ARG%d", x + 1);
832 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
840 if (query->rowlimit) {
841 rowlimit = query->rowlimit;
846 }
else if (!bogus_chan) {
847 if (query->rowlimit > 1) {
848 rowlimit = query->rowlimit;
849 if (!(resultset =
ast_calloc(1,
sizeof(*resultset)))) {
861 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
886 res = SQLNumResultCols(stmt, &colcount);
887 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
889 SQLCloseCursor(stmt);
890 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
903 SQLCloseCursor(stmt);
904 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
915 res = SQLFetch(stmt);
916 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
918 if (res == SQL_NO_DATA) {
928 SQLCloseCursor(stmt);
929 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
942 for (y = 0; y < rowlimit; y++) {
944 for (x = 0; x < colcount; x++) {
951 SQLCloseCursor(stmt);
952 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
963 SQLLEN octetlength = 0;
965 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname,
sizeof(colname), &collength,
NULL,
NULL,
NULL,
NULL);
966 ast_debug(3,
"Got collength of %d for column '%s' (offset %d)\n", (
int)collength, colname, x);
967 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
968 snprintf(colname,
sizeof(colname),
"field%d", x);
971 SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH,
NULL, 0,
NULL, &octetlength);
985 SQLCloseCursor(stmt);
986 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
996 strcpy((
char *)resultset +
sizeof(*resultset),
ast_str_buffer(colnames));
1000 buflen = strlen(
buf);
1008 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1018 buf[buflen++] =
',';
1024 if (escapecommas && (ptrcoldata[i] ==
'\\' || ptrcoldata[i] ==
',')) {
1025 buf[buflen++] =
'\\';
1027 buf[buflen++] = ptrcoldata[i];
1029 if (buflen >=
len - 2) {
1033 if (ptrcoldata[i] ==
'\0') {
1044 row =
ast_calloc(1,
sizeof(*row) + buflen + 1);
1046 ast_log(
LOG_ERROR,
"Unable to allocate space for more rows in this resultset.\n");
1050 strcpy((
char *)row +
sizeof(*row),
buf);
1054 res = SQLFetch(stmt);
1055 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1056 if (res != SQL_NO_DATA) {
1068 snprintf(rowcount,
sizeof(rowcount),
"%d", y);
1092 ast_log(
LOG_ERROR,
"Rows retrieved, but unable to store it in the channel. Results fail.\n");
1094 SQLCloseCursor(stmt);
1095 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1101 odbc_store->
data = resultset;
1107 SQLCloseCursor(stmt);
1108 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1110 if (resultset && !multirow) {
1127 if (*
data == character) {
1155 .
name =
"SQL_ESC_BACKSLASHES",
1178 resultset = store->
data;
1199 .
name =
"ODBC_FETCH",
1224 if (query->acf->name)
1225 ast_free((
char *)query->acf->name);
1240 const char *tmp2 =
NULL;
1243 if (!cfg || !catg) {
1247 if (!(*query =
ast_calloc(1,
sizeof(**query)))) {
1257 for (i = 0; i < 5; i++) {
1259 ast_copy_string((*query)->writehandle[i], writeconf.dsn[i],
sizeof((*query)->writehandle[i]));
1269 for (i = 0; i < 5; i++) {
1271 ast_copy_string((*query)->readhandle[i], readconf.dsn[i],
sizeof((*query)->readhandle[i]));
1275 for (i = 0; i < 5; i++) {
1277 ast_copy_string((*query)->readhandle[i], (*query)->writehandle[i],
sizeof((*query)->readhandle[i]));
1284 ast_log(
LOG_WARNING,
"Parameter 'read' is deprecated for category %s. Please use 'readsql' instead.\n", catg);
1299 ast_log(
LOG_ERROR,
"There is SQL, but no ODBC class to be used for reading: %s\n", catg);
1306 ast_log(
LOG_WARNING,
"Parameter 'write' is deprecated for category %s. Please use 'writesql' instead.\n", catg);
1318 if ((*query)->sql_write &&
ast_strlen_zero((*query)->writehandle[0])) {
1321 ast_log(
LOG_ERROR,
"There is SQL, but no ODBC class to be used for writing: %s\n", catg);
1343 if (strcasecmp(
tmp,
"multirow") == 0)
1346 sscanf(
tmp,
"%30d", &((*query)->rowlimit));
1350 sscanf(
tmp,
"%30d", &((*query)->minargs));
1354 if (!(*query)->acf) {
1366 if (
ast_asprintf((
char **)&((*query)->acf->name),
"%s_%s",
tmp, catg) < 0) {
1367 (*query)->acf->name =
NULL;
1370 if (
ast_asprintf((
char **)&((*query)->acf->name),
"ODBC_%s", catg) < 0) {
1371 (*query)->acf->name =
NULL;
1375 if (!(*query)->acf->name) {
1405 if ((*query)->sql_read && (*query)->sql_write) {
1407 "Runs the following query, as defined in func_odbc.conf, performing\n"
1408 "substitution of the arguments into the query as specified by ${ARG1},\n"
1409 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n"
1410 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
1412 "\nRead:\n%s\n\nWrite:\n%s%s%s",
1413 (*query)->sql_insert ?
1414 "If the write query affects no rows, the insert query will be\n"
1415 "performed.\n" :
"",
1417 (*query)->sql_write,
1418 (*query)->sql_insert ?
"\n\nInsert:\n" :
"",
1419 (*query)->sql_insert ? (*query)->sql_insert :
"");
1420 }
else if ((*query)->sql_read) {
1422 "Runs the following query, as defined in func_odbc.conf, performing\n"
1423 "substitution of the arguments into the query as specified by ${ARG1},\n"
1424 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s",
1425 (*query)->sql_read);
1426 }
else if ((*query)->sql_write) {
1428 "Runs the following query, as defined in func_odbc.conf, performing\n"
1429 "substitution of the arguments into the query as specified by ${ARG1},\n"
1430 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n"
1431 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
1432 "This function may only be set.\n%s\nSQL:\n%s%s%s",
1433 (*query)->sql_insert ?
1434 "If the write query affects no rows, the insert query will be\n"
1435 "performed.\n" :
"",
1436 (*query)->sql_write,
1437 (*query)->sql_insert ?
"\n\nInsert:\n" :
"",
1438 (*query)->sql_insert ? (*query)->sql_insert :
"");
1442 ast_log(
LOG_WARNING,
"Section '%s' was found, but there was no SQL to execute. Ignoring.\n", catg);
1452 if ((*query)->sql_read) {
1456 if ((*query)->sql_write) {
1469 char *char_args, varname[15];
1478 "Usage: odbc read <name> <args> [exec]\n"
1479 " Evaluates the SQL provided in the ODBC function <name>, and\n"
1480 " optionally executes the function. This function is intended for\n"
1481 " testing purposes. Remember to quote arguments containing spaces.\n";
1485 int wordlen = strlen(
a->word), which = 0;
1489 if (!strncasecmp(query->acf->name,
a->word, wordlen)) {
1490 if (++which >
a->n) {
1499 }
else if (
a->pos == 4) {
1500 static const char *
const completions[] = {
"exec",
NULL };
1507 if (
a->argc < 4 ||
a->argc > 5) {
1518 if (!strcmp(query->acf->name,
a->argv[2])) {
1524 ast_cli(
a->fd,
"No such query '%s'\n",
a->argv[2]);
1529 if (!query->sql_read) {
1530 ast_cli(
a->fd,
"The function %s has no readsql parameter.\n",
a->argv[2]);
1547 for (i = 0; i <
args.argc; i++) {
1548 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
1555 if (
a->argc == 5 && !strcmp(
a->argv[4],
"exec")) {
1559 int dsn_num, executed = 0;
1561 int rows = 0, res, x;
1562 SQLSMALLINT colcount = 0, collength;
1572 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
1580 ast_debug(1,
"Found handle %s\n", query->readhandle[dsn_num]);
1589 res = SQLNumResultCols(stmt, &colcount);
1590 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1592 SQLCloseCursor(stmt);
1593 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
1599 if (colcount <= 0) {
1600 SQLCloseCursor(stmt);
1601 SQLFreeHandle (SQL_HANDLE_STMT, stmt);
1603 ast_cli(
a->fd,
"Returned %d columns. Query executed on handle %d:%s [%s]\n", colcount, dsn_num, query->readhandle[dsn_num],
ast_str_buffer(sql));
1608 res = SQLFetch(stmt);
1609 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1610 SQLCloseCursor(stmt);
1611 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1613 if (res == SQL_NO_DATA) {
1614 ast_cli(
a->fd,
"Returned %d rows. Query executed on handle %d:%s [%s]\n", rows, dsn_num, query->readhandle[dsn_num],
ast_str_buffer(sql));
1623 for (x = 0; x < colcount; x++) {
1624 res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname,
sizeof(colname), &collength,
NULL,
NULL,
NULL,
NULL);
1625 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
1626 snprintf(colname,
sizeof(colname),
"field%d", x);
1630 SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH,
NULL, 0,
NULL, &octetlength);
1638 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1640 SQLCloseCursor(stmt);
1641 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1652 res = SQLFetch(stmt);
1653 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
1656 ast_cli(
a->fd,
"%-20.20s %s\n",
"----------",
"----------");
1658 SQLCloseCursor(stmt);
1659 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1661 ast_cli(
a->fd,
"Returned %d row%s. Query executed on handle %d [%s]\n", rows, rows == 1 ?
"" :
"s", dsn_num, query->readhandle[dsn_num]);
1685 char *char_args, *char_values, varname[15];
1694 "Usage: odbc write <name> <args> <value> [exec]\n"
1695 " Evaluates the SQL provided in the ODBC function <name>, and\n"
1696 " optionally executes the function. This function is intended for\n"
1697 " testing purposes. Remember to quote arguments containing spaces.\n";
1701 int wordlen = strlen(
a->word), which = 0;
1705 if (!strncasecmp(query->acf->name,
a->word, wordlen)) {
1706 if (++which >
a->n) {
1715 }
else if (
a->pos == 5) {
1716 static const char *
const completions[] = {
"exec",
NULL };
1723 if (
a->argc < 5 ||
a->argc > 6) {
1734 if (!strcmp(query->acf->name,
a->argv[2])) {
1740 ast_cli(
a->fd,
"No such query '%s'\n",
a->argv[2]);
1745 if (!query->sql_write) {
1746 ast_cli(
a->fd,
"The function %s has no writesql parameter.\n",
a->argv[2]);
1767 for (i = 0; i <
args.argc; i++) {
1768 snprintf(varname,
sizeof(varname),
"ARG%d", i + 1);
1774 for (i = 0; i <
values.argc; i++) {
1775 snprintf(varname,
sizeof(varname),
"VAL%d", i + 1);
1786 if (
a->argc == 6 && !strcmp(
a->argv[5],
"exec")) {
1790 int dsn_num, executed = 0;
1794 for (dsn_num = 0; dsn_num < 5; dsn_num++) {
1807 SQLRowCount(stmt, &rows);
1808 SQLCloseCursor(stmt);
1809 SQLFreeHandle(SQL_HANDLE_STMT, stmt);
1811 ast_cli(
a->fd,
"Affected %d rows. Query executed on handle %d [%s]\n", (
int)rows, dsn_num, query->writehandle[dsn_num]);
1817 ast_cli(
a->fd,
"Failed to execute query.\n");
1875 if (!strcasecmp(catg,
"general")) {
1882 else if (err == EINVAL)
1987 if (!strcasecmp(catg,
"general")) {
2012 .
requires =
"res_odbc",
Asterisk main include file. File version handling, generic pbx functions.
#define ast_realloc(p, len)
A wrapper for realloc()
#define ast_strdup(str)
A wrapper for strdup()
#define ast_strdupa(s)
duplicate a string in memory from the stack
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
#define ast_calloc(num, len)
A wrapper for calloc()
@ AO2_ALLOC_OPT_LOCK_MUTEX
#define ao2_link_flags(container, obj, flags)
Add an object to a container.
#define ao2_find(container, arg, flags)
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
@ OBJ_SEARCH_PARTIAL_KEY
The arg parameter is a partial search key similar to OBJ_SEARCH_KEY.
@ OBJ_SEARCH_OBJECT
The arg parameter is an object of the same type.
@ OBJ_NOLOCK
Assume that the ao2_container is already locked.
@ OBJ_SEARCH_MASK
Search option field mask.
@ OBJ_SEARCH_KEY
The arg parameter is a search key, but is not an object.
#define ao2_alloc(data_size, destructor_fn)
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
General Asterisk PBX channel definitions.
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
#define ast_channel_lock(chan)
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
#define ast_channel_unref(c)
Decrease channel reference count.
#define ast_dummy_channel_alloc()
Create a fake channel structure.
#define ast_channel_unlock(chan)
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Standard Command Line Interface.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define AST_CLI_DEFINE(fn, txt,...)
void ast_cli(int fd, const char *fmt,...)
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
#define ast_cli_register_multiple(e, len)
Register multiple commands.
#define ast_datastore_alloc(info, uid)
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Generic File Format Support. Should be included by clients of the file handling routines....
struct ao2_container * dsns
static ast_rwlock_t single_db_connection_lock
static SQLHSTMT execute(struct odbc_obj *obj, void *data, int silent)
Common execution function for SQL queries.
static SQLHSTMT generic_execute(struct odbc_obj *obj, void *data)
static struct ast_custom_function escape_function
static int acf_odbc_write(struct ast_channel *chan, const char *cmd, char *s, const char *value)
static int exec_odbcfinish(struct ast_channel *chan, const char *data)
static char * cli_odbc_write(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_custom_function escape_backslashes_function
static struct ast_threadstorage colnames_buf
static SQLHSTMT silent_execute(struct odbc_obj *obj, void *data)
static int acf_odbc_read(struct ast_channel *chan, const char *cmd, char *s, char *buf, size_t len)
static const struct ast_datastore_info odbc_info
static int connection_dead(struct odbc_obj *connection)
Determine if the connection has died.
static struct ast_threadstorage sql2_buf
static char * cli_odbc_read(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static struct ast_custom_function fetch_function
static int init_acf_query(struct ast_config *cfg, char *catg, struct acf_odbc_query **query)
static int acf_fetch(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int dsn_cmp(void *obj, void *arg, int flags)
static struct dsn * get_dsn(const char *name)
Retrieve a DSN, or create it if it does not exist.
static void odbc_datastore_free(void *data)
static int acf_escape_ticks(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int acf_escape(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len, char character)
#define DEFAULT_SINGLE_DB_CONNECTION
static int dsn_hash(const void *obj, const int flags)
static char * app_odbcfinish
static struct odbc_obj * get_odbc_obj(const char *dsn_name, struct dsn **dsn)
Get a DB handle via a DSN or directly.
static void dsn_destructor(void *obj)
static struct dsn * create_dsn(const char *name)
Create a DSN and connect to the database.
static struct ast_threadstorage coldata_buf
static int load_module(void)
static int acf_escape_backslashes(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int unload_module(void)
static int single_db_connection
static struct ast_cli_entry cli_func_odbc[]
static int free_acf_query(struct acf_odbc_query *query)
static void release_obj_or_dsn(struct odbc_obj **obj, struct dsn **dsn)
Release an ODBC obj or a DSN.
static struct ast_threadstorage sql_buf
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
Configuration File Parser.
#define ast_config_load(filename, flags)
Load a config file.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
@ CONFIG_FLAG_FILEUNCHANGED
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
#define AST_RWLIST_REMOVE_HEAD
#define AST_LIST_HEAD_DESTROY(head)
Destroys a list head structure.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_HEAD_INIT(head)
Initializes a list head structure.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_RWLIST_TRAVERSE
#define AST_RWLIST_INSERT_HEAD
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
#define ast_rwlock_wrlock(a)
#define ast_rwlock_rdlock(a)
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
int ast_atomic_fetchadd_int(volatile int *p, int v)
Atomically add v to *p and return the previous value of *p.
#define ast_rwlock_unlock(a)
Asterisk module definitions.
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
@ AST_MODULE_SUPPORT_CORE
#define ASTERISK_GPL_KEY
The text the key() function should return.
int ast_unregister_application(const char *app)
Unregister an application.
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Core PBX routines and definitions.
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define ast_custom_function_register(acf)
Register a custom function.
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, without removing any previously set value.
void ast_odbc_release_obj(struct odbc_obj *obj)
Releases an ODBC object previously allocated by ast_odbc_request_obj()
unsigned int ast_odbc_get_max_connections(const char *name)
Return the current configured maximum number of connections for a class.
SQLRETURN ast_odbc_ast_str_SQLGetData(struct ast_str **buf, int pmaxlen, SQLHSTMT StatementHandle, SQLUSMALLINT ColumnNumber, SQLSMALLINT TargetType, SQLLEN *StrLen_or_Ind)
Wrapper for SQLGetData to use with dynamic strings.
SQLHSTMT ast_odbc_direct_execute(struct odbc_obj *obj, SQLHSTMT(*exec_cb)(struct odbc_obj *obj, void *data), void *data)
Executes an non prepared statement and returns the resulting statement handle.
SQLRETURN ast_odbc_execute_sql(struct odbc_obj *obj, SQLHSTMT *stmt, const char *sql)
Execute a unprepared SQL query.
#define ast_odbc_request_obj(name, check)
Get a ODBC connection object.
struct odbc_obj * ast_odbc_retrieve_transaction_obj(struct ast_channel *chan, const char *objname)
Retrieve an ODBC transaction connection with the given ODBC class name.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_build(x, field, fmt, args...)
Set a field to a complex (built) value.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
String manipulation functions.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char * ast_str_append_escapecommas(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string, with escaping of commas.
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
#define ast_str_make_space(buf, new_len)
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Main Channel structure associated with a channel.
descriptor for a cli entry.
Data structure associated with a custom dialplan function.
Structure for a data store type.
Structure for a data store object.
Structure used to handle boolean flags.
Support for dynamic strings.
struct odbc_obj * connection
struct odbc_datastore_row::@175 list
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
#define ast_test_flag(p, flag)
#define ast_clear_flag(p, flag)
#define ast_set_flag(p, flag)