[Asterisk-cvs] asterisk-addons res_config_mysql.c, NONE, 1.1 Makefile, 1.7, 1.8

markster at lists.digium.com markster at lists.digium.com
Thu Dec 2 20:43:35 CST 2004


Update of /usr/cvsroot/asterisk-addons
In directory mongoose.digium.com:/tmp/cvs-serv18464

Modified Files:
	Makefile 
Added Files:
	res_config_mysql.c 
Log Message:
Add res_config_mysql (bug #2613)


--- NEW FILE: res_config_mysql.c ---
/*
 * Asterisk -- A telephony toolkit for Linux.
 *
 * Copyright (C) 1999-2004, Digium, Inc.
 *
 * Mark Spencer <markster at digium.com>  - Asterisk Author
 * Matthew Boehm <mboehm at cytelcom.com> - MySQL RealTime Driver Author
 *
 * res_config_mysql.c <mysql plugin for RealTime configuration engine >
 *
 * v1.4 - (12-02-04) - Added realtime_multi_mysql function
 *                      This function will return an ast_config with categories,
 *                      unlike standard realtime_mysql which only returns
 *                      a linked list of ast_variables
 *
 * v1.3 - (12-01-04) - Added support other operators
 *                     Ex: =, !=, LIKE, NOT LIKE, RLIKE, etc...
 *
 * v1.2 - (11-DD-04) - Added reload. Updated load and unload.
 *                     Code beautification (doc/CODING-GUIDELINES)
 */

#include <asterisk/channel.h>
#include <asterisk/logger.h>
#include <asterisk/config.h>
#include <asterisk/config_pvt.h>
#include <asterisk/module.h>
#include <asterisk/lock.h>
#include <asterisk/options.h>
#include <asterisk/cli.h>
#include <asterisk/utils.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>
#include <mysql_version.h>
#include <errmsg.h>

static char *res_config_mysql_desc = "MySQL RealTime Configuration Driver";
static struct ast_config_reg reg_mysql;

AST_MUTEX_DEFINE_STATIC(mysql_lock);
#define RES_CONFIG_MYSQL_CONF "res_mysql.conf"
MYSQL         mysql;
static char   dbhost[50];
static char   dbuser[50];
static char   dbpass[50];
static char   dbname[50];
static char   dbsock[50];
static int    dbport;
static int    connected;
static time_t connect_time;

static int parse_config(void);
static int mysql_reconnect(void);
static int realtime_mysql_status(int fd, int argc, char **argv);

STANDARD_LOCAL_USER;

LOCAL_USER_DECL;

static char cli_realtime_mysql_status_usage[] =
"Usage: show realtime mysql status\n"
"       Shows connection information for the MySQL RealTime driver\n";

static struct ast_cli_entry cli_realtime_mysql_status = {
        { "realtime", "mysql", "status", NULL }, realtime_mysql_status,
        "Shows connection information for the MySQL RealTime driver", cli_realtime_mysql_status_usage, NULL };

static struct ast_variable *realtime_mysql(const char *database, const char *table, va_list ap)
{
	MYSQL_RES *result;
	MYSQL_ROW row;
	MYSQL_FIELD *fields;
	int numFields, i;
	char sql[256];
	char *stringp;
	char *chunk;
	char *op;
	const char *newparam, *newval;
	struct ast_variable *var=NULL, *prev=NULL;

	if(!table) {
		ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
		return NULL;
	}

	/* Get the first parameter and first value in our list of passed paramater/value pairs */
	newparam = va_arg(ap, const char *);
	newval = va_arg(ap, const char *);
	if(!newparam || !newval)  {
		ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
		mysql_close(&mysql);
		return NULL;
	}

	/* Create the first part of the query using the first parameter/value pairs we just extracted
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */

	if(!strchr(newparam, ' ')) op = " ="; else op = "";

	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
	while((newparam = va_arg(ap, const char *))) {
		newval = va_arg(ap, const char *);
		if(!strchr(newparam, ' ')) op = " ="; else op = "";
		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
	}
	va_end(ap);

	ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);

	/* We now have our complete statement; Lets connect to the server and execute it. */
	if(!mysql_reconnect()) {
		return NULL;
	}

	ast_mutex_lock(&mysql_lock);
	if(mysql_real_query(&mysql, sql, strlen(sql))) {
		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
		ast_mutex_unlock(&mysql_lock);
		return NULL;
	}

	/* Toss up here. Each has its pros and cons. Gonna use store result cause most people will be running database
           either locally or on same network. And since the tables are small text based, shouldn't be that big of a problem
           unless you're retrieving a few million rows.
           mysql_store_result: Will copy all the rows returned by the query to local memory. This save network time,
                               but could possibly use up lots of memory if the result set is large.
             mysql_use_result: Will keep the result set on the server and will retrieve each row at a time from server.
                               Reduces local memory usage, but increases network traffic for large sets. Also, the server
                               could go down part way thru our retrieval process and we wouldn't get all the rows. */

	result = mysql_store_result(&mysql);
	numFields = mysql_num_fields(result);
	fields = mysql_fetch_fields(result);

	while((row = mysql_fetch_row(result))) {
		for(i = 0; i < numFields; i++) {
			stringp = row[i];
			while(stringp) {
				chunk = strsep(&stringp, ";");
				if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
					if(prev) {
						prev->next = ast_new_variable(fields[i].name, chunk);
						if (prev->next) {
							prev = prev->next;
						}
					} else {
						prev = var = ast_new_variable(fields[i].name, chunk);
					}
				}
			}
		}
	}

	ast_mutex_unlock(&mysql_lock);
	mysql_free_result(result);

	return var;
}

