Started with boost/serialization error handling.
[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
14#define VERSION 0
15#define REVISION 1
16#define RELEASE 0
17
388f4ab0 18#define PIDFILE "/var/run/bpdyndnsd.pid"
27baf279 19#define OBJECT_FILE "/home/bjoern/intranator/bpdyndnsd/objects.ser"
388f4ab0 20
4545a371
BS
21#include <iostream>
22#include <list>
23#include <string>
24
25#include <boost/foreach.hpp>
26
27#include "updater.cpp"
28#include "config.cpp"
254bbf53 29#include "logger.cpp"
4545a371
BS
30
31#include "service.cpp"
27baf279 32#include "serviceholder.cpp"
4545a371
BS
33
34#include "dhs.cpp"
35#include "ods.cpp"
36
388f4ab0
BS
37#include <sys/types.h>
38#include <signal.h>
39
4545a371
BS
40using namespace std;
41
85a0abf9
BS
42typedef boost::shared_ptr<Updater> UpdaterPtr;
43
c5675c01
BS
44UpdaterPtr updater;
45bool online_mode = 1;
46
4545a371 47/**
388f4ab0
BS
48 * Checks if a bpdyndnsd process is already running.
49 * @param updater Shared Pointer to updater, needed for logging.
50 * @return 0 if process not running already or pid of already running process.
51 */
c5675c01 52int check_for_running_process()
388f4ab0
BS
53{
54 ifstream pidfile(PIDFILE);
55 if ( pidfile.is_open() )
56 {
57 int pid;
58 pidfile >> pid;
59 if ( pid > 0 )
60 updater->get_logger()->print_pid_found(pid);
61 else
62 return 0;
63
64 // check if process still running ret_val==-1 -> not runnig, ret_val==0 -> running
65 if ( kill(pid,0) == 0)
66 {
67 updater->get_logger()->print_process_already_running(pid);
68 pidfile.close();
69 return pid;
70 }
71 }
72 pidfile.close();
73 return 0;
74}
75
c5675c01
BS
76
77/**
78 * Writes the pid into the pidfile.
79 * @param pid The process's pid.
80 */
388f4ab0
BS
81void write_pidfile(int pid)
82{
83 ofstream pidfile(PIDFILE);
84 if ( pidfile.is_open() )
85 {
86 pidfile << pid << endl;
87 }
88 pidfile.close();
89}
90
c5675c01
BS
91
92/**
93 * Signal SIGTERM caught, releasing resources and exit.
94 * @param param Parameter from the signal interface.
95 */
96void terminate(int param)
97{
98 updater->get_logger()->print_caught_sigterm();
2bc1878a
BS
99
100 // unfortunately we can't call serialize_services in any destructor
101 // cause some singleton are already destroyed !?!
102 updater->get_config()->serialize_services();
c5675c01 103 updater.reset();
39acb828 104 exit(0);
c5675c01
BS
105}
106
107
2bc1878a 108
c5675c01
BS
109/**
110 * Signal SIGUSR1 caught, switching to offline mode.
111 * @param param Parameter from the signal interface.
112 */
113void switch_to_offline(int param)
114{
8bca3c5d 115 updater->get_logger()->print_caught_siguser1();
b011a02a 116 // TODO: How about using an enum for online_mode instead of magic numbers?
c5675c01
BS
117 online_mode = 0;
118}
119
120
121/**
122 * Signal SIGHUP caught, reloading config and switching to online mode.
39acb828 123 * @param param Parameter from the signal interface.
c5675c01
BS
124 */
125void reload_config(int param)
126{
8bca3c5d 127 updater->get_logger()->print_caught_sighup();
c5675c01
BS
128 updater->reload_config();
129 online_mode = 1;
130}
131
132
133/**
134 * Initialize the signals we handle.
135 */
8bca3c5d 136int init_signals()
c5675c01 137{
8bca3c5d
BS
138 sighandler_t ret_val;
139 ret_val = signal(SIGTERM,terminate);
140 if ( ret_val == SIG_ERR )
141 return -1;
142 ret_val = signal(SIGUSR1,switch_to_offline);
143 if ( ret_val == SIG_ERR )
144 return -1;
145 ret_val = signal(SIGHUP,reload_config);
146 if ( ret_val == SIG_ERR )
147 return -1;
5ac72dd8
BS
148
149 return 0;
c5675c01
BS
150}
151
152
388f4ab0 153/**
b1be615b
BS
154 * @brief The main part.
155 * @param argc Number of arguments
156 * @param argv Command line arguments
157 * @return 0 if all is fine.
4545a371
BS
158 */
159int main(int argc, char *argv[])
160{
38060291 161 // initialize Updater
c5675c01
BS
162 UpdaterPtr _updater(new Updater);
163 updater = _updater;
164 _updater.reset();
38060291 165
b011a02a
TJ
166 // TODO: Why do errors return zero exit status?
167
254bbf53 168 // load the cmd options
38060291 169 if ( updater->init_config_from_cmd(argc,argv) != 0 )
1cf4e2b5 170 return 0;
38060291 171
254bbf53 172 // load the config and service files
38060291 173 if ( updater->init_config_from_files() != 0 )
98bd3874 174 return 0;
4545a371 175
388f4ab0 176 // open pidfile and check for running process
c5675c01 177 if ( check_for_running_process() != 0)
388f4ab0 178 return 0;
3434b35f 179
c5675c01 180 // init signal handling
8bca3c5d
BS
181 if ( init_signals() != 0)
182 {
183 updater->get_logger()->print_error_setting_signal();
184 return 0;
185 }
254bbf53
BS
186
187 // initialize daemon mode if configured
59c8d63c
BS
188 updater->get_logger()->print_daemon_mode(updater->get_config()->get_daemon_mode());
189 if ( updater->get_config()->get_daemon_mode() == 1 )
388f4ab0
BS
190 {
191 int pid = fork();
192 if ( pid < 0 )
193 {
194 // error fork
195 updater->get_logger()->print_error_fork();
196 return 0;
197 }
198 else if ( pid > 0 )
199 {
200 // parent
201 write_pidfile(pid);
202 updater->get_logger()->print_runnig_as_daemon(pid);
203 return 0;
204 }
205 // child starts here
206 }
207
208 // service processing starts here
209 do
210 {
c5675c01
BS
211 if ( online_mode == 1 )
212 {
213 // update all configured services
214 updater->update_services();
215 }
8bca3c5d
BS
216 else
217 {
218 updater->get_logger()->print_offline_mode();
219 }
388f4ab0 220
59c8d63c
BS
221 if ( updater->get_config()->get_daemon_mode() == 1 )
222 sleep(10); // TODO: in a final release, correct the sleep value to something suitable
223
224 }while ( updater->get_config()->get_daemon_mode() == 1 );
4545a371 225
2bc1878a
BS
226
227 // serialize services
228 updater->get_config()->serialize_services();
229
4545a371
BS
230 return 0;
231}