102 |
static void check_gid(Service_T); |
static void check_gid(Service_T); |
103 |
static void check_size(Service_T); |
static void check_size(Service_T); |
104 |
static void check_perm(Service_T); |
static void check_perm(Service_T); |
105 |
|
void check_match(Service_T); |
106 |
|
int check_match_ignore(Service_T, char *); |
107 |
|
void check_match_if(Service_T, char *); |
108 |
static int check_skip(Service_T); |
static int check_skip(Service_T); |
109 |
static int check_timeout(Service_T); |
static int check_timeout(Service_T); |
110 |
static void check_checksum(Service_T); |
static void check_checksum(Service_T); |
121 |
ProcessTree_T *oldptree=NULL; |
ProcessTree_T *oldptree=NULL; |
122 |
int oldptreesize=0; |
int oldptreesize=0; |
123 |
|
|
124 |
|
#define MATCH_LINE_LENGTH 512 |
125 |
|
|
126 |
/* ---------------------------------------------------------------- Public */ |
/* ---------------------------------------------------------------- Public */ |
127 |
|
|
286 |
return FALSE; |
return FALSE; |
287 |
} else { |
} else { |
288 |
s->inf->st_mode= stat_buf.st_mode; |
s->inf->st_mode= stat_buf.st_mode; |
289 |
|
if (s->inf->st_ino==0) { |
290 |
|
s->inf->st_ino_prev= stat_buf.st_ino; |
291 |
|
s->inf->readpos= stat_buf.st_size; |
292 |
|
} else { |
293 |
|
s->inf->st_ino_prev= s->inf->st_ino; |
294 |
|
} |
295 |
|
s->inf->st_ino= stat_buf.st_ino; |
296 |
s->inf->st_uid= stat_buf.st_uid; |
s->inf->st_uid= stat_buf.st_uid; |
297 |
s->inf->st_gid= stat_buf.st_gid; |
s->inf->st_gid= stat_buf.st_gid; |
298 |
s->inf->st_size= stat_buf.st_size; |
s->inf->st_size= stat_buf.st_size; |
330 |
if(s->timestamplist) |
if(s->timestamplist) |
331 |
check_timestamp(s); |
check_timestamp(s); |
332 |
|
|
333 |
|
if(s->matchlist) |
334 |
|
check_match(s); |
335 |
|
|
336 |
return TRUE; |
return TRUE; |
337 |
|
|
338 |
} |
} |
964 |
} |
} |
965 |
} |
} |
966 |
|
|
967 |
|
/** |
968 |
|
* Match content |
969 |
|
*/ |
970 |
|
void check_match(Service_T s) { |
971 |
|
char line[MATCH_LINE_LENGTH]; |
972 |
|
FILE *file; |
973 |
|
int inode_checked=FALSE; |
974 |
|
int advance=0; |
975 |
|
int ignore; |
976 |
|
|
977 |
|
ASSERT(s && s->matchlist); |
978 |
|
|
979 |
|
/* did inode change -> read position = 0 */ |
980 |
|
if((inode_checked==FALSE) && (s->inf->st_ino != s->inf->st_ino_prev)) { |
981 |
|
s->inf->readpos= 0; |
982 |
|
} |
983 |
|
inode_checked= TRUE; |
984 |
|
|
985 |
|
/* did file decrease (readpos > file_size) -> read position = 0 */ |
986 |
|
if(s->inf->readpos > s->inf->st_size) { |
987 |
|
s->inf->readpos= 0; |
988 |
|
} |
989 |
|
|
990 |
|
/* Do we need to match? (readpos < file_size) */ |
991 |
|
if(!(s->inf->readpos < s->inf->st_size)){ |
992 |
|
return; |
993 |
|
} |
994 |
|
|
995 |
|
/* Open the file */ |
996 |
|
if(NULL==(file=fopen(s->path, "r"))) { |
997 |
|
/* We can't open the file */ |
998 |
|
DEBUG("FILE: cannot open file %s: %s!\n", s->path, strerror(errno)); |
999 |
|
return; |
1000 |
|
} |
1001 |
|
|
1002 |
|
while (TRUE) { |
1003 |
|
ignore=FALSE; |
1004 |
|
|
1005 |
|
/* Seek to the read position */ |
1006 |
|
if (fseek(file, s->inf->readpos, SEEK_SET)!=0) { |
1007 |
|
/* We can not seek to the read position */ |
1008 |
|
DEBUG("FILE: cannot seek file %s: %s!\n", s->path, strerror(errno)); |
1009 |
|
goto final; |
1010 |
|
} |
1011 |
|
|
1012 |
|
if(NULL==fgets(line, MATCH_LINE_LENGTH, file)) { |
1013 |
|
/* We can not read the content! */ |
1014 |
|
if (!feof(file)) { |
1015 |
|
DEBUG("FILE: cannot read file %s: %s!\n", s->path, strerror(errno)); |
1016 |
|
} |
1017 |
|
goto final; |
1018 |
|
} |
1019 |
|
|
1020 |
|
/* Close the file */ |
1021 |
|
|
1022 |
|
/* Empty line? Should not happen... but who knows */ |
1023 |
|
if (strlen(line) == 0) { |
1024 |
|
/* ==> ERROR */ |
1025 |
|
goto final; |
1026 |
|
} |
1027 |
|
|
1028 |
|
/* Complete line oder just beginning? (igore full buffers) */ |
1029 |
|
if ((strlen(line)<(MATCH_LINE_LENGTH)-1) && |
1030 |
|
(line[strlen(line)-1] != '\n')) { |
1031 |
|
/* we gonna read it next time */ |
1032 |
|
goto final; |
1033 |
|
} |
1034 |
|
|
1035 |
|
advance=strlen(line); |
1036 |
|
|
1037 |
|
/* |
1038 |
|
Does this line end with '\n'? Otherwise ignore and check it |
1039 |
|
as soon as it is complete |
1040 |
|
*/ |
1041 |
|
if (strlen(line)==(MATCH_LINE_LENGTH)-1) { |
1042 |
|
int rv=0; |
1043 |
|
|
1044 |
|
while (((unsigned char) rv != '\n') && (rv!=EOF)) { |
1045 |
|
rv=fgetc(file); |
1046 |
|
advance++; |
1047 |
|
} |
1048 |
|
|
1049 |
|
if (rv==EOF) { |
1050 |
|
break; |
1051 |
|
} |
1052 |
|
} |
1053 |
|
|
1054 |
|
/* Set read position to the end of last read */ |
1055 |
|
s->inf->readpos+=advance; |
1056 |
|
|
1057 |
|
/* Remove appending newline */ |
1058 |
|
if (line[strlen(line)-1] == '\n') { |
1059 |
|
line[strlen(line)-1] = 0; |
1060 |
|
} |
1061 |
|
|
1062 |
|
check_match_if(s, line); |
1063 |
|
} |
1064 |
|
|
1065 |
|
final: |
1066 |
|
|
1067 |
|
fclose(file); |
1068 |
|
} |
1069 |
|
|
1070 |
|
/** |
1071 |
|
* Match line for "ignore" statements |
1072 |
|
*/ |
1073 |
|
int check_match_ignore(Service_T s, char *line) { |
1074 |
|
|
1075 |
|
int rv=FALSE; |
1076 |
|
Match_T ml; |
1077 |
|
Match_T prev=NULL; |
1078 |
|
int match_return; |
1079 |
|
|
1080 |
|
/* Check ignores */ |
1081 |
|
|
1082 |
|
for(ml= s->matchlist; ml; prev=ml, ml= ml->next) { |
1083 |
|
if (ml->ignore) { |
1084 |
|
#ifdef HAVE_REGEX_H |
1085 |
|
match_return=regexec(ml->regex_comp, |
1086 |
|
line, |
1087 |
|
0, |
1088 |
|
NULL, |
1089 |
|
0); |
1090 |
|
#else |
1091 |
|
if (strstr(line, ml->match_string) == NULL) { |
1092 |
|
match_return= -1; |
1093 |
|
} else { |
1094 |
|
match_return= 0; |
1095 |
|
} |
1096 |
|
#endif |
1097 |
|
if((match_return==0) ^ (ml->not)) { |
1098 |
|
/* We match! -> line is ignored! */ |
1099 |
|
DEBUG("FILE: Regular expression %s\"%s\" " |
1100 |
|
"ignore match on content line\n", |
1101 |
|
ml->not?"not ":"", |
1102 |
|
ml->match_string); |
1103 |
|
rv=TRUE; |
1104 |
|
break; |
1105 |
|
} |
1106 |
|
} |
1107 |
|
} |
1108 |
|
|
1109 |
|
/* Optimize match list => put recent match in front */ |
1110 |
|
|
1111 |
|
if (prev!=NULL && rv==TRUE) { |
1112 |
|
prev->next=ml->next; |
1113 |
|
ml->next=s->matchlist; |
1114 |
|
s->matchlist=ml; |
1115 |
|
} |
1116 |
|
|
1117 |
|
return rv; |
1118 |
|
} |
1119 |
|
|
1120 |
|
/** |
1121 |
|
* Match line for "if" statements |
1122 |
|
*/ |
1123 |
|
void check_match_if(Service_T s, char *line) { |
1124 |
|
|
1125 |
|
Match_T ml; |
1126 |
|
int match_return; |
1127 |
|
int ignore_tested= FALSE; |
1128 |
|
|
1129 |
|
/* Check non ignores */ |
1130 |
|
|
1131 |
|
for(ml= s->matchlist; ml; ml= ml->next) { |
1132 |
|
|
1133 |
|
if (!(ml->ignore)) { |
1134 |
|
|
1135 |
|
#ifdef HAVE_REGEX_H |
1136 |
|
match_return=regexec(ml->regex_comp, |
1137 |
|
line, |
1138 |
|
0, |
1139 |
|
NULL, |
1140 |
|
0); |
1141 |
|
#else |
1142 |
|
if (strstr(line, ml->match_string) == NULL) { |
1143 |
|
match_return= -1; |
1144 |
|
} else { |
1145 |
|
match_return= 0; |
1146 |
|
} |
1147 |
|
#endif |
1148 |
|
|
1149 |
|
if((match_return==0) ^ (ml->not)) { |
1150 |
|
/* Check if we have to test for ignores! */ |
1151 |
|
if (!ignore_tested && check_match_ignore(s, line)) { |
1152 |
|
return; |
1153 |
|
} |
1154 |
|
|
1155 |
|
Event_post(s, EVENT_MATCH, TRUE, ml->action, |
1156 |
|
"'%s' content match " |
1157 |
|
"[%s]", |
1158 |
|
s->name, line); |
1159 |
|
DEBUG("FILE: Regular expression %s\"%s\" " |
1160 |
|
"DOES match on content line\n", |
1161 |
|
ml->not?"not ":"", |
1162 |
|
ml->match_string); |
1163 |
|
} else { |
1164 |
|
DEBUG("FILE: Regular expression %s\"%s\" " |
1165 |
|
"does not match on content line\n", |
1166 |
|
ml->not?"not ":"", |
1167 |
|
ml->match_string); |
1168 |
|
} |
1169 |
|
} |
1170 |
|
} |
1171 |
|
|
1172 |
|
return; |
1173 |
|
} |
1174 |
|
|
1175 |
/** |
/** |
1176 |
* Device test |
* Device test |