Sat Aug 6 00:39:57 2011

Asterisk developer's documentation


func_odbc.c File Reference

ODBC lookups. More...

#include "asterisk.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include "asterisk/module.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/options.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/config.h"
#include "asterisk/res_odbc.h"
#include "asterisk/app.h"

Go to the source code of this file.

Data Structures

struct  acf_odbc_query
struct  queries

Enumerations

enum  { OPT_ESCAPECOMMAS = (1 << 0) }

Functions

static void __reg_module (void)
static void __unreg_module (void)
static int acf_escape (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len)
static int acf_odbc_read (struct ast_channel *chan, char *cmd, char *s, char *buf, size_t len)
static int acf_odbc_write (struct ast_channel *chan, char *cmd, char *s, const char *value)
static int free_acf_query (struct acf_odbc_query *query)
static SQLHSTMT generic_prepare (struct odbc_obj *obj, void *data)
static int init_acf_query (struct ast_config *cfg, char *catg, struct acf_odbc_query **query)
static int load_module (void)
static int odbc_load_module (void)
static int odbc_unload_module (void)
static int reload (void)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ODBC lookups" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static const struct ast_module_infoast_module_info = &__mod_info
static char * config = "func_odbc.conf"
static struct ast_custom_function escape_function
enum { ... }  odbc_option_flags


Detailed Description

ODBC lookups.

Author:
Tilghman Lesher <func_odbc__200508@the-tilghman.com>

Definition in file func_odbc.c.


Enumeration Type Documentation

anonymous enum

Enumerator:
OPT_ESCAPECOMMAS 

Definition at line 57 of file func_odbc.c.

00057      {
00058    OPT_ESCAPECOMMAS =   (1 << 0),
00059 } odbc_option_flags;


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 671 of file func_odbc.c.

static void __unreg_module ( void   )  [static]

Definition at line 671 of file func_odbc.c.

static int acf_escape ( struct ast_channel chan,
char *  cmd,
char *  data,
char *  buf,
size_t  len 
) [static]

Definition at line 378 of file func_odbc.c.

00379 {
00380    char *out = buf;
00381 
00382    for (; *data && out - buf < len; data++) {
00383       if (*data == '\'') {
00384          *out = '\'';
00385          out++;
00386       }
00387       *out++ = *data;
00388    }
00389    *out = '\0';
00390 
00391    return 0;
00392 }

static int acf_odbc_read ( struct ast_channel chan,
char *  cmd,
char *  s,
char *  buf,
size_t  len 
) [static]

Definition at line 217 of file func_odbc.c.

References acf_odbc_query::acf, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_alloc(), ast_channel_free(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), AST_STANDARD_APP_ARGS, ast_test_flag, ast_verbose(), acf_odbc_query::dsn, generic_prepare(), acf_odbc_query::list, LOG_ERROR, LOG_WARNING, ast_custom_function::name, OPT_ESCAPECOMMAS, option_verbose, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), acf_odbc_query::sql_read, and VERBOSE_PREFIX_4.

Referenced by init_acf_query().

