134#define DEFAULT_SINGLE_DB_CONNECTION 0 
  188#define DSN_BUCKETS 37 
  192static int dsn_hash(
const void *obj, 
const int flags)
 
  194    const struct dsn *object;
 
 
  212static int dsn_cmp(
void *obj, 
void *arg, 
int flags)
 
  214    const struct dsn *object_left = obj;
 
  215    const struct dsn *object_right = arg;
 
  216    const char *right_key = arg;
 
  221        right_key = object_right->
name;
 
  224        cmp = strcmp(object_left->
name, right_key);
 
  227        cmp = strncmp(object_left->
name, right_key, strlen(right_key));
 
 
  306    res = SQLGetConnectAttr(
connection->
con, SQL_ATTR_CONNECTION_DEAD, &dead, 0, 0);
 
  307    if (SQL_SUCCEEDED(res)) {
 
  308        return dead == SQL_CD_TRUE ? 1 : 0;
 
  319    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
  399                obj = (*dsn)->connection;
 
 
  429            (*dsn)->connection = 
NULL;
 
  441    } 
else if (obj && *obj) {
 
 
  491    res = SQLAllocHandle (SQL_HANDLE_STMT, obj->
con, &stmt);
 
  492    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  498    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO) && (res != SQL_NO_DATA)) {
 
  499        if (res == SQL_ERROR && !silent) {
 
  501            SQLINTEGER nativeerror=0, numfields=0;
 
  502            SQLSMALLINT diagbytes=0;
 
  503            unsigned char state[10], diagnostic[256];
 
  505            SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes);
 
  506            for (i = 0; i < numfields; i++) {
 
  507                SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, 
state, &nativeerror, diagnostic, 
sizeof(diagnostic), &diagbytes);
 
  510                    ast_log(
LOG_WARNING, 
"Oh, that was good.  There are really %d diagnostics?\n", (
int)numfields);
 
  519        SQLCloseCursor(stmt);
 
  520        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 
  544    char *t, varname[15];
 
  545    int i, dsn_num, bogus_chan = 0;
 
  546    int transactional = 0;
 
  553    SQLHSTMT stmt = 
NULL;
 
  557    const char *
status = 
"FAILURE";
 
  560    if (!
buf || !insertbuf) {
 
  566        if (!strcmp(query->
acf->
name, cmd)) {
 
  621    snprintf(varname, 
sizeof(varname), 
"%u", 
args.argc);
 
  623    for (i = 0; i < 
args.argc; i++) {
 
  624        snprintf(varname, 
sizeof(varname), 
"ARG%d", i + 1);
 
  630    for (i = 0; i < 
values.argc; i++) {
 
  631        snprintf(varname, 
sizeof(varname), 
"VAL%d", i + 1);
 
  649        for (i = 0; i < 
args.argc; i++) {
 
  650            snprintf(varname, 
sizeof(varname), 
"ARG%d", i + 1);
 
  654        for (i = 0; i < 
values.argc; i++) {
 
  655            snprintf(varname, 
sizeof(varname), 
"VAL%d", i + 1);
 
  667    for (dsn_num = 0; dsn_num < 5; dsn_num++) {
 
  671                ast_log(
LOG_WARNING, 
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
 
  684            if (!transactional) {
 
  691        SQLRowCount(stmt, &rows);
 
  692        SQLCloseCursor(stmt);
 
  693        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  699            if (!transactional) {
 
  703            for (transactional = 0, dsn_num = 0; dsn_num < 5; dsn_num++) {
 
  707                        ast_log(
LOG_WARNING, 
"Transactions do not work well with multiple DSNs for 'writehandle'\n");
 
  724                    SQLRowCount(stmt, &rows);
 
  725                    SQLCloseCursor(stmt);
 
  726                    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  740        snprintf(varname, 
sizeof(varname), 
"%d", (
int)rows);
 
  745    if (!transactional) {
 
 
  760    char varname[15], rowcount[12] = 
"-1";
 
  762    int res, x, y, buflen = 0, escapecommas, rowlimit = 1, multirow = 0, dsn_num, bogus_chan = 0;
 
  766    SQLHSTMT stmt = 
NULL;
 
  767    SQLSMALLINT colcount=0;
 
  769    SQLSMALLINT collength;
 
  773    const char *
status = 
"FAILURE";
 
  776    if (!sql || !colnames) {
 
  787        if (!strcmp(query->
acf->
name, cmd)) {
 
  822    snprintf(varname, 
sizeof(varname), 
"%u", 
args.argc);
 
  824    for (x = 0; x < 
args.argc; x++) {
 
  825        snprintf(varname, 
sizeof(varname), 
"ARG%d", x + 1);
 
  837        for (x = 0; x < 
args.argc; x++) {
 
  838            snprintf(varname, 
sizeof(varname), 
"ARG%d", x + 1);
 
  846        if (!(resultset = 
ast_calloc(1, 
sizeof(*resultset)))) {
 
  860    } 
else if (!bogus_chan) {
 
  863            if (!(resultset = 
ast_calloc(1, 
sizeof(*resultset)))) {
 
  875    for (dsn_num = 0; dsn_num < 5; dsn_num++) {
 
  900    res = SQLNumResultCols(stmt, &colcount);
 
  901    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  903        SQLCloseCursor(stmt);
 
  904        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  917        SQLCloseCursor(stmt);
 
  918        SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
  929    res = SQLFetch(stmt);
 
  930    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
  932        if (res == SQL_NO_DATA) {
 
  942        SQLCloseCursor(stmt);
 
  943        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  956    for (y = 0; y < rowlimit; y++) {
 
  958        for (x = 0; x < colcount; x++) {
 
  965                SQLCloseCursor(stmt);
 
  966                SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
  977                SQLLEN octetlength = 0;
 
  979                res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname, 
sizeof(colname), &collength, 
NULL, 
NULL, 
NULL, 
NULL);
 
  980                ast_debug(3, 
"Got collength of %d for column '%s' (offset %d)\n", (
int)collength, colname, x);
 
  981                if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
 
  982                    snprintf(colname, 
sizeof(colname), 
"field%d", x);
 
  985                SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH, 
NULL, 0, 
NULL, &octetlength);
 
  999                        SQLCloseCursor(stmt);
 
 1000                        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1010                    strcpy((
char *)resultset + 
sizeof(*resultset), 
ast_str_buffer(colnames));
 
 1014            buflen = strlen(
buf);
 
 1022            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1032                buf[buflen++] = 
',';
 
 1038                if (escapecommas && (ptrcoldata[i] == 
'\\' || ptrcoldata[i] == 
',')) {
 
 1039                    buf[buflen++] = 
'\\';
 
 1041                buf[buflen++] = ptrcoldata[i];
 
 1043                if (buflen >= 
len - 2) {
 
 1047                if (ptrcoldata[i] == 
'\0') {
 
 1058            row = 
ast_calloc(1, 
sizeof(*row) + buflen + 1);
 
 1060                ast_log(
LOG_ERROR, 
"Unable to allocate space for more rows in this resultset.\n");
 
 1064            strcpy((
char *)row + 
sizeof(*row), 
buf);
 
 1068            res = SQLFetch(stmt);
 
 1069            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1070                if (res != SQL_NO_DATA) {
 
 1082        snprintf(rowcount, 
sizeof(rowcount), 
"%d", y);
 
 1106                ast_log(
LOG_ERROR, 
"Rows retrieved, but unable to store it in the channel.  Results fail.\n");
 
 1108                SQLCloseCursor(stmt);
 
 1109                SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1115            odbc_store->
data = resultset;
 
 1121    SQLCloseCursor(stmt);
 
 1122    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1124    if (resultset && !multirow) {
 
 
 1141        if (*
data == character) {
 
 
 1169    .
name = 
"SQL_ESC_BACKSLASHES",
 
 
 1192    resultset = store->
data;
 
 
 1213    .
name = 
"ODBC_FETCH",
 
 
 1254    const char *tmp2 = 
NULL;
 
 1257    if (!cfg || !catg) {
 
 1261    if (!(*query = 
ast_calloc(1, 
sizeof(**query)))) {
 
 1271        for (i = 0; i < 5; i++) {
 
 1273                ast_copy_string((*query)->writehandle[i], writeconf.dsn[i], 
sizeof((*query)->writehandle[i]));
 
 1283        for (i = 0; i < 5; i++) {
 
 1285                ast_copy_string((*query)->readhandle[i], readconf.dsn[i], 
sizeof((*query)->readhandle[i]));
 
 1289        for (i = 0; i < 5; i++) {
 
 1291                ast_copy_string((*query)->readhandle[i], (*query)->writehandle[i], 
sizeof((*query)->readhandle[i]));
 
 1298            ast_log(
LOG_WARNING, 
"Parameter 'read' is deprecated for category %s.  Please use 'readsql' instead.\n", catg);
 
 1302            if (!((*query)->sql_read = 
ast_strdup(tmp))) {
 
 1313        ast_log(
LOG_ERROR, 
"There is SQL, but no ODBC class to be used for reading: %s\n", catg);
 
 1320            ast_log(
LOG_WARNING, 
"Parameter 'write' is deprecated for category %s.  Please use 'writesql' instead.\n", catg);
 
 1324            if (!((*query)->sql_write = 
ast_strdup(tmp))) {
 
 1332    if ((*query)->sql_write && 
ast_strlen_zero((*query)->writehandle[0])) {
 
 1335        ast_log(
LOG_ERROR, 
"There is SQL, but no ODBC class to be used for writing: %s\n", catg);
 
 1341            if (!((*query)->sql_insert = 
ast_strdup(tmp))) {
 
 1357        if (strcasecmp(tmp, 
"multirow") == 0)
 
 1360            sscanf(tmp, 
"%30d", &((*query)->rowlimit));
 
 1364        sscanf(tmp, 
"%30d", &((*query)->minargs));
 
 1368    if (!(*query)->acf) {
 
 1380        if (
ast_asprintf((
char **)&((*query)->acf->name), 
"%s_%s", tmp, catg) < 0) {
 
 1384        if (
ast_asprintf((
char **)&((*query)->acf->name), 
"ODBC_%s", catg) < 0) {
 
 1385            (*query)->acf->name = 
NULL;
 
 1389    if (!(*query)->acf->name) {
 
 1419    if ((*query)->sql_read && (*query)->sql_write) {
 
 1421                    "Runs the following query, as defined in func_odbc.conf, performing\n" 
 1422                    "substitution of the arguments into the query as specified by ${ARG1},\n" 
 1423                    "${ARG2}, ... ${ARGn}.  When setting the function, the values are provided\n" 
 1424                    "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 
 1426                    "\nRead:\n%s\n\nWrite:\n%s%s%s",
 
 1427                    (*query)->sql_insert ?
 
 1428                        "If the write query affects no rows, the insert query will be\n" 
 1429                        "performed.\n" : 
"",
 
 1431                    (*query)->sql_write,
 
 1432                    (*query)->sql_insert ? 
"\n\nInsert:\n" : 
"",
 
 1433                    (*query)->sql_insert ? (*query)->sql_insert : 
"");
 
 1434    } 
else if ((*query)->sql_read) {
 
 1436                    "Runs the following query, as defined in func_odbc.conf, performing\n" 
 1437                    "substitution of the arguments into the query as specified by ${ARG1},\n" 
 1438                    "${ARG2}, ... ${ARGn}.  This function may only be read, not set.\n\nSQL:\n%s",
 
 1439                    (*query)->sql_read);
 
 1440    } 
else if ((*query)->sql_write) {
 
 1442                    "Runs the following query, as defined in func_odbc.conf, performing\n" 
 1443                    "substitution of the arguments into the query as specified by ${ARG1},\n" 
 1444                    "${ARG2}, ... ${ARGn}.  The values are provided either in whole as\n" 
 1445                    "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 
 1446                    "This function may only be set.\n%s\nSQL:\n%s%s%s",
 
 1447                    (*query)->sql_insert ?
 
 1448                        "If the write query affects no rows, the insert query will be\n" 
 1449                        "performed.\n" : 
"",
 
 1450                    (*query)->sql_write,
 
 1451                    (*query)->sql_insert ? 
"\n\nInsert:\n" : 
"",
 
 1452                    (*query)->sql_insert ? (*query)->sql_insert : 
"");
 
 1456        ast_log(
LOG_WARNING, 
"Section '%s' was found, but there was no SQL to execute.  Ignoring.\n", catg);
 
 1466    if ((*query)->sql_read) {
 
 1470    if ((*query)->sql_write) {
 
 
 1483    char *char_args, varname[15];
 
 1492            "Usage: odbc read <name> <args> [exec]\n" 
 1493            "       Evaluates the SQL provided in the ODBC function <name>, and\n" 
 1494            "       optionally executes the function.  This function is intended for\n" 
 1495            "       testing purposes.  Remember to quote arguments containing spaces.\n";
 
 1499            int wordlen = strlen(
a->word), which = 0;
 
 1503                if (!strncasecmp(query->
acf->
name, 
a->word, wordlen)) {
 
 1504                    if (++which > 
a->n) {
 
 1513        } 
else if (
a->pos == 4) {
 
 1514            static const char * 
const completions[] = { 
"exec", 
NULL };
 
 1521    if (
a->argc < 4 || 
a->argc > 5) {
 
 1532        if (!strcmp(query->
acf->
name, 
a->argv[2])) {
 
 1538        ast_cli(
a->fd, 
"No such query '%s'\n", 
a->argv[2]);
 
 1544        ast_cli(
a->fd, 
"The function %s has no readsql parameter.\n", 
a->argv[2]);
 
 1561    for (i = 0; i < 
args.argc; i++) {
 
 1562        snprintf(varname, 
sizeof(varname), 
"ARG%d", i + 1);
 
 1569    if (
a->argc == 5 && !strcmp(
a->argv[4], 
"exec")) {
 
 1573        int dsn_num, executed = 0;
 
 1575        int rows = 0, res, x;
 
 1576        SQLSMALLINT colcount = 0, collength;
 
 1586        for (dsn_num = 0; dsn_num < 5; dsn_num++) {
 
 1603            res = SQLNumResultCols(stmt, &colcount);
 
 1604            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1606                SQLCloseCursor(stmt);
 
 1607                SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
 1613            if (colcount <= 0) {
 
 1614                SQLCloseCursor(stmt);
 
 1615                SQLFreeHandle (SQL_HANDLE_STMT, stmt);
 
 1622            res = SQLFetch(stmt);
 
 1623            if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1624                SQLCloseCursor(stmt);
 
 1625                SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1627                if (res == SQL_NO_DATA) {
 
 1637                for (x = 0; x < colcount; x++) {
 
 1638                    res = SQLDescribeCol(stmt, x + 1, (
unsigned char *)colname, 
sizeof(colname), &collength, 
NULL, 
NULL, 
NULL, 
NULL);
 
 1639                    if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) {
 
 1640                        snprintf(colname, 
sizeof(colname), 
"field%d", x);
 
 1644                    SQLColAttribute(stmt, x + 1, SQL_DESC_OCTET_LENGTH, 
NULL, 0, 
NULL, &octetlength);
 
 1652                    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1654                        SQLCloseCursor(stmt);
 
 1655                        SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1666                res = SQLFetch(stmt);
 
 1667                if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
 
 1670                ast_cli(
a->fd, 
"%-20.20s  %s\n", 
"----------", 
"----------");
 
 1672            SQLCloseCursor(stmt);
 
 1673            SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1675            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]);
 
 
 1699    char *char_args, *char_values, varname[15];
 
 1708            "Usage: odbc write <name> <args> <value> [exec]\n" 
 1709            "       Evaluates the SQL provided in the ODBC function <name>, and\n" 
 1710            "       optionally executes the function.  This function is intended for\n" 
 1711            "       testing purposes.  Remember to quote arguments containing spaces.\n";
 
 1715            int wordlen = strlen(
a->word), which = 0;
 
 1719                if (!strncasecmp(query->
acf->
name, 
a->word, wordlen)) {
 
 1720                    if (++which > 
a->n) {
 
 1729        } 
else if (
a->pos == 5) {
 
 1730            static const char * 
const completions[] = { 
"exec", 
NULL };
 
 1737    if (
a->argc < 5 || 
a->argc > 6) {
 
 1748        if (!strcmp(query->
acf->
name, 
a->argv[2])) {
 
 1754        ast_cli(
a->fd, 
"No such query '%s'\n", 
a->argv[2]);
 
 1760        ast_cli(
a->fd, 
"The function %s has no writesql parameter.\n", 
a->argv[2]);
 
 1781    for (i = 0; i < 
args.argc; i++) {
 
 1782        snprintf(varname, 
sizeof(varname), 
"ARG%d", i + 1);
 
 1788    for (i = 0; i < 
values.argc; i++) {
 
 1789        snprintf(varname, 
sizeof(varname), 
"VAL%d", i + 1);
 
 1800    if (
a->argc == 6 && !strcmp(
a->argv[5], 
"exec")) {
 
 1804        int dsn_num, executed = 0;
 
 1808        for (dsn_num = 0; dsn_num < 5; dsn_num++) {
 
 1821            SQLRowCount(stmt, &rows);
 
 1822            SQLCloseCursor(stmt);
 
 1823            SQLFreeHandle(SQL_HANDLE_STMT, stmt);
 
 1825            ast_cli(
a->fd, 
"Affected %d rows.  Query executed on handle %d [%s]\n", (
int)rows, dsn_num, query->
writehandle[dsn_num]);
 
 1831            ast_cli(
a->fd, 
"Failed to execute query.\n");
 
 
 1889        if (!strcasecmp(catg, 
"general")) {
 
 1896            else if (err == EINVAL)
 
 
 2001        if (!strcasecmp(catg, 
"general")) {
 
 
 2026    .
requires = 
"res_odbc",
 
void ast_cli_unregister_multiple(void)
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.
#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 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 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 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 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.
@ CONFIG_FLAG_FILEUNCHANGED
const char * ast_variable_retrieve(struct ast_config *config, const char *category, const char *variable)
#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.
size_t attribute_pure ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within 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)
char *attribute_pure ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str 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.
struct acf_odbc_query::@185 list
struct ast_custom_function * acf
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::@186 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)