static struct ast_config *realtime_multi_mysql(const char *database, const char *table, va_list ap)
{
	MYSQL_RES *result;
	MYSQL_ROW row;
	MYSQL_FIELD *fields;
	int numFields, i;
	char sql[256];
	const char *initfield = NULL;
	char *title = NULL;
	char *stringp;
	char *chunk;
	char *op;
	const char *newparam, *newval;
	struct ast_variable *var=NULL, *prev=NULL;
	struct ast_config *cfg = NULL;
	struct ast_category *cat = NULL;

	if(!table) {
		ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
		return NULL;
	}

	/* Get the first parameter and first value in our list of passed paramater/value pairs */
	newparam = va_arg(ap, const char *);
	newval = va_arg(ap, const char *);
	if(!newparam || !newval)  {
		ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
		mysql_close(&mysql);
		return NULL;
	}

	initfield = ast_strdupa(newparam);
	if(initfield && (op = strchr(initfield, ' '))) {
		*op = '\0';
	}

	/* Create the first part of the query using the first parameter/value pairs we just extracted
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */

	if(!strchr(newparam, ' ')) op = " ="; else op = "";

	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
	while((newparam = va_arg(ap, const char *))) {
		newval = va_arg(ap, const char *);
		if(!strchr(newparam, ' ')) op = " ="; else op = "";
		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
	}

	if(initfield) {
		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " ORDER BY %s", initfield);
	}

	va_end(ap);

	ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);

	/* We now have our complete statement; Lets connect to the server and execute it. */
	if(!mysql_reconnect()) {
		return NULL;
	}

	ast_mutex_lock(&mysql_lock);
	if(mysql_real_query(&mysql, sql, strlen(sql))) {
		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
		ast_mutex_unlock(&mysql_lock);
		return NULL;
	}

	result = mysql_store_result(&mysql);
	numFields = mysql_num_fields(result);
	fields = mysql_fetch_fields(result);

	while((row = mysql_fetch_row(result))) {
		for(i = 0; i < numFields; i++) {
			stringp = row[i];
			while(stringp) {
				chunk = strsep(&stringp, ";");
				if(chunk && !ast_strlen_zero(ast_strip(chunk))) {
					if(initfield && !strcmp(initfield, fields[i].name) && !title) {
						title = ast_strdupa(chunk);
					}
					if(prev) {
						prev->next = ast_new_variable(fields[i].name, chunk);
						if (prev->next) {
							prev = prev->next;
						}
					} else {
						prev = var = ast_new_variable(fields[i].name, chunk);
					}
				}
			}
		}
		if(var) {
			cat = ast_new_category(title ? title : "");
			if(cat) {
				cat->root = var;
				if(!cfg) {
					cfg = ast_new_config();
				}
				if(cfg) {
					ast_category_append(cfg, cat);
				} else {
					ast_category_destroy(cat);
				}
			} else {
				ast_log(LOG_WARNING, "Out of memory!\n");
				ast_destroy_realtime(var);
			}
		}
	}

	ast_mutex_unlock(&mysql_lock);
	mysql_free_result(result);

	return cfg;
}

