taskrambler  v0.1.8
Web server and task management solution.
taskrambler.c
Go to the documentation of this file.
1 /**
2  * \file
3  *
4  * \author Georg Hopp
5  *
6  * \copyright
7  * Copyright © 2012 Georg Hopp
8  *
9  * This program is free software: you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program. If not, see <http://www.gnu.org/licenses/>.
21  */
22 
23 #include <unistd.h>
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <sys/time.h>
33 #include <sys/signal.h>
34 #include <sys/param.h>
35 #include <sys/stat.h>
36 #include <sys/mman.h>
37 #include <errno.h>
38 
39 #include "server.h"
40 #include "logger.h"
41 #include "http/worker.h"
42 #include "auth.h"
45 #include "interface/subject.h"
46 #include "config/config.h"
47 #include "config/value.h"
48 
49 #include "class.h"
50 #include "logger.h"
51 
52 #include "utils/signalHandling.h"
53 #include "utils/memory.h"
54 #include "utils/mime_type.h"
55 
56 #define DEFAULT_SECS 10
57 //#define DEFAULT_USECS (1000000 / HZ * 2)
58 //#define DEFAULT_SECS 1
59 #define DEFAULT_USECS 0
60 
61 
62 void nullhandler() {}
63 
64 void daemonize(void);
65 
66 Logger logger;
67 Config config;
68 
69 int
71 {
72  long psize = sysconf(_SC_PAGESIZE);
73  struct rlimit limit = {RLIM_INFINITY, RLIM_INFINITY};
74 
75  pid_t pid;
76  int status;
77  int shm;
78  struct randval * value;
79 
80  logger = new(LoggerSyslog, LOGGER_DEBUG);
81  config = new(Config, CONFIGDIR "/taskrambler.conf");
82 
83  if (NULL == config) {
85  "unable to load configuration file: %s\n",
86  CONFIGDIR "/taskrambler.conf");
87 
88  if (! INSTANCE_OF(LoggerStderr, logger)) {
89  fprintf(stderr,
90  "unable to load configuration file: %s\n",
91  CONFIGDIR "/taskrambler.conf");
92  }
93 
94  return 1;
95  }
96 
97  setrlimit(RLIMIT_CPU, &limit);
98 
99  getrlimit(RLIMIT_NOFILE, &limit);
100  limit.rlim_cur = limit.rlim_max;
101  setrlimit(RLIMIT_NOFILE, &limit);
102 
103  init_signals();
104  daemonize();
105 
106  shm = shm_open("/fooshm", O_RDWR|O_CREAT, S_IRWXU);
107  if (-1 == ftruncate(shm, psize)) {
108  doShutdown = 1;
109  }
110 
111  switch((pid = fork())) {
112  case -1:
113  break;
114 
115  case 0:
116  {
117  sigset_t block_these, pause_mask;
118  struct sigaction s;
119  struct itimerval interval;
120 
121  value = mmap (0, sizeof(struct randval), PROT_READ|PROT_WRITE,
122  MAP_SHARED, shm, 0);
123  value->timestamp = 0;
124  value->value = 0;
125 
126  close(shm);
127 
128  // Block SIGALRM
129  sigemptyset(&block_these);
130  sigaddset(&block_these, SIGALRM);
131  sigprocmask(SIG_BLOCK, &block_these, &pause_mask);
132 
133  // Set up handler for SIGALRM
134  sigemptyset(&s.sa_mask);
135  sigaddset(&s.sa_mask, SIGINT);
136  s.sa_flags = 0;
137  s.sa_handler = nullhandler;
138  if (sigaction(SIGALRM, &s, NULL) < 0) {
139  perror("sigaction SIGALRM");
140  exit (1);
141  }
142 
143  interval.it_value.tv_sec = DEFAULT_SECS;
144  interval.it_value.tv_usec = DEFAULT_USECS;
145  interval.it_interval.tv_sec = DEFAULT_SECS;
146  interval.it_interval.tv_usec = DEFAULT_USECS;
147 
148  setitimer(ITIMER_REAL, &interval, NULL);
149 
150  // child
151  while(!doShutdown) {
152  value->timestamp = time(NULL);
153  value->value = rand() % 100;
154  sigsuspend(&pause_mask);
155  }
156  }
157  break;
158 
159  default:
160  {
161  Storage users;
162  Storage passwords;
163  Auth auth;
164  Application application;
165  Router router;
166  ApplicationAdapterHttp adapterHttp;
167  HttpWorker worker;
168  Server server;
169 
170  ConfigValue ldap_base =
171  configGet(config, CSTRA("ldap_base"));
172  ConfigValue ldap_host =
173  configGet(config, CSTRA("ldap_host"));
174  ConfigValue runtime_dir =
175  configGet(config, CSTRA("runtime_dir"));
176  ConfigValue port =
177  configGet(config, CSTRA("port"));
178 
179  char user_storage[512];
180  char password_storage[512];
181 
182  strcpy(user_storage, (runtime_dir->value).string);
183  strcpy(password_storage, (runtime_dir->value).string);
184  strcat(user_storage, "/users.db");
185  strcat(password_storage, "/passwords.db");
186 
187  value = mmap (0, sizeof(int), PROT_READ|PROT_WRITE,
188  MAP_SHARED, shm, 0);
189 
190  shm_unlink("/fooshm");
191  close(shm);
192 
193  auth = new(Auth);
194  authCreate(
195  auth,
196  AUTH_LDAP,
197  (ldap_host->value).string,
198  CONFSTRA(ldap_base));
199 
200  users = new(Storage, user_storage);
201  passwords = new(Storage, password_storage);
202 
203  if (NULL == users || NULL == passwords) {
204  puts("error opening database files...\n");
205  doShutdown = 1;
206  }
207 
208  authCreate(auth, AUTH_STORAGE, passwords);
209 
210  application = new(
211  Application,
212  value,
213  users,
214  passwords,
215  "14de9e60-d497-4754-be72-f3bed52541fc",
216  auth);
217 
218  router = new(Router, application);
219  adapterHttp = new(ApplicationAdapterHttp, application, router);
220 
221  worker = new(HttpWorker, "taskrambler");
222  subjectAttach(worker, adapterHttp);
223 
224  server = new(
225  Server,
226  logger,
227  worker,
228  (int)(port->value).number,
229  SOMAXCONN);
230 
231  if (NULL != server && !doShutdown) {
232  serverRun(server);
233  }
234  else {
235  kill(pid, SIGINT);
236  }
237 
238  do {
239  pid_t w;
240 
241  w = waitpid(pid, &status, 0);
242 
243  while (w == -1) {
244  switch(errno) {
245  case EINTR: w = waitpid(pid, &status, 0);
246  break;
247  case ECHILD: perror("no child");
248  // DROP THROUGH
249  default: w = 0;
250  }
251  }
252 
253  if (0 < w) {
254  if (WIFEXITED(status)) {
255  loggerLog(logger, LOGGER_INFO,
256  "child exited, status=%d\n",
257  WEXITSTATUS(status));
258  } else if (WIFSIGNALED(status)) {
259  loggerLog(logger, LOGGER_INFO,
260  "killed by signal %d\n",
261  WTERMSIG(status));
262  } else if (WIFSTOPPED(status)) {
263  loggerLog(logger, LOGGER_INFO,
264  "stopped by signal %d\n",
265  WSTOPSIG(status));
266  } else if (WIFCONTINUED(status)) {
267  loggerLog(logger, LOGGER_INFO, "continued\n");
268  }
269  }
270  } while (!WIFEXITED(status) && !WIFSIGNALED(status));
271 
272  delete(server);
273  delete(worker);
274  delete(adapterHttp);
275  delete(router);
276  delete(application);
277  delete(passwords);
278  delete(users);
279  delete(auth);
280 
281  clearMimeTypes();
283  }
284 
285  break;
286  }
287 
288  delete(config);
289  delete(logger);
290  memCleanup();
291 
292  return 0;
293 }
294 
295 // vim: set ts=4 sw=4:
int authCreate(Auth, AuthModule,...)
Definition: auth/create.c:33
ConfigValue configGet(Config, const char *, size_t)
Definition: config/get.c:31
Logger logger
Definition: taskrambler.c:66
int value
Definition: application.h:42
void assetPoolCleanup(void)
Definition: pool.c:88
int main()
Definition: taskrambler.c:70
Config config
Definition: taskrambler.c:67
#define CSTRA(val)
Const STRing Argument.
Definition: memory.h:26
void serverRun(Server this)
Definition: run.c:36
void loggerLog(void *, logger_level, const char *const,...)
Definition: i_logger.c:38
#define DEFAULT_USECS
Definition: taskrambler.c:59
void daemonize(void)
Definition: daemonize.c:38
volatile int doShutdown
#define DEFAULT_SECS
Definition: taskrambler.c:56
void subjectAttach(void *, void *)
Definition: subject.c:32
void init_signals(void)
void memCleanup()
Definition: memory.c:862
#define INSTANCE_OF(class, obj)
Definition: class/class.h:89
void clearMimeTypes(void)
Definition: mime_type.c:106
void nullhandler()
Definition: taskrambler.c:62
#define CONFSTRA(val)
Definition: config/value.h:33