/**********************************************************************
* PTlink IRC Services is (C) CopyRight PTlink IRC Software 1999-2004 *
* http://software.pt-link.net *
* This program is distributed under GNU Public License *
* Please read the file COPYING for copyright information. *
**********************************************************************
Description: dynamic configuration support module
* $Id: dbconf.c,v 1.8 2005/10/18 16:25:06 jpinto Exp $
*/
#include "module.h"
#include "my_sql.h"
#include "my_sql.h"
#define DBCONF
#include "dbconf.h"
SVS_Module mod_info =
/* module, version, description */
{"dbconf", "1.0", "dbconf support module" };
#define DB_VERSION 1
/** functionsand events we require **/
/* void (*FunctionPointer)(void);*/
int mysql_connection;
MOD_REQUIRES
MOD_FUNC(mysql_connection)
MOD_END
/** function and events we provide **/
/* void my_function(void); */
int dbconf_cmd_line(int argc, char **argv);
MOD_PROVIDES
DBCONF_FUNCTIONS
MOD_FUNC(dbconf_cmd_line)
MOD_END
/** Internal functions declaration **/
/* void internal_function(void); */
/** Local variables **/
/* int my_local_variable; */
int dc_log;
/** load code **/
int mod_load(void)
{
dc_log = log_open(mod_info.name, mod_info.name);
if(dc_log<0)
{
errlog("Could not open dbconf log file!");
return -1;
}
if(sql_check_inst_upgrade(mod_info.name, DB_VERSION, NULL) < 0)
return -1;
return 0;
}
/** unload code **/
void mod_unload(void)
{
return;
}
/** internal functions implementation starts here **/
/*
* dbconf_get_or_build
* For each item of the dbitems array
* If the value exists on the db
* update its description
* set the value pointer if found
* else
* try to add item, returns -1 if fails
* returns:
* -1 , error adding item
* >=0 number of items added to the db
*/
int dbconf_get_or_build(char *module, dbConfItem* dbitems)
{
int new_item = 0;
dbConfItem* item = dbitems;
while(item && item->name)
{
if(sql_singlequery("SELECT value FROM dbconf WHERE module=%s AND name=%s"
" ORDER BY module, name",
sql_str(module), sql_str(item->name)) > 0)
{
/* read the value */
if(!strcmp(item->type, "str") || !strcmp(item->type, "word"))
{
FREE(*(char **)item->vptr);
*(char **)item->vptr = sql_field(0) ? strdup(sql_field(0)) : NULL;
}
else
if(!strcmp(item->type,"int") && sql_field_i(0))
*(int*) item->vptr = sql_field_i(0);
else
if(!strcmp(item->type,"time") && sql_field(0))
{
if(ftime_str(sql_field(0)) == -1)
{
errlog("Invalid time value on %s.%s",
module, item->name);
return -1;
}
*(int*) item->vptr = ftime_str(sql_field(0));
}
else
if(!strcmp(item->type,"switch") && sql_field(0))
*(int*) item->vptr = (!strcasecmp(sql_field(0),"on"));
/* update type and description */
sql_execute("UPDATE dbconf SET stype=%s, ddesc=%s"
" WHERE module=%s AND name=%s",
sql_str(item->type),
sql_str(item->desc), sql_str(module), sql_str(item->name));
}
else
{
sqlb_init("dbconf");
sqlb_add_str("module", module);
sqlb_add_str("name", item->name);
sqlb_add_str("stype", item->type);
sqlb_add_str("ddesc", item->desc);
sqlb_add_str("optional", item->optional);
sqlb_add_str("configured", "n");
sqlb_add_str("value", item->def);
if(sql_execute(sqlb_insert()) < 0)
{
errlog("Error adding dbconf item %s!", item->name);
return -1;
}
if(!strcmp(item->type, "str") || !strcmp(item->type, "word"))
{
FREE(*(char **)item->vptr);
*(char **)item->vptr = item->def ? strdup(item->def): NULL;
}
else
if(!strcmp(item->type, "int") && item->def)
*(int*) item->vptr = atoi(item->def);
else
if(!strcmp(item->type, "switch"))
*(int*) item->vptr = (!strcasecmp(item->def,"on"));
else
if(!strcmp(item->type,"time") && item->def)
{
if(ftime_str(item->def) == -1)
{
errlog("Invalid default time value on %s.%s",
module, item->name);
return -1;
}
*(int*) item->vptr = ftime_str(item->def);
}
++new_item;
}
item++;
}
if(new_item)
stdlog(L_INFO, "Installed %d new configuration item(s)", new_item);
return new_item;
}
/* change_item
* Change a dbconf item, the value is validated accoring to the item type
* Returns:
* 0 - Change was successfull
* -1 - Item was not found
* -2 - Item of type SWITCH but value is not ON/OFF
* -3 - Item of type TIME but value is not a time
* -4 - Item of type WORD but value is not a word
* -5 - Item of type INT but value is not an positive integer
* -6 - Unable to unset item, is not optional
*/
static int change_item(char *item, char *value)
{
MYSQL_RES *res;
MYSQL_ROW row;
int error = 0;
res = sql_query("SELECT module,name,stype,optional FROM dbconf WHERE "
"CONCAT(module,'.', name) = %s", sql_str(item));
if(!res || !(row = sql_next_row(res)))
error = -1;
else
if((value == NULL) && (*row[3]=='n')) /* this item is not optional */
error = -6;
else
if(strcasecmp(row[2],"switch") == 0) /* "SWITCH" item */
{
if(strcasecmp(value,"on") && strcasecmp(value,"off"))
error = -2;
} else
if(strcasecmp(row[2], "time") == 0) /* "TIME" item */
{
if(ftime_str(value) == -1)
error = -3;
} else
if((strcasecmp(row[2], "word") == 0) && value) /* "WORD" item */
{
if(strchr(value, ' '))
error = -4;
} else
if(strcasecmp(row[2], "int") == 0) /* "INT" item */
{
if(!is_posint(value))
error = -5;
}
sql_free(res);
if(error)
return error;
if(sql_execute("UPDATE dbconf SET value=%s "
"WHERE CONCAT(module,'.',name)=%s", sql_str(value), sql_str(item)) < 0)
return -6;
return 0;
}
int dbconf_cmd_line(int argc, char **argv)
{
const char* usage = "Usage:\n"
"ircsvs conf list [pattern]\n"
"ircsvs conf export [pattern]\n"
"ircsvs conf set module.setting value\n"
"ircsvs conf unset module.setting\n";
char* cmd;
char buf[128];
if(argc<1)
{
printf("%s", usage);
return -1;
}
cmd = argv[0];
if((strcasecmp(cmd, "list") == 0) || (strcasecmp(cmd, "export") == 0))
{
MYSQL_RES *res;
MYSQL_ROW row;
char *where;
int is_export = (strcasecmp(cmd, "export") == 0);
if(argc>1)
{
char buf2[128];
snprintf(buf2, sizeof(buf2), "%%%s%%", argv[1]);
snprintf(buf, sizeof(buf), " WHERE CONCAT(module,'.',name) LIKE %s",
sql_str(buf2));
where = buf;
}
else
where = "";
res = sql_query("SELECT module, name, value, ddesc, stype, optional"
" FROM dbconf %s", where);
printf("####### Configuration list #######\n");
while((row = sql_next_row(res)))
{
char *line;
line = row[3];
/* show each line from the ddesc field prefixed with # */
while(line)
{
char *p = line;
char *c = strchr(line,'\n');
if(c)
{
*c = '\0';
line = c+1;
} else line = NULL;
printf("# %s\n", p);
}
if(strcmp(row[4],"switch") == 0)
printf("# This is a switch option, possible values are On or Off\n");
else
if(strcmp(row[4],"time") == 0)
printf("# Time value [m=minutes;h=hours;d=days;M=months,Y=years]\n");
else
if(*row[5] == 'y')
printf("# This setting is optional, you can unset to disable\n");
if(is_export)
{
if(strcmp(row[4],"word") && strcmp(row[4],"str"))
printf("./ircsvs conf set %s.%s %s", row[0], row[1], row[2] ? row[2] : "NULL");
else
if(row[2])
printf("./ircsvs conf set %s.%s \"%s\"", row[0], row[1], row[2]);
else
printf("./ircsvs conf unset %s.%s", row[0], row[1]);
}
else
{
if(strcmp(row[4],"word") && strcmp(row[4],"str"))
printf("%s.%s = %s", row[0], row[1], row[2] ? row[2] : "NULL");
else
if(row[2])
printf("%s.%s = \"%s\"", row[0], row[1], row[2]);
else
printf("%s.%s = *NOT SET*", row[0], row[1]);
}
printf("\n\n");
}
printf("##################################\n");
sql_free(res);
} else
if((strcasecmp(cmd, "set") == 0) || (strcasecmp(cmd, "unset") == 0))
{
int r;
const char *msg = NULL;
int unset = (strcasecmp(cmd, "unset") == 0);
if((!unset && (argc < 3)) || !strchr(argv[1], '.'))
{
printf("%s", usage);
return -1;
}
r = change_item(argv[1], unset ? NULL : argv[2]);
switch(r)
{
case 0:
msg = NULL;
break;
case -1:
msg = "There is no item %s !\n";
break;
case -2:
msg = "Value for %s must be On/Off !\n";
break;
case -3:
msg = "Value for %s must be a time value !\n";
break;
case -4:
msg = "Value for %s must be a word !\n";
break;
case -5:
msg = "Value for %s must be a positive integer !\n";
break;
case -6:
msg = "Value for %s can't be unset, is not an optional setting!\n";
break;
default:
msg = "Unknown error changing %s !\n";
break;
}
/* check for errors */
if(msg)
{
printf(msg, argv[1]);
return r;
}
if(unset)
printf("%s successfully unset\n", argv[1]);
else
printf("%s successfully changed to: %s\n", argv[1], argv[2]);
}
return 0;
};
/* dbconf_get
* For each item of the dbitems array
* Get the value from the dbconf table
* If the item is missing, report error and return -1
* If the value is null and the item is mandatory, report error
* and return -2
* return 0 on success
*/
int dbconf_get(dbConfGet *dbitems)
{
dbConfGet* item = dbitems;
char *stype;
while(item && item->name)
{
if(sql_singlequery("SELECT value, stype, optional FROM dbconf WHERE module=%s AND name=%s"
" ORDER BY module, name",
sql_str(item->module), sql_str(item->name)) > 0)
{
stype = sql_field(1);
/* read the value */
if(!strcmp(stype, "str") || !strcmp(stype, "word"))
{
FREE(*(char **)item->vptr);
*(char **)item->vptr = sql_field(0) ? strdup(sql_field(0)) : NULL;
}
else
if(!strcmp(stype,"int") && sql_field_i(0))
*(int*) item->vptr = sql_field_i(0);
else
if(!strcmp(stype,"time") && sql_field(0))
{
if(ftime_str(sql_field(0)) == -1)
{
errlog("Invalid time value on %s.%s",
item->module, item->name);
return -1;
}
*(int*) item->vptr = ftime_str(sql_field(0));
}
if(!strcmp(stype,"switch") && sql_field(0))
*(int*) item->vptr = (!strcasecmp(sql_field(0),"on"));
} else
{
errlog("Unable to find configuratiom item %s.%s",
item->module, item->name);
return -1;
}
if((*(sql_field(2)) == 'n') && (item->vptr == NULL))
{
errlog("Mandatory item %s.%s is not set!",
item->module, item->name);
return -2;
}
++item;
}
return 0;
}
/* End of module */
syntax highlighted by Code2HTML, v. 0.9.1