alert.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C), 2000-2003 by Contributors to the monit codebase. 
00003  * All Rights Reserved.
00004  *
00005  * This program is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU General Public License as
00007  * published by the Free Software Foundation; either version 2 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful, but
00011  * WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * General Public License for more details.
00014  * 
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program; if not, write to the Free Software Foundation,
00017  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00018  */
00019 
00020 #include <config.h>
00021 
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <stdarg.h>
00025 
00026 #ifdef HAVE_STRING_H
00027 #include <string.h>
00028 #endif
00029 
00030 #include "monitor.h"
00031 #include "net.h"
00032 #include "alert.h"
00033 
00034 #define DO_TIMEOUT   0
00035 #define DO_RESTART   1
00036 #define DO_CHECKSUM  2
00037 #define DO_RESOURCE  3
00038 #define DO_STOP      4
00039 #define DO_FAILED    5
00040 #define DO_TIMESTAMP 6
00041 
00042 
00043 /* Private Prototypes */
00044 static int count(char *, char *);
00045 static void copy_mail(Mail_T, Mail_T);
00046 static void replace(char **, char *, char *);
00047 static void smtp_alert(Process_T, int, char *, va_list);
00048 static void substitute(Mail_T*, char *name, char *event);
00049 
00050 /* Private Variables */
00051 static char desc[][STRLEN]= {"timed out", "restarted", "checksum error", 
00052                              "matches resource limitation", "stopped",
00053                              "failed", "timestamp error"};
00054 
00055 static char desclog[][STRLEN]= {"Timeout", "Restart", "Checksum error", 
00056                                 "Resource limit matched", "Stop",
00057                                 "Failed", "Timestamp error"};
00058 
00059 
00075 /* ------------------------------------------------------------------ Public */
00076 
00077 
00084 void smtp_alert_timeout(Process_T p, char *m, ...) {
00085 
00086   va_list ap;
00087 
00088   ASSERT(p);
00089   
00090   va_start(ap, m);
00091   smtp_alert(p, DO_TIMEOUT, m, ap);
00092   va_end(ap);
00093   
00094   
00095 }
00096 
00097 
00104 void smtp_alert_checksum(Process_T p, char *m, ...) {
00105 
00106   va_list ap;
00107   
00108   ASSERT(p);
00109 
00110   va_start(ap, m);
00111   smtp_alert(p, DO_CHECKSUM, m, ap);
00112   va_end(ap);
00113   
00114 }
00115 
00116 
00122 void smtp_alert_restart(Process_T p, char *m, ...) {
00123 
00124   va_list ap;
00125   
00126   ASSERT(p);
00127 
00128   va_start(ap, m);
00129   smtp_alert(p, DO_RESTART, m, ap);
00130   va_end(ap);
00131   
00132 }
00133 
00134 
00140 void smtp_alert_resource(Process_T p, char *m, ...) {
00141 
00142   va_list ap;
00143   
00144   ASSERT(p);
00145 
00146   va_start(ap, m);
00147   smtp_alert(p, DO_RESOURCE, m, ap);
00148   va_end(ap);
00149   
00150 }
00151 
00152 
00158 void smtp_alert_stop(Process_T p, char *m, ...) {
00159 
00160   va_list ap;
00161   
00162   ASSERT(p);
00163 
00164   va_start(ap, m);
00165   smtp_alert(p, DO_STOP, m, ap);
00166   va_end(ap);
00167   
00168 }
00169 
00170 
00176 void smtp_alert_failed(Process_T p, char *m, ...) {
00177 
00178   va_list ap;
00179 
00180   ASSERT(p);
00181 
00182   va_start(ap, m);
00183   smtp_alert(p, DO_FAILED, m, ap);
00184   va_end(ap);
00185 
00186 }
00187 
00188 
00194 void smtp_alert_timestamp(Process_T p, char *m, ...) {
00195 
00196   va_list ap;
00197 
00198   ASSERT(p);
00199 
00200   va_start(ap, m);
00201   smtp_alert(p, DO_TIMESTAMP, m, ap);
00202   va_end(ap);
00203 
00204 }
00205 
00206 
00207 /* ----------------------------------------------------------------- Private */
00208 
00209 
00210 /*
00211  * Send a smtp notification 
00212  */
00213 static void smtp_alert(Process_T p, int event, char *optmsg, va_list ap) {
00214 
00215   ASSERT(p);
00216 
00217   if(p->maillist) {
00218 
00219     Mail_T m;
00220     sigset_t ns, os;
00221     Mail_T list= NULL;
00222 
00223     /* Set a SIGUSR1 block here */
00224     sigemptyset(&ns);
00225     sigaddset(&ns, SIGUSR1);
00226     pthread_sigmask(SIG_BLOCK, &ns, &os);
00227     
00228     /*
00229      * Build a mail-list with recipients that has registered interest
00230      * for this event.
00231      */
00232     for(m= p->maillist; m; m= m->next) {
00233       
00234       int notify[]= { m->alert_on_timeout,
00235               m->alert_on_restart,
00236               m->alert_on_checksum,
00237               m->alert_on_resource,
00238               m->alert_on_stop,
00239               m->alert_on_restart,
00240               m->alert_on_timestamp};
00241       
00242       if ( notify[event] ) {
00243 
00244     Mail_T tmp= NEW(tmp);
00245     
00246     copy_mail(tmp, m);
00247 
00248     if(optmsg)
00249         tmp->opt_message= format(optmsg, ap);
00250     
00251     substitute(&tmp, p->name, desc[event]);
00252     
00253     tmp->next= list;
00254     list= tmp;
00255     
00256         if ( Run.debug )
00257         log("%s notification is sent to %s\n", desclog[event], m->to);
00258 
00259       }
00260 
00261     }
00262 
00263     if(list) {
00264       
00265       sendmail(list);
00266       gc_mail_list(&list);
00267       
00268     }
00269 
00270     /* Release the SIGUSR1 block */
00271     pthread_sigmask(SIG_SETMASK, &os, NULL);
00272 
00273   }
00274   
00275 }
00276 
00277 
00278 static void substitute(Mail_T *m, char *name, char *event) {
00279 
00280   char *now= get_ctime();
00281   char *host= get_localhostname();
00282 
00283   ASSERT(m && name && event);
00284 
00285   replace(&(*m)->from, "$HOST", host);
00286   replace(&(*m)->subject, "$DATE", now);
00287   replace(&(*m)->message, "$DATE", now);
00288   replace(&(*m)->subject, "$HOST", host);
00289   replace(&(*m)->message, "$HOST", host);
00290   replace(&(*m)->subject, "$PROGRAM", name);
00291   replace(&(*m)->message, "$PROGRAM", name);
00292   replace(&(*m)->subject, "$EVENT", event);
00293   replace(&(*m)->message, "$EVENT", event);
00294  
00295   free(now);
00296   free(host);
00297 
00298 }
00299 
00300 
00301 static void replace(char **src, char *old, char *new) {
00302 
00303   int i;
00304   int d;
00305 
00306   ASSERT(src && old && new);
00307   
00308   i= count(*src, old);
00309   d= strlen(new)-strlen(old);
00310   
00311   if(i==0)
00312       return;
00313   if(d>0)
00314       d*= i;
00315   else
00316       d= 0;
00317   
00318   {
00319     char *p, *q;
00320     int l= strlen(old);
00321     char buf[strlen(*src)+d+1];
00322 
00323     q= *src;
00324     *buf= '\0';
00325     
00326     while((p= strstr(q, old))) {
00327       
00328       *p= '\0';
00329       strcat(buf, q);
00330       strcat(buf, new);
00331       p+= l;
00332       q= p;
00333       
00334     }
00335     
00336     strcat(buf, q);
00337     free(*src);
00338     *src= xstrdup(buf);
00339 
00340   }
00341   
00342 }
00343 
00344 
00345 static int count(char *src, char *needle) {
00346 
00347   int i= 0;
00348   char *p= src;
00349 
00350   ASSERT(src && needle);
00351   
00352   while((p= strstr(p, needle))) { i++;  p++; }
00353 
00354   return i;
00355 
00356 }
00357   
00358 
00359 static void copy_mail(Mail_T n, Mail_T o) {
00360 
00361   ASSERT(n && o);
00362   
00363   n->to= xstrdup(o->to);
00364   n->from=
00365       o->from?
00366       xstrdup(o->from):
00367       Run.MailFormat.from?
00368       xstrdup(Run.MailFormat.from):
00369       xstrdup(ALERT_FROM);
00370   n->subject=
00371       o->subject?
00372       xstrdup(o->subject):
00373       Run.MailFormat.subject?
00374       xstrdup(Run.MailFormat.subject):
00375       xstrdup(ALERT_SUBJECT);
00376   n->message=
00377       o->message?
00378       xstrdup(o->message):
00379       Run.MailFormat.message?
00380       xstrdup(Run.MailFormat.message):
00381       xstrdup(ALERT_MESSAGE);
00382   n->opt_message= NULL;
00383   
00384 }
00385