Move exit_now variable to main() function
[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;
e4ebcadc 29volatile bool caught_sig_hup = false;
a6aac246
TJ
30volatile bool caught_sig_usr1 = false;
31volatile bool caught_sig_usr2 = false;
e4ebcadc 32volatile bool caught_sig_rtmin = false;
3f39b968 33volatile bool caught_sig_rtmax = false;
e4ebcadc 34volatile bool caught_sig_term = false;
a6aac246 35
4545a371 36/**
388f4ab0
BS
37 * Checks if a bpdyndnsd process is already running.
38 * @param updater Shared Pointer to updater, needed for logging.
39 * @return 0 if process not running already or pid of already running process.
40 */
c5675c01 41int check_for_running_process()
388f4ab0
BS
42{
43 ifstream pidfile(PIDFILE);
44 if ( pidfile.is_open() )
45 {
46 int pid;
47 pidfile >> pid;
48 if ( pid > 0 )
49 updater->get_logger()->print_pid_found(pid);
50 else
51 return 0;
52
53 // check if process still running ret_val==-1 -> not runnig, ret_val==0 -> running
54 if ( kill(pid,0) == 0)
55 {
56 updater->get_logger()->print_process_already_running(pid);
57 pidfile.close();
58 return pid;
59 }
60 }
61 pidfile.close();
62 return 0;
63}
64
c5675c01
BS
65
66/**
67 * Writes the pid into the pidfile.
68 * @param pid The process's pid.
69 */
667c672c 70int write_pidfile(int pid)
388f4ab0
BS
71{
72 ofstream pidfile(PIDFILE);
73 if ( pidfile.is_open() )
74 {
75 pidfile << pid << endl;
76 }
667c672c
BS
77 else
78 {
79 updater->get_logger()->print_error_opening_rw(PIDFILE);
80 return -1;
81 }
388f4ab0 82 pidfile.close();
667c672c 83 return 0;
388f4ab0
BS
84}
85
c5675c01
BS
86
87/**
e304c27b
BS
88 * Parent shutdown function
89 * @return 0 if all is fine, -1 otherwise
90 */
91int shutdown_parent(bool remove_pid, int ret_val)
92{
93 // starting shutdown_parent
94 updater->get_logger()->print_starting_shutdown_parent();
95
96 // remove pidfile if requested
97 if(remove_pid)
98 unlink(PIDFILE);
99
100 // shutdown parent complete
101 updater->get_logger()->print_shutdown_parent_succeeded();
102
103 // release shared pointer
104 updater.reset();
105
106 exit(ret_val);
107}
108
109
110/**
111 * Shutdown function
112 * @return 0 if all is fine, -1 otherwise
113 */
114int shutdown()
115{
116 int ret_val = 0;
117
118 // starting shutdown
119 updater->get_logger()->print_starting_shutdown();
120
121 // serialize actual service objects
122 if ( updater->get_service_holder()->serialize_services() != 0 )
123 ret_val = -1;
124
125 // unlink pidfile
126 unlink(PIDFILE);
127
128 // shutdown complete
129 updater->get_logger()->print_shutdown_succeeded();
130
131 // release shared pointer
132 updater.reset();
133
134 return ret_val;
135}
136
137
138/**
e4ebcadc 139 * Signal SIGTERM caught (exit program)
c5675c01
BS
140 * @param param Parameter from the signal interface.
141 */
e4ebcadc 142void sigterm_func(int param)
c5675c01 143{
212c7ac3 144 caught_sig_term = true;
08a5a621 145} /*lint !e715 */
c5675c01
BS
146
147
148/**
e4ebcadc 149 * Signal SIGUSR1 caught (switch to offline mode)
c5675c01
BS
150 * @param param Parameter from the signal interface.
151 */
e4ebcadc 152void sigusr1_func(int param)
c5675c01 153{
a6aac246 154 caught_sig_usr1 = true;
08a5a621 155} /*lint !e715 */
c5675c01
BS
156
157
158/**
3f39b968 159 * Signal SIGHUP caught (reload config and reset log level)
39acb828 160 * @param param Parameter from the signal interface.
c5675c01 161 */
e4ebcadc 162void sighup_func(int param)
c5675c01 163{
e4ebcadc 164 caught_sig_hup = true;
64ff14c3
BS
165} /*lint !e715 */
166
167
168/**
e4ebcadc 169 * Signal SIGUSR2 caught (switch to online mode)
64ff14c3
BS
170 * @param param Parameter from the signal interface.
171 */
e4ebcadc 172void sigusr2_func(int param)
64ff14c3 173{
a6aac246 174 caught_sig_usr2 = true;
64ff14c3
BS
175} /*lint !e715 */
176
177
178/**
e4ebcadc 179 * Signal SIGRTMIN caught (switch to online mode with webcheck enabled)
64ff14c3
BS
180 * @param param Parameter from the signal interface.
181 */
e4ebcadc 182void sigrtmin_func(int param)
64ff14c3 183{
e4ebcadc 184 caught_sig_rtmin = true;
08a5a621 185} /*lint !e715 */
c5675c01
BS
186
187
188/**
3f39b968
TJ
189 * Signal SIGRTMAX caught (increase log level)
190 * @param param Parameter from the signal interface.
191 */
192void sigrtmax_func(int param)
193{
194 caught_sig_rtmax = true;
195} /*lint !e715 */
196
197
198/**
c5675c01 199 * Initialize the signals we handle.
e0080b78 200 * @return 0 if all is fine, -1 on error.
c5675c01 201 */
8bca3c5d 202int init_signals()
c5675c01 203{
8bca3c5d 204 sighandler_t ret_val;
e4ebcadc 205 ret_val = signal(SIGTERM, sigterm_func);
8bca3c5d 206 if ( ret_val == SIG_ERR )
667c672c
BS
207 {
208 updater->get_logger()->print_error_setting_signal("SIGTERM");
8bca3c5d 209 return -1;
667c672c 210 }
e4ebcadc 211 ret_val = signal(SIGUSR1, sigusr1_func);
8bca3c5d 212 if ( ret_val == SIG_ERR )
667c672c
BS
213 {
214 updater->get_logger()->print_error_setting_signal("SIGUSR1");
8bca3c5d 215 return -1;
667c672c 216 }
e4ebcadc 217 ret_val = signal(SIGHUP, sighup_func);
8bca3c5d 218 if ( ret_val == SIG_ERR )
667c672c
BS
219 {
220 updater->get_logger()->print_error_setting_signal("SIGHUP");
8bca3c5d 221 return -1;
667c672c 222 }
e4ebcadc 223 ret_val = signal(SIGUSR2, sigusr2_func);
64ff14c3
BS
224 if ( ret_val == SIG_ERR )
225 {
226 updater->get_logger()->print_error_setting_signal("SIGUSR2");
227 return -1;
228 }
e4ebcadc 229 ret_val = signal(SIGRTMIN, sigrtmin_func);
64ff14c3
BS
230 if ( ret_val == SIG_ERR )
231 {
232 updater->get_logger()->print_error_setting_signal("SIGRTMIN");
233 return -1;
234 }
3f39b968
TJ
235 ret_val = signal(SIGRTMAX, sigrtmax_func);
236 if ( ret_val == SIG_ERR )
237 {
238 updater->get_logger()->print_error_setting_signal("SIGRTMAX");
239 return -1;
240 }
5ac72dd8
BS
241
242 return 0;
c5675c01
BS
243}
244
245
388f4ab0 246/**
584b9407
BS
247 * Try to run in daemon mode if enabled in config.
248 * @param daemon_mode True if process should detach to init (run as daemon), false if not detach to init.
249 * @return 0 if all is fine, -1 on error.
250 */
251int init_daemon_mode(bool daemon_mode)
252{
253 updater->get_logger()->print_daemon_mode(daemon_mode);
254 if ( daemon_mode == true )
255 {
256 int pid = fork();
257 if ( pid < 0 )
258 {
259 // error fork
260 updater->get_logger()->print_error_fork();
261 return -1;
262 }
263 else if ( pid > 0 )
264 {
265 // parent continues here
266 if ( write_pidfile(pid) != 0 )
267 {
268 if ( kill(pid,SIGTERM) != 0 )
e304c27b 269 {
584b9407 270 updater->get_logger()->print_error_kill_child(pid);
557b6f56 271 shutdown_parent(false,-1); /*lint !e534 */
e304c27b 272 }
584b9407 273 else
e304c27b 274 {
584b9407 275 updater->get_logger()->print_child_killed(pid);
557b6f56 276 shutdown_parent(true,-1); /*lint !e534 */
e304c27b 277 }
584b9407
BS
278 }
279 updater->get_logger()->print_runnig_as_daemon(pid);
557b6f56 280 shutdown_parent(false,0); /*lint !e534 */
584b9407
BS
281 }
282 // child starts here
283 }
e304c27b
BS
284 else
285 {
286 if ( write_pidfile(getpid()) != 0 )
287 {
557b6f56 288 shutdown(); /*lint !e534 */
e304c27b
BS
289 exit(-1);
290 }
291 }
584b9407
BS
292 return 0;
293}
294
295/**
b1be615b
BS
296 * @brief The main part.
297 * @param argc Number of arguments
298 * @param argv Command line arguments
299 * @return 0 if all is fine.
4545a371
BS
300 */
301int main(int argc, char *argv[])
302{
38060291 303 // initialize Updater
c3c84086 304 updater = Updater::Ptr(new Updater);
38060291 305
efbde536
BS
306 // load config and initialize helper classes
307 if ( updater->load_config(argc,argv) != 0 )
667c672c 308 return -1;
4545a371 309
388f4ab0 310 // open pidfile and check for running process
c5675c01 311 if ( check_for_running_process() != 0)
667c672c 312 return -1;
3434b35f 313
c5675c01 314 // init signal handling
8bca3c5d 315 if ( init_signals() != 0)
667c672c 316 return -1;
254bbf53 317
584b9407
BS
318 // init daemon_mode if enabled
319 if ( init_daemon_mode(updater->get_config()->get_daemon_mode()) != 0 )
320 return -1;
388f4ab0 321
dbaf4b42 322 // Should we start in offline mode?
d55e13a6 323 bool old_online_state = false;
a6aac246
TJ
324 bool is_online = !updater->get_config()->get_start_offline();
325 bool webcheck_enabled = updater->get_config()->get_webcheck_enabled();
f829f1f3 326 bool exit_now = false;
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}