/** * \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: