#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "asterisk.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>
Include dependency graph for func_odbc.c:
Go to the source code of this file.
Data Structures | |
struct | acf_odbc_query |
Functions | |
static char * | acf_escape (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static char * | acf_odbc_read (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static void | acf_odbc_write (struct ast_channel *chan, char *cmd, char *data, const char *value) |
AST_LIST_HEAD_STATIC (queries, acf_odbc_query) | |
char * | description (void) |
Provides a description of the module. | |
static int | free_acf_query (struct acf_odbc_query *query) |
static int | init_acf_query (struct ast_config *cfg, char *catg, struct acf_odbc_query **query) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module (void) |
Initialize the module. | |
static int | odbc_load_module (void) |
static int | odbc_unload_module (void) |
int | reload (void) |
Reload stuff. | |
int | unload_module (void) |
Cleanup all module structures, sockets, etc. | |
int | usecount (void) |
Provides a usecount. | |
Variables | |
static char * | config = "func_odbc.conf" |
static struct ast_custom_function | escape_function |
static char * | tdesc = "ODBC lookups" |
Definition in file func_odbc.c.
static char* acf_escape | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 384 of file func_odbc.c.
00385 { 00386 char *in, *out = buf; 00387 for (in = data; *in && out - buf < len; in++) { 00388 if (*in == '\'') { 00389 *out = '\''; 00390 out++; 00391 } 00392 *out = *in; 00393 out++; 00394 } 00395 *out = '\0'; 00396 return buf; 00397 }
static char* acf_odbc_read | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 237 of file func_odbc.c.
References AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, ast_verbose(), odbc_obj::con, fetch_odbc_obj(), list, LOG_ERROR, LOG_WARNING, odbc_smart_execute(), option_verbose, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and VERBOSE_PREFIX_4.
Referenced by init_acf_query().
00238 { 00239 odbc_obj *obj; 00240 struct acf_odbc_query *query; 00241 char *s, *arg, sql[2048] = "", varname[15]; 00242 int count=0, res, x, buflen = 0; 00243 SQLHSTMT stmt; 00244 SQLSMALLINT colcount=0; 00245 SQLINTEGER indicator; 00246 #ifdef NEEDTRACE 00247 SQLINTEGER enable = 1; 00248 char *tracefile = "/tmp/odbc.trace"; 00249 #endif 00250 00251 AST_LIST_LOCK(&queries); 00252 AST_LIST_TRAVERSE(&queries, query, list) { 00253 if (!strcmp(query->acf->name, cmd)) { 00254 break; 00255 } 00256 } 00257 00258 if (!query) { 00259 ast_log(LOG_ERROR, "No such function '%s'\n", cmd); 00260 AST_LIST_UNLOCK(&queries); 00261 return ""; 00262 } 00263 00264 obj = fetch_odbc_obj(query->dsn, 0); 00265 00266 if (!obj) { 00267 ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn); 00268 AST_LIST_UNLOCK(&queries); 00269 return ""; 00270 } 00271 00272 #ifdef NEEDTRACE 00273 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER); 00274 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile)); 00275 #endif 00276 00277 /* Parse our arguments */ 00278 if (!(s = ast_strdupa(data))) { 00279 AST_LIST_UNLOCK(&queries); 00280 return ""; 00281 } 00282 00283 while ((arg = strsep(&s, "|"))) { 00284 count++; 00285 snprintf(varname, sizeof(varname), "ARG%d", count); 00286 /* arg is by definition non-NULL, so this works, here */ 00287 pbx_builtin_pushvar_helper(chan, varname, arg); 00288 } 00289 00290 pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1); 00291 00292 /* Restore prior values */ 00293 for (x = 1; x <= count; x++) { 00294 snprintf(varname, sizeof(varname), "ARG%d", x); 00295 pbx_builtin_setvar_helper(chan, varname, NULL); 00296 } 00297 00298 AST_LIST_UNLOCK(&queries); 00299 00300 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); 00301 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00302 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00303 return ""; 00304 } 00305 00306 res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); 00307 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00308 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); 00309 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00310 return ""; 00311 } 00312 00313 res = odbc_smart_execute(obj, stmt); 00314 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00315 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql); 00316 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00317 return ""; 00318 } 00319 00320 res = SQLNumResultCols(stmt, &colcount); 00321 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00322 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00323 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00324 return ""; 00325 } 00326 00327 memset(buf, 0, len); 00328 00329 res = SQLFetch(stmt); 00330 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00331 if (res == SQL_NO_DATA) { 00332 if (option_verbose > 3) { 00333 ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql); 00334 } 00335 } else if (option_verbose > 3) { 00336 ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql); 00337 } 00338 goto acf_out; 00339 } 00340 00341 for (x = 0; x < colcount; x++) { 00342 int i; 00343 char coldata[256]; 00344 00345 buflen = strlen(buf); 00346 res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator); 00347 if (indicator == SQL_NULL_DATA) { 00348 coldata[0] = '\0'; 00349 res = SQL_SUCCESS; 00350 } 00351 00352 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00353 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00354 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00355 return ""; 00356 } 00357 00358 /* Copy data, encoding '\' and ',' for the argument parser */ 00359 for (i = 0; i < sizeof(coldata); i++) { 00360 if (coldata[i] == '\\' || coldata[i] == ',') { 00361 buf[buflen++] = '\\'; 00362 } 00363 buf[buflen++] = coldata[i]; 00364 00365 if (buflen >= len - 2) { 00366 buf[buflen >= len ? len - 1 : buflen] = '\0'; 00367 break; 00368 } 00369 00370 if (coldata[i] == '\0') 00371 break; 00372 } 00373 00374 buf[buflen - 1] = ','; 00375 } 00376 /* Trim trailing comma */ 00377 buf[buflen - 1] = '\0'; 00378 00379 acf_out: 00380 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00381 return buf; 00382 }
static void acf_odbc_write | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 76 of file func_odbc.c.
References ast_channel_alloc(), ast_channel_free(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strdupa, odbc_obj::con, fetch_odbc_obj(), list, LOG_ERROR, LOG_WARNING, odbc_obj_connect(), odbc_obj_disconnect(), pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), s, strsep(), and t.
Referenced by init_acf_query().
00077 { 00078 odbc_obj *obj; 00079 struct acf_odbc_query *query; 00080 char *s, *t, *arg, buf[2048]="", varname[15]; 00081 int res, argcount=0, valcount=0, i, retry=0; 00082 struct ast_channel *ast; 00083 SQLHSTMT stmt; 00084 SQLINTEGER nativeerror=0, numfields=0, rows=0; 00085 SQLSMALLINT diagbytes=0; 00086 unsigned char state[10], diagnostic[256]; 00087 #ifdef NEEDTRACE 00088 SQLINTEGER enable = 1; 00089 char *tracefile = "/tmp/odbc.trace"; 00090 #endif 00091 00092 AST_LIST_LOCK(&queries); 00093 AST_LIST_TRAVERSE(&queries, query, list) { 00094 if (!strcmp(query->acf->name, cmd)) { 00095 break; 00096 } 00097 } 00098 00099 if (!query) { 00100 ast_log(LOG_ERROR, "No such function '%s'\n", cmd); 00101 AST_LIST_UNLOCK(&queries); 00102 return; 00103 } 00104 00105 obj = fetch_odbc_obj(query->dsn, 0); 00106 00107 if (!obj) { 00108 ast_log(LOG_ERROR, "No such DSN registered: %s (check res_odbc.conf)\n", query->dsn); 00109 AST_LIST_UNLOCK(&queries); 00110 return; 00111 } 00112 00113 /* Parse our arguments */ 00114 s = ast_strdupa(data); 00115 if (value) { 00116 t = ast_strdupa(value); 00117 } else { 00118 t = ""; 00119 } 00120 00121 if (!s || !t) { 00122 ast_log(LOG_ERROR, "Out of memory\n"); 00123 AST_LIST_UNLOCK(&queries); 00124 return; 00125 } 00126 00127 /* XXX You might be tempted to change this section into using 00128 * pbx_builtin_pushvar_helper(). However, note that if you try 00129 * to set a NULL (like for VALUE), then nothing gets set, and the 00130 * value doesn't get masked out. Even worse, when you subsequently 00131 * try to remove the value you just set, you'll wind up unsetting 00132 * the previous value (which is wholly undesireable). Hence, this 00133 * has to remain the way it is done here. XXX 00134 */ 00135 00136 /* Save old arguments as variables in a fake channel */ 00137 ast = ast_channel_alloc(0); 00138 while ((arg = strsep(&s, "|"))) { 00139 argcount++; 00140 snprintf(varname, sizeof(varname), "ARG%d", argcount); 00141 pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname)); 00142 pbx_builtin_setvar_helper(chan, varname, arg); 00143 } 00144 00145 /* Parse values, just like arguments */ 00146 while ((arg = strsep(&t, "|"))) { 00147 valcount++; 00148 snprintf(varname, sizeof(varname), "VAL%d", valcount); 00149 pbx_builtin_setvar_helper(ast, varname, pbx_builtin_getvar_helper(chan, varname)); 00150 pbx_builtin_setvar_helper(chan, varname, arg); 00151 } 00152 00153 /* Additionally set the value as a whole */ 00154 /* Note that pbx_builtin_setvar_helper will quite happily take a NULL for the 3rd argument */ 00155 pbx_builtin_setvar_helper(ast, "VALUE", pbx_builtin_getvar_helper(chan, "VALUE")); 00156 pbx_builtin_setvar_helper(chan, "VALUE", value); 00157 00158 pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1); 00159 00160 /* Restore prior values */ 00161 for (i=1; i<=argcount; i++) { 00162 snprintf(varname, sizeof(varname), "ARG%d", argcount); 00163 pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname)); 00164 } 00165 00166 for (i=1; i<=valcount; i++) { 00167 snprintf(varname, sizeof(varname), "VAL%d", argcount); 00168 pbx_builtin_setvar_helper(chan, varname, pbx_builtin_getvar_helper(ast, varname)); 00169 } 00170 pbx_builtin_setvar_helper(chan, "VALUE", pbx_builtin_getvar_helper(ast, "VALUE")); 00171 00172 ast_channel_free(ast); 00173 AST_LIST_UNLOCK(&queries); 00174 00175 retry_write: 00176 #ifdef NEEDTRACE 00177 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACE, &enable, SQL_IS_INTEGER); 00178 SQLSetConnectAttr(obj->con, SQL_ATTR_TRACEFILE, tracefile, strlen(tracefile)); 00179 #endif 00180 00181 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); 00182 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00183 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00184 pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1"); 00185 return; 00186 } 00187 00188 res = SQLPrepare(stmt, (unsigned char *)buf, SQL_NTS); 00189 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00190 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", buf); 00191 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00192 pbx_builtin_setvar_helper(chan, "ODBCROWS", "-1"); 00193 return; 00194 } 00195 00196 res = SQLExecute(stmt); 00197 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00198 if (res == SQL_ERROR) { 00199 SQLGetDiagField(SQL_HANDLE_STMT, stmt, 1, SQL_DIAG_NUMBER, &numfields, SQL_IS_INTEGER, &diagbytes); 00200 for (i = 0; i <= numfields; i++) { 00201 SQLGetDiagRec(SQL_HANDLE_STMT, stmt, i + 1, state, &nativeerror, diagnostic, sizeof(diagnostic), &diagbytes); 00202 ast_log(LOG_WARNING, "SQL Execute returned an error %d: %s: %s (%d)\n", res, state, diagnostic, diagbytes); 00203 if (i > 10) { 00204 ast_log(LOG_WARNING, "Oh, that was good. There are really %d diagnostics?\n", (int)numfields); 00205 break; 00206 } 00207 } 00208 } 00209 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00210 odbc_obj_disconnect(obj); 00211 /* All handles are now invalid (after a disconnect), so we gotta redo all handles */ 00212 odbc_obj_connect(obj); 00213 if (!retry) { 00214 retry = 1; 00215 goto retry_write; 00216 } 00217 rows = -1; 00218 } else { 00219 /* Rows affected */ 00220 SQLRowCount(stmt, &rows); 00221 } 00222 00223 /* Output the affected rows, for all cases. In the event of failure, we 00224 * flag this as -1 rows. Note that this is different from 0 affected rows 00225 * which would be the case if we succeeded in our query, but the values did 00226 * not change. */ 00227 snprintf(varname, sizeof(varname), "%d", (int)rows); 00228 pbx_builtin_setvar_helper(chan, "ODBCROWS", varname); 00229 00230 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00231 ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", buf); 00232 } 00233 00234 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00235 }
AST_LIST_HEAD_STATIC | ( | queries | , | |
acf_odbc_query | ||||
) |
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 640 of file func_odbc.c.
00641 { 00642 return tdesc; 00643 }
static int free_acf_query | ( | struct acf_odbc_query * | query | ) | [static] |
Definition at line 516 of file func_odbc.c.
References free.
Referenced by odbc_load_module(), odbc_unload_module(), and reload().
00517 { 00518 if (query) { 00519 if (query->acf) { 00520 if (query->acf->name) 00521 free(query->acf->name); 00522 if (query->acf->syntax) 00523 free(query->acf->syntax); 00524 if (query->acf->desc) 00525 free(query->acf->desc); 00526 free(query->acf); 00527 } 00528 free(query); 00529 } 00530 return 0; 00531 }
static int init_acf_query | ( | struct ast_config * | cfg, | |
char * | catg, | |||
struct acf_odbc_query ** | query | |||
) | [static] |
Definition at line 413 of file func_odbc.c.
References acf_odbc_read(), acf_odbc_write(), ast_strlen_zero(), ast_variable_retrieve(), calloc, cfg, and free.
Referenced by odbc_load_module(), and reload().
00414 { 00415 char *tmp; 00416 00417 if (!cfg || !catg) { 00418 return -1; 00419 } 00420 00421 *query = calloc(1, sizeof(struct acf_odbc_query)); 00422 if (! (*query)) 00423 return -1; 00424 00425 if ((tmp = ast_variable_retrieve(cfg, catg, "dsn"))) { 00426 ast_copy_string((*query)->dsn, tmp, sizeof((*query)->dsn)); 00427 } else { 00428 return -1; 00429 } 00430 00431 if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) { 00432 ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read)); 00433 } 00434 00435 if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) { 00436 ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write)); 00437 } 00438 00439 (*query)->acf = calloc(1, sizeof(struct ast_custom_function)); 00440 if (! (*query)->acf) { 00441 free(*query); 00442 return -1; 00443 } 00444 00445 if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) { 00446 asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg); 00447 } else { 00448 asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg); 00449 } 00450 00451 if (!((*query)->acf->name)) { 00452 free((*query)->acf); 00453 free(*query); 00454 return -1; 00455 } 00456 00457 asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name); 00458 00459 if (!((*query)->acf->syntax)) { 00460 free((char *)(*query)->acf->name); 00461 free((*query)->acf); 00462 free(*query); 00463 return -1; 00464 } 00465 00466 (*query)->acf->synopsis = "Runs the referenced query with the specified arguments"; 00467 if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) { 00468 asprintf((char **)&((*query)->acf->desc), 00469 "Runs the following query, as defined in func_odbc.conf, performing\n" 00470 "substitution of the arguments into the query as specified by ${ARG1},\n" 00471 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n" 00472 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00473 "\nRead:\n%s\n\nWrite:\n%s\n", 00474 (*query)->sql_read, 00475 (*query)->sql_write); 00476 } else if (!ast_strlen_zero((*query)->sql_read)) { 00477 asprintf((char **)&((*query)->acf->desc), 00478 "Runs the following query, as defined in func_odbc.conf, performing\n" 00479 "substitution of the arguments into the query as specified by ${ARG1},\n" 00480 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s\n", 00481 (*query)->sql_read); 00482 } else if (!ast_strlen_zero((*query)->sql_write)) { 00483 asprintf((char **)&((*query)->acf->desc), 00484 "Runs the following query, as defined in func_odbc.conf, performing\n" 00485 "substitution of the arguments into the query as specified by ${ARG1},\n" 00486 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n" 00487 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00488 "This function may only be set.\nSQL:\n%s\n", 00489 (*query)->sql_write); 00490 } 00491 00492 /* Could be out of memory, or could be we have neither sql_read nor sql_write */ 00493 if (! ((*query)->acf->desc)) { 00494 free((char *)(*query)->acf->syntax); 00495 free((char *)(*query)->acf->name); 00496 free((*query)->acf); 00497 free(*query); 00498 return -1; 00499 } 00500 00501 if (ast_strlen_zero((*query)->sql_read)) { 00502 (*query)->acf->read = NULL; 00503 } else { 00504 (*query)->acf->read = acf_odbc_read; 00505 } 00506 00507 if (ast_strlen_zero((*query)->sql_write)) { 00508 (*query)->acf->write = NULL; 00509 } else { 00510 (*query)->acf->write = acf_odbc_write; 00511 } 00512 00513 return 0; 00514 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 655 of file func_odbc.c.
References ASTERISK_GPL_KEY.
00656 { 00657 return ASTERISK_GPL_KEY; 00658 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 635 of file func_odbc.c.
References odbc_load_module().
00636 { 00637 return odbc_load_module(); 00638 }
static int odbc_load_module | ( | void | ) | [static] |
Definition at line 533 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(), cfg, escape_function, free_acf_query(), init_acf_query(), list, LOG_ERROR, and LOG_WARNING.
Referenced by load_module(), and reload().
00534 { 00535 int res = 0; 00536 struct ast_config *cfg; 00537 char *catg; 00538 00539 AST_LIST_LOCK(&queries); 00540 00541 cfg = ast_config_load(config); 00542 if (!cfg) { 00543 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config); 00544 AST_LIST_UNLOCK(&queries); 00545 return -1; 00546 } 00547 00548 for (catg = ast_category_browse(cfg, NULL); 00549 catg; 00550 catg = ast_category_browse(cfg, catg)) { 00551 struct acf_odbc_query *query = NULL; 00552 00553 if (init_acf_query(cfg, catg, &query)) { 00554 ast_log(LOG_ERROR, "Out of memory\n"); 00555 free_acf_query(query); 00556 } else { 00557 AST_LIST_INSERT_HEAD(&queries, query, list); 00558 ast_custom_function_register(query->acf); 00559 } 00560 } 00561 00562 ast_config_destroy(cfg); 00563 ast_custom_function_register(&escape_function); 00564 00565 AST_LIST_UNLOCK(&queries); 00566 return res; 00567 }
static int odbc_unload_module | ( | void | ) | [static] |
Definition at line 569 of file func_odbc.c.
References ast_custom_function_unregister(), AST_LIST_EMPTY, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, escape_function, free_acf_query(), and list.
Referenced by reload(), and unload_module().
00570 { 00571 struct acf_odbc_query *query; 00572 00573 AST_LIST_LOCK(&queries); 00574 while (!AST_LIST_EMPTY(&queries)) { 00575 query = AST_LIST_REMOVE_HEAD(&queries, list); 00576 ast_custom_function_unregister(query->acf); 00577 free_acf_query(query); 00578 } 00579 00580 ast_custom_function_unregister(&escape_function); 00581 00582 /* Allow any threads waiting for this lock to pass (avoids a race) */ 00583 AST_LIST_UNLOCK(&queries); 00584 AST_LIST_LOCK(&queries); 00585 00586 AST_LIST_UNLOCK(&queries); 00587 return 0; 00588 }
int reload | ( | void | ) |
Reload stuff.
This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 590 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(), cfg, free_acf_query(), init_acf_query(), list, LOG_ERROR, and LOG_WARNING.
00591 { 00592 int res = 0; 00593 struct ast_config *cfg; 00594 struct acf_odbc_query *oldquery; 00595 char *catg; 00596 00597 AST_LIST_LOCK(&queries); 00598 00599 while (!AST_LIST_EMPTY(&queries)) { 00600 oldquery = AST_LIST_REMOVE_HEAD(&queries, list); 00601 ast_custom_function_unregister(oldquery->acf); 00602 free_acf_query(oldquery); 00603 } 00604 00605 cfg = ast_config_load(config); 00606 if (!cfg) { 00607 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config); 00608 goto reload_out; 00609 } 00610 00611 for (catg = ast_category_browse(cfg, NULL); 00612 catg; 00613 catg = ast_category_browse(cfg, catg)) { 00614 struct acf_odbc_query *query = NULL; 00615 00616 if (init_acf_query(cfg, catg, &query)) { 00617 ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg); 00618 } else { 00619 AST_LIST_INSERT_HEAD(&queries, query, list); 00620 ast_custom_function_register(query->acf); 00621 } 00622 } 00623 00624 ast_config_destroy(cfg); 00625 reload_out: 00626 AST_LIST_UNLOCK(&queries); 00627 return res; 00628 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 630 of file func_odbc.c.
References odbc_unload_module().
00631 { 00632 return odbc_unload_module(); 00633 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 645 of file func_odbc.c.
References ast_mutex_trylock(), ast_mutex_unlock(), and lock.
00646 { 00647 if (! ast_mutex_trylock(&(&queries)->lock)) { 00648 ast_mutex_unlock(&(&queries)->lock); 00649 return 0; 00650 } else { 00651 return 1; 00652 } 00653 }
char* config = "func_odbc.conf" [static] |
Definition at line 50 of file func_odbc.c.
struct ast_custom_function escape_function [static] |
Definition at line 399 of file func_odbc.c.
Referenced by odbc_load_module(), and odbc_unload_module().
char* tdesc = "ODBC lookups" [static] |
Definition at line 48 of file func_odbc.c.