new upstream release (3.3.0); modify package compatibility for Stretch
[ossec-hids.git] / src / monitord / generate_reports.c
1 /* Copyright (C) 2010 Trend Micro Inc.
2  * All right reserved.
3  *
4  * This program is a free software; you can redistribute it
5  * and/or modify it under the terms of the GNU General Public
6  * License (version 2) as published by the FSF - Free Software
7  * Foundation
8  */
9
10 #include "shared.h"
11 #include "monitord.h"
12
13 static const char *(monthss[]) = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
14                                   "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
15                                  };
16
17
18 void generate_reports(int cday, int cmon, int cyear)
19 {
20     int s = 0;
21
22     if (!mond.smtpserver) {
23         return;
24     }
25
26     if (mond.reports) {
27         int twait = 0;
28         int childcount = 0;
29
30         while (mond.reports[s]) {
31             pid_t pid;
32             if (mond.reports[s]->emailto == NULL) {
33                 s++;
34                 continue;
35             }
36
37             /* We create a new process to run the report and send the email.
38              * To avoid crashing monitord if something goes wrong.
39              */
40             pid = fork();
41             if (pid < 0) {
42                 merror("%s: ERROR: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno));
43                 s++;
44                 continue;
45             } else if (pid == 0) {
46                 char fname[256];
47                 char aname[256];
48                 fname[255] = '\0';
49                 aname[255] = '\0';
50                 snprintf(fname, 255, "/logs/.report-%d.log", getpid());
51
52                 merror("%s: INFO: Starting daily reporting for '%s'", ARGV0, mond.reports[s]->title);
53                 mond.reports[s]->r_filter.fp = fopen(fname, "w+");
54                 if (!mond.reports[s]->r_filter.fp) {
55                     merror("%s: ERROR: Unable to open temporary reports file.", ARGV0);
56                     s++;
57                     continue;
58                 }
59
60                 /* Open the log file */
61                 snprintf(aname, 255, "%s/%d/%s/ossec-%s-%02d.log",
62                          ALERTS, cyear, monthss[cmon], "alerts", cday);
63                 os_strdup(aname, mond.reports[s]->r_filter.filename);
64
65                 /* Start report */
66                 os_ReportdStart(&mond.reports[s]->r_filter);
67                 fflush(mond.reports[s]->r_filter.fp);
68
69                 fclose(mond.reports[s]->r_filter.fp);
70
71                 struct stat sb;
72                 int sr;
73                 if((sr = stat(fname, &sb)) < 0) {
74                     merror("Cannot stat %s: %s", fname, strerror(errno));
75                 }
76
77                 if (sb.st_size == 0) {
78                     merror("%s: INFO: Report '%s' empty.", ARGV0, mond.reports[s]->title);
79                 } else if (OS_SendCustomEmail2(mond.reports[s]->emailto,
80                                               mond.reports[s]->title,
81                                               mond.smtpserver,
82                                               mond.emailfrom,
83                                               mond.emailidsname,
84                                               fname)
85                            != 0) {
86                     merror("%s: WARN: Unable to send report email.", ARGV0);
87                 }
88
89                 if(unlink(fname) < 0) {
90                     merror("%s: ERROR: Cannot unlink file %s: %s", ARGV0, fname, strerror(errno));
91                 }
92
93                 free(mond.reports[s]->r_filter.filename);
94                 mond.reports[s]->r_filter.filename = NULL;
95
96                 exit(0);
97             } else {
98                 /* Sleep between each report. Time is not important in here. */
99                 sleep(20);
100                 childcount++;
101             }
102
103             s++;
104         }
105
106         while (childcount) {
107             int wp;
108             wp = waitpid((pid_t) - 1, NULL, WNOHANG);
109             if (wp < 0) {
110                 merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
111             } else if (wp == 0) {
112                 /* If there is still any report left, sleep 5 and try again */
113                 sleep(5);
114                 twait++;
115
116                 if (twait > 2) {
117                     merror("%s: WARN: Report taking too long to complete. Waiting for it to finish...", ARGV0);
118                     sleep(10);
119                     if (twait > 10) {
120                         merror("%s: WARN: Report took too long. Moving on...", ARGV0);
121                         break;
122                     }
123                 }
124             } else {
125                 childcount--;
126             }
127         }
128     }
129     return;
130 }
131