static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
{
	my_ulonglong numrows;
	char sql[256];
	const char *newparam, *newval;

	if(!table) {
		ast_log(LOG_WARNING, "MySQL RealTime: No table specified.\n");
		return 0;
	}

	/* Get the first parameter and first value in our list of passed paramater/value pairs */
	newparam = va_arg(ap, const char *);
	newval = va_arg(ap, const char *);
	if(!newparam || !newval)  {
		ast_log(LOG_WARNING, "MySQL RealTime: Realtime retrieval requires at least 1 parameter and 1 value to search on.\n");
		mysql_close(&mysql);
		return 0;
	}

	/* Create the first part of the query using the first parameter/value pairs we just extracted
	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */

	snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
	while((newparam = va_arg(ap, const char *))) {
		newval = va_arg(ap, const char *);
		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
	}
	va_end(ap);
	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);

	ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);

	/* We now have our complete statement; Lets connect to the server and execute it. */
	if(!mysql_reconnect()) {
		return 0;
	}

	ast_mutex_lock(&mysql_lock);
	if(mysql_real_query(&mysql, sql, strlen(sql))) {
		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
		ast_mutex_unlock(&mysql_lock);
		return 0;
	}

	numrows = mysql_affected_rows(&mysql);
	ast_mutex_unlock(&mysql_lock);

	ast_log(LOG_DEBUG,"MySQL RealTime: Updated %llu rows on table: %s\n", numrows, table);

	if(numrows) {
		return 0;
	}

	return -1;
}

static struct ast_config *config_mysql(const char *database, const char *table, const char *file, struct ast_config *new_config_s, struct ast_category **new_cat_p, struct ast_variable **new_v_p, int recur)
{
	MYSQL_RES *result;
	MYSQL_ROW row;
	my_ulonglong num_rows;
	struct ast_config *new;
	struct ast_variable *cur_v, *new_v;
	struct ast_category *cur_cat, *new_cat;
	char sql[250] = "";
	char last[80] = "";
	int cat_started = 0;
	int var_started = 0;
	int last_cat_metric = 0;

	last[0] = '\0';

	if(!file || !strcmp(file, RES_CONFIG_MYSQL_CONF)) {
		ast_log(LOG_WARNING, "MySQL RealTime: Cannot configure myself.\n");
		return NULL;
	}

	snprintf(sql, sizeof(sql), "SELECT category, var_name, var_val, cat_metric FROM %s WHERE filename='%s' and commented=0 ORDER BY filename, cat_metric desc, var_metric asc, category, var_name, var_val, id", table, file);

	if(new_config_s) {
		new = new_config_s;
		cat_started++;
	} else {
		new = ast_new_config();
	}
	
	if(!new) {
		ast_log(LOG_WARNING, "MySQL RealTime: Cannot create new config. Out of memory!\n");
		return NULL;
	}

	ast_log(LOG_DEBUG, "MySQL RealTime: Static SQL: %s\n", sql);

	/* We now have our complete statement; Lets connect to the server and execute it. */
	if(!mysql_reconnect()) {
		return NULL;
	}

	ast_mutex_lock(&mysql_lock);
	if(mysql_real_query(&mysql, sql, strlen(sql))) {
		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
		ast_log(LOG_DEBUG, "MySQL RealTime: Query Failed because: %s\n", mysql_error(&mysql));
		ast_mutex_unlock(&mysql_lock);
		return NULL;
	}

