/* Copyright (C) 2010 Trend Micro Inc.
 * All right reserved.
 *
 * This program is a free software; you can redistribute it
 * and/or modify it under the terms of the GNU General Public
 * License (version 2) as published by the FSF - Free Software
 * Foundation
 */

#include "shared.h"
#include "monitord.h"

static const char *(monthss[]) = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
                                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
                                 };


void generate_reports(int cday, int cmon, int cyear)
{
    int s = 0;

    if (!mond.smtpserver) {
        return;
    }

    if (mond.reports) {
        int twait = 0;
        int childcount = 0;

        while (mond.reports[s]) {
            pid_t pid;
            if (mond.reports[s]->emailto == NULL) {
                s++;
                continue;
            }

            /* We create a new process to run the report and send the email.
             * To avoid crashing monitord if something goes wrong.
             */
            pid = fork();
            if (pid < 0) {
                merror("%s: ERROR: Fork failed. cause: %d - %s", ARGV0, errno, strerror(errno));
                s++;
                continue;
            } else if (pid == 0) {
                char fname[256];
                char aname[256];
                fname[255] = '\0';
                aname[255] = '\0';
                snprintf(fname, 255, "/logs/.report-%d.log", getpid());

                merror("%s: INFO: Starting daily reporting for '%s'", ARGV0, mond.reports[s]->title);
                mond.reports[s]->r_filter.fp = fopen(fname, "w+");
                if (!mond.reports[s]->r_filter.fp) {
                    merror("%s: ERROR: Unable to open temporary reports file.", ARGV0);
                    s++;
                    continue;
                }

                /* Open the log file */
                snprintf(aname, 255, "%s/%d/%s/ossec-%s-%02d.log",
                         ALERTS, cyear, monthss[cmon], "alerts", cday);
                os_strdup(aname, mond.reports[s]->r_filter.filename);

                /* Start report */
                os_ReportdStart(&mond.reports[s]->r_filter);
                fflush(mond.reports[s]->r_filter.fp);

                fclose(mond.reports[s]->r_filter.fp);

                struct stat sb;
                int sr;
                if((sr = stat(fname, &sb)) < 0) {
                    merror("Cannot stat %s: %s", fname, strerror(errno));
                }

                if (sb.st_size == 0) {
                    merror("%s: INFO: Report '%s' empty.", ARGV0, mond.reports[s]->title);
                } else if (OS_SendCustomEmail2(mond.reports[s]->emailto,
                                              mond.reports[s]->title,
                                              mond.smtpserver,
                                              mond.emailfrom,
                                              mond.emailidsname,
                                              fname)
                           != 0) {
                    merror("%s: WARN: Unable to send report email.", ARGV0);
                }

                if(unlink(fname) < 0) {
                    merror("%s: ERROR: Cannot unlink file %s: %s", ARGV0, fname, strerror(errno));
                }

                free(mond.reports[s]->r_filter.filename);
                mond.reports[s]->r_filter.filename = NULL;

                exit(0);
            } else {
                /* Sleep between each report. Time is not important in here. */
                sleep(20);
                childcount++;
            }

            s++;
        }

        while (childcount) {
            int wp;
            wp = waitpid((pid_t) - 1, NULL, WNOHANG);
            if (wp < 0) {
                merror(WAITPID_ERROR, ARGV0, errno, strerror(errno));
            } else if (wp == 0) {
                /* If there is still any report left, sleep 5 and try again */
                sleep(5);
                twait++;

                if (twait > 2) {
                    merror("%s: WARN: Report taking too long to complete. Waiting for it to finish...", ARGV0);
                    sleep(10);
                    if (twait > 10) {
                        merror("%s: WARN: Report took too long. Moving on...", ARGV0);
                        break;
                    }
                }
            } else {
                childcount--;
            }
        }
    }
    return;
}

