| 1 |
/*
|
| 2 |
* LMS version 1.1-cvs
|
| 3 |
*
|
| 4 |
* (C) Copyright 2001-2003 LMS Developers
|
| 5 |
*
|
| 6 |
* Please, see the doc/AUTHORS for more information about authors!
|
| 7 |
*
|
| 8 |
* This program is free software; you can redistribute it and/or modify
|
| 9 |
* it under the terms of the GNU General Public License Version 2 as
|
| 10 |
* published by the Free Software Foundation.
|
| 11 |
*
|
| 12 |
* This program is distributed in the hope that it will be useful,
|
| 13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
| 14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
| 15 |
* GNU General Public License for more details.
|
| 16 |
*
|
| 17 |
* You should have received a copy of the GNU General Public License
|
| 18 |
* along with this program; if not, write to the Free Software
|
| 19 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
|
| 20 |
* USA.
|
| 21 |
*
|
| 22 |
* $Id: lmsd.c,v 1.3 2003/08/15 12:00:00 lexx Exp $
|
| 23 |
*/
|
| 24 |
|
| 25 |
|
| 26 |
#include <stdio.h>
|
| 27 |
#include <unistd.h>
|
| 28 |
#include <string.h>
|
| 29 |
#include <syslog.h>
|
| 30 |
#include <time.h>
|
| 31 |
#include <assert.h>
|
| 32 |
#include <dlfcn.h>
|
| 33 |
#include <stdlib.h>
|
| 34 |
|
| 35 |
#include "lmsd.h"
|
| 36 |
#include "util.h"
|
| 37 |
#include "sql.h"
|
| 38 |
#include "inifile.h"
|
| 39 |
|
| 40 |
|
| 41 |
void help(char * appname)
|
| 42 |
{
|
| 43 |
printf("usage: %s [options]\n\nAvailable options:\n", appname);
|
| 44 |
printf("\t-h\tshow this help\n");
|
| 45 |
printf("\t-q\tdo a reload and quit\n");
|
| 46 |
printf("\t-r\treload configuration at start\n");
|
| 47 |
printf("\t-c <file>\tspecify config file path (default: /etc/lms/lms.ini)\n");
|
| 48 |
printf("\n\n\n");
|
| 49 |
}
|
| 50 |
|
| 51 |
int main(int argc, char ** argv)
|
| 52 |
{
|
| 53 |
int c, m;
|
| 54 |
|
| 55 |
unsigned char * config_path = "/etc/lms/lms.ini";
|
| 56 |
unsigned char *sql_user, *sql_pass, *sql_db, *sql_host, *off;
|
| 57 |
unsigned int scan_delay;
|
| 58 |
unsigned char opt_quit = 0, opt_reload_now = 0;
|
| 59 |
|
| 60 |
|
| 61 |
struct globals * g = (struct globals*) arealloc(NULL, sizeof(struct globals));
|
| 62 |
|
| 63 |
g->sql_query = &sql_query;
|
| 64 |
g->sql_count = &sql_count;
|
| 65 |
g->sql_flushquery = &sql_flushquery;
|
| 66 |
g->sql_getcolid = &sql_getcolid;
|
| 67 |
g->sql_getrow = &sql_getrow;
|
| 68 |
g->sql_flushrow = &sql_flushrow;
|
| 69 |
g->sql_strgetdata = &sql_strgetdata;
|
| 70 |
|
| 71 |
g->amalloc = &amalloc;
|
| 72 |
g->arealloc = &arealloc;
|
| 73 |
g->ini_get_conf = &ini_get_conf;
|
| 74 |
g->str_replace = &str_replace;
|
| 75 |
g->str_concat = &str_concat;
|
| 76 |
|
| 77 |
g->api_version = APIVERSION;
|
| 78 |
g->config = NULL;
|
| 79 |
g->modules = NULL;
|
| 80 |
g->dbh = NULL;
|
| 81 |
|
| 82 |
while((c = getopt(argc, argv, "hc:qr")) != EOF)
|
| 83 |
{
|
| 84 |
switch(c)
|
| 85 |
{
|
| 86 |
case 'h':
|
| 87 |
help(argv[0]);
|
| 88 |
exit(1);
|
| 89 |
break;
|
| 90 |
case 'c':
|
| 91 |
config_path = strdup(optarg);
|
| 92 |
break;
|
| 93 |
case 'r': opt_reload_now = 1; break;
|
| 94 |
case 'q': opt_quit = 1; break;
|
| 95 |
}
|
| 96 |
}
|
| 97 |
|
| 98 |
openlog("lmsd", LOG_PERROR|LOG_PID, LOG_DAEMON);
|
| 99 |
|
| 100 |
if(!(g->config = ini_load_conf(config_path)))
|
| 101 |
{
|
| 102 |
syslog(LOG_CRIT, "Unable to load configuration file: %s", config_path);
|
| 103 |
exit(1);
|
| 104 |
}
|
| 105 |
|
| 106 |
off = ini_get_conf(g->config, "lmsd", "lmsd", "yes");
|
| 107 |
if(strcmp(off, "no") == 0 || strcmp(off, "off") == 0 || strcmp(off, "0") == 0 || strcmp(off, "disable") == 0)
|
| 108 |
{
|
| 109 |
syslog(LOG_WARNING, "lmsd= is set to %s, exitting.", off);
|
| 110 |
return(0);
|
| 111 |
}
|
| 112 |
|
| 113 |
sql_host = ini_get_conf(g->config, "database", "host", "localhost");
|
| 114 |
sql_user = ini_get_conf(g->config, "database", "user", "lms");
|
| 115 |
sql_pass = ini_get_conf(g->config, "database", "password", "SPECIFY_PASSWORD_IN_CONFIGURATION");
|
| 116 |
sql_db = ini_get_conf(g->config, "database", "database", "lms");
|
| 117 |
|
| 118 |
if(!(g->dbh = sql_connect(sql_host, sql_user, sql_pass, sql_db)))
|
| 119 |
{
|
| 120 |
syslog(LOG_CRIT, "Unable to initialize SQL subsystem, aborting.");
|
| 121 |
exit(1);
|
| 122 |
}
|
| 123 |
|
| 124 |
for(m = 0; ;m++)
|
| 125 |
{
|
| 126 |
unsigned char key[20];
|
| 127 |
unsigned char * modname;
|
| 128 |
unsigned char * args;
|
| 129 |
struct module * mod;
|
| 130 |
struct module * (*init)(struct globals *, struct module*);
|
| 131 |
|
| 132 |
snprintf(key, 20, "load%d", m);
|
| 133 |
modname = ini_get_conf(g->config, "lmsd", key, NULL);
|
| 134 |
if(!modname) break;
|
| 135 |
|
| 136 |
snprintf(key, 20, "args%d", m);
|
| 137 |
args = ini_get_conf(g->config, "lmsd", key, "");
|
| 138 |
|
| 139 |
mod = (struct module*) amalloc(sizeof(struct module));
|
| 140 |
|
| 141 |
mod->filename = strdup(modname);
|
| 142 |
mod->dlh = dlopen(mod->filename, RTLD_NOW);
|
| 143 |
if(!mod->dlh)
|
| 144 |
{
|
| 145 |
syslog(LOG_CRIT, "Unable to load module %d (filename: %s): %s", m, modname, dlerror());
|
| 146 |
exit(1);
|
| 147 |
}
|
| 148 |
init = dlsym(mod->dlh, "init");
|
| 149 |
if(!init)
|
| 150 |
{
|
| 151 |
syslog(LOG_CRIT, "Unable to find initialization function in module %d (filename: %s). Is that file really a lmsd module?", m, modname);
|
| 152 |
exit(1);
|
| 153 |
}
|
| 154 |
|
| 155 |
mod->args = parse_module_argstring(args);
|
| 156 |
|
| 157 |
if(! (mod = init(g, mod)))
|
| 158 |
{
|
| 159 |
syslog(LOG_CRIT, "Unable to initialize module %d (filename: %s). Perhaps there is a version mismatch?", m, modname);
|
| 160 |
exit(1);
|
| 161 |
}
|
| 162 |
|
| 163 |
mod->next = g->modules;
|
| 164 |
g->modules = mod;
|
| 165 |
|
| 166 |
syslog(LOG_INFO, "Succefully initialized module %d (filename: %s).", m, modname);
|
| 167 |
}
|
| 168 |
if(! g->modules)
|
| 169 |
syslog(LOG_WARNING, "No modules specified in configuration.");
|
| 170 |
else
|
| 171 |
syslog(LOG_NOTICE, "%d modules initialized.", m);
|
| 172 |
|
| 173 |
scan_delay = atoi(ini_get_conf(g->config, "lmsd", "scandelay", "5000"));
|
| 174 |
if(scan_delay < 1000)
|
| 175 |
{
|
| 176 |
syslog(LOG_WARNING, "Scan delay of %d ms too short, using default value of 5000 ms.", scan_delay);
|
| 177 |
scan_delay = 5000;
|
| 178 |
}
|
| 179 |
|
| 180 |
if(scan_delay > 500000)
|
| 181 |
{
|
| 182 |
syslog(LOG_WARNING, "Scan delay of %d ms too large, using default value of 5000 ms.", scan_delay);
|
| 183 |
scan_delay = 5000;
|
| 184 |
}
|
| 185 |
scan_delay *= 1000;
|
| 186 |
|
| 187 |
|
| 188 |
while(1)
|
| 189 |
{
|
| 190 |
int n;
|
| 191 |
int reload = 0;
|
| 192 |
struct module * m;
|
| 193 |
|
| 194 |
if(opt_quit)
|
| 195 |
reload = 1;
|
| 196 |
else if(opt_reload_now)
|
| 197 |
reload = 1;
|
| 198 |
else if(sql_query(g->dbh, "SELECT * FROM reload LIMIT 1", 0))
|
| 199 |
reload = 1;
|
| 200 |
|
| 201 |
if(reload)
|
| 202 |
{
|
| 203 |
syslog(LOG_DEBUG, "Detected a configuration reload signal, calling modules...");
|
| 204 |
|
| 205 |
for(m = g->modules; m; m = m->next)
|
| 206 |
m->reload(m, g);
|
| 207 |
|
| 208 |
opt_reload_now = 0;
|
| 209 |
sql_query(g->dbh, "DELETE FROM reload", 0);
|
| 210 |
}
|
| 211 |
if(opt_quit) exit(0);
|
| 212 |
usleep(scan_delay);
|
| 213 |
}
|
| 214 |
|
| 215 |
}
|