#include "asterisk.h"
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.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 |
Enumerations | |
enum | { OPT_ESCAPECOMMAS = (1 << 0) } |
Functions | |
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) |
AST_LIST_HEAD_STATIC (queries, acf_odbc_query) | |
AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,"ODBC lookups",.load=load_module,.unload=unload_module,.reload=reload,) | |
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 char * | config = "func_odbc.conf" |
static struct ast_custom_function | escape_function |
enum { ... } | odbc_option_flags |
Definition in file func_odbc.c.
anonymous enum |
Definition at line 56 of file func_odbc.c.
00056 { 00057 OPT_ESCAPECOMMAS = (1 << 0), 00058 } odbc_option_flags;
static int acf_escape | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 377 of file func_odbc.c.
00378 { 00379 char *out = buf; 00380 00381 for (; *data && out - buf < len; data++) { 00382 if (*data == '\'') { 00383 *out = '\''; 00384 out++; 00385 } 00386 *out++ = *data; 00387 } 00388 *out = '\0'; 00389 00390 return 0; 00391 }
static int acf_odbc_read | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | s, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 216 of file func_odbc.c.
References 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(), generic_prepare(), LOG_ERROR, LOG_WARNING, OPT_ESCAPECOMMAS, option_verbose, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), and VERBOSE_PREFIX_4.
Referenced by init_acf_query().
00217 { 00218 struct odbc_obj *obj; 00219 struct acf_odbc_query *query; 00220 char sql[2048] = "", varname[15]; 00221 int res, x, buflen = 0, escapecommas, bogus_chan = 0; 00222 AST_DECLARE_APP_ARGS(args, 00223 AST_APP_ARG(field)[100]; 00224 ); 00225 SQLHSTMT stmt; 00226 SQLSMALLINT colcount=0; 00227 SQLLEN indicator; 00228 00229 AST_LIST_LOCK(&queries); 00230 AST_LIST_TRAVERSE(&queries, query, list) { 00231 if (!strcmp(query->acf->name, cmd)) { 00232 break; 00233 } 00234 } 00235 00236 if (!query) { 00237 ast_log(LOG_ERROR, "No such function '%s'\n", cmd); 00238 AST_LIST_UNLOCK(&queries); 00239 return -1; 00240 } 00241 00242 obj = ast_odbc_request_obj(query->dsn, 0); 00243 00244 if (!obj) { 00245 ast_log(LOG_ERROR, "No such DSN registered (or out of connections): %s (check res_odbc.conf)\n", query->dsn); 00246 AST_LIST_UNLOCK(&queries); 00247 return -1; 00248 } 00249 00250 if (!chan) { 00251 if ((chan = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/func_odbc"))) 00252 bogus_chan = 1; 00253 } 00254 00255 if (chan) 00256 ast_autoservice_start(chan); 00257 00258 AST_STANDARD_APP_ARGS(args, s); 00259 for (x = 0; x < args.argc; x++) { 00260 snprintf(varname, sizeof(varname), "ARG%d", x + 1); 00261 pbx_builtin_pushvar_helper(chan, varname, args.field[x]); 00262 } 00263 00264 pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1); 00265 00266 /* Restore prior values */ 00267 for (x = 0; x < args.argc; x++) { 00268 snprintf(varname, sizeof(varname), "ARG%d", x + 1); 00269 pbx_builtin_setvar_helper(chan, varname, NULL); 00270 } 00271 00272 /* Save this flag, so we can release the lock */ 00273 escapecommas = ast_test_flag(query, OPT_ESCAPECOMMAS); 00274 00275 AST_LIST_UNLOCK(&queries); 00276 00277 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql); 00278 00279 if (!stmt) { 00280 ast_odbc_release_obj(obj); 00281 if (chan) 00282 ast_autoservice_stop(chan); 00283 if (bogus_chan) 00284 ast_channel_free(chan); 00285 return -1; 00286 } 00287 00288 res = SQLNumResultCols(stmt, &colcount); 00289 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00290 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00291 SQLCloseCursor(stmt); 00292 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00293 ast_odbc_release_obj(obj); 00294 if (chan) 00295 ast_autoservice_stop(chan); 00296 if (bogus_chan) 00297 ast_channel_free(chan); 00298 return -1; 00299 } 00300 00301 *buf = '\0'; 00302 00303 res = SQLFetch(stmt); 00304 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00305 int res1 = -1; 00306 if (res == SQL_NO_DATA) { 00307 if (option_verbose > 3) { 00308 ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql); 00309 } 00310 res1 = 0; 00311 } else if (option_verbose > 3) { 00312 ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql); 00313 } 00314 SQLCloseCursor(stmt); 00315 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00316 ast_odbc_release_obj(obj); 00317 if (chan) 00318 ast_autoservice_stop(chan); 00319 if (bogus_chan) 00320 ast_channel_free(chan); 00321 return res1; 00322 } 00323 00324 for (x = 0; x < colcount; x++) { 00325 int i; 00326 char coldata[256]; 00327 00328 buflen = strlen(buf); 00329 res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator); 00330 if (indicator == SQL_NULL_DATA) { 00331 coldata[0] = '\0'; 00332 res = SQL_SUCCESS; 00333 } 00334 00335 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00336 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00337 SQLCloseCursor(stmt); 00338 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00339 ast_odbc_release_obj(obj); 00340 if (chan) 00341 ast_autoservice_stop(chan); 00342 if (bogus_chan) 00343 ast_channel_free(chan); 00344 return -1; 00345 } 00346 00347 /* Copy data, encoding '\' and ',' for the argument parser */ 00348 for (i = 0; i < sizeof(coldata); i++) { 00349 if (escapecommas && (coldata[i] == '\\' || coldata[i] == ',')) { 00350 buf[buflen++] = '\\'; 00351 } 00352 buf[buflen++] = coldata[i]; 00353 00354 if (buflen >= len - 2) 00355 break; 00356 00357 if (coldata[i] == '\0') 00358 break; 00359 } 00360 00361 buf[buflen - 1] = ','; 00362 buf[buflen] = '\0'; 00363 } 00364 /* Trim trailing comma */ 00365 buf[buflen - 1] = '\0'; 00366 00367 SQLCloseCursor(stmt); 00368 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00369 ast_odbc_release_obj(obj); 00370 if (chan) 00371 ast_autoservice_stop(chan); 00372 if (bogus_chan) 00373 ast_channel_free(chan); 00374 return 0; 00375 }
static int acf_odbc_write | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | s, | |||
const char * | value | |||
) | [static] |
Definition at line 97 of file func_odbc.c.
References 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, generic_prepare(), LOG_ERROR, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), and t.
Referenced by init_acf_query().
00098 { 00099 struct odbc_obj *obj; 00100 struct acf_odbc_query *query; 00101 char *t, buf[2048]="", varname[15]; 00102 int i, bogus_chan = 0; 00103 AST_DECLARE_APP_ARGS(values, 00104 AST_APP_ARG(field)[100]; 00105 ); 00106 AST_DECLARE_APP_ARGS(args, 00107 AST_APP_ARG(field)[100]; 00108 ); 00109 SQLHSTMT stmt; 00110 SQLLEN rows=0; 00111 00112 AST_LIST_LOCK(&queries); 00113 AST_LIST_TRAVERSE(&queries, query, list) { 00114 if (!strcmp(query->acf->name, cmd)) { 00115 break; 00116 } 00117 } 00118 00119 if (!query) { 00120 ast_log(LOG_ERROR, "No such function '%s'\n", cmd); 00121 AST_LIST_UNLOCK(&queries); 00122 return -1; 00123 } 00124 00125 obj = ast_odbc_request_obj(query->dsn, 0); 00126 00127 if (!obj) { 00128 ast_log(LOG_ERROR, "No database handle available with the name of '%s' (check res_odbc.conf)\n", query->dsn); 00129 AST_LIST_UNLOCK(&queries); 00130 return -1; 00131 } 00132 00133 if (!chan) { 00134 if ((chan = ast_channel_alloc(0, 0, "", "", "", "", "", 0, "Bogus/func_odbc"))) 00135 bogus_chan = 1; 00136 } 00137 00138 if (chan) 00139 ast_autoservice_start(chan); 00140 00141 /* Parse our arguments */ 00142 t = value ? ast_strdupa(value) : ""; 00143 00144 if (!s || !t) { 00145 ast_log(LOG_ERROR, "Out of memory\n"); 00146 AST_LIST_UNLOCK(&queries); 00147 if (chan) 00148 ast_autoservice_stop(chan); 00149 if (bogus_chan) 00150 ast_channel_free(chan); 00151 return -1; 00152 } 00153 00154 AST_STANDARD_APP_ARGS(args, s); 00155 for (i = 0; i < args.argc; i++) { 00156 snprintf(varname, sizeof(varname), "ARG%d", i + 1); 00157 pbx_builtin_pushvar_helper(chan, varname, args.field[i]); 00158 } 00159 00160 /* Parse values, just like arguments */ 00161 /* Can't use the pipe, because app Set removes them */ 00162 AST_NONSTANDARD_APP_ARGS(values, t, ','); 00163 for (i = 0; i < values.argc; i++) { 00164 snprintf(varname, sizeof(varname), "VAL%d", i + 1); 00165 pbx_builtin_pushvar_helper(chan, varname, values.field[i]); 00166 } 00167 00168 /* Additionally set the value as a whole (but push an empty string if value is NULL) */ 00169 pbx_builtin_pushvar_helper(chan, "VALUE", value ? value : ""); 00170 00171 pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1); 00172 00173 /* Restore prior values */ 00174 for (i = 0; i < args.argc; i++) { 00175 snprintf(varname, sizeof(varname), "ARG%d", i + 1); 00176 pbx_builtin_setvar_helper(chan, varname, NULL); 00177 } 00178 00179 for (i = 0; i < values.argc; i++) { 00180 snprintf(varname, sizeof(varname), "VAL%d", i + 1); 00181 pbx_builtin_setvar_helper(chan, varname, NULL); 00182 } 00183 pbx_builtin_setvar_helper(chan, "VALUE", NULL); 00184 00185 AST_LIST_UNLOCK(&queries); 00186 00187 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, buf); 00188 00189 if (stmt) { 00190 /* Rows affected */ 00191 SQLRowCount(stmt, &rows); 00192 } 00193 00194 /* Output the affected rows, for all cases. In the event of failure, we 00195 * flag this as -1 rows. Note that this is different from 0 affected rows 00196 * which would be the case if we succeeded in our query, but the values did 00197 * not change. */ 00198 snprintf(varname, sizeof(varname), "%d", (int)rows); 00199 pbx_builtin_setvar_helper(chan, "ODBCROWS", varname); 00200 00201 if (stmt) { 00202 SQLCloseCursor(stmt); 00203 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00204 } 00205 if (obj) 00206 ast_odbc_release_obj(obj); 00207 00208 if (chan) 00209 ast_autoservice_stop(chan); 00210 if (bogus_chan) 00211 ast_channel_free(chan); 00212 00213 return 0; 00214 }
AST_LIST_HEAD_STATIC | ( | queries | , | |
acf_odbc_query | ||||
) |
AST_MODULE_INFO | ( | ASTERISK_GPL_KEY | , | |
AST_MODFLAG_DEFAULT | , | |||
"ODBC lookups" | , | |||
. | load = load_module , |
|||
. | unload = unload_module , |
|||
. | reload = reload | |||
) |
static int free_acf_query | ( | struct acf_odbc_query * | query | ) | [static] |
Definition at line 521 of file func_odbc.c.
References free.
Referenced by odbc_load_module(), odbc_unload_module(), and reload().
00522 { 00523 if (query) { 00524 if (query->acf) { 00525 if (query->acf->name) 00526 free((char *)query->acf->name); 00527 if (query->acf->syntax) 00528 free((char *)query->acf->syntax); 00529 if (query->acf->desc) 00530 free((char *)query->acf->desc); 00531 free(query->acf); 00532 } 00533 free(query); 00534 } 00535 return 0; 00536 }
static SQLHSTMT generic_prepare | ( | struct odbc_obj * | obj, | |
void * | data | |||
) | [static] |
Definition at line 71 of file func_odbc.c.
References ast_log(), odbc_obj::con, and LOG_WARNING.
Referenced by acf_odbc_read(), and acf_odbc_write().
00072 { 00073 int res; 00074 char *sql = data; 00075 SQLHSTMT stmt; 00076 00077 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); 00078 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00079 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00080 return NULL; 00081 } 00082 00083 res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); 00084 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00085 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); 00086 SQLCloseCursor(stmt); 00087 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00088 return NULL; 00089 } 00090 00091 return stmt; 00092 }
static int init_acf_query | ( | struct ast_config * | cfg, | |
char * | catg, | |||
struct acf_odbc_query ** | query | |||
) | [static] |
Definition at line 405 of file func_odbc.c.
References acf_odbc_read(), acf_odbc_write(), asprintf, ast_calloc, ast_clear_flag, ast_false(), ast_set_flag, ast_strlen_zero(), ast_variable_retrieve(), free, and OPT_ESCAPECOMMAS.
Referenced by odbc_load_module(), and reload().
00406 { 00407 const char *tmp; 00408 00409 if (!cfg || !catg) { 00410 return -1; 00411 } 00412 00413 *query = ast_calloc(1, sizeof(struct acf_odbc_query)); 00414 if (! (*query)) 00415 return -1; 00416 00417 if ((tmp = ast_variable_retrieve(cfg, catg, "dsn"))) { 00418 ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn)); 00419 } else { 00420 free(*query); 00421 *query = NULL; 00422 return -1; 00423 } 00424 00425 if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) { 00426 ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read)); 00427 } 00428 00429 if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) { 00430 ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write)); 00431 } 00432 00433 /* Allow escaping of embedded commas in fields to be turned off */ 00434 ast_set_flag((*query), OPT_ESCAPECOMMAS); 00435 if ((tmp = ast_variable_retrieve(cfg, catg, "escapecommas"))) { 00436 if (ast_false(tmp)) 00437 ast_clear_flag((*query), OPT_ESCAPECOMMAS); 00438 } 00439 00440 (*query)->acf = ast_calloc(1, sizeof(struct ast_custom_function)); 00441 if (! (*query)->acf) { 00442 free(*query); 00443 *query = NULL; 00444 return -1; 00445 } 00446 00447 if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) { 00448 asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg); 00449 } else { 00450 asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg); 00451 } 00452 00453 if (!((*query)->acf->name)) { 00454 free((*query)->acf); 00455 free(*query); 00456 *query = NULL; 00457 return -1; 00458 } 00459 00460 asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name); 00461 00462 if (!((*query)->acf->syntax)) { 00463 free((char *)(*query)->acf->name); 00464 free((*query)->acf); 00465 free(*query); 00466 *query = NULL; 00467 return -1; 00468 } 00469 00470 (*query)->acf->synopsis = "Runs the referenced query with the specified arguments"; 00471 if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) { 00472 asprintf((char **)&((*query)->acf->desc), 00473 "Runs the following query, as defined in func_odbc.conf, performing\n" 00474 "substitution of the arguments into the query as specified by ${ARG1},\n" 00475 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n" 00476 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00477 "\nRead:\n%s\n\nWrite:\n%s\n", 00478 (*query)->sql_read, 00479 (*query)->sql_write); 00480 } else if (!ast_strlen_zero((*query)->sql_read)) { 00481 asprintf((char **)&((*query)->acf->desc), 00482 "Runs the following query, as defined in func_odbc.conf, performing\n" 00483 "substitution of the arguments into the query as specified by ${ARG1},\n" 00484 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s\n", 00485 (*query)->sql_read); 00486 } else if (!ast_strlen_zero((*query)->sql_write)) { 00487 asprintf((char **)&((*query)->acf->desc), 00488 "Runs the following query, as defined in func_odbc.conf, performing\n" 00489 "substitution of the arguments into the query as specified by ${ARG1},\n" 00490 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n" 00491 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00492 "This function may only be set.\nSQL:\n%s\n", 00493 (*query)->sql_write); 00494 } 00495 00496 /* Could be out of memory, or could be we have neither sql_read nor sql_write */ 00497 if (! ((*query)->acf->desc)) { 00498 free((char *)(*query)->acf->syntax); 00499 free((char *)(*query)->acf->name); 00500 free((*query)->acf); 00501 free(*query); 00502 *query = NULL; 00503 return -1; 00504 } 00505 00506 if (ast_strlen_zero((*query)->sql_read)) { 00507 (*query)->acf->read = NULL; 00508 } else { 00509 (*query)->acf->read = acf_odbc_read; 00510 } 00511 00512 if (ast_strlen_zero((*query)->sql_write)) { 00513 (*query)->acf->write = NULL; 00514 } else { 00515 (*query)->acf->write = acf_odbc_write; 00516 } 00517 00518 return 0; 00519 }
static int load_module | ( | void | ) | [static] |
Definition at line 639 of file func_odbc.c.
References odbc_load_module().
00640 { 00641 return odbc_load_module(); 00642 }
static int odbc_load_module | ( | void | ) | [static] |
Definition at line 538 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, free_acf_query(), init_acf_query(), and LOG_NOTICE.
Referenced by load_module(), and reload().
00539 { 00540 int res = 0; 00541 struct ast_config *cfg; 00542 char *catg; 00543 00544 AST_LIST_LOCK(&queries); 00545 00546 cfg = ast_config_load(config); 00547 if (!cfg) { 00548 ast_log(LOG_NOTICE, "Unable to load config for func_odbc: %s\n", config); 00549 AST_LIST_UNLOCK(&queries); 00550 return AST_MODULE_LOAD_DECLINE; 00551 } 00552 00553 for (catg = ast_category_browse(cfg, NULL); 00554 catg; 00555 catg = ast_category_browse(cfg, catg)) { 00556 struct acf_odbc_query *query = NULL; 00557 00558 if (init_acf_query(cfg, catg, &query)) { 00559 free_acf_query(query); 00560 } else { 00561 AST_LIST_INSERT_HEAD(&queries, query, list); 00562 ast_custom_function_register(query->acf); 00563 } 00564 } 00565 00566 ast_config_destroy(cfg); 00567 ast_custom_function_register(&escape_function); 00568 00569 AST_LIST_UNLOCK(&queries); 00570 return res; 00571 }
static int odbc_unload_module | ( | void | ) | [static] |
Definition at line 573 of file func_odbc.c.
References ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, and free_acf_query().
Referenced by reload(), and unload_module().
00574 { 00575 struct acf_odbc_query *query; 00576 00577 AST_LIST_LOCK(&queries); 00578 while (!AST_LIST_EMPTY(&queries)) { 00579 query = AST_LIST_REMOVE_HEAD(&queries, list); 00580 ast_custom_function_unregister(query->acf); 00581 free_acf_query(query); 00582 } 00583 00584 ast_custom_function_unregister(&escape_function); 00585 00586 /* Allow any threads waiting for this lock to pass (avoids a race) */ 00587 AST_LIST_UNLOCK(&queries); 00588 AST_LIST_LOCK(&queries); 00589 00590 AST_LIST_UNLOCK(&queries); 00591 return 0; 00592 }
static int reload | ( | void | ) | [static] |
Definition at line 594 of file func_odbc.c.
References 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(), LOG_ERROR, and LOG_WARNING.
00595 { 00596 int res = 0; 00597 struct ast_config *cfg; 00598 struct acf_odbc_query *oldquery; 00599 char *catg; 00600 00601 AST_LIST_LOCK(&queries); 00602 00603 while (!AST_LIST_EMPTY(&queries)) { 00604 oldquery = AST_LIST_REMOVE_HEAD(&queries, list); 00605 ast_custom_function_unregister(oldquery->acf); 00606 free_acf_query(oldquery); 00607 } 00608 00609 cfg = ast_config_load(config); 00610 if (!cfg) { 00611 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config); 00612 goto reload_out; 00613 } 00614 00615 for (catg = ast_category_browse(cfg, NULL); 00616 catg; 00617 catg = ast_category_browse(cfg, catg)) { 00618 struct acf_odbc_query *query = NULL; 00619 00620 if (init_acf_query(cfg, catg, &query)) { 00621 ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg); 00622 } else { 00623 AST_LIST_INSERT_HEAD(&queries, query, list); 00624 ast_custom_function_register(query->acf); 00625 } 00626 } 00627 00628 ast_config_destroy(cfg); 00629 reload_out: 00630 AST_LIST_UNLOCK(&queries); 00631 return res; 00632 }
static int unload_module | ( | void | ) | [static] |
Definition at line 634 of file func_odbc.c.
References odbc_unload_module().
00635 { 00636 return odbc_unload_module(); 00637 }
char* config = "func_odbc.conf" [static] |
Definition at line 54 of file func_odbc.c.
struct ast_custom_function escape_function [static] |
Definition at line 393 of file func_odbc.c.
enum { ... } odbc_option_flags |