00218 {
00219    struct odbc_obj *obj;
00220    struct acf_odbc_query *query;
00221    char sql[2048] = "", varname[15];
00222    int res, x, buflen = 1, escapecommas, bogus_chan = 0;
00223    AST_DECLARE_APP_ARGS(args,
00224       AST_APP_ARG(field)[100];
00225    );
00226    SQLHSTMT stmt;
00227    SQLSMALLINT colcount=0;
00228    SQLLEN indicator;
00229 
00230    AST_LIST_LOCK(&queries);
00231    AST_LIST_TRAVERSE(&queries, query, list) {
00232       if (!strcmp(query->acf->name, cmd)) {
00233          break;
00234       }
00235    }
00236 
00237    if (!query) {
00238       ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
00239       AST_LIST_UNLOCK(&queries);
00240       return -1;
00241    }
00242 
00243    obj = ast_odbc_request_obj(query->dsn, 0);
00244 
00245    if (!obj) {
00246       ast_log(LOG_ERROR, "No such DSN registered (or out of connections): %s (check res_odbc.conf)\n", query->dsn);
00247       AST_LIST_UNLOCK(&queries);
00248       return -1;
00249    }
00250 
00251    if (!chan) {
00252       if ((chan = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/func_odbc")))
00253          bogus_chan = 1;
00254    }
00255 
00256    if (chan)
00257       ast_autoservice_start(chan);
00258 
00259    AST_STANDARD_APP_ARGS(args, s);
00260    for (x = 0; x < args.argc; x++) {
00261       snprintf(varname, sizeof(varname), "ARG%d", x + 1);
00262       pbx_builtin_pushvar_helper(chan, varname, args.field[x]);
00263    }
00264 
00265    pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1);
00266 
00267    /* Restore prior values */
00268    for (x = 0; x < args.argc; x++) {
00269       snprintf(varname, sizeof(varname), "ARG%d", x + 1);
00270       pbx_builtin_setvar_helper(chan, varname, NULL);
00271    }
00272 
00273    /* Save this flag, so we can release the lock */
00274    escapecommas = ast_test_flag(query, OPT_ESCAPECOMMAS);
00275 
00276    AST_LIST_UNLOCK(&queries);
00277 
00278    stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql);
00279 
00280    if (!stmt) {
00281       ast_odbc_release_obj(obj);
00282       if (chan)
00283          ast_autoservice_stop(chan);
00284       if (bogus_chan)
00285          ast_channel_free(chan);
00286       return -1;
00287    }
00288 
00289    res = SQLNumResultCols(stmt, &colcount);
00290    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00291       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00292       SQLCloseCursor(stmt);
00293       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00294       ast_odbc_release_obj(obj);
00295       if (chan)
00296          ast_autoservice_stop(chan);
00297       if (bogus_chan)
00298          ast_channel_free(chan);
00299       return -1;
00300    }
00301 
00302    *buf = '\0';
00303 
00304    res = SQLFetch(stmt);
00305    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00306       int res1 = -1;
00307       if (res == SQL_NO_DATA) {
00308          if (option_verbose > 3) {
00309             ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql);
00310          }
00311          res1 = 0;
00312       } else if (option_verbose > 3) {
00313          ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql);
00314       }
00315       SQLCloseCursor(stmt);
00316       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00317       ast_odbc_release_obj(obj);
00318       if (chan)
00319          ast_autoservice_stop(chan);
00320       if (bogus_chan)
00321          ast_channel_free(chan);
00322       return res1;
00323    }
00324 
00325    for (x = 0; x < colcount; x++) {
00326       int i;
00327       char coldata[256];
00328 
00329       buflen = strlen(buf);
00330       res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator);
00331       if (indicator == SQL_NULL_DATA) {
00332          coldata[0] = '\0';
00333          res = SQL_SUCCESS;
00334       }
00335 
00336       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00337          ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00338          SQLCloseCursor(stmt);
00339          SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00340          ast_odbc_release_obj(obj);
00341          if (chan)
00342             ast_autoservice_stop(chan);
00343          if (bogus_chan)
00344             ast_channel_free(chan);
00345          return -1;
00346       }
00347 
00348       /* Copy data, encoding '\' and ',' for the argument parser */
00349       for (i = 0; i < sizeof(coldata); i++) {
00350          if (escapecommas && (coldata[i] == '\\' || coldata[i] == ',')) {
00351             buf[buflen++] = '\\';
00352          }
00353          buf[buflen++] = coldata[i];
00354 
00355          if (buflen >= len - 2)
00356             break;
00357 
00358          if (coldata[i] == '\0')
00359             break;
00360       }
00361 
00362       buf[buflen - 1] = ',';
00363       buf[buflen] = '\0';
00364    }
00365    /* Trim trailing comma */
00366    buf[buflen - 1] = '\0';
00367 
00368    SQLCloseCursor(stmt);
00369    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00370    ast_odbc_release_obj(obj);
00371    if (chan)
00372       ast_autoservice_stop(chan);
00373    if (bogus_chan)
00374       ast_channel_free(chan);
00375    return 0;
00376 }

static int acf_odbc_write ( struct ast_channel chan,
char *  cmd,
char *  s,
const char *  value 
) [static]

Definition at line 98 of file func_odbc.c.

