/* * Copyright (C), 2000-2007 by the monit project group. * All Rights Reserved. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License * along with this program. If not, see . */ #include #ifdef HAVE_STDIO_H #include #endif #ifdef HAVE_STDLIB_H #include #endif #ifdef HAVE_STDARG_H #include #endif #ifdef HAVE_STRING_H #include #endif #ifdef HAVE_UNISTD_H #include #endif #ifdef HAVE_SIGNAL_H #include #endif #include "monitor.h" #include "event.h" #include "net.h" #include "alert.h" /** * Implementation of the alert module * * @author Jan-Henrik Haukeland, * @author Martin Pala * @author Christian Hopp * * @version \$Id: alert.c,v 1.55 2007/07/25 12:54:28 hauk Exp $ * @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_PASSED if passed */ int handle_alert(Event_T E) { Service_T s; int rv = HANDLER_PASSED; 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; sigset_t ns, os; Mail_T list= NULL; set_signal_block(&ns, &os); /* * 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)) && ( /* 'changed/matched' event types are sent always */ E->id == EVENT_CHANGED || E->id == EVENT_MATCH || /* 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)) && ( /* 'changed' event type is sent always */ E->id == EVENT_CHANGED || E->id == EVENT_MATCH || /* 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); } unset_signal_block(&os); } 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); Util_getRFC822Date(&e->collected, timestamp, STRLEN); 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= xstrdup(o->to); n->from= o->from? xstrdup(o->from): Run.MailFormat.from? xstrdup(Run.MailFormat.from): xstrdup(ALERT_FROM); n->subject= o->subject? xstrdup(o->subject): Run.MailFormat.subject? xstrdup(Run.MailFormat.subject): xstrdup(ALERT_SUBJECT); n->message= o->message? xstrdup(o->message): Run.MailFormat.message? xstrdup(Run.MailFormat.message): xstrdup(ALERT_MESSAGE); } static void replace_bare_linefeed(Mail_T *m) { Util_replaceString(&(*m)->message, "\r\n", "\n"); Util_replaceString(&(*m)->message, "\n", "\r\n"); }