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