References acf_odbc_query::acf, AST_APP_ARG, ast_autoservice_start(), ast_autoservice_stop(), ast_channel_alloc(), ast_channel_free(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_odbc_prepare_and_execute(), ast_odbc_release_obj(), ast_odbc_request_obj(), AST_STANDARD_APP_ARGS, ast_strdupa, acf_odbc_query::dsn, generic_prepare(), acf_odbc_query::list, LOG_ERROR, ast_custom_function::name, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), acf_odbc_query::sql_write, and t.

Referenced by init_acf_query().

00099 {
00100    struct odbc_obj *obj;
00101    struct acf_odbc_query *query;
00102    char *t, buf[2048]="", varname[15];
00103    int i, bogus_chan = 0;
00104    AST_DECLARE_APP_ARGS(values,
00105       AST_APP_ARG(field)[100];
00106    );
00107    AST_DECLARE_APP_ARGS(args,
00108       AST_APP_ARG(field)[100];
00109    );
00110    SQLHSTMT stmt;
00111    SQLLEN rows=0;
00112 
00113    AST_LIST_LOCK(&queries);
00114    AST_LIST_TRAVERSE(&queries, query, list) {
00115       if (!strcmp(query->acf->name, cmd)) {
00116          break;
00117       }
00118    }
00119 
00120    if (!query) {
00121       ast_log(LOG_ERROR, "No such function '%s'\n", cmd);
00122       AST_LIST_UNLOCK(&queries);
00123       return -1;
00124    }
00125 
00126    obj = ast_odbc_request_obj(query->dsn, 0);
00127 
00128    if (!obj) {
00129       ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", query->dsn);
00130       AST_LIST_UNLOCK(&queries);
00131       return -1;
00132    }
00133 
00134    if (!chan) {
00135       if ((chan = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/func_odbc")))
00136          bogus_chan = 1;
00137    }
00138 
00139    if (chan)
00140       ast_autoservice_start(chan);
00141 
00142    /* Parse our arguments */
00143    t = value ? ast_strdupa(value) : "";
00144 
00145    if (!s || !t) {
00146       ast_log(LOG_ERROR, "Out of memory\n");
00147       AST_LIST_UNLOCK(&queries);
00148       if (chan)
00149          ast_autoservice_stop(chan);
00150       if (bogus_chan)
00151          ast_channel_free(chan);
00152       return -1;
00153    }
00154 
00155    AST_STANDARD_APP_ARGS(args, s);
00156    for (i = 0; i < args.argc; i++) {
00157       snprintf(varname, sizeof(varname), "ARG%d", i + 1);
00158       pbx_builtin_pushvar_helper(chan, varname, args.field[i]);
00159    }
00160 
00161    /* Parse values, just like arguments */
00162    /* Can't use the pipe, because app Set removes them */
00163    AST_NONSTANDARD_APP_ARGS(values, t, ',');
00164    for (i = 0; i < values.argc; i++) {
00165       snprintf(varname, sizeof(varname), "VAL%d", i + 1);
00166       pbx_builtin_pushvar_helper(chan, varname, values.field[i]);
00167    }
00168 
00169    /* Additionally set the value as a whole (but push an empty string if value is NULL) */
00170    pbx_builtin_pushvar_helper(chan, "VALUE", value ? value : "");
00171 
00172    pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1);
00173 
00174    /* Restore prior values */
00175    for (i = 0; i < args.argc; i++) {
00176       snprintf(varname, sizeof(varname), "ARG%d", i + 1);
00177       pbx_builtin_setvar_helper(chan, varname, NULL);
00178    }
00179 
00180    for (i = 0; i < values.argc; i++) {
00181       snprintf(varname, sizeof(varname), "VAL%d", i + 1);
00182       pbx_builtin_setvar_helper(chan, varname, NULL);
00183    }
00184    pbx_builtin_setvar_helper(chan, "VALUE", NULL);
00185 
00186    AST_LIST_UNLOCK(&queries);
00187 
00188    stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, buf);
00189 
00190    if (stmt) {
00191       /* Rows affected */
00192       SQLRowCount(stmt, &rows);
00193    }
00194 
00195    /* Output the affected rows, for all cases.  In the event of failure, we
00196     * flag this as -1 rows.  Note that this is different from 0 affected rows
00197     * which would be the case if we succeeded in our query, but the values did
00198     * not change. */
00199    snprintf(varname, sizeof(varname), "%d", (int)rows);
00200    pbx_builtin_setvar_helper(chan, "ODBCROWS", varname);
00201 
00202    if (stmt) {
00203       SQLCloseCursor(stmt);
00204       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00205    }
00206    if (obj)
00207       ast_odbc_release_obj(obj);
00208 
00209    if (chan)
00210       ast_autoservice_stop(chan);
00211    if (bogus_chan)
00212       ast_channel_free(chan);
00213 
00214    return 0;
00215 }

