1 /*-
2 * Copyright (c) 1998-2008 DHIS, Dynamic Host Information System
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 */
27
28 #include<string.h>
29 #include<stdio.h>
30
31 #include "dhisd.h"
32 #include "online.h"
33 #include "network.h"
34 #include "ddb.h"
35 #include "qrc.h"
36 #include "misc.h"
37
38 /* Locally defined prototypes */
39 void sig_parse(int);
40 void sig_hup(int);
41 void sig_usr1(int);
42 void sig_usr2(int);
43 void sig_void(int);
44 void sig_chld(int);
45 void sig_term(int);
46 void usage(char *);
47
48
49 int do_reload=0;
50 int do_parse=0;
51 int debug_level = 0;
52
53 char logfile[256];
54 char pid_file[256];
55 char database_file[256];
56 char conf_file[256];
57
58 extern int udp_port;
59 extern char dhisd_bind_address[32];
60 extern int db_mode;
61
62 #ifdef WITH_MYSQL
63 char sql_server[128];
64 char sql_user[128];
65 char sql_password[128];
66 char sql_dbase[128];
67 #endif
68
69
read_conf(void)70 int read_conf(void) {
71
72 FILE *fp;
73 char str[256];
74
75 DSYSLOG(1,(LOG_DEBUG,"read_conf(): Reading configuration File\n"));
76
77 #ifdef WITH_MYSQL
78 sql_server[0]='\0';
79 sql_user[0]='\0';
80 sql_password[0]='\0';
81 sql_dbase[0]='\0';
82 #endif
83
84 fp=fopen(conf_file,"r");
85 if(fp==NULL) return 0;
86 while(fgets(str,255,fp)!=NULL) {
87 char command[256];
88 off_nl(str);
89 strcpy(command,line_entry(1,str));
90 strtolower(command);
91 if(!strcmp(command,"bindaddress"))
92 strncpy(dhisd_bind_address,line_entry(2,str),31);
93 if(!strcmp(command,"pidfile"))
94 strncpy(pid_file,line_entry(2,str),255);
95 if(!strcmp(command,"logfile"))
96 strncpy(logfile,line_entry(2,str),255);
97 if(!strcmp(command,"dbfile"))
98 strncpy(database_file,line_entry(2,str),255);
99 if(!strcmp(command,"bindport"))
100 udp_port=atoi(line_entry(2,str));
101 #ifdef WITH_MYSQL
102 if(!strcmp(command,"mysqlserver"))
103 strncpy(sql_server,line_entry(2,str),127);
104 if(!strcmp(command,"mysqluser"))
105 strncpy(sql_user,line_entry(2,str),127);
106 if(!strcmp(command,"mysqlpassword"))
107 strncpy(sql_password,line_entry(2,str),127);
108 if(!strcmp(command,"mysqldbase"))
109 strncpy(sql_dbase,line_entry(2,str),127);
110 #endif
111 }
112 fclose(fp);
113 return 1;
114 }
115
sig_parse(int s)116 void sig_parse(int s) {
117
118 if(s!=SIGALRM) return;
119 do_parse=1;
120 signal(SIGALRM,sig_parse);
121 alarm(PARSE_TIMEOUT);
122 }
123
sig_hup(int s)124 void sig_hup(int s) {
125
126 if(s!=SIGHUP) return;
127 DSYSLOG(0,(LOG_INFO,"sig_hup(): Reload HUP Received\n"));
128 do_reload=1;
129 signal(SIGHUP,sig_hup);
130 }
131
sig_void(int s)132 void sig_void(int s) {
133
134 if(s!=SIGCHLD) return; /* Just so that cc doesn't complain */
135 return;
136 }
137
sig_usr1(int s)138 void sig_usr1(int s) {
139 if(s!=SIGUSR1) return;
140 debug_level++;
141 syslog(LOG_DEBUG,"debug level %d\n", debug_level);
142 signal(SIGUSR1,sig_usr1);
143 }
144
sig_usr2(int s)145 void sig_usr2(int s) {
146 if(s!=SIGUSR2) return;
147 debug_level = 0;
148 syslog(LOG_DEBUG,"debug level %d\n", debug_level);
149 signal(SIGUSR2,sig_usr2);
150 }
151
152
sig_chld(int s)153 void sig_chld(int s) {
154
155 if(s!=SIGCHLD) return;
156 int r;
157 wait(&r);
158 signal(SIGCHLD,sig_chld);
159 }
160
sig_term(int s)161 void sig_term(int s) {
162
163 if(s!=SIGTERM && s!=SIGKILL && s!=SIGINT && s!=SIGQUIT) return;
164 signal(SIGCHLD,sig_void);
165 on_free();
166 net_close();
167 msg_log("SIGTERM received. Exiting ...");
168 unlink(pid_file);
169 exit(0);
170 }
171
172
usage(char * s)173 void usage(char *s) {
174
175 fprintf(stderr,"Syntax: %s [-D] [-P pid_file] [-l log_file] [-c config_file]\n",s);
176
177 #ifdef WITH_MYSQL
178 fprintf(stderr," [-d dbfile|mysql] [-b ipv4_interface_address] [-p udp_port] \n");
179 #else
180 fprintf(stderr," [-d dbfile] [-b ipv4_interface_address] [-p udp_port] \n");
181 #endif
182
183 exit(0);
184 }
185
main(int argc,char * argv[])186 int main(int argc,char *argv[]) {
187
188 FILE *fp;
189 char str[128];
190 extern char *optarg;
191 extern int optreset;
192 extern int optind;
193 int c;
194
195 strcpy(logfile,DHISD_LOG);
196 strcpy(pid_file,DHISD_PID);
197 strcpy(database_file,DHISD_DB_FILE);
198 strcpy(conf_file,DHISD_CONF_FILE);
199
200 while((c=getopt(argc,argv,"Dhp:P:l:b:d:c:")) !=EOF) {
201 switch(c) {
202 case('c'): strcpy(conf_file,optarg);break;
203 }
204 }
205
206 read_conf();
207 optreset=1;
208 optind=1;
209
210 while((c=getopt(argc,argv,"Dhp:P:l:b:d:c:")) !=EOF) {
211 switch(c) {
212 case('l'):strcpy(logfile,optarg);break;
213 case('P'):strcpy(pid_file,optarg);break;
214 case('p'):udp_port=atoi(optarg);break;
215 case('b'):strcpy(dhisd_bind_address,optarg);break;
216 case('d'):strcpy(database_file,optarg);break;
217 case('D'):debug_level++;break;
218 case('h'): usage(argv[0]);
219 case('c'): strcpy(conf_file,optarg);break;
220 default: usage(argv[0]);
221 }
222 }
223
224
225 #ifdef WITH_MYSQL
226 if(!strcmp(database_file,"mysql")) db_mode=DB_MYSQL;
227 if(db_mode==DB_MYSQL && (sql_server[0]=='\0' || sql_user[0]=='\0'
228 || sql_password[0]=='\0' || sql_dbase[0]=='\0')) {
229 syslog(LOG_ERR,"Unable to read all SQL login parameters. Cannot start server! Exiting ...");
230 fprintf(stderr,"Unable to read all SQL login parameters. Cannot start server! Exiting ...\n");
231
232 exit(255);
233 }
234 #endif
235
236 #ifndef DONT_FORK
237 setsid();
238 if(fork()) _exit(0);
239 #endif
240
241 if(!db_reload()) {
242 #ifdef WITH_MYSQL
243 if(db_mode==DB_MYSQL) {
244
245 // If MySQL read failed we may need to wait for the mysql server
246 // to start. We try 3 times with 15 second intervals.
247 int count;
248 for(count=0;count<3;count++) {
249 sleep(15);
250 if(db_reload()) break;
251 }
252 if(count==3) {
253 syslog(LOG_ERR,"SQL database read failed: Please double-check your login data.");
254 exit(255);
255 }
256
257 } else {
258 #endif
259 syslog(LOG_ERR,"Unable to load database. Exiting ...");
260 exit(255);
261 #ifdef WITH_MYSQL
262 }
263 #endif
264 }
265
266
267 if(net_init()) {
268 syslog(LOG_ERR,"Unable to initialise network");
269
270 DSYSLOG(1,(LOG_DEBUG,"main(): Failed to initialise network\n"));
271
272 exit(255);
273 }
274
275 #ifndef DONT_FORK
276 close(0);
277 close(1);
278 close(2);
279 #endif
280
281 unlink(pid_file);
282 fp=fopen(pid_file,"w");
283 if(fp!=NULL) {
284 fprintf(fp,"%d",(int)getpid());
285 fclose(fp);
286 }
287
288
289
290 sprintf(str,"Datagram Server Started [%d]",(int)getpid());
291 msg_log(str);
292 syslog(LOG_INFO,"DHIS Server Started");
293
294 signal(SIGUSR1,sig_usr1);
295 signal(SIGUSR2,sig_usr2);
296 signal(SIGTERM,sig_term);
297 signal(SIGKILL,sig_term);
298 signal(SIGINT,sig_term);
299 signal(SIGQUIT,sig_term);
300 signal(SIGHUP,sig_hup);
301 signal(SIGALRM,sig_parse);
302 signal(SIGCHLD,sig_chld);
303 alarm(PARSE_TIMEOUT);
304
305
306 for(;;) {
307 msg_t msg;
308 int from;
309 if(net_check_message())
310 if(net_read_message(&msg,&from))
311 net_do_dgram(msg,from);
312
313 if(do_reload) {
314 db_reload();
315 do_reload=0;
316 }
317
318 if(do_parse) {
319 on_parse();
320 do_parse=0;
321 }
322 usleep(100000); // Sleep for 100 ms
323 }
324 }
325
326