All pastes #21290 Raw Edit

Something

public c v1 · immutable
#21290 ·published 2005-08-27 05:47 UTC
rendered paste body
/* * Asterisk -- A telephony toolkit for Linux. * * func_odbc *  * Copyright (c) 2005 Tilghman Lesher * * Tilghman Lesher <func_odbc__200508@the-tilghman.com> * */#include <sys/types.h>#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <asterisk/file.h>#include <asterisk/logger.h>#include <asterisk/options.h>#include <asterisk/channel.h>#include <asterisk/pbx.h>#include <asterisk/module.h>#include <asterisk/config.h>#include <asterisk/res_odbc.h>static char *tdesc = "ODBC lookups";static char *config = "func_odbc.conf";struct acf_odbc_query {	char name[30];	char dsn[30];	char sql[512];	struct ast_custom_function *acf;	unsigned int deleteme:1;	struct acf_odbc_query *next;};static struct acf_odbc_query *queries = NULL;AST_MUTEX_DEFINE_STATIC(query_lock);/* * Master control routine */static char *acf_odbc_exec(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len){	odbc_obj *obj;	struct acf_odbc_query *query;	char *s, *arg, sql[512] = "";	int count=0, res, x;	struct ast_channel *ast;	SQLHSTMT stmt;	SQLSMALLINT colcount=0;	SQLINTEGER indicator;	ast_mutex_lock(&query_lock);	for (query=queries; query; query = query->next) {		if (!strcasecmp(query->name, cmd + 5)) {			break;		}	}	if (!query) {		ast_log(LOG_ERROR, "No such function '%s'\n", cmd);		return "";	}	obj = fetch_odbc_obj(query->dsn, 0);	/* Parse our arguments */	s = ast_strdupa(data);	if (!s) {		ast_log(LOG_ERROR, "Out of memory\n");		return "";	}	/* Set up arguments as variables in a fake channel */	ast = ast_channel_alloc(0);	while ((arg = strsep(&s, "|"))) {		count++;		snprintf(buf, len, "ARG%d", count);		pbx_builtin_setvar_helper(ast, buf, arg);	}	pbx_substitute_variables_helper(ast, query->sql, sql, sizeof(sql) - 1);	ast_channel_free(ast);	ast_mutex_unlock(&query_lock);	res = SQLAllocHandle (SQL_HANDLE_STMT, obj->con, &stmt);	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {		ast_log(LOG_WARNING, "SQL Alloc Handle failed!\n");		return "";	}	res = SQLPrepare(stmt, buf, SQL_NTS);	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {		ast_log(LOG_WARNING, "SQL Prepare failed![%s]\n", sql);		SQLFreeHandle (SQL_HANDLE_STMT, stmt);		return "";	}	res = odbc_smart_execute(obj, stmt);	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {		ast_log(LOG_WARNING, "SQL Execute error!\n[%s]\n\n", sql);		SQLFreeHandle (SQL_HANDLE_STMT, stmt);		return "";	}	res = SQLNumResultCols(stmt, &colcount);	if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {		ast_log(LOG_WARNING, "SQL Column Count error!\n[%s]\n\n", sql);		SQLFreeHandle (SQL_HANDLE_STMT, stmt);		return "";	}	memset(buf, 0, len);	for (x=0; x<colcount; x++) {		int buflen, coldatalen;		char coldata[256];		buflen = strlen(buf);		res = SQLGetData(stmt, x + 1, SQL_CHAR, coldata, sizeof(coldata), &indicator);		if (indicator == SQL_NULL_DATA) {			coldata[0] = '\0';			res = SQL_SUCCESS;		}		if ((res != SQL_SUCCESS) && (res != SQL_SUCCESS_WITH_INFO)) {			ast_log(LOG_WARNING, "SQL Get Data error!\n[%s]\n\n", sql);			SQLFreeHandle(SQL_HANDLE_STMT, stmt);			return "";		}		strncat(buf + buflen, coldata, len - buflen);		coldatalen = strlen(coldata);		strncat(buf + buflen + coldatalen, ",", len - buflen - coldatalen);	}	/* Trim trailing comma */	buf[strlen(buf) - 1] = '\0';	SQLFreeHandle(SQL_HANDLE_STMT, stmt);	return buf;}static int odbc_load_module(void){	int res = 0;	struct ast_config *cfg;	char *tmp, *catg;	ast_mutex_lock(&query_lock);	cfg = ast_config_load(config);	if (!cfg) {		ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);		goto out;	}	for (catg = ast_category_browse(cfg, NULL);		 catg;		 catg = ast_category_browse(cfg, catg)) {		int ok = 1;		struct acf_odbc_query *query;		query = calloc(1, sizeof(struct acf_odbc_query));		if (!query) {			ast_log(LOG_ERROR, "Out of memory\n");			goto out2;		}		ast_copy_string(query->name, catg, sizeof(query->name) - 1);		tmp = ast_variable_retrieve(cfg, catg, "dsn");		if (tmp) {			ast_copy_string(query->dsn, tmp, sizeof(query->dsn) - 1);		} else {			ok = 0;		}		tmp = ast_variable_retrieve(cfg, catg, "sql");		if (tmp) {			ast_copy_string(query->sql, tmp, sizeof(query->sql) - 1);		} else {			ok = 0;		}		query->acf = calloc(1, sizeof(struct ast_custom_function));		if (query->acf) {			asprintf(&(query->acf->name), "ODBC_%s", catg);			asprintf(&(query->acf->syntax), "ODBC_%s(<arg1>[...[,<argN>]])", catg);			query->acf->synopsis = "Runs the referenced query with the specified arguments";			query->acf->desc =					"Runs the referenced query, as defined in func_odbc.conf, performing substitution of the arguments\n"					"into the query as specified by ${ARG1}, ${ARG2}, ... ${ARGn}\n";			query->acf->read = acf_odbc_exec;			if (! query->acf->name || ! query->acf->syntax) {				ok = 0;			}		} else {			ok = 0;		}		if (ok) {			query->next = queries;			queries = query;			ast_custom_function_register(query->acf);		} else {			ast_log(LOG_ERROR, "Out of memory\n");			free(query);		}	}out2:	ast_config_destroy(cfg);out:	ast_mutex_unlock(&query_lock);	return res;}static int odbc_unload_module(void){	struct acf_odbc_query *query, *lastquery = NULL;	ast_mutex_lock(&query_lock);	for (query = queries; query; query = query->next) {		if (lastquery)			free(lastquery);		if (ast_custom_function_unregister(query->acf)) {			ast_log(LOG_ERROR, "PANIC!  Cannot unregister function?  System will be left in a weird state (Recommend restart)\n");			lastquery = NULL;		} else {			free(query->acf->name);			free(query->acf->syntax);			free(query->acf);			lastquery = query;		}	}	if (lastquery)		free(lastquery);	queries = NULL;	ast_mutex_unlock(&query_lock);	return 0;}int reload(void){	int res = 0, found=0;	struct ast_config *cfg;	struct acf_odbc_query *q, *prevq = NULL, *qdel = NULL;	char *tmp, *catg;	ast_mutex_lock(&query_lock);	for (q = queries; q; q = q->next) {		q->deleteme = 1;	}	cfg = ast_config_load(config);	if (!cfg) {		ast_log(LOG_WARNING, "Unable to load config for func_odbc: %s\n", config);		goto out;	}	for (catg = ast_category_browse(cfg, NULL);		 catg;		 catg = ast_category_browse(cfg, catg)) {		int ok = 1;		struct acf_odbc_query *query = NULL;		for (q = queries; q; q = q->next) {			if (!strcasecmp(catg, q->name)) {				q->deleteme = 0;				found = 1;				break;			}		}		if (!found) {			query = calloc(1, sizeof(struct acf_odbc_query));			if (!query) {				ast_log(LOG_ERROR, "Out of memory\n");				goto out2;			}			ast_copy_string(query->name, catg, sizeof(query->name) - 1);			/* The ACF is kept within the structure, to prevent a memory leak */			query->acf = calloc(1, sizeof(struct ast_custom_function));			if (query->acf) {				vasprintf(&(query->acf->name), "ODBC_%s", catg);				vasprintf(&(query->acf->syntax), "ODBC_%s(<arg1>[...[,<argN>]])", catg);				query->acf->synopsis = "Runs the referenced query with the specified arguments";				query->acf->desc =						"Runs the referenced query, as defined in func_odbc.conf, performing substitution of the arguments\n"						"into the query as specified by ${ARG1}, ${ARG2}, ... ${ARGn}\n";				query->acf->read = acf_odbc_exec;				if (! query->acf->name || ! query->acf->syntax) {					ok = 0;				}			} else {				ok = 0;			}			if (ok) {				query->next = queries;				queries = query;				ast_custom_function_register(query->acf);			} else {				ast_log(LOG_ERROR, "Out of memory\n");				free(query);			}		}		/* Do this section whether it is new or not */		if (query) {			tmp = ast_variable_retrieve(cfg, catg, "dsn");			if (tmp) {				ast_copy_string(query->dsn, tmp, sizeof(query->dsn) - 1);			} else {				ok = 0;			}			tmp = ast_variable_retrieve(cfg, catg, "sql");			if (tmp) {				ast_copy_string(query->sql, tmp, sizeof(query->sql) - 1);			} else {				ok = 0;			}		}	} /* Loop back for another category */	/* Any remaining sets will now be destroyed */	for (q = queries; q; q = q->next) {		if (qdel) {			free(qdel);			qdel = NULL;		}		if (q->deleteme) {			if (ast_custom_function_unregister(q->acf)) {				ast_log(LOG_ERROR, "Cannot unregister function?  Refusing to make 'ODBC_%s' go away.\n", q->name);			} else {				free(q->acf->name);				free(q->acf->syntax);				free(q->acf);				if (prevq) {					prevq->next = q->next;				} else {					queries = q->next;				}				qdel = q;			}		}	}	if (qdel)		free(qdel);out2:	ast_config_destroy(cfg);out:	ast_mutex_unlock(&query_lock);	return res;}int unload_module(void){	return odbc_unload_module();}int load_module(void){	return odbc_load_module();}char *description(void){	return tdesc;}int usecount(void){	if (! ast_mutex_trylock(&query_lock)) {		ast_mutex_unlock(&query_lock);		return 0;	} else {		return 1;	}}char *key(){	return ASTERISK_GPL_KEY;}