static int free_acf_query ( struct acf_odbc_query query  )  [static]

Definition at line 542 of file func_odbc.c.

References acf_odbc_query::acf, ast_custom_function::desc, free, ast_custom_function::name, and ast_custom_function::syntax.

Referenced by odbc_load_module(), odbc_unload_module(), and reload().

00543 {
00544    if (query) {
00545       if (query->acf) {
00546          if (query->acf->name)
00547             free((char *)query->acf->name);
00548          if (query->acf->syntax)
00549             free((char *)query->acf->syntax);
00550          if (query->acf->desc)
00551             free((char *)query->acf->desc);
00552          free(query->acf);
00553       }
00554       free(query);
00555    }
00556    return 0;
00557 }

static SQLHSTMT generic_prepare ( struct odbc_obj obj,
void *  data 
) [static]

Definition at line 72 of file func_odbc.c.

References ast_log(), and LOG_WARNING.

Referenced by acf_odbc_read(), and acf_odbc_write().

00073 {
00074    int res;
00075    char *sql = data;
00076    SQLHSTMT stmt;
00077 
00078    res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);
00079    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00080       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00081       return NULL;
00082    }
00083 
00084    res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS);
00085    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00086       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);
00087       SQLCloseCursor(stmt);
00088       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00089       return NULL;
00090    }
00091 
00092    return stmt;
00093 }

static int init_acf_query ( struct ast_config cfg,
char *  catg,
struct acf_odbc_query **  query 
) [static]

Definition at line 406 of file func_odbc.c.

References acf_odbc_query::acf, acf_odbc_read(), acf_odbc_write(), asprintf, ast_calloc, ast_clear_flag, ast_copy_string(), ast_false(), ast_log(), ast_set_flag, ast_strlen_zero(), ast_variable_retrieve(), errno, free, LOG_ERROR, LOG_WARNING, OPT_ESCAPECOMMAS, ast_custom_function::read, and ast_custom_function::synopsis.

Referenced by odbc_load_module(), and reload().

