diff -ru --exclude CVS monit.orig/event.c monit/event.c
--- monit.orig/event.c 2005-01-06 21:51:49.000000000 +0100
+++ monit/event.c 2005-07-29 12:25:27.000000000 +0200
@@ -59,6 +59,7 @@
{EVENT_PERMISSION, "Permission failed", "Permission passed"},
{EVENT_RESOURCE, "Resource limit matched", "Resource limit passed"},
{EVENT_SIZE, "Size failed", "Size passed"},
+ {EVENT_MATCH, "Regex match", "No regex match"},
{EVENT_TIMEOUT, "Timeout", "Timeout recovery"},
{EVENT_TIMESTAMP, "Timestamp failed", "Timestamp passed"},
{EVENT_UID, "UID failed", "UID passed"},
diff -ru --exclude CVS monit.orig/event.h monit/event.h
--- monit.orig/event.h 2005-01-06 21:51:49.000000000 +0100
+++ monit/event.h 2005-07-29 12:24:29.000000000 +0200
@@ -38,6 +38,7 @@
#define EVENT_EXEC 0x1000
#define EVENT_CHANGED 0x2000
#define EVENT_ICMP 0x4000
+#define EVENT_MATCH 0x8000
#define EVENT_DESCRIPTION(E) Event_get_description(E)
#define IS_EVENT_SET(value, mask) ((value & mask) != 0)
diff -ru --exclude CVS monit.orig/gc.c monit/gc.c
--- monit.orig/gc.c 2005-01-24 02:04:36.000000000 +0100
+++ monit/gc.c 2005-07-29 13:25:34.000000000 +0200
@@ -50,6 +50,7 @@
static void _gc_inf(Info_T *);
static void _gcpdl(Dependant_T *);
static void _gcso(Size_T *);
+static void _gcmatch(Match_T *);
static void _gcchecksum(Checksum_T *);
static void _gcperm(Perm_T *);
static void _gcuid(Uid_T *);
@@ -173,6 +174,9 @@
if((*s)->sizelist)
_gcso(&(*s)->sizelist);
+ if((*s)->matchlist)
+ _gcmatch(&(*s)->matchlist);
+
if((*s)->checksum)
_gcchecksum(&(*s)->checksum);
@@ -435,6 +439,22 @@
}
+static void _gcmatch(Match_T *s) {
+
+ ASSERT(s);
+
+ if((*s)->next)
+ _gcmatch(&(*s)->next);
+
+ if((*s)->action)
+ _gc_eventaction(&(*s)->action);
+
+ FREE((*s)->regex_string);
+ FREE((*s)->regex_comp);
+ FREE(*s);
+
+}
+
static void _gcchecksum(Checksum_T *s) {
diff -ru --exclude CVS monit.orig/http/cervlet.c monit/http/cervlet.c
--- monit.orig/http/cervlet.c 2005-04-05 21:52:57.000000000 +0200
+++ monit/http/cervlet.c 2005-07-29 13:36:12.000000000 +0200
@@ -111,6 +111,7 @@
static void print_service_rules_timestamp(HttpResponse, Service_T);
static void print_service_rules_device(HttpResponse, Service_T);
static void print_service_rules_size(HttpResponse, Service_T);
+static void print_service_rules_match(HttpResponse, Service_T);
static void print_service_rules_checksum(HttpResponse, Service_T);
static void print_service_rules_process(HttpResponse, Service_T);
static void print_service_params_port(HttpResponse, Service_T);
@@ -121,6 +122,7 @@
static void print_service_params_timestamp(HttpResponse, Service_T);
static void print_service_params_device(HttpResponse, Service_T);
static void print_service_params_size(HttpResponse, Service_T);
+static void print_service_params_match(HttpResponse, Service_T);
static void print_service_params_checksum(HttpResponse, Service_T);
static void print_service_params_process(HttpResponse, Service_T);
static void print_status(HttpRequest, HttpResponse);
@@ -774,6 +776,7 @@
print_service_params_timestamp(res, s);
print_service_params_device(res, s);
print_service_params_size(res, s);
+ print_service_params_match(res, s);
print_service_params_checksum(res, s);
print_service_params_process(res, s);
@@ -786,6 +789,7 @@
print_service_rules_timestamp(res, s);
print_service_rules_device(res, s);
print_service_rules_size(res, s);
+ print_service_rules_match(res, s);
print_service_rules_checksum(res, s);
print_service_rules_process(res, s);
@@ -1305,6 +1309,8 @@
out_print(res, "Resource ");
if(IS_EVENT_SET(r->events, EVENT_SIZE))
out_print(res, "Size ");
+ if(IS_EVENT_SET(r->events, EVENT_MATCH))
+ out_print(res, "Match ");
if(IS_EVENT_SET(r->events, EVENT_TIMEOUT))
out_print(res, "Timeout ");
if(IS_EVENT_SET(r->events, EVENT_TIMESTAMP))
@@ -1570,6 +1576,27 @@
}
}
+static void print_service_rules_match(HttpResponse res, Service_T s) {
+
+ if(s->matchlist) {
+
+ Match_T ml;
+ EventAction_T a;
+
+ for(ml= s->matchlist; ml; ml= ml->next) {
+
+ a= ml->action;
+
+
+ out_print(res,
+ "
Associated size | If match \"%s\" then %s |
",
+ ml->regex_string,
+ actionnames[a->failed->id]);
+
+ }
+ }
+}
+
static void print_service_rules_checksum(HttpResponse res, Service_T s) {
@@ -1963,6 +1990,25 @@
}
}
+static void print_service_params_match(HttpResponse res, Service_T s) {
+
+ if(s->type == TYPE_FILE) {
+
+ if(!Util_hasServiceStatus(s)) {
+
+ out_print(res,
+ "Match regex | - |
");
+
+ } else {
+
+ out_print(res,
+ "Match regex | %s |
",
+ (s->error & EVENT_MATCH)?" color='#ff0000'":"",
+ (s->error & EVENT_MATCH)?"yes":"no");
+ }
+ }
+}
+
static void print_service_params_checksum(HttpResponse res, Service_T s) {
diff -ru --exclude CVS monit.orig/l.l monit/l.l
--- monit.orig/l.l 2005-04-03 13:56:51.000000000 +0200
+++ monit/l.l 2005-07-29 11:57:24.000000000 +0200
@@ -234,6 +234,7 @@
perm(ission)? { return PERMISSION; }
exec(ute)? { return EXEC; }
size { return SIZE; }
+match { return MATCH; }
connection { return CONNECTION; }
unmonitor { return UNMONITOR; }
icmp { return ICMP; }
diff -ru --exclude CVS monit.orig/monit.pod monit/monit.pod
--- monit.orig/monit.pod 2005-04-05 21:52:57.000000000 +0200
+++ monit/monit.pod 2005-07-29 17:15:13.000000000 +0200
@@ -1237,6 +1237,13 @@
check file su with path /bin/su
if size != 95564 then exec "/sbin/ifconfig eth0 down"
+=over 4
+
+=item IF MATCH regex THEN action
+
+=back
+
+... blah ...
=head2 SPACE TESTING
diff -ru --exclude CVS monit.orig/monitor.h monit/monitor.h
--- monit.orig/monitor.h 2005-04-23 02:48:40.000000000 +0200
+++ monit/monitor.h 2005-07-29 14:13:22.000000000 +0200
@@ -553,6 +553,18 @@
EventAction_T action; /**< Description of the action upon event occurence */
} *Perm_T;
+/** Defines match object */
+typedef struct mymatch {
+ char *regex_string; /**< Match string */
+#ifdef HAVE_REGEX_H
+ regex_t *regex_comp; /**< Match compile */
+#endif
+ EventAction_T action; /**< Description of the action upon event occurence */
+
+ /** For internal use */
+ struct mymatch *next; /**< next match in chain */
+} *Match_T;
+
/** Defines uid object */
typedef struct myuid {
@@ -588,6 +600,7 @@
mode_t st_mode; /**< Permission */
uid_t st_uid; /**< Owner's uid */
gid_t st_gid; /**< Owner's gid */
+ ino_t st_ino; /**< Inode */
time_t timestamp; /**< Timestamp */
/* Device specific */
@@ -605,6 +618,8 @@
/* File specific */
size_t st_size; /**< Size */
+ size_t readpos; /**< Position for regex matching */
+ ino_t st_ino_prev; /**< Previous inode for regex matching */
char *cs_sum; /**< Checksum */
/* Process specific */
@@ -621,7 +636,6 @@
int cpu_percent; /**< pecentage * 10 */
int total_cpu_percent; /**< pecentage * 10 */
time_t uptime; /**< Process uptime */
-
} *Info_T;
@@ -660,6 +674,7 @@
Port_T portlist; /**< Portnumbers to check, either local or at a host */
Resource_T resourcelist; /**< Resouce check list */
Size_T sizelist; /**< Size check list */
+ Match_T matchlist; /**< Content Match list */
Timestamp_T timestamplist; /**< Timestamp check list */
Uid_T uid; /**< Uid check */
diff -ru --exclude CVS monit.orig/monitrc monit/monitrc
--- monit.orig/monitrc 2005-04-01 10:07:33.000000000 +0200
+++ monit/monitrc 2005-07-29 17:28:55.000000000 +0200
@@ -121,6 +121,8 @@
#
# size -- Must be followed by compare operator, number, optional
# a size unit and an action.
+#
+# match -- Must be followed by a regular expression and an action.
#
# every -- Only check the service at every n cycles.
#
diff -ru --exclude CVS monit.orig/p.y monit/p.y
--- monit.orig/p.y 2005-04-03 13:56:51.000000000 +0200
+++ monit/p.y 2005-07-29 13:27:00.000000000 +0200
@@ -150,6 +150,7 @@
static struct myuid uidset;
static struct myperm permset;
static struct mysize sizeset;
+ static struct mymatch matchset;
static struct myicmp icmpset;
static struct mymail mailset;
static struct myport portset;
@@ -188,6 +189,7 @@
static gid_t get_gid(char *, gid_t);
static void addchecksum(Checksum_T);
static void addperm(Perm_T);
+ static void addmatch(Match_T);
static void adduid(Uid_T);
static void addgid(Gid_T);
static void addeuid(uid_t);
@@ -257,7 +259,7 @@
%token TIMESTAMP CHANGED SECOND MINUTE HOUR DAY
%token SSLAUTO SSLV2 SSLV3 TLSV1 CERTMD5
%token BYTE KILOBYTE MEGABYTE GIGABYTE
-%token INODE SPACE PERMISSION SIZE
+%token INODE SPACE PERMISSION SIZE MATCH
%token EXEC UNMONITOR ICMP ICMPECHO NONEXIST INVALID DATA RECOVERED
%token URL CONTENT PID PPID
%token URLOBJECT
@@ -325,6 +327,7 @@
| gid
| checksum
| size
+ | match
| mode
| group
| depend
@@ -970,6 +973,7 @@
| PERMISSION { eventset |= EVENT_PERMISSION; }
| RESOURCE { eventset |= EVENT_RESOURCE; }
| SIZE { eventset |= EVENT_SIZE; }
+ | MATCH { eventset |= EVENT_MATCH; }
| TIMEOUT { eventset |= EVENT_TIMEOUT; }
| TIMESTAMP { eventset |= EVENT_TIMESTAMP; }
| UID { eventset |= EVENT_UID; }
@@ -1249,8 +1253,15 @@
}
;
+match : IF MATCH STRING THEN action1 recovery {
+ matchset.regex_string= xstrdup($3);
+ addeventaction(&(matchset).action, $5, $6);
+ addmatch(&matchset);
+ }
+ ;
+
size : IF SIZE operator NUMBER unit THEN action1 recovery {
- sizeset.operator= $3;
+ sizeset.operator= $4;
sizeset.size= ((unsigned long)$4 * $5);
addeventaction(&(sizeset).action, $7, $8);
addsize(&sizeset, FALSE);
@@ -1897,6 +1908,37 @@
}
+/*
+ * Set Perm object in the current service
+ */
+static void addmatch(Match_T ms) {
+
+ Match_T m;
+ int reg_return;
+
+ ASSERT(ms);
+
+#ifdef HAVE_REGEX_H
+ NEW(m);
+ NEW(m->regex_comp);
+
+ m->regex_string= ms->regex_string;
+ m->action= ms->action;
+ reg_return= regcomp(m->regex_comp, ms->regex_string, REG_NOSUB|REG_EXTENDED);
+
+ if (reg_return!=0) {
+ char errbuf[STRLEN];
+ regerror(reg_return, ms->regex_comp, errbuf, STRLEN);
+ yyerror2("regex parsing error:%s", errbuf);
+ }
+
+ m->next= current->matchlist;
+ current->matchlist= m;
+#else
+ yyerror2("regex matching requires regex support!", );
+#endif
+}
+
/*
* Set Uid object in the current service
diff -ru --exclude CVS monit.orig/util.c monit/util.c
--- monit.orig/util.c 2005-04-12 00:27:53.000000000 +0200
+++ monit/util.c 2005-07-29 15:45:42.000000000 +0200
@@ -1529,10 +1529,12 @@
*/
void Util_resetInfo(Service_T s) {
memset(s->inf, 0, sizeof *(s->inf));
- s->inf->_pid= -1;
- s->inf->_ppid= -1;
- s->inf->pid= -1;
- s->inf->ppid= -1;
+ s->inf->_pid= -1;
+ s->inf->_ppid= -1;
+ s->inf->pid= -1;
+ s->inf->ppid= -1;
+ s->inf->st_ino_prev= 0;
+ s->inf->readpos= 0;
}
diff -ru --exclude CVS monit.orig/validate.c monit/validate.c
--- monit.orig/validate.c 2005-05-11 23:28:02.000000000 +0200
+++ monit/validate.c 2005-08-01 14:32:47.000000000 +0200
@@ -102,6 +102,7 @@
static void check_gid(Service_T);
static void check_size(Service_T);
static void check_perm(Service_T);
+static void check_match(Service_T);
static int check_skip(Service_T);
static int check_timeout(Service_T);
static void check_checksum(Service_T);
@@ -282,6 +283,13 @@
return FALSE;
} else {
s->inf->st_mode= stat_buf.st_mode;
+ if (s->inf->st_ino==0) {
+ s->inf->st_ino_prev= stat_buf.st_ino;
+ s->inf->readpos= stat_buf.st_size;
+ } else {
+ s->inf->st_ino_prev= s->inf->st_ino;
+ }
+ s->inf->st_ino= stat_buf.st_ino;
s->inf->st_uid= stat_buf.st_uid;
s->inf->st_gid= stat_buf.st_gid;
s->inf->st_size= stat_buf.st_size;
@@ -319,6 +327,9 @@
if(s->timestamplist)
check_timestamp(s);
+ if(s->matchlist)
+ check_match(s);
+
return TRUE;
}
@@ -950,6 +961,95 @@
}
}
+/**
+ * Match content
+ */
+static void check_match(Service_T s) {
+ Match_T ml;
+ char line[STRLEN];
+ FILE *file;
+ int regex_return;
+ int inode_checked=FALSE;
+
+ ASSERT(s && s->matchlist);
+
+ while (TRUE) {
+ /* did inode change -> read position = 0 */
+ if((inode_checked==FALSE) && (s->inf->st_ino != s->inf->st_ino_prev)) {
+ s->inf->readpos= 0;
+ }
+ inode_checked= TRUE;
+
+ /* did file decrease (readpos > file_size) -> read position = 0 */
+ if(s->inf->readpos > s->inf->st_size) {
+ s->inf->readpos= 0;
+ }
+
+ /* Do we need to match? (readpos < file_size) */
+ if(!(s->inf->readpos < s->inf->st_size)){
+ break;
+ }
+
+ /* Open the file */
+ if(NULL==(file=fopen(s->path, "r"))) {
+ /* We can't open the file */
+ /* ==> ERROR */
+ break;
+ }
+
+ /* Seek to the read position */
+ if (fseek(file, s->inf->readpos, SEEK_SET)!=0) {
+ /* We can not seek to the read position */
+ /* ==> ERROR */
+ fclose(file);
+ break;
+ }
+
+ if(NULL==fgets(line, STRLEN-1, file)) {
+ /* We can not read the content! */
+ /* ==> ERROR */
+ fclose(file);
+ break;
+ }
+
+ /* Close the file */
+ fclose(file);
+
+ /* Empty line? Should not happen... but who knows */
+ if (strlen(line) == 0) {
+ /* ==> ERROR */
+ break;
+ }
+
+ /* Complete line oder just beginning? (igore full buffers) */
+ if ((strlen(line)<(STRLEN-1)) && (line[strlen(line)-1] != '\n')) {
+ /* we gonna read it next time */
+ break;
+ }
+
+ for(ml= s->matchlist; ml; ml= ml->next) {
+ regex_return=regexec(ml->regex_comp,
+ line,
+ 0,
+ NULL,
+ 0);
+
+ if(regex_return==0) {
+ /* We match! */
+ Event_post(s, EVENT_MATCH, TRUE, ml->action,
+ "'%s' content line matches regular expression",
+ s->name);
+
+ /* ==> more talkative! */
+ } else {
+ DEBUG("FILE: Regular expression does not match on content line\n");
+ }
+ }
+
+ /* Set read position to the end of last read */
+ s->inf->readpos+=strlen(line);
+ }
+}
/**
* Device test