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