	if((result = mysql_store_result(&mysql))) {
		num_rows = mysql_num_rows(result);
		ast_log(LOG_DEBUG, "MySQL RealTime: Found %llu rows.\n", num_rows);

		cat_started = 0;

		cur_cat = *new_cat_p;
		cur_v = *new_v_p;

		if(cur_cat) {
			cat_started = 1;
		}

		if(cur_v) {
			var_started = 1;
		}

		/* There might exist a better way to access the column names other than counting,
                   but I believe that would require another loop that we don't need. */

		while((row = mysql_fetch_row(result))) {
			if(!strcmp(row[1], "#include") && recur < MAX_INCLUDE_LEVEL) {
				config_mysql(database, table, row[2], new, &cur_cat, &cur_v, recur + 1);
			} else {
				if(strcmp(last, row[0]) || last_cat_metric != atoi(row[3])) {
					strncpy(last, row[0], sizeof(last) - 1);
					last_cat_metric	= atoi(row[3]);
					new_cat = (struct ast_category *) ast_new_category(row[0]);

					if(!cat_started) {
						cat_started++;
						new->root = new_cat;
						cur_cat = new->root;
					} else {
						cur_cat->next = new_cat;
						cur_cat = cur_cat->next;
					}
					var_started = 0;
				}

				new_v = ast_new_variable(row[1], row[2]);

				if (!var_started) {
					var_started++;
					cur_cat->root = new_v;
					cur_v = cur_cat->root;
				} else {
					cur_v->next = new_v;
					cur_v = cur_v->next;
				}
			}
		}
		mysql_free_result(result);
		ast_mutex_unlock(&mysql_lock);
	} else {
		ast_log(LOG_WARNING, "MySQL RealTime: Could not find config '%s' in database.\n", file);
		mysql_free_result(result);
		ast_mutex_unlock(&mysql_lock);
	}

	return new;
}

int load_module (void)
{
	parse_config();

	if(!mysql_reconnect()) {
		ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
	}

	memset(&reg_mysql, 0, sizeof(struct ast_config_reg));
	strncpy(reg_mysql.name, "mysql", sizeof(reg_mysql.name) - 1);

	reg_mysql.static_func = config_mysql;
	reg_mysql.realtime_func = realtime_mysql;
	reg_mysql.update_func = update_mysql;
	reg_mysql.realtime_multi_func = realtime_multi_mysql;

	ast_cust_config_register(&reg_mysql);
	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime driver loaded.\n");
	ast_cli_register(&cli_realtime_mysql_status);
	return 0;
}

int unload_module (void)
{
	mysql_close(&mysql);
	ast_cli_unregister(&cli_realtime_mysql_status);
	ast_cust_config_deregister(&reg_mysql);
	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime unloaded.\n");

	if(ast_mutex_lock(&mysql_lock)) {
		ast_mutex_unlock(&mysql_lock);
	}

	STANDARD_HANGUP_LOCALUSERS;

	return 0;
}

int reload (void)
{
	if(ast_mutex_lock(&mysql_lock)) {
		ast_log(LOG_WARNING, "MySQL RealTime: Couldn't reload. Use count %i.\n", usecount());
		return 1;   
	}

	ast_mutex_unlock(&mysql_lock);
	mysql_close(&mysql);

	connected = 0;

	parse_config();

	if(!mysql_reconnect()) {
		ast_log(LOG_WARNING, "MySQL RealTime: Couldn't establish connection. Check debug.\n");
		ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
	}

	ast_verbose(VERBOSE_PREFIX_2 "MySQL RealTime reloaded.\n");
	return 0;
}

