/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "server.h"
#include "logger.h"
#include "http/worker.h"
#include "auth.h"
#include "application/application.h"
#include "application/adapter/http.h"
#include "interface/subject.h"
#include "config/config.h"
#include "config/value.h"
#include "class.h"
#include "logger.h"
#include "utils/signalHandling.h"
#include "utils/memory.h"
#include "utils/mime_type.h"
#define DEFAULT_SECS 10
//#define DEFAULT_USECS (1000000 / HZ * 2)
//#define DEFAULT_SECS 1
#define DEFAULT_USECS 0
void nullhandler() {}
void daemonize(void);
Logger logger;
Config config;
int
main()
{
long psize = sysconf(_SC_PAGESIZE);
struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
pid_t pid;
int status;
int shm;
struct randval * value;
logger = new(LoggerSyslog, LOGGER_DEBUG);
config = new(Config, CONFIGDIR "/taskrambler.conf");
if (NULL == config) {
loggerLog(logger, LOGGER_INFO,
"unable to load configuration file: %s\n",
CONFIGDIR "/taskrambler.conf");
if (! INSTANCE_OF(LoggerStderr, logger)) {
fprintf(stderr,
"unable to load configuration file: %s\n",
CONFIGDIR "/taskrambler.conf");
}
return 1;
}
setrlimit(RLIMIT_CPU, &limit);
getrlimit(RLIMIT_NOFILE, &limit);
limit.rlim_cur = limit.rlim_max;
setrlimit(RLIMIT_NOFILE, &limit);
init_signals();
daemonize();
shm = shm_open("/fooshm", O_RDWR|O_CREAT, S_IRWXU);
if (-1 == ftruncate(shm, psize)) {
doShutdown = 1;
}
switch((pid = fork())) {
case -1:
break;
case 0:
{
sigset_t block_these, pause_mask;
struct sigaction s;
struct itimerval interval;
value = mmap (0, sizeof(struct randval), PROT_READ|PROT_WRITE,
MAP_SHARED, shm, 0);
value->timestamp = 0;
value->value = 0;
close(shm);
// Block SIGALRM
sigemptyset(&block_these);
sigaddset(&block_these, SIGALRM);
sigprocmask(SIG_BLOCK, &block_these, &pause_mask);
// Set up handler for SIGALRM
sigemptyset(&s.sa_mask);
sigaddset(&s.sa_mask, SIGINT);
s.sa_flags = 0;
s.sa_handler = nullhandler;
if (sigaction(SIGALRM, &s, NULL) < 0) {
perror("sigaction SIGALRM");
exit (1);
}
interval.it_value.tv_sec = DEFAULT_SECS;
interval.it_value.tv_usec = DEFAULT_USECS;
interval.it_interval.tv_sec = DEFAULT_SECS;
interval.it_interval.tv_usec = DEFAULT_USECS;
setitimer(ITIMER_REAL, &interval, NULL);
// child
while(!doShutdown) {
value->timestamp = time(NULL);
value->value = rand() % 100;
sigsuspend(&pause_mask);
}
memCleanup();
_exit(EXIT_SUCCESS);
}
default:
{
Storage users;
Storage passwords;
AuthLdap authLdap;
AuthStorage authStorage;
Application application;
ApplicationAdapterHttp adapterHttp;
HttpWorker worker;
Server server;
ConfigValue ldap_base =
configGet(config, CSTRA("ldap_base"));
ConfigValue ldap_host =
configGet(config, CSTRA("ldap_host"));
ConfigValue runtime_dir =
configGet(config, CSTRA("runtime_dir"));
ConfigValue port =
configGet(config, CSTRA("port"));
char user_storage[512];
char password_storage[512];
strcpy(user_storage, (runtime_dir->value).string);
strcpy(password_storage, (runtime_dir->value).string);
strcat(user_storage, "/users.db");
strcat(password_storage, "/passwords.db");
value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE,
MAP_SHARED, shm, 0);
shm_unlink("/fooshm");
close(shm);
authLdap = new(
AuthLdap,
(ldap_host->value).string,
CONFSTRA(ldap_base));
users = new(Storage, user_storage);
passwords = new(Storage, password_storage);
authStorage = new(AuthStorage, passwords);
application = new(
Application,
value,
users,
passwords,
2,
authLdap,
authStorage);
adapterHttp = new(ApplicationAdapterHttp, application);
worker = new(HttpWorker, "taskrambler");
subjectAttach(worker, adapterHttp);
server = new(
Server,
logger,
worker,
(int)(port->value).number,
SOMAXCONN);
if (NULL != server) {
serverRun(server);
}
else {
doShutdown = 1;
kill(pid, SIGINT);
}
do {
pid_t w;
w = waitpid(pid, &status, 0);
while (w == -1) {
switch(errno) {
case EINTR: w = waitpid(pid, &status, 0);
break;
case ECHILD: perror("no child");
// DROP THROUGH
default: w = 0;
}
}
if (0 < w) {
if (WIFEXITED(status)) {
loggerLog(logger, LOGGER_INFO,
"child exited, status=%d\n",
WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
loggerLog(logger, LOGGER_INFO,
"killed by signal %d\n",
WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
loggerLog(logger, LOGGER_INFO,
"stopped by signal %d\n",
WSTOPSIG(status));
} else if (WIFCONTINUED(status)) {
loggerLog(logger, LOGGER_INFO, "continued\n");
}
}
} while (!WIFEXITED(status) && !WIFSIGNALED(status));
delete(server);
delete(worker);
delete(adapterHttp);
delete(application);
delete(authStorage);
delete(passwords);
delete(users);
delete(authLdap);
clearMimeTypes();
assetPoolCleanup();
}
break;
}
delete(config);
delete(logger);
memCleanup();
return 0;
}
// vim: set ts=4 sw=4: