1 static const char rcsid[] = "$Id: main.c,v 1.20 2005/05/04 03:56:40 dengxf Exp $";
2
3 /*
4 * Copyright (c) 2003-2004 Deng XueFeng <dsnofe@hotmail.com>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Deng XueFeng.
18 * 4. Neither the name of the author nor the names of any co-contributors
19 * may be used to endorse or promote products derived from this software
20 * without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY DENG XUEFENG AND CONTRIBUTORS ``AS IS'' AND
23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <signal.h>
39 #include <syslog.h>
40 #include <stdarg.h>
41 #include <unistd.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <sys/types.h>
46 #include <sys/time.h>
47 #include <sys/wait.h>
48 #include <sys/resource.h>
49
50 #include "plcat.h"
51 #include "mylog.h"
52 #include "listen.h"
53 #include "pop3d.h"
54 #include "mydaemon.h"
55 #include "cfg.h"
56 #include "sig.h"
57
58 static int quit_flag = 0;
59
60 static char config_file[] = "/usr/local/etc/mps/pop3d.conf";
61 static char pid_file[] = "/var/run/mps.pid";
62 static int *pop3dpid = NULL;
63
64 int pop3d_port = 110;
65 int max_errs = 5;
66 int multi_process = 5;
67 int max_backlog = 32;
68 int max_client = 1000;
69 int max_timeout = 10 * 1000;
70 char serv_ip[16] = "";
71
72 int debug_flag = 0;
73 int pop3d_fd = 0;
74 int cur_process = 0;
75
76 extern int errno;
77
close_child(void)78 static void close_child(void)
79 {
80 kill(0, SIGINT);
81 }
82
sig_stop_handler(int signo)83 static void sig_stop_handler(int signo)
84 {
85 quit_flag = 1;
86 INFO("[INFO]: Received SIG%s and EXIT\n", sigs[signo-1]);
87 close_child();
88 }
89
sig_exit_handler(int signo)90 static void sig_exit_handler(int signo)
91 {
92 INFO("[INFO]: Received SIG%s and EXIT\n", sigs[signo-1]);
93 exit(EXIT_FAILURE);
94 }
95
sig_handler(int signo)96 static void sig_handler(int signo)
97 {
98 INFO("[INFO]: Received SIG%s\n", sigs[signo-1]);
99 }
100
pop3d_child(int id)101 static int pop3d_child(int id)
102 {
103 int pid;
104
105 pid = fork();
106 if (pid < 0) {
107 INFO("[INFO]: fork(2) Failed first time: %s", strerror(errno));
108 return (0);
109 } else if (pid == 0) {
110 signal(SIGINT, sig_exit_handler);
111 sleep(1);
112 pop3d(id);
113 return (1);
114 } else {
115 pop3dpid[id] = pid;
116 cur_process++;
117 return (1);
118 }
119 }
120
get_id(int pid)121 static int get_id(int pid)
122 {
123 int i;
124
125 i = 0;
126 while (i < multi_process) {
127 if (pop3dpid[i] == pid)
128 return (i);
129 i++;
130 }
131 INFO("[EXIT]: get_pid: failed get pid: %d\n", pid);
132 close_child();
133 return (multi_process);
134 }
135
sig_chld_handler(int signo)136 void sig_chld_handler(int signo)
137 {
138 int id;
139 pid_t pid;
140
141 INFO("[INFO]: Received SIG%s\n", sigs[signo-1]);
142 while((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
143 cur_process--;
144 if ((quit_flag == 0) && (debug_flag == 0)) {
145 id = get_id(pid);
146 pop3d_child(id);
147 }
148 }
149 }
150
parse_conf(const char * cfg_file)151 static int parse_conf(const char *cfg_file)
152 {
153 char *value;
154
155 if (init_conf(cfg_file) != 0)
156 return (-1);
157 if ((value = get_conf("Client_Max_Errors")) != NULL)
158 max_errs = atoi(value);
159 if ((value = get_conf("Client_Time_Out")) != NULL)
160 max_timeout = 1000 * atoi(value);
161 if ((value = get_conf("Per_Process_Max_Client")) != NULL)
162 max_client = atoi(value);
163 if ((value = get_conf("Multi_Process")) != NULL)
164 multi_process = atoi(value);
165 if ((value = get_conf("Max_Backlog")) != NULL)
166 max_backlog = atoi(value);
167 if ((value = get_conf("Server_Port")) != NULL)
168 pop3d_port = atoi(value);
169 if ((value = get_conf("Server_Address")) != NULL)
170 strncpy(serv_ip, value, sizeof(serv_ip));
171 if ((value = get_conf("Pid_File")) != NULL)
172 strncpy(pid_file, value, sizeof(pid_file));
173 close_conf();
174 return (0);
175 }
176
delpid(void)177 static void delpid(void)
178 {
179 unlink(pid_file);
180 }
181
savepid(void)182 static int savepid(void)
183 {
184 int fd;
185 int pid;
186 char str[12];
187
188 fd = open(pid_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
189 if (fd < 0)
190 return (errno);
191 pid = getpid();
192 sprintf(str, "%d\n", pid);
193 if (write(fd, str, strlen(str)) != (int)strlen(str)) {
194 pid = errno;
195 close(fd);
196 return (pid);
197 }
198 close(fd);
199 return (0);
200 }
201
checkpid(void)202 static int checkpid(void)
203 {
204 int fd;
205 int res;
206 int pid;
207 char str[12];
208
209 fd = open(pid_file, O_RDONLY);
210 if (fd < 0)
211 return (-1);
212 if ((res = read(fd, str, sizeof(str))) <= 0) {
213 close(fd);
214 return (-1);
215 }
216 close(fd);
217 str[res - 1] = 0x00;
218 pid = atoi(str);
219 res = kill(pid, 0);
220 if (res != 0) {
221 INFO("[-ERR]: kill(2) Failed: %s\n", strerror(errno));
222 return (-1);
223 }
224 return (pid);
225 }
226
myexit(void)227 static void myexit(void)
228 {
229 int res;
230
231 res = checkpid();
232 if (res > 0) {
233 kill(res, SIGUSR1);
234 printf("[INFO] POP3D IS STOPPED\n");
235 } else
236 printf("[INFO] POP3D IS NOT RUNNING\n");
237 }
238
usage(void)239 static void usage(void)
240 {
241 printf("Usage: mps [-c configfile] [-d] [-q]\n");
242 printf(" -c Specified configfile, default is /usr/local/etc/mps/pop3d.conf\n");
243 printf(" -d Debug Mod\n");
244 printf(" -q Quit\n");
245 exit(EXIT_FAILURE);
246 }
247
main(int argc,char ** argv)248 int main(int argc, char **argv)
249 {
250 char opt;
251 char cfg_file[256];
252 int err;
253 int i;
254
255 (void) memset(cfg_file, 0, sizeof(config_file));
256 while ((opt = getopt(argc, argv, "c:dq")) != -1) {
257 switch(opt) {
258 case 'c':
259 strlcpy(cfg_file, optarg, sizeof(cfg_file));
260 cfg_file[255] = '\0';
261 break;
262 case 'd':
263 debug_flag = 1;
264 break;
265 case 'q':
266 quit_flag = 1;
267 break;
268 default :
269 usage();
270 }
271 }
272 if (cfg_file[0] == '\0')
273 strlcpy(cfg_file, config_file, sizeof(cfg_file));
274 if (parse_conf(cfg_file) != 0)
275 usage();
276 if (quit_flag == 1) {
277 myexit();
278 exit(EXIT_SUCCESS);
279 }
280 if (checkpid() > 0) {
281 printf("[INFO] POP3D IS RUNNING NOW\n");
282 exit(EXIT_SUCCESS);
283 }
284 if (atexit(delpid) != 0) {
285 INFO("[INFO]: Register delpid Failed: %s\n", strerror(errno));
286 exit(EXIT_SUCCESS);
287 }
288 delpid();
289 if (debug_flag == 1)
290 multi_process = 1;
291 else
292 mydaemon();
293 if ((i = savepid()) != 0) {
294 INFO("[INFO]: savepid() Failed: %s\n", strerror(i));
295 exit(EXIT_FAILURE);
296 } else
297 INFO("[INFO]: savepid() Successful\n");
298
299 pop3dpid = malloc((multi_process+1) * sizeof(int));
300 if (pop3dpid == NULL) {
301 INFO("[-ERR]: malloc(3): %s\n", strerror(errno));
302 exit(EXIT_FAILURE);
303 }
304 memset(pop3dpid, 0, (multi_process+1) * sizeof(int));
305
306 pop3d_fd = newlisten(&err, serv_ip, pop3d_port, 10, max_backlog);
307 switch (pop3d_fd) {
308 case ERROR_PORT:
309 INFO("-ERR INVALID PORT: [%d].\n", pop3d_port);
310 exit(EXIT_FAILURE);
311 case ERROR_IP:
312 INFO("-ERR INVALID IP ADDRESS: [%s].\n", serv_ip);
313 exit(EXIT_FAILURE);
314 case ERROR_SOCKET:
315 INFO("-ERR CREATE SOCKET FAILED: [%s].\n", strerror(err));
316 exit(EXIT_FAILURE);
317 case ERROR_REUSE:
318 INFO("-ERR SETSOCKOPT REUSEADDR FAILED: [%s].\n", strerror(err));
319 exit(EXIT_FAILURE);
320 case ERROR_LINGER:
321 INFO("-ERR SETSOCKOPT LINGER FAILED: [%s].\n", strerror(err));
322 exit(EXIT_FAILURE);
323 case ERROR_BIND:
324 INFO("-ERR BIND SOCKET FAILED: [%s].\n", strerror(err));
325 exit(EXIT_FAILURE);
326 case ERROR_LISTEN:
327 INFO("-ERR LISTEN SOCKET FAILED: [%s].\n", strerror(err));
328 exit(EXIT_FAILURE);
329 default:
330 break;
331 }
332 signal(SIGILL, sig_exit_handler);
333 signal(SIGABRT, sig_exit_handler);
334 signal(SIGFPE, sig_exit_handler);
335 signal(SIGBUS, sig_exit_handler);
336 signal(SIGPIPE, sig_handler);
337 signal(SIGTERM, sig_stop_handler);
338 signal(SIGQUIT, sig_stop_handler);
339 signal(SIGINT, sig_handler);
340 signal(SIGUSR1, sig_stop_handler);
341 signal(SIGUSR2, sig_stop_handler);
342 signal(SIGCHLD, sig_chld_handler);
343 if (debug_flag == 1) {
344 signal(SIGTERM, sig_exit_handler);
345 signal(SIGQUIT, sig_exit_handler);
346 signal(SIGINT, sig_exit_handler);
347 signal(SIGUSR1, sig_exit_handler);
348 signal(SIGUSR2, sig_exit_handler);
349 pop3d(0);
350 return (0);
351 }
352
353 i = 0;
354 while (i < multi_process) {
355 if (pop3d_child(i) == 0) {
356 close_child();
357 goto WAIT_TO_EXIT;
358 }
359 i++;
360 }
361 WAIT_TO_EXIT:
362 while(1) {
363 sleep(30);
364 if (cur_process == 0)
365 break;
366 }
367 close(pop3d_fd);
368 INFO("EXIT SUCCESSFUL\n");
369 return (0);
370 }
371