int parse_config (void)
{
	struct ast_config *config;
	char *s;

	config = ast_load(RES_CONFIG_MYSQL_CONF);

	if(config) {
		if(!(s=ast_variable_retrieve(config, "general", "dbuser"))) {
			ast_log(LOG_WARNING, "MySQL RealTime: No database user found, using 'asterisk' as default.\n");
			strncpy(dbuser, "asterisk", sizeof(dbuser) - 1);
		} else {
			strncpy(dbuser, s, sizeof(dbuser) - 1);
		}

		if(!(s=ast_variable_retrieve(config, "general", "dbpass"))) {
                        ast_log(LOG_WARNING, "MySQL RealTime: No database password found, using 'asterisk' as default.\n");
                        strncpy(dbpass, "asterisk", sizeof(dbpass) - 1);
                } else {
                        strncpy(dbpass, s, sizeof(dbpass) - 1);
                }

		if(!(s=ast_variable_retrieve(config, "general", "dbhost"))) {
                        ast_log(LOG_WARNING, "MySQL RealTime: No database host found, using localhost via socket.\n");
			dbhost[0] = '\0';
                } else {
                        strncpy(dbhost, s, sizeof(dbhost) - 1);
                }

		if(!(s=ast_variable_retrieve(config, "general", "dbname"))) {
                        ast_log(LOG_WARNING, "MySQL RealTime: No database name found, using 'asterisk' as default.\n");
			strncpy(dbname, "asterisk", sizeof(dbname) - 1);
                } else {
                        strncpy(dbname, s, sizeof(dbname) - 1);
                }

		if(!(s=ast_variable_retrieve(config, "general", "dbport"))) {
                        ast_log(LOG_WARNING, "MySQL RealTime: No database port found, using 3306 as default.\n");
			dbport = 3306;
                } else {
			dbport = atoi(s);
                }

		if(dbhost && !(s=ast_variable_retrieve(config, "general", "dbsock"))) {
                        ast_log(LOG_WARNING, "MySQL RealTime: No database socket found, using '/tmp/mysql.sock' as default.\n");
                        strncpy(dbsock, "/tmp/mysql.sock", sizeof(dbsock) - 1);
                } else {
                        strncpy(dbsock, s, sizeof(dbsock) - 1);
                }
	}
	ast_destroy(config);

	if(dbhost) {
		ast_log(LOG_DEBUG, "MySQL RealTime Host: %s\n", dbhost);
		ast_log(LOG_DEBUG, "MySQL RealTime Port: %i\n", dbport);
	} else {
		ast_log(LOG_DEBUG, "MySQL RealTime Socket: %s\n", dbsock);
	}
	ast_log(LOG_DEBUG, "MySQL RealTime User: %s\n", dbuser);
	ast_log(LOG_DEBUG, "MySQL RealTime Password: %s\n", dbpass);

	return 1;
}

char *description (void)
{
	return res_config_mysql_desc;
}

int usecount (void)
{
	/* Try and get a lock. If unsuccessful, than that means a query is currently being run.
	   Lets be nice and don't interrupt the query. */
	if(ast_mutex_lock(&mysql_lock)) {
		ast_log(LOG_DEBUG, "MySQL RealTime: Usecount 1. Query in progress.\n");
		return 1;
	}
	ast_mutex_unlock(&mysql_lock);
	return 0;
}

char *key ()
{
	return ASTERISK_GPL_KEY;
}

static int mysql_reconnect()
{
	if((!connected) && (dbhost || dbsock) && dbuser && dbpass && dbname) {
		if(!mysql_init(&mysql)) {
			ast_log(LOG_WARNING, "MySQL RealTime: Insufficient memory to allocate MySQL resource.\n");
			connected = 0;
			return 0;
		}
		if(mysql_real_connect(&mysql, dbhost, dbuser, dbpass, dbname, dbport, dbsock, 0)) {
			ast_log(LOG_DEBUG, "MySQL RealTime: Successfully connected to database.\n");
			connected = 1;
			connect_time = time(NULL);
			return 1;
		} else {
			ast_log(LOG_ERROR, "MySQL RealTime: Failed to connect database server %s on %s. Check debug for more info.\n", dbname, dbhost);
			ast_log(LOG_DEBUG, "MySQL RealTime: Cannot Connect: %s\n", mysql_error(&mysql));
			connected = 0;
			return 0;
		}
	} else {
		int error;
		error = mysql_ping(&mysql);

		if(error != 0) {
			connected = 0;
			ast_log(LOG_ERROR, "MySQL RealTime: Attempted to reconnect. Failed. Check debug for more info.\n");
			ast_log(LOG_DEBUG, "MySQL RealTime: Server Error: %s\n", mysql_error(&mysql));
			return 0;
		}
		ast_log(LOG_DEBUG, "MySQL RealTime: Everything is fine.\n");
		connected = 1;
		return 1;
	}
}

