blob: 0901ebea27f499fda0fff92329c2bec680f09181 [file] [log] [blame]
/*
* Copyright (C) Tildeslash Ltd. All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations
* including the two.
*
* You must obey the GNU Affero General Public License in all respects
* for all of the code used other than OpenSSL.
*/
#include "config.h"
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STDARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SIGNAL_H
#include <signal.h>
#endif
#include "monit.h"
#include "event.h"
#include "net.h"
#include "alert.h"
// libmonit
#include "system/Time.h"
#include "util/Str.h"
/**
* Implementation of the alert module
*
* @file
*/
/* -------------------------------------------------------------- Prototypes */
static void copy_mail(Mail_T, Mail_T);
static void replace_bare_linefeed(Mail_T *);
static void substitute(Mail_T *, Event_T);
/* ------------------------------------------------------------------ Public */
/**
* Notify registred users about the event
* @param E An Event object
* @return If failed, return HANDLER_ALERT flag or HANDLER_SUCCEEDED if succeeded
*/
int handle_alert(Event_T E) {
Service_T s;
int rv = HANDLER_SUCCEEDED;
ASSERT(E);
s= Event_get_source(E);
if(!s) {
LogError("Aborting alert\n");
return rv;
}
if(s->maillist || Run.maillist) {
Mail_T m;
Mail_T n;
Mail_T list= NULL;
/*
* Build a mail-list with local recipients that has registered interest
* for this event.
*/
for(m= s->maillist; m; m= m->next) {
if(
/* particular event notification type is allowed for given recipient */
IS_EVENT_SET(m->events, Event_get_id(E)) &&
(
/* state change notification is sent always */
E->state_changed ||
/* in the case that the state is failed for more cycles we check
* whether we should send the reminder */
(E->state && m->reminder && E->count % m->reminder == 0)
)
)
{
Mail_T tmp= NULL;
NEW(tmp);
copy_mail(tmp, m);
substitute(&tmp, E);
replace_bare_linefeed(&tmp);
tmp->next= list;
list= tmp;
DEBUG("%s notification is sent to %s\n", Event_get_description(E), m->to);
}
}
/*
* Build a mail-list with global recipients that has registered interest
* for this event. Recipients which are defined in the service localy
* overrides the same recipient events which are registered globaly.
*/
for(m= Run.maillist; m; m= m->next) {
int skip= FALSE;
for(n= s->maillist; n; n= n->next) {
if(IS(m->to, n->to)) {
skip= TRUE;
break;
}
}
if(
/* the local service alert definition has not overrided the global one */
!skip &&
/* particular event notification type is allowed for given recipient */
IS_EVENT_SET(m->events, Event_get_id(E)) &&
(
/* state change notification is sent always */
E->state_changed ||
/* in the case that the state is failed for more cycles we check
* whether we should send the reminder */
(E->state && m->reminder && E->count % m->reminder == 0)
)
)
{
Mail_T tmp= NULL;
NEW(tmp);
copy_mail(tmp, m);
substitute(&tmp, E);
replace_bare_linefeed(&tmp);
tmp->next= list;
list= tmp;
DEBUG("%s notification is sent to %s\n", Event_get_description(E), m->to);
}
}
if(list) {
if(!sendmail(list))
rv = HANDLER_ALERT;
gc_mail_list(&list);
}
}
return rv;
}
static void substitute(Mail_T *m, Event_T e) {
char timestamp[STRLEN];
ASSERT(m && e);
Util_replaceString(&(*m)->from, "$HOST", Run.localhostname);
Util_replaceString(&(*m)->subject, "$HOST", Run.localhostname);
Util_replaceString(&(*m)->message, "$HOST", Run.localhostname);
Time_string(e->collected.tv_sec, timestamp);
Util_replaceString(&(*m)->subject, "$DATE", timestamp);
Util_replaceString(&(*m)->message, "$DATE", timestamp);
Util_replaceString(&(*m)->subject, "$SERVICE", Event_get_source_name(e));
Util_replaceString(&(*m)->message, "$SERVICE", Event_get_source_name(e));
Util_replaceString(&(*m)->subject, "$EVENT", Event_get_description(e));
Util_replaceString(&(*m)->message, "$EVENT", Event_get_description(e));
Util_replaceString(&(*m)->subject, "$DESCRIPTION", NVLSTR(Event_get_message(e)));
Util_replaceString(&(*m)->message, "$DESCRIPTION", NVLSTR(Event_get_message(e)));
Util_replaceString(&(*m)->subject, "$ACTION", Event_get_action_description(e));
Util_replaceString(&(*m)->message, "$ACTION", Event_get_action_description(e));
}
static void copy_mail(Mail_T n, Mail_T o) {
ASSERT(n && o);
n->to= Str_dup(o->to);
n->from=
o->from?
Str_dup(o->from):
Run.MailFormat.from?
Str_dup(Run.MailFormat.from):
Str_dup(ALERT_FROM);
n->replyto =
o->replyto?
Str_dup(o->replyto):
Run.MailFormat.replyto?
Str_dup(Run.MailFormat.replyto):
NULL;
n->subject=
o->subject?
Str_dup(o->subject):
Run.MailFormat.subject?
Str_dup(Run.MailFormat.subject):
Str_dup(ALERT_SUBJECT);
n->message=
o->message?
Str_dup(o->message):
Run.MailFormat.message?
Str_dup(Run.MailFormat.message):
Str_dup(ALERT_MESSAGE);
}
static void replace_bare_linefeed(Mail_T *m) {
Util_replaceString(&(*m)->message, "\r\n", "\n");
Util_replaceString(&(*m)->message, "\n", "\r\n");
}