ze-filter  (ze-filter-0.8.0-develop-180218)
ze-main.c
Go to the documentation of this file.
1 
2 /*
3  *
4  * ze-filter - Mail Server Filter for sendmail
5  *
6  * Copyright (c) 2001-2018 - Jose-Marcio Martins da Cruz
7  *
8  * Auteur : Jose Marcio Martins da Cruz
9  * jose.marcio.mc@gmail.org
10  *
11  * Historique :
12  * Creation : janvier 2002
13  *
14  * This program is free software, but with restricted license :
15  *
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20  *
21  * More details about ze-filter license can be found at ze-filter
22  * web site : http://foss.jose-marcio.org
23  */
24 
25 #include <ze-sys.h>
26 
27 #include "ze-filter.h"
28 
29 #define USE_SIGACTION 1
30 
32 
33 void usage(void);
34 void hardcoded_xfiles(void);
35 int j_survey();
36 
37 static pid_t pid_parent = 0;
38 static pid_t pid_filter = 0;
39 
40 static int DONE = FALSE;
41 
42 static void cleanup_after_configure();
43 
44 static time_t dt_cleanup_spool = 21600;
45 static time_t quarantine_max_age = 172800;
46 
47 static bool foreground = FALSE;
48 
49 
50 /* ****************************************************************************
51  * *
52  * *
53  ******************************************************************************/
54 
55 typedef struct {
56  char *name;
57  char *desc;
58  int log;
59  void (*fdump) ();
60 } table2log_T;
61 
63  {"regex", "Regular expressions used in pattern matching", FALSE,
65  {"iprbwl", "Real-time IP blacklists", FALSE, dump_iprbwl_table},
66  {"urlbl", "URLBL", FALSE, dump_urlbl_table},
67  {"oradata", "Oracle filter data", FALSE, dump_oradata_table},
68  {"oracle-checks", "Oracle checks", FALSE, dump_oracle_defs},
69  {"xfiles", "XFILES table", FALSE, dump_xfiles_table},
70  {NULL, NULL, FALSE, NULL}
71 };
72 
73 int
74 main(argc, argv)
75  int argc;
76  char *argv[];
77 {
78  int c;
79  const char *args = "p:i:u:hvc:l:t:mnzxqfoM:CV";
80  char s[256];
81 
82  int mkcf = MK_CF_NONE;
83 
85 
86  ze_logFacility = LOG_LOCAL5;
87 
88  openlog("ze-filter", LOG_PID | LOG_NOWAIT | LOG_NDELAY, ze_logFacility);
89 
91 
92  /*
93  * throttle_init (10000);
94  */
95 
96  /*
97  ** Process command line options
98  ** args
99  ** p : socket
100  ** inet:2000@localhost
101  ** local:/var/sock
102  ** i : 2000 (inet)
103  ** u : /var/sock
104  ** h : help
105  ** c : configuration file
106  ** l : log level
107  ** m : create configuration file
108  ** n : create configuration file from actual configuration
109  ** q : enable designated quarantine
110  ** v : version / compile time options
111  ** version / configuration file options
112  ** filter options
113  ** z : core dump enabled
114  */
115  while ((c = getopt(argc, argv, args)) != -1) {
116  switch (c) {
117  case 'h': /* OK */
118  cf_opt.arg_h = TRUE;
119  usage();
120  exit(0);
121  break;
122  case 'x':
123  ze_logLevel = 7;
125  exit(0);
126  break;
127  case 'v':
128  cf_opt.arg_v++;
130  break;
131 
132  case 'm':
133  mkcf = MK_CF_RUNNING;
135  break;
136 
137  case 'n':
138  mkcf = MK_CF_DEFAULT;
140  break;
141 
142  case 'M':
143  if (optarg != NULL) {
144  char *s = NULL;
145 
146  s = "nul";
147  if (STRNCASEEQUAL(optarg, s, strlen(s))) {
148  mkcf = MK_CF_NULL;
150  break;
151  }
152  s = "def";
153  if (STRNCASEEQUAL(optarg, s, strlen(s))) {
154  mkcf = MK_CF_DEFAULT;
156  break;
157  }
158  s = "run";
159  if (STRNCASEEQUAL(optarg, s, strlen(s))) {
160  mkcf = MK_CF_RUNNING;
162  break;
163  }
164  }
165  break;
166 
167  case 'C':
168  {
169  uint32_t i;
170 
171  printf("%s\n", ZE_CFARGS);
172 #if 1
173  i = PCRE_MAJOR << 16 | PCRE_MINOR << 8;
174  printf("%X\n", i);
175  printf("pcre %d.%d\n", PCRE_MAJOR, PCRE_MINOR);
176  i = DB_VERSION;
177  printf("%X\n", i);
178  printf("%s\n", DB_VERSION_STRING);
179 #endif
180  }
181  exit(0);
182  break;
183 
184  case 'V':
185  printf("%s\n", VERSION);
186  exit(0);
187  break;
188 
189  case 'q':
190  cf_opt.arg_q = TRUE;
191  break;
192 
193  /*
194  */
195  case 'c':
196  if (optarg == NULL || *optarg == '\0') {
197  (void) fprintf(stderr, "Erreur %s\n", optarg);
198  exit(EX_USAGE);
199  }
200  if (cf_opt.arg_c != NULL) {
201  ZE_MessageInfo(0, "Only one c option, please");
202  exit(EX_USAGE);
203  }
204  if ((cf_opt.arg_c = strdup(optarg)) == NULL) {
205  ZE_LogSysError("FATAL ERROR - memory allocation cf_opt.arg_c");
206  exit(1);
207  }
209  break;
210 
211  /*
212  */
213  /*
214  * definition socket
215  */
216  case 'p':
217  if (optarg == NULL || *optarg == '\0') {
218  (void) fprintf(stderr, "Illegal conn: %s\n", optarg);
219  exit(EX_USAGE);
220  }
221  cf_opt.arg_p = optarg;
222  break;
223  case 'u':
224  if (optarg == NULL || *optarg == '\0') {
225  (void) fprintf(stderr, "Erreur %s\n", optarg);
226  exit(EX_USAGE);
227  }
228  cf_opt.arg_u = optarg;
229  break;
230  case 'i':
231  if (optarg == NULL || *optarg == '\0') {
232  (void) fprintf(stderr, "Erreur %s\n", optarg);
233  exit(EX_USAGE);
234  }
235  cf_opt.arg_i = optarg;
236  break;
237 
238  /*
239  */
240  case 'd':
241  break;
242 
243  case 'f':
244  foreground = TRUE;
245  break;
246 
247  /*
248  */
249  case 'l':
250  if (optarg == NULL || *optarg == '\0') {
251  (void) fprintf(stderr, "Erreur %s\n", optarg);
252  exit(EX_USAGE);
253  }
254  if (cf_opt.arg_l != NULL) {
255  ZE_MessageInfo(0, "Only one l option, please");
256  exit(1);
257  }
258  if ((cf_opt.arg_l = strdup(optarg)) == NULL) {
259  ZE_LogSysError("FATAL ERROR - memory allocation cf_opt.arg_l");
260  exit(1);
261  }
262  break;
263  case 't':
264  if (optarg == NULL || *optarg == '\0') {
265  (void) fprintf(stderr, "Erreur %s\n", optarg);
266  exit(EX_USAGE);
267  } else {
268  table2log_T *p = tablog;
269 
270  while (p->name != NULL) {
271  if (strcasecmp(p->name, optarg) == 0) {
272  p->log = TRUE;
273  cf_opt.arg_t = TRUE;
274  break;
275  }
276  p++;
277  }
278  if (p->name == NULL) {
279  (void) fprintf(stderr, "Unknown table : %s\n", optarg);
280  exit(EX_USAGE);
281  }
282  ze_logLevel = 7;
283  }
284  break;
285 
286  case 'z':
287  cf_opt.arg_z = TRUE;
288  core_enabled = TRUE;
289  break;
290 
291  case 'o':
292  exit(0);
293  break;
294 
295  default:
296  (void) fprintf(stderr, "Error reading command line options : %c\n", c);
297  exit(1);
298  }
299  }
300 
301  if (cf_opt.arg_c != NULL)
303 
304  if (mkcf != MK_CF_NONE) {
305  ze_logLevel = 7;
306  if (mkcf == MK_CF_RUNNING)
307  configure("ze-filter", conf_file, TRUE);
308  mk_cf_file(STDOUT_FILENO, mkcf, TRUE);
309  closelog();
310  exit(0);
311  }
312 
313  if (!(cf_opt.arg_t || cf_opt.arg_v || cf_opt.arg_m))
314  ZE_MessageInfo(9, "Starting %s", PACKAGE);
315 
316  configure("ze-filter", conf_file, FALSE);
317 
319  cf_opt.arg_i);
320 
321  if (cf_opt.arg_v) {
322  /*
323  * dump_j_conf(STDOUT_FILENO);
324  */
325  dump_j_conf(-1);
326  closelog();
327  exit(0);
328  }
329 
330  {
331  table2log_T *t = tablog;
332  int log = FALSE;
333 
334  printf(" %s\n", PACKAGE);
335  printf(" Compiled on %s %s\n", __DATE__, __TIME__);
336  for (t = tablog; t->name != NULL; t++) {
337  if (t->log == TRUE) {
338  log = TRUE;
339  if (t->fdump != NULL)
340  t->fdump();
341  }
342  }
343  if (log) {
344  closelog();
345  exit(0);
346  }
347  }
348 
349  ZE_MessageInfo(9, "... Joe's ze-filter OK !");
350 
351  return j_survey();
352 }
353 
354 /* ****************************************************************************
355  * *
356  * *
357  ******************************************************************************/
358 
359 int pipe_filter[2];
360 int fd_pipe = -1;
361 
362 static int need_load_conf = FALSE;
363 static int DT_ALARM = DT_SIGALRM;
364 static int sighup_group = FALSE;
365 static int last_cleanup = 0;
366 
367 static RETSIGTYPE
368 father_signal_handler(signo)
369  int signo;
370 {
371  time_t now = time(NULL);
372  int msg;
373 
374 #if !USE_SIGACTION
375  signal(signo, father_signal_handler);
376 #endif
377 
378  ZE_MessageInfo(20, "*** Received SIGNAL %d : %s", signo, ctime(&now));
379 
380  switch (signo) {
381  case SIGTERM:
382  if (!DONE)
383  ZE_MessageInfo(10, " *** Terminate command received");
384  msg = MSG_TERM;
385  if (pid_filter > 0)
387  ZE_LogMsgDebug(20, "MSG SEND : %d", msg);
388  DONE = TRUE;
389  break;
390  case SIGUSR1:
391  ZE_MessageInfo(10, " *** Dump counters command received");
392  msg = MSG_DUMP;
393  if (pid_filter > 0)
395  ZE_LogMsgDebug(20, "MSG SEND : %d", msg);
396  break;
397  case SIGUSR2:
398  ZE_MessageInfo(10, " *** Reset counters command received");
399  reset_state();
400  msg = MSG_RESET;
401  if (pid_filter > 0)
403  ZE_LogMsgDebug(20, "MSG SEND : %d", msg);
404  break;
405  case SIGHUP:
406  ZE_MessageInfo(10, " *** Reload configuration files command received");
407  if (!sighup_group)
408  need_load_conf = TRUE;
409  sighup_group = FALSE;
410  break;
411  case SIGCHLD:
412  (void) WAIT_NOHANG(-1, NULL);
413  break;
414  case SIGALRM:
415  break;
416  default:
417  ZE_LogMsgWarning(0, "Undefined behavior for signal %d !", signo);
418  break;
419  }
420 }
421 
422 
423 /* ****************************************************************************
424  * *
425  * *
426  ******************************************************************************/
427 #define SET_SIG_HANDLER(handler) \
428  do { \
429  struct sigaction act; \
430  \
431  memset(&act, 0, sizeof (act)); \
432  act.sa_handler = SIG_IGN; \
433  sigaction(SIGPIPE, &act, NULL); \
434  \
435  act.sa_handler = handler; \
436  sigaction(SIGTERM, &act, NULL); \
437  sigaction(SIGUSR1, &act, NULL); \
438  sigaction(SIGUSR2, &act, NULL); \
439  sigaction(SIGALRM, &act, NULL); \
440  sigaction(SIGCHLD, &act, NULL); \
441  sigaction(SIGHUP, &act, NULL); \
442  sigaction(SIGCHLD, &act, NULL); \
443  } while (0);
444 
445 
446 bool
448 {
449 #if USE_SIGACTION
450  SET_SIG_HANDLER(father_signal_handler);
451 #else
452  signal(SIGPIPE, SIG_IGN);
453 
454  signal(SIGTERM, father_signal_handler);
455  signal(SIGUSR1, father_signal_handler);
456  signal(SIGUSR2, father_signal_handler);
457  signal(SIGHUP, father_signal_handler);
458  signal(SIGALRM, father_signal_handler);
459  signal(SIGCHLD, father_signal_handler);
460 #endif
461  return TRUE;
462 }
463 
464 
465 /* ****************************************************************************
466  * *
467  * *
468  ******************************************************************************/
469 int
470 j_set_uid_gid(user, group)
471  char *user;
472  char *group;
473 {
474  struct passwd *pw;
475  struct group *gr;
476  int res = 0;
477 
478  uid_t uid = getuid();
479  gid_t gid = getgid();
480 
481  if (uid != 0) {
482  ZE_LogMsgWarning(0, "Only root can set user and group");
483  return 0;
484  }
485 
486  if ((gr = getgrnam(group)) != NULL) {
487  ZE_LogMsgDebug(20, "GID DE %s : %ld", group, (long) gr->gr_gid);
488  if (gid == gr->gr_gid) {
489  ZE_LogMsgWarning(0, "ze-filter is already running as group %s", group);
490  } else {
491  if ((uid == 0) && (setregid(gr->gr_gid, gr->gr_gid) < 0)) {
492  ZE_LogSysError("Can't set process gid = %ld", (long) gr->gr_gid);
493  return 1;
494  }
495  }
496  } else {
497  ZE_LogSysError("Error getgrnam(%s)", group);
498  return 1;
499  }
500 
501  if ((pw = getpwnam(user)) != NULL) {
502  ZE_LogMsgDebug(20, "UID DE %s : %ld", user, (long) pw->pw_uid);
503  if (uid == pw->pw_uid) {
504  ZE_LogMsgWarning(0, "ze-filter is already running as user %s", user);
505  } else {
506  if ((uid == 0) && (setreuid(pw->pw_uid, pw->pw_uid) < 0)) {
507  ZE_LogSysError("Can't set process uid = %ld", (long) pw->pw_uid);
508  return 1;
509  }
510  }
511  } else {
512  ZE_LogSysError("Error getpwnam(%s)", user);
513  return 1;
514  }
515 
516  return res;
517 }
518 
519 /* ************************************
520  * *
521  * *
522  **************************************/
523 
524 int
526 {
527  char *user, *group;
528  int fd;
529 
530  if (!foreground) {
531  printf(" Let's daemonize ze-filter...\n");
532  switch (fork()) {
533  case 0:
534  printf(" ze-filter daemonized !\n");
535  break;
536  case -1:
537  perror(" Error daemonizing ze-filter ");
538  exit(1);
539  break;
540  default:
541  exit(0);
542  }
543  }
544 
545  if (setpgid(0, 0) < 0)
546  ZE_LogSysError("Can't set process group leader");
547 
548  if (!foreground) {
549  signal(SIGHUP, SIG_IGN);
550  switch (fork()) {
551  case 0:
552  break;
553  case -1:
554  perror(" Error daemonizing ze-filter ");
555  exit(1);
556  break;
557  default:
558  exit(0);
559  }
560 
562 
563  umask(0000);
564 
565  if ((fd = open("/dev/null", O_RDONLY, 0)) < 0)
566  ZE_LogSysError("Can't open /dev/null read-only");
567 
568  if (dup2(fd, STDIN_FILENO) < 0)
569  ZE_LogSysError("Can't redirect stdin");
570 
571  close(fd);
572 
573  if ((fd = open("/dev/null", O_WRONLY, 0)) < 0)
574  ZE_LogSysError("Can't open /dev/null write-only");
575 
576  if (dup2(fd, STDOUT_FILENO) < 0)
577  ZE_LogSysError("Can't redirect stdout");
578 
579  if (dup2(fd, STDERR_FILENO) < 0)
580  ZE_LogSysError("Can't redirect stderr");
581 
582  close(fd);
583  }
584 
585  /*
586  * Set user and group IDs
587  */
588  if ((user = cf_get_str(CF_USER)) == NULL || strlen(user) == 0)
589  user = RUN_AS_USER;
590  if ((group = cf_get_str(CF_GROUP)) == NULL || strlen(group) == 0)
591  group = RUN_AS_GROUP;
592  j_set_uid_gid(user, group);
593 
594  /*
595  * Change directory to work directory
596  */
597  /*
598  ** use cf_opt.arg_t instead of needing to change configuration file
599  */
600  {
601  char *workdir = cf_get_str(CF_WORKDIR);
602 
603  if (workdir == NULL || strlen(workdir) == 0)
604  workdir = ZE_WORKDIR;
605 
606  if (chdir(workdir) < 0) {
607  ZE_LogSysError("Can't do chdir(%s) : ", workdir);
608  exit(EX_SOFTWARE);
609  }
610  }
611 
613 
614  return 0;
615 }
616 
617 /* ****************************************************************************
618  * *
619  * *
620  ******************************************************************************/
621 static void
622 cleanup_after_configure()
623 {
625 
626  dt_cleanup_spool = cf_get_int(CF_CLEANUP_INTERVAL);;
627  quarantine_max_age = cf_get_int(CF_QUARANTINE_LIFETIME);
628 
629 #if 0
630  {
631  void *sh_buf;
632  SHMOBJ_T sh_obj;
633 
634  memset(&sh_obj, 0, sizeof (SHMOBJ_T));
635 
636  sh_buf =
637  open_shared_file(&sh_obj, "/var/ze-filter/files/ze-shared", 0x10000);
638 
639  close_shared_file(&sh_obj);
640 
641  }
642 #endif
643 }
644 
645 /* ****************************************************************************
646  * *
647  * *
648  ******************************************************************************/
649 #define TL_DIM 128
650 #define TL_DT 180
651 #define TL_MAX 5
652 
653 static time_t tlaunch[TL_DIM];
654 
655 static void
656 tlaunch_init()
657 {
658  time_t now;
659  int i;
660 
661  now = time(NULL) - TL_DT - 1;
662  for (i = 0; i < TL_DIM; i++)
663  tlaunch[i] = now;
664 }
665 
666 static bool
667 tlaunch_check()
668 {
669  int i, n;
670  time_t now = time(NULL);
671 
672  for (i = 0, n = 0; i < TL_DIM; i++)
673  if (tlaunch[i] + TL_DT > now)
674  n++;
675 
676  return n < TL_MAX;
677 }
678 
679 static int
680 tlaunch_count(tm)
681  int tm;
682 {
683  int i, n;
684  time_t now = time(NULL);
685 
686  for (i = 0, n = 0; i < TL_DIM; i++)
687  if (tlaunch[i] + tm > now)
688  n++;
689 
690  return n;
691 }
692 
693 static bool
694 tlaunch_register()
695 {
696  int i, n, tmin;
697  time_t now;
698 
699  if (!tlaunch_check())
700  return FALSE;
701 
702  now = time(NULL);
703  n = 0;
704  tmin = tlaunch[0];
705  for (i = 0; i < TL_DIM; i++) {
706  if (tlaunch[i] < tmin) {
707  n = i;
708  tmin = tlaunch[i];
709  }
710  }
711  tlaunch[n] = now;
712 
713  return TRUE;
714 }
715 
716 /* ****************************************************************************
717  * *
718  * *
719  ******************************************************************************/
720 #define MAX_SIG_ERR 64
721 
722 #define FD_SET_FLAG(fd,flag) \
723  do { \
724  int oflag; \
725  if ((oflag = fcntl(fd, F_GETFL, 0)) < 0) \
726  { \
727  ZE_LogSysError("fcntl F_GETFL error"); \
728  } else { \
729  /* Shall set write pipe to O_NONBLOCK mode ??? */ \
730  if (fcntl(fd, F_SETFL, oflag | flag) < 0) \
731  ZE_LogSysError("fcntl F_SETFL error"); \
732  } \
733  } while (0)
734 
735 int
737 {
738  pid_t res_filter = 0;
739  time_t now = time(NULL);
740  int nsigerr = 0;
741 
742  daemon_init();
743 
744  init_proc_state();
745 
746  pid_parent = getpid();
747 
749 
750  atexit(remove_pid_file);
751 
752  cleanup_after_configure();
753 
754  alarm(2 * DT_ALARM);
755 
757  ZE_LogMsgError(0, "can't setup signal handler");
758  exit(1);
759  }
760 
761  tlaunch_init();
762 
763  while (!DONE) {
764  if (fd_pipe >= 0) {
765  int msg = 0;
766 
767  ZE_MessageInfo(15, "Father will try to receive on fd = %d", fd_pipe);
768  while (recv_message_pipe(fd_pipe, &msg)) {
769  ZE_MessageInfo(15, "FATHER RECEIVED %3d", msg);
770  switch (msg) {
771  case MSG_OK:
772  break;
773  default:
774  break;
775  }
776  }
777  }
778 
779  if (pid_filter == 0) {
780  if (tlaunch_register()) {
781  int flag;
782 
783  close(pipe_filter[0]);
784  close(pipe_filter[1]);
785  fd_pipe = -1;
786  if (open_channel(pipe_filter) < 0) {
787  ZE_LogSysError("pipe(pipe_filter)");
788  exit(1);
789  }
790 
791  if ((pid_filter = fork()) == -1) {
792  ZE_LogSysError("Forking ze-filter");
793  exit(1);
794  }
795 
796  if (pid_filter == 0) {
797  struct sigaction act;
798 
799  close(pipe_filter[1]);
800  fd_pipe = pipe_filter[0];
801 
802 #if 1
803  FD_SET_FLAG(pipe_filter[0], O_NONBLOCK);
804 #else
805  if ((flag = fcntl(pipe_filter[0], F_GETFL, 0)) < 0) {
806  ZE_LogSysError("can't get pipe status");
807  } else {
808  if (fcntl(pipe_filter[0], F_SETFL, flag | O_NONBLOCK) < 0)
809  ZE_LogSysError("fcntl pipe_filter[0]");
810  }
811 #endif
812 
813  ZE_MessageInfo(15, "Child : pipe = %d %d", pipe_filter[0],
814  pipe_filter[1]);
815 
816  /*
817  ** It seems that FreeBSD doesn't like default SIGALRM behaviour
818  */
819  SET_SIG_HANDLER(SIG_DFL);
820 
821  return zeFilter();
822  }
823 
824  ZE_LogMsgDebug(20, "pid_filter : %ld", (long) pid_filter);
825 
826  close(pipe_filter[0]);
827  fd_pipe = pipe_filter[1];
828 
829 #if 1
830  FD_SET_FLAG(pipe_filter[1], O_NONBLOCK);
831 #else
832  if ((flag = fcntl(pipe_filter[1], F_GETFL, 0)) < 0) {
833  ZE_LogSysError("fcntl F_GETFL error");
834  } else {
835  /*
836  * Shall set write pipe to O_NONBLOCK mode ???
837  */
838  if (fcntl(pipe_filter[1], F_SETFL, flag | O_NONBLOCK) < 0)
839  ZE_LogSysError("fcntl F_SETFL error");
840  }
841 #endif
842  } else {
843  static time_t lastlog = 0;
844  static int n = 0;
845 
846  if (lastlog + 60 < now) {
848  "Spawning too fast : %d in less than %d secs (%d)",
849  tlaunch_count(TL_DT), TL_DT, n++);
850  lastlog = now;
851  }
852  }
853  }
854 
855  /*
856  * While not working, I'll wait here for the next signal...
857  */
858  sleep(DT_ALARM);
859 
860  now = time(NULL);
861 
862  /*
863  * send life signal
864  */
865  {
866  int msg = MSG_OK;
867 
868  if (pid_filter > 0)
870  ZE_MessageInfo(12, "%s : MSG SEND : %d", ZE_FUNCTION, msg);
871  }
872 
873  /*
874  * Well ! My boss want to reconfigure
875  */
876  if (need_load_conf) {
877  ZE_MessageInfo(9, "LETS RECONFIGURE...");
878 
879  configure("ze-filter", conf_file, FALSE);
880 
881  cleanup_after_configure();
882 
883  sighup_group = TRUE;
884  kill(0, SIGHUP);
885  need_load_conf = FALSE;
886  }
887 
888  /*
889  * Is ze-filter filter running ???
890  */
891  if (pid_filter > 0) {
892  int status = 0;
893 
894  res_filter = WAIT_NOHANG(-1, &status);
895 
896  ZE_MessageDebug(20, "%s : PID FILTER : %5d - RES %5d\n", ZE_FUNCTION,
897  pid_filter, res_filter);
898 
899  if (res_filter == -1) {
900  ZE_LogSysError("waitpid(pid_filter = %d) ", pid_filter);
901  if (errno == EINVAL && ++nsigerr > MAX_SIG_ERR) {
902  ZE_LogMsgError(0, "waitpid(pid_filter = %d - Too many errors) ",
903  pid_filter);
904  goto fin;
905  }
906  if (errno == ECHILD)
907  res_filter = pid_filter;
908  } else
909  nsigerr = 0;
910 
911  if (res_filter > 0) {
912  if (WIFSIGNALED(status)) {
913  int sig = WTERMSIG(status);
914 
915  ZE_MessageInfo(9, "Filter %d died after received signal %d",
916  res_filter, sig);
917  }
918 
919  if (WIFEXITED(status)) {
920  int ret = WEXITSTATUS(status);
921 
922  if (ret != 0)
923  ZE_MessageInfo(9, "Filter %d died and returned code %d", res_filter,
924  ret);
925  }
926  }
927 
928  /*
929  * does child died ?
930  */
931  if (res_filter == pid_filter) {
932  ZE_LogMsgWarning(0, "Filter died : doing clean-up to relaunch");
934  pid_filter = 0;
935  }
936  }
937 
938  /*
939  * cleans quarantine spool dir
940  */
941  if ((dt_cleanup_spool > 0) && (now > last_cleanup + dt_cleanup_spool)) {
942  char *spooldir = cf_get_str(CF_SPOOLDIR);
943 
944  cleanup_spool(spooldir, quarantine_max_age);
945  last_cleanup = time(NULL);
946  }
947  }
948 
949 fin:
950  now = time(NULL) + 5;
951  while (now > time(NULL) && pid_filter != 0) {
952  pid_t pid = pid_filter;
953 
954  pid = WAIT_NOHANG(-1, NULL);
955 
956  if (pid == -1 || pid == pid_filter)
957  break;
958 
959  sleep(1);
960  }
961 
962  remove_pid_file();
963 
964  exit(0);
965 }
966 
967 /* ****************************************************************************
968  * *
969  * *
970  ******************************************************************************/
971 void
973 {
974  printf("Usage : ze-filter options\n %s\n"
975  " Compiled on %s %s\n"
976  " -p : socket\n"
977  " inet:2000@localhost\n"
978  " local:/var/sock\n"
979  " -i : 2000 (AF_INET)\n"
980  " -u : /var/sock (AF_UNIX)\n"
981  " -h : help\n"
982  " -c : configuration file\n"
983  " -l : log level\n"
984  " -m : create configuration file (running conf)\n"
985  " -n : create configuration file (default)\n"
986  " -M : create configuration file (default)\n"
987  " null : null filter configuration\n"
988  " default : configuration with minimal features enabled\n"
989  " running : current filter configuration\n"
990  " -v : version / runtime configuration\n"
991  " -vv : version / compile time configuration\n"
992  " -C : configure options\n"
993  " -x : compile time X-FILES definition\n"
994  " -t tablename, where tablename choosen between : \n",
995  PACKAGE, __DATE__, __TIME__);
996 
997  {
998  table2log_T *p = tablog;
999 
1000  /*
1001  * printf(" ");
1002  */
1003  while (p->name != NULL) {
1004  printf(" %-16s %s\n", p->name, p->desc);
1005  /*
1006  * printf("%s %s ", p == tablog ? "" : "|", p->name);
1007  */
1008  p++;
1009  }
1010  printf("\n");
1011  }
1012  printf("\n %s\n %s\n\n", PACKAGE, COPYRIGHT);
1013 }
1014 
1015 /* ****************************************************************************
1016  * *
1017  * *
1018  ******************************************************************************/
1019 typedef struct xfilesdef_T xfilesdef_T;
1020 
1021 struct xfilesdef_T {
1022  char *ext;
1023  char *label;
1024  char *origin;
1025 };
1026 
1027 #include <xfilesdef.h>
1028 
1029 void
1031 {
1032  xfilesdef_T *p = xfilesdef;
1033 
1034  printf("ze-filter compile-time xfile definitions\n %s\n"
1035  " Compiled on %s %s\n\n", PACKAGE, __DATE__, __TIME__);
1036 
1037  printf(" Ext ORIGIN File Type\n"
1038  " ------------------------------------------------------\n");
1039 
1040  for (p = xfilesdef; p->ext != NULL; p++)
1041  printf(" %-5s %-12s %s\n", p->ext, p->origin, p->label);
1042  printf("\n %s\n\n", COPYRIGHT);
1043 }
#define CF_SPOOLDIR
Definition: cfh-defs.h:68
char * arg_p
Definition: ze-config.h:44
#define WEXITSTATUS(stat_val)
Definition: ze-sys.h:305
bool core_enabled
Definition: ze-main.c:31
#define MSG_TERM
Definition: ze-main.h:31
#define MK_CF_NULL
Definition: ze-cf.h:40
bool setup_supervisor_signal_handler()
Definition: ze-main.c:447
#define VERSION
Definition: version.h:25
void dump_regex_table()
Definition: ze-mailregex.c:103
#define CF_GROUP
Definition: cfh-defs.h:38
bool enable_coredump(bool)
Definition: ze-resource.c:334
void dump_urlbl_table()
Definition: ze-dns-urlbl.c:396
#define ZE_FUNCTION
Definition: ze-sys.h:471
char * define_milter_sock(char *cf, char *p, char *u, char *i)
char * arg_l
Definition: ze-config.h:48
int open_channel(int *)
Definition: ze-ipc.c:39
#define ZE_WORKDIR
Definition: defs.h:33
bool arg_m
Definition: ze-config.h:41
#define COPYRIGHT
Definition: version.h:31
void dump_j_conf(int)
Definition: ze-config.c:748
int ze_logLevel
Definition: zeSyslog.c:34
#define TL_DIM
Definition: ze-main.c:649
#define STRNCASEEQUAL(a, b, n)
Definition: macros.h:75
bool arg_z
Definition: ze-config.h:51
int pipe_filter[2]
Definition: ze-main.c:359
int ze_logFacility
Definition: zeSyslog.c:35
int j_survey()
Definition: ze-main.c:736
void dump_iprbwl_table()
bool recv_message_pipe(int, int *)
Definition: ze-ipc.c:158
void zeLog_SetOutput(bool, bool)
Definition: zeSyslog.c:490
#define WIFEXITED(stat_val)
Definition: ze-sys.h:308
#define FALSE
Definition: macros.h:160
void mk_cf_file(int, bool, bool)
Definition: ze-cf.c:353
#define ZE_LogMsgError(level,...)
Definition: zeSyslog.h:113
void(* fdump)()
Definition: ze-main.c:59
#define MK_CF_DEFAULT
Definition: ze-cf.h:41
char * label
Definition: ze-main.c:1023
int fd_pipe
Definition: ze-main.c:360
void init_proc_state()
Definition: ze-stats.c:502
#define WAIT_NOHANG(pid, stat)
Definition: macros.h:30
void usage(void)
Definition: ze-main.c:972
int cf_get_int(int id)
Definition: ze-cf.c:803
char * arg_c
Definition: ze-config.h:47
char * name
Definition: ze-main.c:56
void dump_xfiles_table()
Definition: ze-fileexp.c:398
#define CHAN_FATHER
Definition: ze-ipc.h:27
#define ZE_MessageDebug(level,...)
Definition: zeSyslog.h:89
#define CF_USER
Definition: cfh-defs.h:37
#define FD_SET_FLAG(fd, flag)
Definition: ze-main.c:722
void init_default_file_extensions()
Definition: ze-fileexp.c:195
table2log_T tablog[]
Definition: ze-main.c:62
#define MSG_RESET
Definition: ze-main.h:33
bool arg_h
Definition: ze-config.h:38
char * arg_u
Definition: ze-config.h:46
char * desc
Definition: ze-main.c:57
#define CF_PID_FILE
Definition: cfh-defs.h:69
#define ZE_LogMsgDebug(level,...)
Definition: zeSyslog.h:109
char * ext
Definition: ze-main.c:1022
int j_set_uid_gid(char *user, char *group)
Definition: ze-main.c:470
#define RUN_AS_GROUP
Definition: defs.h:28
int arg_v
Definition: ze-config.h:39
#define ZE_MessageInfo(level,...)
Definition: zeSyslog.h:90
#define MSG_OK
Definition: ze-main.h:30
#define DB_VERSION
Definition: zeDb.h:32
#define TRUE
Definition: macros.h:157
#define ZE_MessageWarning(level,...)
Definition: zeSyslog.h:92
int log
Definition: ze-main.c:58
bool create_pid_file(char *fname)
bool arg_t
Definition: ze-config.h:50
void dump_oradata_table()
Definition: ze-oracle.c:69
OPT_REC_T cf_opt
Definition: ze-config.c:40
#define ZE_LogSysError(...)
Definition: zeSyslog.h:129
void dump_oracle_defs()
#define DT_SIGALRM
Definition: ze-main.h:28
void remove_milter_sock()
void cleanup_spool(char *, unsigned long)
Definition: ze-cleanspool.c:36
char * cf_get_str(int id)
Definition: ze-cf.c:854
char * conf_file
Definition: ze-cf.c:38
#define ZE_CFARGS
Definition: defs.h:66
char * arg_i
Definition: ze-config.h:45
void reset_state()
Definition: ze-stats.c:528
#define RUN_AS_USER
Definition: defs.h:25
#define ZE_LogMsgWarning(level,...)
Definition: zeSyslog.h:112
int configure(char *, char *, bool)
Definition: ze-cf.c:1203
int daemon_init()
Definition: ze-main.c:525
#define PACKAGE
Definition: version.h:28
#define TL_DT
Definition: ze-main.c:650
#define MK_CF_RUNNING
Definition: ze-cf.h:42
#define SET_SIG_HANDLER(handler)
Definition: ze-main.c:427
#define CF_CLEANUP_INTERVAL
Definition: cfh-defs.h:71
#define MSG_DUMP
Definition: ze-main.h:34
#define CF_QUARANTINE_LIFETIME
Definition: cfh-defs.h:72
char arg_q
Definition: ze-config.h:49
int zeFilter()
Definition: ze-filter.c:504
void remove_pid_file(void)
#define CF_SOCKET
Definition: cfh-defs.h:46
#define RETSIGTYPE
Definition: config.h:815
#define MAX_SIG_ERR
Definition: ze-main.c:720
char * workdir
#define CF_WORKDIR
Definition: cfh-defs.h:67
int main(int argc, argv)
Definition: ze-main.c:74
long uint32_t
Definition: ze-sys.h:489
int msg[MAX_SCORE+2]
Definition: ze-stats.c:41
#define MK_CF_NONE
Definition: ze-cf.h:39
int setup_file_descriptors()
Definition: ze-resource.c:240
char * origin
Definition: ze-main.c:1024
#define TL_MAX
Definition: ze-main.c:651
void hardcoded_xfiles(void)
Definition: ze-main.c:1030
int send_msg_channel(int[], int, int)