Log message on startup
[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
TJ
33volatile bool caught_sig_rtmin = false;
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/**
e4ebcadc 159 * Signal SIGHUP caught (reload config)
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/**
189 * Initialize the signals we handle.
e0080b78 190 * @return 0 if all is fine, -1 on error.
c5675c01 191 */
8bca3c5d 192int init_signals()
c5675c01 193{
8bca3c5d 194 sighandler_t ret_val;
e4ebcadc 195 ret_val = signal(SIGTERM, sigterm_func);
8bca3c5d 196 if ( ret_val == SIG_ERR )
667c672c
BS
197 {
198 updater->get_logger()->print_error_setting_signal("SIGTERM");
8bca3c5d 199 return -1;
667c672c 200 }
e4ebcadc 201 ret_val = signal(SIGUSR1, sigusr1_func);
8bca3c5d 202 if ( ret_val == SIG_ERR )
667c672c
BS
203 {
204 updater->get_logger()->print_error_setting_signal("SIGUSR1");
8bca3c5d 205 return -1;
667c672c 206 }
e4ebcadc 207 ret_val = signal(SIGHUP, sighup_func);
8bca3c5d 208 if ( ret_val == SIG_ERR )
667c672c
BS
209 {
210 updater->get_logger()->print_error_setting_signal("SIGHUP");
8bca3c5d 211 return -1;
667c672c 212 }
e4ebcadc 213 ret_val = signal(SIGUSR2, sigusr2_func);
64ff14c3
BS
214 if ( ret_val == SIG_ERR )
215 {
216 updater->get_logger()->print_error_setting_signal("SIGUSR2");
217 return -1;
218 }
e4ebcadc 219 ret_val = signal(SIGRTMIN, sigrtmin_func);
64ff14c3
BS
220 if ( ret_val == SIG_ERR )
221 {
222 updater->get_logger()->print_error_setting_signal("SIGRTMIN");
223 return -1;
224 }
5ac72dd8
BS
225
226 return 0;
c5675c01
BS
227}
228
229
388f4ab0 230/**
584b9407
BS
231 * Try to run in daemon mode if enabled in config.
232 * @param daemon_mode True if process should detach to init (run as daemon), false if not detach to init.
233 * @return 0 if all is fine, -1 on error.
234 */
235int init_daemon_mode(bool daemon_mode)
236{
237 updater->get_logger()->print_daemon_mode(daemon_mode);
238 if ( daemon_mode == true )
239 {
240 int pid = fork();
241 if ( pid < 0 )
242 {
243 // error fork
244 updater->get_logger()->print_error_fork();
245 return -1;
246 }
247 else if ( pid > 0 )
248 {
249 // parent continues here
250 if ( write_pidfile(pid) != 0 )
251 {
252 if ( kill(pid,SIGTERM) != 0 )
e304c27b 253 {
584b9407 254 updater->get_logger()->print_error_kill_child(pid);
557b6f56 255 shutdown_parent(false,-1); /*lint !e534 */
e304c27b 256 }
584b9407 257 else
e304c27b 258 {
584b9407 259 updater->get_logger()->print_child_killed(pid);
557b6f56 260 shutdown_parent(true,-1); /*lint !e534 */
e304c27b 261 }
584b9407
BS
262 }
263 updater->get_logger()->print_runnig_as_daemon(pid);
557b6f56 264 shutdown_parent(false,0); /*lint !e534 */
584b9407
BS
265 }
266 // child starts here
267 }
e304c27b
BS
268 else
269 {
270 if ( write_pidfile(getpid()) != 0 )
271 {
557b6f56 272 shutdown(); /*lint !e534 */
e304c27b
BS
273 exit(-1);
274 }
275 }
584b9407
BS
276 return 0;
277}
278
279/**
b1be615b
BS
280 * @brief The main part.
281 * @param argc Number of arguments
282 * @param argv Command line arguments
283 * @return 0 if all is fine.
4545a371
BS
284 */
285int main(int argc, char *argv[])
286{
38060291 287 // initialize Updater
c3c84086 288 updater = Updater::Ptr(new Updater);
38060291 289
efbde536
BS
290 // load config and initialize helper classes
291 if ( updater->load_config(argc,argv) != 0 )
667c672c 292 return -1;
4545a371 293
388f4ab0 294 // open pidfile and check for running process
c5675c01 295 if ( check_for_running_process() != 0)
667c672c 296 return -1;
3434b35f 297
c5675c01 298 // init signal handling
8bca3c5d 299 if ( init_signals() != 0)
667c672c 300 return -1;
254bbf53 301
584b9407
BS
302 // init daemon_mode if enabled
303 if ( init_daemon_mode(updater->get_config()->get_daemon_mode()) != 0 )
304 return -1;
388f4ab0 305
dbaf4b42 306 // Should we start in offline mode?
d55e13a6 307 bool old_online_state = false;
a6aac246
TJ
308 bool is_online = !updater->get_config()->get_start_offline();
309 bool webcheck_enabled = updater->get_config()->get_webcheck_enabled();
dbaf4b42 310
c5a6b1fe
TJ
311 // One shot run if daemon mode is disabled
312 if (updater->get_config()->get_daemon_mode() != 1)
313 exit_now = true;
314
e38d7604
TJ
315 // Tell the world we are running
316 updater->get_logger()->print_started();
317
388f4ab0
BS
318 // service processing starts here
319 do
320 {
a6aac246
TJ
321 // Signal processing
322 if (caught_sig_usr1)
323 {
324 caught_sig_usr1 = false;
325 updater->get_logger()->print_caught_siguser1();
326
327 // Go offline
328 is_online = false;
329 } else if (caught_sig_usr2)
330 {
331 caught_sig_usr2 = false;
332 updater->get_logger()->print_caught_siguser2();
333
334 // Go online
335 is_online = true;
336 webcheck_enabled = false;
e4ebcadc 337 } else if (caught_sig_rtmin)
a6aac246 338 {
e4ebcadc 339 caught_sig_rtmin = false;
a6aac246
TJ
340 updater->get_logger()->print_caught_sigrtmin();
341
342 // Go online - with webcheck
343 is_online = true;
344 webcheck_enabled = true;
212c7ac3
TJ
345 } else if (caught_sig_term)
346 {
e4ebcadc 347 caught_sig_term = false;
212c7ac3
TJ
348 updater->get_logger()->print_caught_sigterm();
349
350 exit_now = true;
e4ebcadc
TJ
351 } else if (caught_sig_hup)
352 {
353 caught_sig_hup = false;
354 updater->get_logger()->print_caught_sighup();
355
356 if ( updater->reload_config() != 0 )
357 {
358 updater->get_logger()->print_conf_reload_failed_exit();
359 exit(-1);
360 }
a6aac246
TJ
361 }
362
363 // State handling
98dd88bd 364 if ( is_online == true )
c5675c01 365 {
46fffdd6 366 // Check if webcheck_enabled differs due to caught singnal then set it in config correspondingly
43f4565e 367 if ( updater->get_config()->get_webcheck_enabled() != webcheck_enabled ) /*lint !e731 */
46fffdd6
BS
368 updater->get_config()->set_webcheck_enabled(webcheck_enabled);
369
c5675c01 370 // update all configured services
d55e13a6 371 updater->update_services(is_online != old_online_state);
c5675c01 372 }
8bca3c5d
BS
373 else
374 {
50d63110 375 // We are in offline mode, do nothing, expect printing "offline mode".
8bca3c5d
BS
376 updater->get_logger()->print_offline_mode();
377 }
388f4ab0 378
d55e13a6
TJ
379 // Keep old online state so we can determine
380 // if we switched from offline to online
381 old_online_state = is_online;
382
a7beeb20 383 // Snore, snore... don't hog the cpu if we are in daemon_mode.
c5a6b1fe 384 if ( !exit_now )
557b6f56 385 sleep(10); /*lint !e534 */
c5a6b1fe 386 } while ( !exit_now );
4545a371 387
50d63110 388 // Serialize services to save their actual state.
e304c27b 389 if ( shutdown() != 0 )
667c672c 390 return -1;
2bc1878a 391
4545a371
BS
392 return 0;
393}