#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"
Include dependency graph for func_odbc.c:
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 | 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 57 of file func_odbc.c.
00057 { 00058 OPT_ESCAPECOMMAS = (1 << 0), 00059 } odbc_option_flags;
static int acf_escape | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 357 of file func_odbc.c.
00358 { 00359 char *out = buf; 00360 00361 for (; *data && out - buf < len; data++) { 00362 if (*data == '\'') { 00363 *out = '\''; 00364 out++; 00365 } 00366 *out++ = *data; 00367 } 00368 *out = '\0'; 00369 00370 return 0; 00371 }
static int acf_odbc_read | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | s, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 198 of file func_odbc.c.
References AST_APP_ARG, AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_odbc_prepare_and_execute(), ast_odbc_request_obj(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), ast_test_flag, dsn, generic_prepare(), LOG_ERROR, OPT_ESCAPECOMMAS, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), and pbx_substitute_variables_helper().
Referenced by init_acf_query().
00199 { 00200 struct odbc_obj *obj; 00201 struct acf_odbc_query *query; 00202 char sql[2048] = "", varname[15], colnames[2048] = ""; 00203 int res, x, buflen = 0, escapecommas, dsn; 00204 AST_DECLARE_APP_ARGS(args, 00205 AST_APP_ARG(field)[100]; 00206 ); 00207 SQLHSTMT stmt; 00208 SQLSMALLINT colcount=0; 00209 SQLLEN indicator; 00210 SQLSMALLINT collength; 00211 00212 AST_LIST_LOCK(&queries); 00213 AST_LIST_TRAVERSE(&queries, query, list) { 00214 if (!strcmp(query->acf->name, cmd)) { 00215 break; 00216 } 00217 } 00218 00219 if (!query) { 00220 ast_log(LOG_ERROR, "No such function '%s'\n", cmd); 00221 AST_LIST_UNLOCK(&queries); 00222 return -1; 00223 } 00224 00225 AST_STANDARD_APP_ARGS(args, s); 00226 for (x = 0; x < args.argc; x++) { 00227 snprintf(varname, sizeof(varname), "ARG%d", x + 1); 00228 pbx_builtin_pushvar_helper(chan, varname, args.field[x]); 00229 } 00230 00231 pbx_substitute_variables_helper(chan, query->sql_read, sql, sizeof(sql) - 1); 00232 00233 /* Restore prior values */ 00234 for (x = 0; x < args.argc; x++) { 00235 snprintf(varname, sizeof(varname), "ARG%d", x + 1); 00236 pbx_builtin_setvar_helper(chan, varname, NULL); 00237 } 00238 00239 /* Save this flag, so we can release the lock */ 00240 escapecommas = ast_test_flag(query, OPT_ESCAPECOMMAS); 00241 00242 AST_LIST_UNLOCK(&queries); 00243 00244 for (dsn = 0; dsn < 5; dsn++) { 00245 if (!ast_strlen_zero(query->writehandle[dsn])) { 00246 obj = ast_odbc_request_obj(query->writehandle[dsn], 0); 00247 if (obj) 00248 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, sql); 00249 } 00250 if (stmt) 00251 break; 00252 } 00253 00254 if (!stmt) { 00255 ast_log(LOG_ERROR, "Unable to execute query [%s]\n", sql); 00256 if (obj) 00257 ast_odbc_release_obj(obj); 00258 return -1; 00259 } 00260 00261 res = SQLNumResultCols(stmt, &colcount); 00262 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00263 ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql); 00264 SQLFreeHandle (SQL_HANDLE_STMT, stmt); 00265 ast_odbc_release_obj(obj); 00266 return -1; 00267 } 00268 00269 *buf = '\0'; 00270 00271 res = SQLFetch(stmt); 00272 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00273 int res1 = -1; 00274 if (res == SQL_NO_DATA) { 00275 if (option_verbose > 3) { 00276 ast_verbose(VERBOSE_PREFIX_4 "Found no rows [%s]\n", sql); 00277 } 00278 res1 = 0; 00279 } else if (option_verbose > 3) { 00280 ast_log(LOG_WARNING, "Error %d in FETCH [%s]\n", res, sql); 00281 } 00282 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00283 ast_odbc_release_obj(obj); 00284 return res1; 00285 } 00286 00287 for (x = 0; x < colcount; x++) { 00288 int i, namelen; 00289 char coldata[256], colname[256]; 00290 00291 res = SQLDescribeCol(stmt, x + 1, (unsigned char *)colname, sizeof(colname), &collength, NULL, NULL, NULL, NULL); 00292 if (((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) || collength == 0) { 00293 snprintf(colname, sizeof(colname), "field%d", x); 00294 } 00295 00296 if (!ast_strlen_zero(colnames)) 00297 strncat(colnames, ",", sizeof(colnames) - 1); 00298 namelen = strlen(colnames); 00299 00300 /* Copy data, encoding '\' and ',' for the argument parser */ 00301 for (i = 0; i < sizeof(colname); i++) { 00302 if (escapecommas && (colname[i] == '\\' || colname[i] == ',')) { 00303 colnames[namelen++] = '\\'; 00304 } 00305 colnames[namelen++] = colname[i]; 00306 00307 if (namelen >= sizeof(colnames) - 2) { 00308 colnames[namelen >= sizeof(colnames) ? sizeof(colnames) - 1 : namelen] = '\0'; 00309 break; 00310 } 00311 00312 if (colname[i] == '\0') 00313 break; 00314 } 00315 00316 buflen = strlen(buf); 00317 res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator); 00318 if (indicator == SQL_NULL_DATA) { 00319 coldata[0] = '\0'; 00320 res = SQL_SUCCESS; 00321 } 00322 00323 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00324 ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql); 00325 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00326 ast_odbc_release_obj(obj); 00327 return -1; 00328 } 00329 00330 /* Copy data, encoding '\' and ',' for the argument parser */ 00331 for (i = 0; i < sizeof(coldata); i++) { 00332 if (escapecommas && (coldata[i] == '\\' || coldata[i] == ',')) { 00333 buf[buflen++] = '\\'; 00334 } 00335 buf[buflen++] = coldata[i]; 00336 00337 if (buflen >= len - 2) 00338 break; 00339 00340 if (coldata[i] == '\0') 00341 break; 00342 } 00343 00344 buf[buflen - 1] = ','; 00345 buf[buflen] = '\0'; 00346 } 00347 /* Trim trailing comma */ 00348 buf[buflen - 1] = '\0'; 00349 00350 pbx_builtin_setvar_helper(chan, "~ODBCFIELDS~", colnames); 00351 00352 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00353 ast_odbc_release_obj(obj); 00354 return 0; 00355 }
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 AST_APP_ARG, 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_request_obj(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), dsn, generic_prepare(), LOG_ERROR, pbx_builtin_pushvar_helper(), pbx_builtin_setvar_helper(), pbx_substitute_variables_helper(), 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, dsn; 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 /* Parse our arguments */ 00127 t = value ? ast_strdupa(value) : ""; 00128 00129 if (!s || !t) { 00130 ast_log(LOG_ERROR, "Out of memory\n"); 00131 AST_LIST_UNLOCK(&queries); 00132 return -1; 00133 } 00134 00135 AST_STANDARD_APP_ARGS(args, s); 00136 for (i = 0; i < args.argc; i++) { 00137 snprintf(varname, sizeof(varname), "ARG%d", i + 1); 00138 pbx_builtin_pushvar_helper(chan, varname, args.field[i]); 00139 } 00140 00141 /* Parse values, just like arguments */ 00142 /* Can't use the pipe, because app Set removes them */ 00143 AST_NONSTANDARD_APP_ARGS(values, t, ','); 00144 for (i = 0; i < values.argc; i++) { 00145 snprintf(varname, sizeof(varname), "VAL%d", i + 1); 00146 pbx_builtin_pushvar_helper(chan, varname, values.field[i]); 00147 } 00148 00149 /* Additionally set the value as a whole (but push an empty string if value is NULL) */ 00150 pbx_builtin_pushvar_helper(chan, "VALUE", value ? value : ""); 00151 00152 pbx_substitute_variables_helper(chan, query->sql_write, buf, sizeof(buf) - 1); 00153 00154 /* Restore prior values */ 00155 for (i = 0; i < args.argc; i++) { 00156 snprintf(varname, sizeof(varname), "ARG%d", i + 1); 00157 pbx_builtin_setvar_helper(chan, varname, NULL); 00158 } 00159 00160 for (i = 0; i < values.argc; i++) { 00161 snprintf(varname, sizeof(varname), "VAL%d", i + 1); 00162 pbx_builtin_setvar_helper(chan, varname, NULL); 00163 } 00164 pbx_builtin_setvar_helper(chan, "VALUE", NULL); 00165 00166 AST_LIST_UNLOCK(&queries); 00167 00168 for (dsn = 0; dsn < 5; dsn++) { 00169 if (!ast_strlen_zero(query->writehandle[dsn])) { 00170 obj = ast_odbc_request_obj(query->writehandle[dsn], 0); 00171 if (obj) 00172 stmt = ast_odbc_prepare_and_execute(obj, generic_prepare, buf); 00173 } 00174 if (stmt) 00175 break; 00176 } 00177 00178 if (stmt) { 00179 /* Rows affected */ 00180 SQLRowCount(stmt, &rows); 00181 } 00182 00183 /* Output the affected rows, for all cases. In the event of failure, we 00184 * flag this as -1 rows. Note that this is different from 0 affected rows 00185 * which would be the case if we succeeded in our query, but the values did 00186 * not change. */ 00187 snprintf(varname, sizeof(varname), "%d", (int)rows); 00188 pbx_builtin_setvar_helper(chan, "ODBCROWS", varname); 00189 00190 if (stmt) 00191 SQLFreeHandle(SQL_HANDLE_STMT, stmt); 00192 if (obj) 00193 ast_odbc_release_obj(obj); 00194 00195 return 0; 00196 }
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 542 of file func_odbc.c.
References free.
Referenced by reload(), and unload_module().
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 73 of file func_odbc.c.
References ast_log(), odbc_obj::con, and LOG_WARNING.
Referenced by acf_odbc_read(), and acf_odbc_write().
00074 { 00075 int res; 00076 char *sql = data; 00077 SQLHSTMT stmt; 00078 00079 res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt); 00080 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00081 ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n"); 00082 return NULL; 00083 } 00084 00085 res = SQLPrepare(stmt, (unsigned char *)sql, SQL_NTS); 00086 if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) { 00087 ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql); 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 385 of file func_odbc.c.
References acf_odbc_read(), acf_odbc_write(), asprintf, AST_APP_ARG, ast_calloc, ast_clear_flag, AST_DECLARE_APP_ARGS, ast_false(), ast_log(), AST_NONSTANDARD_APP_ARGS, ast_set_flag, ast_strdupa, ast_strlen_zero(), ast_variable_retrieve(), dsn, free, LOG_WARNING, OPT_ESCAPECOMMAS, ast_custom_function::read, and ast_custom_function::write.
Referenced by load_module(), and reload().
00386 { 00387 const char *tmp; 00388 int i; 00389 00390 if (!cfg || !catg) { 00391 return EINVAL; 00392 } 00393 00394 *query = ast_calloc(1, sizeof(struct acf_odbc_query)); 00395 if (! (*query)) 00396 return ENOMEM; 00397 00398 if (((tmp = ast_variable_retrieve(cfg, catg, "writehandle"))) || ((tmp = ast_variable_retrieve(cfg, catg, "dsn")))) { 00399 char *tmp2 = ast_strdupa(tmp); 00400 AST_DECLARE_APP_ARGS(write, 00401 AST_APP_ARG(dsn)[5]; 00402 ); 00403 AST_NONSTANDARD_APP_ARGS(write, tmp2, ','); 00404 for (i = 0; i < 5; i++) { 00405 if (!ast_strlen_zero(write.dsn[i])) 00406 ast_copy_string((*query)->writehandle[i], write.dsn[i], sizeof((*query)->writehandle[i])); 00407 } 00408 } 00409 00410 if ((tmp = ast_variable_retrieve(cfg, catg, "readhandle"))) { 00411 char *tmp2 = ast_strdupa(tmp); 00412 AST_DECLARE_APP_ARGS(read, 00413 AST_APP_ARG(dsn)[5]; 00414 ); 00415 AST_NONSTANDARD_APP_ARGS(read, tmp2, ','); 00416 for (i = 0; i < 5; i++) { 00417 if (!ast_strlen_zero(read.dsn[i])) 00418 ast_copy_string((*query)->readhandle[i], read.dsn[i], sizeof((*query)->readhandle[i])); 00419 } 00420 } else { 00421 /* If no separate readhandle, then use the writehandle for reading */ 00422 for (i = 0; i < 5; i++) { 00423 if (!ast_strlen_zero((*query)->writehandle[i])) 00424 ast_copy_string((*query)->readhandle[i], (*query)->writehandle[i], sizeof((*query)->readhandle[i])); 00425 } 00426 } 00427 00428 if ((tmp = ast_variable_retrieve(cfg, catg, "read"))) { 00429 ast_log(LOG_WARNING, "Parameter 'read' is deprecated for category %s. Please use 'readsql' instead.\n", catg); 00430 ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read)); 00431 } else if ((tmp = ast_variable_retrieve(cfg, catg, "readsql"))) 00432 ast_copy_string((*query)->sql_read, tmp, sizeof((*query)->sql_read)); 00433 00434 if (!ast_strlen_zero((*query)->sql_read) && ast_strlen_zero((*query)->readhandle[0])) { 00435 free(*query); 00436 ast_log(LOG_ERROR, "There is SQL, but no ODBC class to be used for reading: %s\n", catg); 00437 return EINVAL; 00438 } 00439 00440 if ((tmp = ast_variable_retrieve(cfg, catg, "write"))) { 00441 ast_log(LOG_WARNING, "Parameter 'write' is deprecated for category %s. Please use 'writesql' instead.\n", catg); 00442 ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write)); 00443 } else if ((tmp = ast_variable_retrieve(cfg, catg, "writesql"))) 00444 ast_copy_string((*query)->sql_write, tmp, sizeof((*query)->sql_write)); 00445 00446 if (!ast_strlen_zero((*query)->sql_write) && ast_strlen_zero((*query)->writehandle[0])) { 00447 free(*query); 00448 ast_log(LOG_ERROR, "There is SQL, but no ODBC class to be used for writing: %s\n", catg); 00449 return EINVAL; 00450 } 00451 00452 /* Allow escaping of embedded commas in fields to be turned off */ 00453 ast_set_flag((*query), OPT_ESCAPECOMMAS); 00454 if ((tmp = ast_variable_retrieve(cfg, catg, "escapecommas"))) { 00455 if (ast_false(tmp)) 00456 ast_clear_flag((*query), OPT_ESCAPECOMMAS); 00457 } 00458 00459 (*query)->acf = ast_calloc(1, sizeof(struct ast_custom_function)); 00460 if (! (*query)->acf) { 00461 free(*query); 00462 return ENOMEM; 00463 } 00464 00465 if ((tmp = ast_variable_retrieve(cfg, catg, "prefix")) && !ast_strlen_zero(tmp)) { 00466 asprintf((char **)&((*query)->acf->name), "%s_%s", tmp, catg); 00467 } else { 00468 asprintf((char **)&((*query)->acf->name), "ODBC_%s", catg); 00469 } 00470 00471 if (!((*query)->acf->name)) { 00472 free((*query)->acf); 00473 free(*query); 00474 return ENOMEM; 00475 } 00476 00477 asprintf((char **)&((*query)->acf->syntax), "%s(<arg1>[...[,<argN>]])", (*query)->acf->name); 00478 00479 if (!((*query)->acf->syntax)) { 00480 free((char *)(*query)->acf->name); 00481 free((*query)->acf); 00482 free(*query); 00483 return ENOMEM; 00484 } 00485 00486 (*query)->acf->synopsis = "Runs the referenced query with the specified arguments"; 00487 if (!ast_strlen_zero((*query)->sql_read) && !ast_strlen_zero((*query)->sql_write)) { 00488 asprintf((char **)&((*query)->acf->desc), 00489 "Runs the following query, as defined in func_odbc.conf, performing\n" 00490 "substitution of the arguments into the query as specified by ${ARG1},\n" 00491 "${ARG2}, ... ${ARGn}. When setting the function, the values are provided\n" 00492 "either in whole as ${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00493 "\nRead:\n%s\n\nWrite:\n%s\n", 00494 (*query)->sql_read, 00495 (*query)->sql_write); 00496 } else if (!ast_strlen_zero((*query)->sql_read)) { 00497 asprintf((char **)&((*query)->acf->desc), 00498 "Runs the following query, as defined in func_odbc.conf, performing\n" 00499 "substitution of the arguments into the query as specified by ${ARG1},\n" 00500 "${ARG2}, ... ${ARGn}. This function may only be read, not set.\n\nSQL:\n%s\n", 00501 (*query)->sql_read); 00502 } else if (!ast_strlen_zero((*query)->sql_write)) { 00503 asprintf((char **)&((*query)->acf->desc), 00504 "Runs the following query, as defined in func_odbc.conf, performing\n" 00505 "substitution of the arguments into the query as specified by ${ARG1},\n" 00506 "${ARG2}, ... ${ARGn}. The values are provided either in whole as\n" 00507 "${VALUE} or parsed as ${VAL1}, ${VAL2}, ... ${VALn}.\n" 00508 "This function may only be set.\nSQL:\n%s\n", 00509 (*query)->sql_write); 00510 } else { 00511 free((char *)(*query)->acf->syntax); 00512 free((char *)(*query)->acf->name); 00513 free((*query)->acf); 00514 free(*query); 00515 ast_log(LOG_WARNING, "Section %s was found, but there was no SQL to execute. Ignoring.\n", catg); 00516 return EINVAL; 00517 } 00518 00519 if (! ((*query)->acf->desc)) { 00520 free((char *)(*query)->acf->syntax); 00521 free((char *)(*query)->acf->name); 00522 free((*query)->acf); 00523 free(*query); 00524 return ENOMEM; 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 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, init_acf_query(), and LOG_NOTICE.
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 int err; 00579 00580 if ((err = init_acf_query(cfg, catg, &query))) { 00581 if (err == ENOMEM) 00582 ast_log(LOG_ERROR, "Out of memory\n"); 00583 else if (err == EINVAL) 00584 ast_log(LOG_ERROR, "Invalid parameters for category %s\n", catg); 00585 else 00586 ast_log(LOG_ERROR, "%s (%d)\n", strerror(err), err); 00587 } else { 00588 AST_LIST_INSERT_HEAD(&queries, query, list); 00589 ast_custom_function_register(query->acf); 00590 } 00591 } 00592 00593 ast_config_destroy(cfg); 00594 res |= ast_custom_function_register(&escape_function); 00595 00596 AST_LIST_UNLOCK(&queries); 00597 return res; 00598 }
static int reload | ( | void | ) | [static] |
Definition at line 623 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(), and LOG_WARNING.
00624 { 00625 int res = 0; 00626 struct ast_config *cfg; 00627 struct acf_odbc_query *oldquery; 00628 char *catg; 00629 00630 AST_LIST_LOCK(&queries); 00631 00632 while (!AST_LIST_EMPTY(&queries)) { 00633 oldquery = AST_LIST_REMOVE_HEAD(&queries, list); 00634 ast_custom_function_unregister(oldquery->acf); 00635 free_acf_query(oldquery); 00636 } 00637 00638 cfg = ast_config_load(config); 00639 if (!cfg) { 00640 ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config); 00641 goto reload_out; 00642 } 00643 00644 for (catg = ast_category_browse(cfg, NULL); 00645 catg; 00646 catg = ast_category_browse(cfg, catg)) { 00647 struct acf_odbc_query *query = NULL; 00648 00649 if (init_acf_query(cfg, catg, &query)) { 00650 ast_log(LOG_ERROR, "Cannot initialize query %s\n", catg); 00651 } else { 00652 AST_LIST_INSERT_HEAD(&queries, query, list); 00653 ast_custom_function_register(query->acf); 00654 } 00655 } 00656 00657 ast_config_destroy(cfg); 00658 reload_out: 00659 AST_LIST_UNLOCK(&queries); 00660 return res; 00661 }
static int unload_module | ( | void | ) | [static] |
Definition at line 600 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, and free_acf_query().
00601 { 00602 struct acf_odbc_query *query; 00603 int res = 0; 00604 00605 AST_LIST_LOCK(&queries); 00606 while (!AST_LIST_EMPTY(&queries)) { 00607 query = AST_LIST_REMOVE_HEAD(&queries, list); 00608 ast_custom_function_unregister(query->acf); 00609 free_acf_query(query); 00610 } 00611 00612 res |= ast_custom_function_unregister(&escape_function); 00613 00614 /* Allow any threads waiting for this lock to pass (avoids a race) */ 00615 AST_LIST_UNLOCK(&queries); 00616 usleep(1); 00617 AST_LIST_LOCK(&queries); 00618 00619 AST_LIST_UNLOCK(&queries); 00620 return 0; 00621 }
char* config = "func_odbc.conf" [static] |
Definition at line 55 of file func_odbc.c.
struct ast_custom_function escape_function [static] |
enum { ... } odbc_option_flags |