Sat Aug 6 00:39:31 2011

Asterisk developer's documentation


res_config_odbc.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2010, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * Copyright (C) 2004 - 2005 Anthony Minessale II <anthmct@yahoo.com>
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*! \file
00022  *
00023  * \brief odbc+odbc plugin for portable configuration engine
00024  *
00025  * \author Mark Spencer <markster@digium.com>
00026  * \author Anthony Minessale II <anthmct@yahoo.com>
00027  *
00028  * \arg http://www.unixodbc.org
00029  */
00030 
00031 /*** MODULEINFO
00032    <depend>unixodbc</depend>
00033    <depend>ltdl</depend>
00034    <depend>res_odbc</depend>
00035  ***/
00036 
00037 #include "asterisk.h"
00038 
00039 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 310140 $")
00040 
00041 #include <stdio.h>
00042 #include <stdlib.h>
00043 #include <unistd.h>
00044 #include <string.h>
00045 
00046 #include "asterisk/file.h"
00047 #include "asterisk/logger.h"
00048 #include "asterisk/channel.h"
00049 #include "asterisk/pbx.h"
00050 #include "asterisk/config.h"
00051 #include "asterisk/module.h"
00052 #include "asterisk/lock.h"
00053 #include "asterisk/options.h"
00054 #include "asterisk/res_odbc.h"
00055 #include "asterisk/utils.h"
00056 #include "asterisk/stringfields.h"
00057 
00058 struct custom_prepare_struct {
00059    const char *sql;
00060    const char *extra;
00061    AST_DECLARE_STRING_FIELDS(
00062       AST_STRING_FIELD(encoding)[256];
00063    );
00064    va_list ap;
00065 };
00066 
00067 static void decode_chunk(char *chunk)
00068 {
00069    for (; *chunk; chunk++) {
00070       if (*chunk == '^' && strchr("0123456789ABCDEF", chunk[1]) && strchr("0123456789ABCDEF", chunk[2])) {
00071          sscanf(chunk + 1, "%02hhX", chunk);
00072          memmove(chunk + 1, chunk + 3, strlen(chunk + 3) + 1);
00073       }
00074    }
00075 }
00076 
00077 static SQLHSTMT custom_prepare(struct odbc_obj *obj, void *data)
00078 {
00079    int res, x = 1;
00080    struct custom_prepare_struct *cps = data;
00081    const char *newparam, *newval;
00082    char encodebuf[1024];
00083    SQLHSTMT stmt;
00084    va_list ap;
00085 
00086    va_copy(ap, cps->ap);
00087 
00088    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &stmt);
00089    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00090       ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");
00091       return NULL;
00092    }
00093 
00094    res = SQLPrepare(stmt, (unsigned char *)cps->sql, SQL_NTS);
00095    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00096       ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", cps->sql);
00097       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00098       return NULL;
00099    }
00100 
00101    while ((newparam = va_arg(ap, const char *))) {
00102       newval = va_arg(ap, const char *);
00103       if (strchr(newval, ';') || strchr(newval, '^')) {
00104          char *eptr = encodebuf;
00105          const char *vptr = newval;
00106          for (; *vptr && eptr < encodebuf + sizeof(encodebuf); vptr++) {
00107             if (strchr("^;", *vptr)) {
00108                /* We use ^XX, instead of %XX because '%' is a special character in SQL */
00109                snprintf(eptr, encodebuf + sizeof(encodebuf) - eptr, "^%02hhX", *vptr);
00110                eptr += 3;
00111             } else {
00112                *eptr++ = *vptr;
00113             }
00114          }
00115          if (eptr < encodebuf + sizeof(encodebuf)) {
00116             *eptr = '\0';
00117          } else {
00118             encodebuf[sizeof(encodebuf) - 1] = '\0';
00119          }
00120          ast_string_field_set(cps, encoding[x], encodebuf);
00121          newval = cps->encoding[x];
00122       }
00123       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(newval), 0, (void *)newval, 0, NULL);
00124    }
00125    va_end(ap);
00126 
00127    if (!ast_strlen_zero(cps->extra))
00128       SQLBindParameter(stmt, x++, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_CHAR, strlen(cps->extra), 0, (void *)cps->extra, 0, NULL);
00129    return stmt;
00130 }
00131 
00132 static struct ast_variable *realtime_odbc(const char *database, const char *table, va_list ap)
00133 {
00134    struct odbc_obj *obj;
00135    SQLHSTMT stmt;
00136    char sql[1024];
00137    char coltitle[256];
00138    char rowdata[2048];
00139    char *op;
00140    const char *newparam, *newval;
00141    char *stringp;
00142    char *chunk;
00143    SQLSMALLINT collen;
00144    int res;
00145    int x;
00146    struct ast_variable *var=NULL, *prev=NULL;
00147    SQLULEN colsize;
00148    SQLSMALLINT colcount=0;
00149    SQLSMALLINT datatype;
00150    SQLSMALLINT decimaldigits;
00151    SQLSMALLINT nullable;
00152    SQLLEN indicator;
00153    va_list aq;
00154    struct custom_prepare_struct cps = { .sql = sql };
00155 
00156    if (ast_string_field_init(&cps, 256)) {
00157       return NULL;
00158    }
00159    va_copy(cps.ap, ap);
00160    va_copy(aq, ap);
00161 
00162    if (!table) {
00163       ast_string_field_free_memory(&cps);
00164       return NULL;
00165    }
00166 
00167    obj = ast_odbc_request_obj(database, 0);
00168 
00169    if (!obj) {
00170       ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", database);
00171       ast_string_field_free_memory(&cps);
00172       return NULL;
00173    }
00174 
00175    newparam = va_arg(aq, const char *);
00176    if (!newparam) {
00177       ast_odbc_release_obj(obj);
00178       ast_string_field_free_memory(&cps);
00179       return NULL;
00180    }
00181    newval = va_arg(aq, const char *);
00182    op = !strchr(newparam, ' ') ? " =" : "";
00183    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00184       strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00185    while((newparam = va_arg(aq, const char *))) {
00186       op = !strchr(newparam, ' ') ? " =" : "";
00187       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00188          strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00189       newval = va_arg(aq, const char *);
00190    }
00191    va_end(aq);
00192 
00193    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00194 
00195    if (!stmt) {
00196       ast_odbc_release_obj(obj);
00197       ast_string_field_free_memory(&cps);
00198       return NULL;
00199    }
00200 
00201    res = SQLNumResultCols(stmt, &colcount);
00202    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00203       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00204       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00205       ast_odbc_release_obj(obj);
00206       ast_string_field_free_memory(&cps);
00207       return NULL;
00208    }
00209 
00210    res = SQLFetch(stmt);
00211    if (res == SQL_NO_DATA) {
00212       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00213       ast_odbc_release_obj(obj);
00214       ast_string_field_free_memory(&cps);
00215       return NULL;
00216    }
00217    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00218       ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00219       SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00220       ast_odbc_release_obj(obj);
00221       ast_string_field_free_memory(&cps);
00222       return NULL;
00223    }
00224    for (x = 0; x < colcount; x++) {
00225       rowdata[0] = '\0';
00226       colsize = 0;
00227       collen = sizeof(coltitle);
00228       res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00229                &datatype, &colsize, &decimaldigits, &nullable);
00230       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00231          ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00232          if (var)
00233             ast_variables_destroy(var);
00234          ast_odbc_release_obj(obj);
00235          ast_string_field_free_memory(&cps);
00236          return NULL;
00237       }
00238 
00239       indicator = 0;
00240       res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00241       if (indicator == SQL_NULL_DATA)
00242          continue;
00243 
00244       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00245          ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00246          if (var)
00247             ast_variables_destroy(var);
00248          ast_odbc_release_obj(obj);
00249          return NULL;
00250       }
00251       stringp = rowdata;
00252       while (stringp) {
00253          chunk = strsep(&stringp, ";");
00254          if (!ast_strlen_zero(ast_strip(chunk))) {
00255             if (strchr(chunk, '^')) {
00256                decode_chunk(chunk);
00257             }
00258             if (prev) {
00259                prev->next = ast_variable_new(coltitle, chunk);
00260                if (prev->next) {
00261                   prev = prev->next;
00262                }
00263             } else {
00264                prev = var = ast_variable_new(coltitle, chunk);
00265             }
00266          }
00267       }
00268    }
00269 
00270 
00271    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00272    ast_odbc_release_obj(obj);
00273    ast_string_field_free_memory(&cps);
00274    return var;
00275 }
00276 
00277 static struct ast_config *realtime_multi_odbc(const char *database, const char *table, va_list ap)
00278 {
00279    struct odbc_obj *obj;
00280    SQLHSTMT stmt;
00281    char sql[1024];
00282    char coltitle[256];
00283    char rowdata[2048];
00284    const char *initfield=NULL;
00285    char *op;
00286    const char *newparam, *newval;
00287    char *stringp;
00288    char *chunk;
00289    SQLSMALLINT collen;
00290    int res;
00291    int x;
00292    struct ast_variable *var=NULL;
00293    struct ast_config *cfg=NULL;
00294    struct ast_category *cat=NULL;
00295    struct ast_realloca ra;
00296    SQLULEN colsize;
00297    SQLSMALLINT colcount=0;
00298    SQLSMALLINT datatype;
00299    SQLSMALLINT decimaldigits;
00300    SQLSMALLINT nullable;
00301    SQLLEN indicator;
00302    struct custom_prepare_struct cps = { .sql = sql };
00303    va_list aq;
00304 
00305    if (!table || ast_string_field_init(&cps, 256)) {
00306       return NULL;
00307    }
00308    va_copy(cps.ap, ap);
00309    va_copy(aq, ap);
00310 
00311    memset(&ra, 0, sizeof(ra));
00312 
00313    obj = ast_odbc_request_obj(database, 0);
00314    if (!obj) {
00315       ast_string_field_free_memory(&cps);
00316       return NULL;
00317    }
00318 
00319    newparam = va_arg(aq, const char *);
00320    if (!newparam)  {
00321       ast_odbc_release_obj(obj);
00322       ast_string_field_free_memory(&cps);
00323       return NULL;
00324    }
00325    initfield = ast_strdupa(newparam);
00326    if ((op = strchr(initfield, ' '))) 
00327       *op = '\0';
00328    newval = va_arg(aq, const char *);
00329    op = !strchr(newparam, ' ') ? " =" : "";
00330    snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s ?%s", table, newparam, op,
00331       strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00332    while((newparam = va_arg(aq, const char *))) {
00333       op = !strchr(newparam, ' ') ? " =" : "";
00334       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s ?%s", newparam, op,
00335          strcasestr(newparam, "LIKE") && !ast_odbc_backslash_is_escape(obj) ? " ESCAPE '\\'" : "");
00336       newval = va_arg(aq, const char *);
00337    }
00338    if (initfield)
00339       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
00340    va_end(aq);
00341 
00342    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00343 
00344    if (!stmt) {
00345       ast_odbc_release_obj(obj);
00346       ast_string_field_free_memory(&cps);
00347       return NULL;
00348    }
00349 
00350    res = SQLNumResultCols(stmt, &colcount);
00351    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00352       ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);
00353       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00354       ast_odbc_release_obj(obj);
00355       ast_string_field_free_memory(&cps);
00356       return NULL;
00357    }
00358 
00359    cfg = ast_config_new();
00360    if (!cfg) {
00361       ast_log(LOG_WARNING, "Out of memory!\n");
00362       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00363       ast_odbc_release_obj(obj);
00364       ast_string_field_free_memory(&cps);
00365       return NULL;
00366    }
00367 
00368    while ((res=SQLFetch(stmt)) != SQL_NO_DATA) {
00369       var = NULL;
00370       if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00371          ast_log(LOG_WARNING, "SQL Fetch error!\n[%s]\n\n", sql);
00372          continue;
00373       }
00374       cat = ast_category_new("");
00375       if (!cat) {
00376          ast_log(LOG_WARNING, "Out of memory!\n");
00377          continue;
00378       }
00379       for (x=0;x<colcount;x++) {
00380          rowdata[0] = '\0';
00381          colsize = 0;
00382          collen = sizeof(coltitle);
00383          res = SQLDescribeCol(stmt, x + 1, (unsigned char *)coltitle, sizeof(coltitle), &collen, 
00384                   &datatype, &colsize, &decimaldigits, &nullable);
00385          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00386             ast_log(LOG_WARNING, "SQL Describe Column error!\n[%s]\n\n", sql);
00387             ast_category_destroy(cat);
00388             continue;
00389          }
00390 
00391          indicator = 0;
00392          res = SQLGetData(stmt, x + 1, SQL_CHAR, rowdata, sizeof(rowdata), &indicator);
00393          if (indicator == SQL_NULL_DATA)
00394             continue;
00395 
00396          if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00397             ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);
00398             ast_category_destroy(cat);
00399             continue;
00400          }
00401          stringp = rowdata;
00402          while (stringp) {
00403             chunk = strsep(&stringp, ";");
00404             if (!ast_strlen_zero(ast_strip(chunk))) {
00405                if (strchr(chunk, '^')) {
00406                   decode_chunk(chunk);
00407                }
00408                if (initfield && !strcmp(initfield, coltitle)) {
00409                   ast_category_rename(cat, chunk);
00410                }
00411                var = ast_variable_new(coltitle, chunk);
00412                ast_variable_append(cat, var);
00413             }
00414          }
00415       }
00416       ast_category_append(cfg, cat);
00417    }
00418 
00419    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00420    ast_odbc_release_obj(obj);
00421    ast_string_field_free_memory(&cps);
00422    return cfg;
00423 }
00424 
00425 static int update_odbc(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
00426 {
00427    struct odbc_obj *obj;
00428    SQLHSTMT stmt;
00429    char sql[256];
00430    SQLLEN rowcount=0;
00431    const char *newparam, *newval;
00432    int res;
00433    va_list aq;
00434    struct custom_prepare_struct cps = { .sql = sql, .extra = lookup };
00435 
00436    if (!table || ast_string_field_init(&cps, 256)) {
00437       return -1;
00438    }
00439    va_copy(cps.ap, ap);
00440    va_copy(aq, ap);
00441 
00442    if (!(obj = ast_odbc_request_obj(database, 0))) {
00443       ast_string_field_free_memory(&cps);
00444       return -1;
00445    }
00446 
00447    newparam = va_arg(aq, const char *);
00448    if (!newparam)  {
00449       ast_odbc_release_obj(obj);
00450       ast_string_field_free_memory(&cps);
00451       return -1;
00452    }
00453    newval = va_arg(aq, const char *);
00454    snprintf(sql, sizeof(sql), "UPDATE %s SET %s=?", table, newparam);
00455    while((newparam = va_arg(aq, const char *))) {
00456       snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s=?", newparam);
00457       newval = va_arg(aq, const char *);
00458    }
00459    va_end(aq);
00460    snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s=?", keyfield);
00461 
00462    stmt = ast_odbc_prepare_and_execute(obj, custom_prepare, &cps);
00463 
00464    if (!stmt) {
00465       ast_odbc_release_obj(obj);
00466       ast_string_field_free_memory(&cps);
00467       return -1;
00468    }
00469 
00470    res = SQLRowCount(stmt, &rowcount);
00471    SQLFreeHandle (SQL_HANDLE_STMT, stmt);
00472    ast_odbc_release_obj(obj);
00473    ast_string_field_free_memory(&cps);
00474 
00475    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00476       ast_log(LOG_WARNING, "SQL Row Count error!\n[%s]\n\n", sql);
00477       return -1;
00478    }
00479 
00480    if (rowcount >= 0) {
00481       return (int) rowcount;
00482    }
00483 
00484    return -1;
00485 }
00486 
00487 struct config_odbc_obj {
00488    char *sql;
00489    unsigned long cat_metric;
00490    char category[128];
00491    char var_name[128];
00492    char var_val[1024]; /* changed from 128 to 1024 via bug 8251 */
00493    SQLLEN err;
00494 };
00495 
00496 static SQLHSTMT config_odbc_prepare(struct odbc_obj *obj, void *data)
00497 {
00498    struct config_odbc_obj *q = data;
00499    SQLHSTMT sth;
00500    int res;
00501 
00502    res = SQLAllocHandle(SQL_HANDLE_STMT, obj->con, &sth);
00503    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00504       if (option_verbose > 3)
00505          ast_verbose( VERBOSE_PREFIX_4 "Failure in AllocStatement %d\n", res);
00506       return NULL;
00507    }
00508 
00509    res = SQLPrepare(sth, (unsigned char *)q->sql, SQL_NTS);
00510    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00511       if (option_verbose > 3)
00512          ast_verbose( VERBOSE_PREFIX_4 "Error in PREPARE %d\n", res);
00513       SQLFreeHandle(SQL_HANDLE_STMT, sth);
00514       return NULL;
00515    }
00516 
00517    SQLBindCol(sth, 1, SQL_C_ULONG, &q->cat_metric, sizeof(q->cat_metric), &q->err);
00518    SQLBindCol(sth, 2, SQL_C_CHAR, q->category, sizeof(q->category), &q->err);
00519    SQLBindCol(sth, 3, SQL_C_CHAR, q->var_name, sizeof(q->var_name), &q->err);
00520    SQLBindCol(sth, 4, SQL_C_CHAR, q->var_val, sizeof(q->var_val), &q->err);
00521 
00522    return sth;
00523 }
00524 
00525 static struct ast_config *config_odbc(const char *database, const char *table, const char *file, struct ast_config *cfg, int withcomments)
00526 {
00527    struct ast_variable *new_v;
00528    struct ast_category *cur_cat;
00529    int res = 0;
00530    struct odbc_obj *obj;
00531    char sqlbuf[1024] = "";
00532    char *sql = sqlbuf;
00533    size_t sqlleft = sizeof(sqlbuf);
00534    unsigned int last_cat_metric = 0;
00535    SQLSMALLINT rowcount = 0;
00536    SQLHSTMT stmt;
00537    char last[128] = "";
00538    struct config_odbc_obj q;
00539 
00540    memset(&q, 0, sizeof(q));
00541 
00542    if (!file || !strcmp (file, "res_config_odbc.conf"))
00543       return NULL;      /* cant configure myself with myself ! */
00544 
00545    obj = ast_odbc_request_obj(database, 0);
00546    if (!obj)
00547       return NULL;
00548 
00549    ast_build_string(&sql, &sqlleft, "SELECT cat_metric, category, var_name, var_val FROM %s ", table);
00550    ast_build_string(&sql, &sqlleft, "WHERE filename='%s' AND commented=0 ", file);
00551    ast_build_string(&sql, &sqlleft, "ORDER BY cat_metric DESC, var_metric ASC, category, var_name ");
00552    q.sql = sqlbuf;
00553 
00554    stmt = ast_odbc_prepare_and_execute(obj, config_odbc_prepare, &q);
00555 
00556    if (!stmt) {
00557       ast_log(LOG_WARNING, "SQL select error!\n[%s]\n\n", sql);
00558       ast_odbc_release_obj(obj);
00559       return NULL;
00560    }
00561 
00562    res = SQLNumResultCols(stmt, &rowcount);
00563 
00564    if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {
00565       ast_log(LOG_WARNING, "SQL NumResultCols error!\n[%s]\n\n", sql);
00566       SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00567       ast_odbc_release_obj(obj);
00568       return NULL;
00569    }
00570 
00571    if (!rowcount) {
00572       ast_log(LOG_NOTICE, "found nothing\n");
00573       ast_odbc_release_obj(obj);
00574       return cfg;
00575    }
00576 
00577    cur_cat = ast_config_get_current_category(cfg);
00578 
00579    while ((res = SQLFetch(stmt)) != SQL_NO_DATA) {
00580       if (!strcmp (q.var_name, "#include")) {
00581          if (!ast_config_internal_load(q.var_val, cfg, 0)) {
00582             SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00583             ast_odbc_release_obj(obj);
00584             return NULL;
00585          }
00586          continue;
00587       } 
00588       if (strcmp(last, q.category) || last_cat_metric != q.cat_metric) {
00589          cur_cat = ast_category_new(q.category);
00590          if (!cur_cat) {
00591             ast_log(LOG_WARNING, "Out of memory!\n");
00592             break;
00593          }
00594          strcpy(last, q.category);
00595          last_cat_metric   = q.cat_metric;
00596          ast_category_append(cfg, cur_cat);
00597       }
00598 
00599       new_v = ast_variable_new(q.var_name, q.var_val);
00600       ast_variable_append(cur_cat, new_v);
00601    }
00602 
00603    SQLFreeHandle(SQL_HANDLE_STMT, stmt);
00604    ast_odbc_release_obj(obj);
00605    return cfg;
00606 }
00607 
00608 static struct ast_config_engine odbc_engine = {
00609    .name = "odbc",
00610    .load_func = config_odbc,
00611    .realtime_func = realtime_odbc,
00612    .realtime_multi_func = realtime_multi_odbc,
00613    .update_func = update_odbc
00614 };
00615 
00616 static int unload_module (void)
00617 {
00618    ast_module_user_hangup_all();
00619    ast_config_engine_deregister(&odbc_engine);
00620    if (option_verbose)
00621       ast_verbose("res_config_odbc unloaded.\n");
00622    return 0;
00623 }
00624 
00625 static int load_module (void)
00626 {
00627    ast_config_engine_register(&odbc_engine);
00628    if (option_verbose)
00629       ast_verbose("res_config_odbc loaded.\n");
00630    return 0;
00631 }
00632 
00633 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "ODBC Configuration",
00634       .load = load_module,
00635       .unload = unload_module,
00636       );

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