00407 {
00408    const char *tmp;
00409    int res;
00410 
00411    if (!cfg || !catg) {
00412       return -1;
00413    }
00414 
00415    *query = ast_calloc(1, sizeof(struct acf_odbc_query));
00416    if (! (*query))
00417       return -1;
00418 
00419    if ((tmp = ast_variable_retrieve(cfg, catg, "dsn"))) {
00420       ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn));
00421    } else if ((tmp = ast_variable_retrieve(cfg, catg, "writehandle")) || (tmp = ast_variable_retrieve(cfg, catg, "readhandle"))) {
00422       ast_log(LOG_WARNING, "Separate read and write handles are not supported in this version of func_odbc.so\n");
00423       ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn));
00424    } else {
00425       free(*query);
00426       *query = NULL;
00427       ast_log(LOG_ERROR, "No database handle was specified for func_odbc class '%s'\n", catg);
00428       return -1;
00429    }
00430 
00431    if ((tmp = ast_variable_retrieve(cfg, catg, "read")) || (tmp = ast_variable_retrieve(cfg, catg, "readsql"))) {
00432       ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read));
00433    }
00434 
00435    if ((tmp = ast_variable_retrieve(cfg, catg, "write")) || (tmp = ast_variable_retrieve(cfg, catg, "writesql"))) {
00436       ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write));
00437    }
00438 
00439    /* Allow escaping of embedded commas in fields to be turned off */
00440    ast_set_flag((*query), OPT_ESCAPECOMMAS);
00441    if ((tmp = ast_variable_retrieve(cfg, catg, "escapecommas"))) {
00442       if (ast_false(tmp))
00443          ast_clear_flag((*query), OPT_ESCAPECOMMAS);
00444    }
00445 
00446    (*query)->acf = ast_calloc(1, sizeof(struct ast_custom_function));
00447    if (! (*query)->acf) {
00448       free(*query);
00449       *query = NULL;
00450       return -1;
00451    }
00452 
00453    if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) {
00454       if (asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg) < 0) {
00455          ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00456       }
00457    } else {
00458       if (asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg) < 0) {
00459          ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00460       }
00461    }
00462 
00463    if (!((*query)->acf->name)) {
00464       free((*query)->acf);
00465       free(*query);
00466       *query = NULL;
00467       return -1;
00468    }
00469 
00470    if (asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name) < 0) {
00471       ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00472       (*query)->acf->syntax = NULL;
00473    }
00474 
00475    if (!((*query)->acf->syntax)) {
00476       free((char *)(*query)->acf->name);
00477       free((*query)->acf);
00478       free(*query);
00479       *query = NULL;
00480       return -1;
00481    }
00482 
00483    res = 0;
00484    (*query)->acf->synopsis = "Runs the referenced query with the specified arguments";
00485    if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) {
00486       res = asprintf((char **)&((*query)->acf->desc),
00487                 "Runs the following query, as defined in func_odbc.conf, performing\n"
00488                 "substitution of the arguments into the query as specified by ${ARG1},\n"
00489                 "${ARG2}, ... ${ARGn}.  When setting the function, the values are provided\n"
00490                 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
00491                 "\nRead:\n%s\n\nWrite:\n%s\n",
00492                 (*query)->sql_read,
00493                 (*query)->sql_write);
00494    } else if (!ast_strlen_zero((*query)->sql_read)) {
00495       res = asprintf((char **)&((*query)->acf->desc),
00496                 "Runs the following query, as defined in func_odbc.conf, performing\n"
00497                 "substitution of the arguments into the query as specified by ${ARG1},\n"
00498                 "${ARG2}, ... ${ARGn}.  This function may only be read, not set.\n\nSQL:\n%s\n",
00499                 (*query)->sql_read);
00500    } else if (!ast_strlen_zero((*query)->sql_write)) {
00501       res = asprintf((char **)&((*query)->acf->desc),
00502                 "Runs the following query, as defined in func_odbc.conf, performing\n"
00503                 "substitution of the arguments into the query as specified by ${ARG1},\n"
00504                 "${ARG2}, ... ${ARGn}.  The values are provided either in whole as\n"
00505                 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n"
00506                 "This function may only be set.\nSQL:\n%s\n",
00507                 (*query)->sql_write);
00508    } else {
00509       ast_log(LOG_ERROR, "No SQL was found for func_odbc class '%s'\n", catg);
00510    }
00511 
00512    if (res < 0) {
00513       ast_log(LOG_WARNING, "asprintf() failed: %s\n", strerror(errno));
00514       (*query)->acf->desc = NULL;
00515    }
00516 
00517    /* Could be out of memory, or could be we have neither sql_read nor sql_write */
00518    if (!((*query)->acf->desc)) {
00519       free((char *)(*query)->acf->syntax);
00520       free((char *)(*query)->acf->name);
00521       free((*query)->acf);
00522       free(*query);
00523       *query = NULL;
00524       return -1;
00525    }
00526 
00527    if (ast_strlen_zero((*query)->sql_read)) {
00528       (*query)->acf->read = NULL;
00529    } else {
00530       (*query)->acf->read = acf_odbc_read;
00531    }
00532 
00533    if (ast_strlen_zero((*query)->sql_write)) {
00534       (*query)->acf->write = NULL;
00535    } else {
00536       (*query)->acf->write = acf_odbc_write;
00537    }
00538 
00539    return 0;
00540 }

static int load_module ( void   )  [static]

Definition at line 660 of file func_odbc.c.

References odbc_load_module().

00661 {
00662    return odbc_load_module();
00663 }

static int odbc_load_module ( void   )  [static]

Definition at line 559 of file func_odbc.c.

References ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_custom_function_register(), AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_MODULE_LOAD_DECLINE, escape_function, free_acf_query(), init_acf_query(), acf_odbc_query::list, and LOG_NOTICE.

Referenced by load_module(), and reload().