static int realtime_mysql_status(int fd, int argc, char **argv)
{
	char status[256], status2[100] = "";
	int ctime = time(NULL) - connect_time;

	if(mysql_reconnect()) {
		if(dbhost) {
			snprintf(status, 255, "Connected to %s@%s, port %d", dbname, dbhost, dbport);
		} else if(dbsock) {
			snprintf(status, 255, "Connected to %s on socket file %s", dbname, dbsock);
		} else {
			snprintf(status, 255, "Connected to %s@%s", dbname, dbhost);
		}

		if(dbuser && *dbuser) {
			snprintf(status2, 99, " with username %s", dbuser);
		}

		if (ctime > 31536000) {
			ast_cli(fd, "%s%s for %d years, %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 31536000, (ctime % 31536000) / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
		} else if (ctime > 86400) {
			ast_cli(fd, "%s%s for %d days, %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 86400, (ctime % 86400) / 3600, (ctime % 3600) / 60, ctime % 60);
		} else if (ctime > 3600) {
			ast_cli(fd, "%s%s for %d hours, %d minutes, %d seconds.\n", status, status2, ctime / 3600, (ctime % 3600) / 60, ctime % 60);
		} else if (ctime > 60) {
			ast_cli(fd, "%s%s for %d minutes, %d seconds.\n", status, status2, ctime / 60, ctime % 60);
		} else {
			ast_cli(fd, "%s%s for %d seconds.\n", status, status2, ctime);
		}

		return RESULT_SUCCESS;
	} else {
		return RESULT_FAILURE;
	}
}

Index: Makefile
===================================================================
RCS file: /usr/cvsroot/asterisk-addons/Makefile,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- Makefile	2 Oct 2004 14:06:21 -0000	1.7
+++ Makefile	3 Dec 2004 01:42:01 -0000	1.8
@@ -27,7 +27,7 @@
 #
 # MySQL stuff...  Autoconf anyone??
 #
-MODS+=$(shell if [ -d /usr/local/mysql/include ] || [ -d /usr/include/mysql ] || [ -d /usr/local/include/mysql ] || [ -d /opt/mysql/include ]; then echo "cdr_addon_mysql.so app_addon_sql_mysql.so"; fi)
+MODS+=$(shell if [ -d /usr/local/mysql/include ] || [ -d /usr/include/mysql ] || [ -d /usr/local/include/mysql ] || [ -d /opt/mysql/include ]; then echo "cdr_addon_mysql.so app_addon_sql_mysql.so res_config_mysql.so"; fi)
 CFLAGS+=$(shell if [ -d /usr/local/mysql/include ]; then echo "-I/usr/local/mysql/include"; fi)
 CFLAGS+=$(shell if [ -d /usr/include/mysql ]; then echo "-I/usr/include/mysql"; fi)
 CFLAGS+=$(shell if [ -d /usr/local/include/mysql ]; then echo "-I/usr/local/include/mysql"; fi)
@@ -60,6 +60,9 @@
 cdr_addon_mysql.so: cdr_addon_mysql.o
 	$(CC) -shared -Xlinker -x -o $@ $< -lmysqlclient -lz $(MLFLAGS)
 
+res_config_mysql.so: res_config_mysql.o
+	$(CC) -shared -Xlinker -x -o $@ $< -lmysqlclient -lz $(MLFLAGS)
+
 app_addon_sql_mysql.so: app_addon_sql_mysql.o
 	$(CC) -shared -Xlinker -x -o $@ $< -lmysqlclient -lz $(MLFLAGS)
 




More information about the svn-commits mailing list