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