00560 {
00561    int res = 0;
00562    struct ast_config *cfg;
00563    char *catg;
00564 
00565    AST_LIST_LOCK(&queries);
00566 
00567    cfg = ast_config_load(config);
00568    if (!cfg) {
00569       ast_log(LOG_NOTICE, "Unable to load config for func_odbc: %s\n", config);
00570       AST_LIST_UNLOCK(&queries);
00571       return AST_MODULE_LOAD_DECLINE;
00572    }
00573 
00574    for (catg = ast_category_browse(cfg, NULL);
00575         catg;
00576         catg = ast_category_browse(cfg, catg)) {
00577       struct acf_odbc_query *query = NULL;
00578 
00579       if (init_acf_query(cfg, catg, &query)) {
00580          free_acf_query(query);
00581       } else {
00582          AST_LIST_INSERT_HEAD(&queries, query, list);
00583          ast_custom_function_register(query->acf);
00584       }
00585    }
00586 
00587    ast_config_destroy(cfg);
00588    ast_custom_function_register(&escape_function);
00589 
00590    AST_LIST_UNLOCK(&queries);
00591    return res;
00592 }

static int odbc_unload_module ( void   )  [static]

Definition at line 594 of file func_odbc.c.

References acf_odbc_query::acf, ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, escape_function, free_acf_query(), and acf_odbc_query::list.

Referenced by reload(), and unload_module().

00595 {
00596    struct acf_odbc_query *query;
00597 
00598    AST_LIST_LOCK(&queries);
00599    while (!AST_LIST_EMPTY(&queries)) {
00600       query = AST_LIST_REMOVE_HEAD(&queries, list);
00601       ast_custom_function_unregister(query->acf);
00602       free_acf_query(query);
00603    }
00604 
00605    ast_custom_function_unregister(&escape_function);
00606 
00607    /* Allow any threads waiting for this lock to pass (avoids a race) */
00608    AST_LIST_UNLOCK(&queries);
00609    AST_LIST_LOCK(&queries);
00610 
00611    AST_LIST_UNLOCK(&queries);
00612    return 0;
00613 }

static int reload ( void   )  [static]

Definition at line 615 of file func_odbc.c.

References acf_odbc_query::acf, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_custom_function_register(), ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_INSERT_HEAD, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), free_acf_query(), init_acf_query(), acf_odbc_query::list, LOG_ERROR, and LOG_WARNING.

00616 {
00617    int res = 0;
00618    struct ast_config *cfg;
00619    struct acf_odbc_query *oldquery;
00620    char *catg;
00621 
00622    AST_LIST_LOCK(&queries);
00623 
00624    while (!AST_LIST_EMPTY(&queries)) {
00625       oldquery = AST_LIST_REMOVE_HEAD(&queries, list);
00626       ast_custom_function_unregister(oldquery->acf);
00627       free_acf_query(oldquery);
00628    }
00629 
00630    cfg = ast_config_load(config);
00631    if (!cfg) {
00632       ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);
00633       goto reload_out;
00634    }
00635 
00636    for (catg = ast_category_browse(cfg, NULL);
00637         catg;
00638         catg = ast_category_browse(cfg, catg)) {
00639       struct acf_odbc_query *query = NULL;
00640 
00641       if (init_acf_query(cfg, catg, &query)) {
00642          ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg);
00643       } else {
00644          AST_LIST_INSERT_HEAD(&queries, query, list);
00645          ast_custom_function_register(query->acf);
00646       }
00647    }
00648 
00649    ast_config_destroy(cfg);
00650 reload_out:
00651    AST_LIST_UNLOCK(&queries);
00652    return res;
00653 }

static int unload_module ( void   )  [static]

Definition at line 655 of file func_odbc.c.

References odbc_unload_module().

00656 {
00657    return odbc_unload_module();
00658 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "ODBC lookups" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 671 of file func_odbc.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 671 of file func_odbc.c.

char* config = "func_odbc.conf" [static]

Definition at line 55 of file func_odbc.c.

struct ast_custom_function escape_function [static]

Definition at line 394 of file func_odbc.c.

Referenced by odbc_load_module(), and odbc_unload_module().

enum { ... } odbc_option_flags


Generated on Sat Aug 6 00:39:57 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7