Increase log level on SIGRTMAX. Reset it on SIGHUP
[bpdyndnsd] / src / main.cpp
CommitLineData
b1be615b
BS
1/** @file
2 * @brief The main function.
3 *
4 *
5 *
6 * @copyright Intra2net AG
7 * @license GPLv2
8*/
4545a371
BS
9
10#ifdef HAVE_CONFIG_H
11#include <config.h>
12#endif
13
c47386eb 14#define PIDFILE "/var/run/bpdyndnsd/bpdyndnsd.pid"
388f4ab0 15
4545a371 16#include <iostream>
88a594e8 17#include <fstream>
4545a371
BS
18#include <list>
19#include <string>
4545a371 20#include <boost/foreach.hpp>
88a594e8
BS
21#include <sys/types.h>
22#include <signal.h>
23
4de6a9b8 24#include "updater.hpp"
4545a371 25
4545a371
BS
26using namespace std;
27
88a594e8 28Updater::Ptr updater;
c5a6b1fe 29volatile bool exit_now = false;
e4ebcadc 30volatile bool caught_sig_hup = false;
a6aac246
TJ
31volatile bool caught_sig_usr1 = false;
32volatile bool caught_sig_usr2 = false;
e4ebcadc 33volatile bool caught_sig_rtmin = false;
3f39b968 34volatile bool caught_sig_rtmax = false;
e4ebcadc 35volatile bool caught_sig_term = false;
a6aac246 36
4545a371 37/**
388f4ab0
BS
38 * Checks if a bpdyndnsd process is already running.
39 * @param updater Shared Pointer to updater, needed for logging.
40 * @return 0 if process not running already or pid of already running process.
41 */
c5675c01 42int check_for_running_process()
388f4ab0
BS
43{
44 ifstream pidfile(PIDFILE);
45 if ( pidfile.is_open() )
46 {
47 int pid;
48 pidfile >> pid;
49 if ( pid > 0 )
50 updater->get_logger()->print_pid_found(pid);
51 else
52 return 0;
53
54 // check if process still running ret_val==-1 -> not runnig, ret_val==0 -> running
55 if ( kill(pid,0) == 0)
56 {
57 updater->get_logger()->print_process_already_running(pid);
58 pidfile.close();
59 return pid;
60 }
61 }
62 pidfile.close();
63 return 0;
64}
65
c5675c01
BS
66
67/**
68 * Writes the pid into the pidfile.
69 * @param pid The process's pid.
70 */
667c672c 71int write_pidfile(int pid)
388f4ab0
BS
72{
73 ofstream pidfile(PIDFILE);
74 if ( pidfile.is_open() )
75 {
76 pidfile << pid << endl;
77 }
667c672c
BS
78 else
79 {
80 updater->get_logger()->print_error_opening_rw(PIDFILE);
81 return -1;
82 }
388f4ab0 83 pidfile.close();
667c672c 84 return 0;
388f4ab0
BS
85}
86
c5675c01
BS
87
88/**
e304c27b
BS
89 * Parent shutdown function
90 * @return 0 if all is fine, -1 otherwise
91 */
92int shutdown_parent(bool remove_pid, int ret_val)
93{
94 // starting shutdown_parent
95 updater->get_logger()->print_starting_shutdown_parent();
96
97 // remove pidfile if requested
98 if(remove_pid)
99 unlink(PIDFILE);
100
101 // shutdown parent complete
102 updater->get_logger()->print_shutdown_parent_succeeded();
103
104 // release shared pointer
105 updater.reset();
106
107 exit(ret_val);
108}
109
110
111/**
112 * Shutdown function
113 * @return 0 if all is fine, -1 otherwise
114 */
115int shutdown()
116{
117 int ret_val = 0;
118
119 // starting shutdown
120 updater->get_logger()->print_starting_shutdown();
121
122 // serialize actual service objects
123 if ( updater->get_service_holder()->serialize_services() != 0 )
124 ret_val = -1;
125
126 // unlink pidfile
127 unlink(PIDFILE);
128
129 // shutdown complete
130 updater->get_logger()->print_shutdown_succeeded();
131
132 // release shared pointer
133 updater.reset();
134
135 return ret_val;
136}
137
138
139/**
e4ebcadc 140 * Signal SIGTERM caught (exit program)
c5675c01
BS
141 * @param param Parameter from the signal interface.
142 */
e4ebcadc 143void sigterm_func(int param)
c5675c01 144{
212c7ac3 145 caught_sig_term = true;
08a5a621 146} /*lint !e715 */
c5675c01
BS
147
148
149/**
e4ebcadc 150 * Signal SIGUSR1 caught (switch to offline mode)
c5675c01
BS
151 * @param param Parameter from the signal interface.
152 */
e4ebcadc 153void sigusr1_func(int param)
c5675c01 154{
a6aac246 155 caught_sig_usr1 = true;
08a5a621 156} /*lint !e715 */
c5675c01
BS
157
158
159/**
3f39b968 160 * Signal SIGHUP caught (reload config and reset log level)
39acb828 161 * @param param Parameter from the signal interface.
c5675c01 162 */
e4ebcadc 163void sighup_func(int param)
c5675c01 164{
e4ebcadc 165 caught_sig_hup = true;
64ff14c3
BS
166} /*lint !e715 */
167
168
169/**
e4ebcadc 170 * Signal SIGUSR2 caught (switch to online mode)
64ff14c3
BS
171 * @param param Parameter from the signal interface.
172 */
e4ebcadc 173void sigusr2_func(int param)
64ff14c3 174{
a6aac246 175 caught_sig_usr2 = true;
64ff14c3
BS
176} /*lint !e715 */
177
178
179/**
e4ebcadc 180 * Signal SIGRTMIN caught (switch to online mode with webcheck enabled)
64ff14c3
BS
181 * @param param Parameter from the signal interface.
182 */
e4ebcadc 183void sigrtmin_func(int param)
64ff14c3 184{
e4ebcadc 185 caught_sig_rtmin = true;
08a5a621 186} /*lint !e715 */
c5675c01
BS
187
188
189/**
3f39b968
TJ
190 * Signal SIGRTMAX caught (increase log level)
191 * @param param Parameter from the signal interface.
192 */
193void sigrtmax_func(int param)
194{
195 caught_sig_rtmax = true;
196} /*lint !e715 */
197
198
199/**
c5675c01 200 * Initialize the signals we handle.
e0080b78 201 * @return 0 if all is fine, -1 on error.
c5675c01 202 */
8bca3c5d 203int init_signals()
c5675c01 204{
8bca3c5d 205 sighandler_t ret_val;
e4ebcadc 206 ret_val = signal(SIGTERM, sigterm_func);
8bca3c5d 207 if ( ret_val == SIG_ERR )
667c672c
BS
208 {
209 updater->get_logger()->print_error_setting_signal("SIGTERM");
8bca3c5d 210 return -1;
667c672c 211 }
e4ebcadc 212 ret_val = signal(SIGUSR1, sigusr1_func);
8bca3c5d 213 if ( ret_val == SIG_ERR )
667c672c
BS
214 {
215 updater->get_logger()->print_error_setting_signal("SIGUSR1");
8bca3c5d 216 return -1;
667c672c 217 }
e4ebcadc 218 ret_val = signal(SIGHUP, sighup_func);
8bca3c5d 219 if ( ret_val == SIG_ERR )
667c672c
BS
220 {
221 updater->get_logger()->print_error_setting_signal("SIGHUP");
8bca3c5d 222 return -1;
667c672c 223 }
e4ebcadc 224 ret_val = signal(SIGUSR2, sigusr2_func);
64ff14c3
BS
225 if ( ret_val == SIG_ERR )
226 {
227 updater->get_logger()->print_error_setting_signal("SIGUSR2");
228 return -1;
229 }
e4ebcadc 230 ret_val = signal(SIGRTMIN, sigrtmin_func);
64ff14c3
BS
231 if ( ret_val == SIG_ERR )
232 {
233 updater->get_logger()->print_error_setting_signal("SIGRTMIN");
234 return -1;
235 }
3f39b968
TJ
236 ret_val = signal(SIGRTMAX, sigrtmax_func);
237 if ( ret_val == SIG_ERR )
238 {
239 updater->get_logger()->print_error_setting_signal("SIGRTMAX");
240 return -1;
241 }
5ac72dd8
BS
242
243 return 0;
c5675c01
BS
244}
245
246
388f4ab0 247/**
584b9407
BS
248 * Try to run in daemon mode if enabled in config.
249 * @param daemon_mode True if process should detach to init (run as daemon), false if not detach to init.
250 * @return 0 if all is fine, -1 on error.
251 */
252int init_daemon_mode(bool daemon_mode)
253{
254 updater->get_logger()->print_daemon_mode(daemon_mode);
255 if ( daemon_mode == true )
256 {
257 int pid = fork();
258 if ( pid < 0 )
259 {
260 // error fork
261 updater->get_logger()->print_error_fork();
262 return -1;
263 }
264 else if ( pid > 0 )
265 {
266 // parent continues here
267 if ( write_pidfile(pid) != 0 )
268 {
269 if ( kill(pid,SIGTERM) != 0 )
e304c27b 270 {
584b9407 271 updater->get_logger()->print_error_kill_child(pid);
557b6f56 272 shutdown_parent(false,-1); /*lint !e534 */
e304c27b 273 }
584b9407 274 else
e304c27b 275 {
584b9407 276 updater->get_logger()->print_child_killed(pid);
557b6f56 277 shutdown_parent(true,-1); /*lint !e534 */
e304c27b 278 }
584b9407
BS
279 }
280 updater->get_logger()->print_runnig_as_daemon(pid);
557b6f56 281 shutdown_parent(false,0); /*lint !e534 */
584b9407
BS
282 }
283 // child starts here
284 }
e304c27b
BS
285 else
286 {
287 if ( write_pidfile(getpid()) != 0 )
288 {
557b6f56 289 shutdown(); /*lint !e534 */
e304c27b
BS
290 exit(-1);
291 }
292 }
584b9407
BS
293 return 0;
294}
295
296/**
b1be615b
BS
297 * @brief The main part.
298 * @param argc Number of arguments
299 * @param argv Command line arguments
300 * @return 0 if all is fine.
4545a371
BS
301 */
302int main(int argc, char *argv[])
303{
38060291 304 // initialize Updater
c3c84086 305 updater = Updater::Ptr(new Updater);
38060291 306
efbde536
BS
307 // load config and initialize helper classes
308 if ( updater->load_config(argc,argv) != 0 )
667c672c 309 return -1;
4545a371 310
388f4ab0 311 // open pidfile and check for running process
c5675c01 312 if ( check_for_running_process() != 0)
667c672c 313 return -1;
3434b35f 314
c5675c01 315 // init signal handling
8bca3c5d 316 if ( init_signals() != 0)
667c672c 317 return -1;
254bbf53 318
584b9407
BS
319 // init daemon_mode if enabled
320 if ( init_daemon_mode(updater->get_config()->get_daemon_mode()) != 0 )
321 return -1;
388f4ab0 322
dbaf4b42 323 // Should we start in offline mode?
d55e13a6 324 bool old_online_state = false;
a6aac246
TJ
325 bool is_online = !updater->get_config()->get_start_offline();
326 bool webcheck_enabled = updater->get_config()->get_webcheck_enabled();
dbaf4b42 327
c5a6b1fe
TJ
328 // One shot run if daemon mode is disabled
329 if (updater->get_config()->get_daemon_mode() != 1)
330 exit_now = true;
331
e38d7604
TJ
332 // Tell the world we are running
333 updater->get_logger()->print_started();
334
3f39b968
TJ
335 int original_log_level = updater->get_logger()->get_loglevel();
336
388f4ab0
BS
337 // service processing starts here
338 do
339 {
a6aac246
TJ
340 // Signal processing
341 if (caught_sig_usr1)
342 {
343 caught_sig_usr1 = false;
344 updater->get_logger()->print_caught_siguser1();
345
346 // Go offline
347 is_online = false;
348 } else if (caught_sig_usr2)
349 {
350 caught_sig_usr2 = false;
351 updater->get_logger()->print_caught_siguser2();
352
353 // Go online
354 is_online = true;
355 webcheck_enabled = false;
e4ebcadc 356 } else if (caught_sig_rtmin)
a6aac246 357 {
e4ebcadc 358 caught_sig_rtmin = false;
a6aac246
TJ
359 updater->get_logger()->print_caught_sigrtmin();
360
361 // Go online - with webcheck
362 is_online = true;
363 webcheck_enabled = true;
3f39b968
TJ
364 } else if (caught_sig_rtmax)
365 {
366 caught_sig_rtmax = false;
367
368 // Increase log level
369 int new_loglevel = updater->get_logger()->get_loglevel() + 1;
370 updater->get_logger()->print_caught_sigrtmax(new_loglevel);
371 updater->get_logger()->set_loglevel(new_loglevel);
212c7ac3
TJ
372 } else if (caught_sig_term)
373 {
e4ebcadc 374 caught_sig_term = false;
212c7ac3
TJ
375 updater->get_logger()->print_caught_sigterm();
376
377 exit_now = true;
e4ebcadc
TJ
378 } else if (caught_sig_hup)
379 {
380 caught_sig_hup = false;
381 updater->get_logger()->print_caught_sighup();
382
383 if ( updater->reload_config() != 0 )
384 {
385 updater->get_logger()->print_conf_reload_failed_exit();
386 exit(-1);
387 }
3f39b968
TJ
388
389 // Reset log level to startup log level in case it got elevated by SIGRTMAX
390 updater->get_logger()->set_loglevel(original_log_level);
a6aac246
TJ
391 }
392
393 // State handling
98dd88bd 394 if ( is_online == true )
c5675c01 395 {
46fffdd6 396 // Check if webcheck_enabled differs due to caught singnal then set it in config correspondingly
43f4565e 397 if ( updater->get_config()->get_webcheck_enabled() != webcheck_enabled ) /*lint !e731 */
46fffdd6
BS
398 updater->get_config()->set_webcheck_enabled(webcheck_enabled);
399
c5675c01 400 // update all configured services
d55e13a6 401 updater->update_services(is_online != old_online_state);
c5675c01 402 }
8bca3c5d
BS
403 else
404 {
50d63110 405 // We are in offline mode, do nothing, expect printing "offline mode".
8bca3c5d
BS
406 updater->get_logger()->print_offline_mode();
407 }
388f4ab0 408
d55e13a6
TJ
409 // Keep old online state so we can determine
410 // if we switched from offline to online
411 old_online_state = is_online;
412
a7beeb20 413 // Snore, snore... don't hog the cpu if we are in daemon_mode.
c5a6b1fe 414 if ( !exit_now )
557b6f56 415 sleep(10); /*lint !e534 */
c5a6b1fe 416 } while ( !exit_now );
4545a371 417
50d63110 418 // Serialize services to save their actual state.
e304c27b 419 if ( shutdown() != 0 )
667c672c 420 return -1;
2bc1878a 421
4545a371
BS
422 return 0;
423}