summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorkuri igen <kuri@e4.enlightenment.org>2011-01-25 15:45:51 +0100
committerkuri igen <kuri@e4.enlightenment.org>2011-01-25 15:45:51 +0100
commitc2a6bb5b1a4ae437e11231ee637db262f78eb571 (patch)
tree426c0d60d5b551cb833db4463f6aa5bd1c43ec7f /src
Ajout des fichiers du projet smman
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am4
-rw-r--r--src/bin/Makefile.am8
-rw-r--r--src/bin/conf.c94
-rw-r--r--src/bin/conf.h33
-rw-r--r--src/bin/date.c47
-rw-r--r--src/bin/date.h31
-rw-r--r--src/bin/global.h96
-rw-r--r--src/bin/libconf.c232
-rw-r--r--src/bin/libconf.h66
-rw-r--r--src/bin/log.txt181
-rw-r--r--src/bin/logfiles.c209
-rw-r--r--src/bin/logfiles.h40
-rw-r--r--src/bin/logmessages.c184
-rw-r--r--src/bin/logmessages.h36
-rw-r--r--src/bin/main.c178
-rw-r--r--src/bin/main.h42
-rw-r--r--src/bin/rules.c291
-rw-r--r--src/bin/rules.h47
-rw-r--r--src/bin/send.c239
-rw-r--r--src/bin/send.h38
-rw-r--r--src/bin/spy.c355
-rw-r--r--src/bin/spy.h40
22 files changed, 2491 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..addf4ca
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,4 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3SUBDIRS = bin
4
diff --git a/src/bin/Makefile.am b/src/bin/Makefile.am
new file mode 100644
index 0000000..777e147
--- /dev/null
+++ b/src/bin/Makefile.am
@@ -0,0 +1,8 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3bin_PROGRAMS = smman
4
5smman_SOURCES = main.c rules.c spy.c logfiles.c send.c date.c conf.c logmessages.c libconf.c
6
7smman_LDFLAGS = @eina_LIBS@ @ecore_LIBS@ @libcurl_LIBS@
8smman_CPPFLAGS = -W -Wall -O2 -g @eina_CFLAGS@ @ecore_CFLAGS@ @libcurl_CFLAGS@ -DREVISION=\"@revision_number@\" -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS
diff --git a/src/bin/conf.c b/src/bin/conf.c
new file mode 100644
index 0000000..e3f0e43
--- /dev/null
+++ b/src/bin/conf.c
@@ -0,0 +1,94 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file conf.c
21 * @brief Manages configuration loading
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Manages configuration loading
26 */
27#include "conf.h"
28
29/**
30 * @fn int conf_load(void)
31 * @brief This function will init libconf and ask to load our configuration
32 * file
33 *
34 * @return 0
35 */
36int conf_load(void)
37{
38 struct libconfig myconf;
39
40 strcpy(global_ESserver, "http://192.168.2.84:9200/logstash/events/");
41 strcpy(global_rulesdir, "/etc/smman/rules.d/");
42 strcpy(global_conf, "/etc/smman/smman.conf");
43 strcpy(global_type, "syslog");
44 gethostname(global_host, sizeof(global_host));
45
46 einadom_rules = eina_log_domain_register("smman_rules" , EINA_COLOR_LIGHTRED);
47 einadom_spy = eina_log_domain_register("smman_spy" , EINA_COLOR_LIGHTRED);
48 einadom_logfiles = eina_log_domain_register("smman_logfiles", EINA_COLOR_LIGHTRED);
49 einadom_send = eina_log_domain_register("smman_send" , EINA_COLOR_LIGHTRED);
50 einadom_conf = eina_log_domain_register("smman_conf" , EINA_COLOR_LIGHTRED);
51
52 libconfig_init(global_conf, &myconf);
53 libconfig_load(&myconf);
54
55 libconfig_list(&myconf, conf_load_var);
56
57 libconfig_free(&myconf);
58 return(0);
59}
60
61/**
62 * @fn int conf_load_var(char *variable, char *value)
63 * @brief This function is a callback for libconf, and receives a variable +
64 * its value found in a configuration file
65 *
66 * @param variable (char *) Variable's name
67 * @param value (char *) Variable's value
68 *
69 * @return 0
70 */
71int conf_load_var(char *variable, char *value)
72{
73 if( !strcmp(variable, "server") )
74 {
75 EINA_LOG_DOM_DBG(einadom_conf, "Setting ES server to %s", variable);
76 strcpy(global_ESserver, value);
77 }
78 else if( !strcmp(variable, "host") )
79 {
80 EINA_LOG_DOM_DBG(einadom_conf, "Setting default hostname to %s", variable);
81 strcpy(global_host, value);
82 }
83 else if( !strcmp(variable, "type") )
84 {
85 EINA_LOG_DOM_DBG(einadom_conf, "Setting default type to %s", variable);
86 strcpy(global_type, value);
87 }
88 else
89 {
90 EINA_LOG_DOM_ERR(einadom_conf, "Unknown config variable %s", variable);
91 }
92
93 return(0);
94}
diff --git a/src/bin/conf.h b/src/bin/conf.h
new file mode 100644
index 0000000..cca8743
--- /dev/null
+++ b/src/bin/conf.h
@@ -0,0 +1,33 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file conf.h
21 * @brief Contains all includes and prototypes for conf.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for conf.c
26 */
27#include <unistd.h>
28
29#include "libconf.h"
30#include "global.h"
31
32int conf_load(void);
33int conf_load_var(char *variable, char *value);
diff --git a/src/bin/date.c b/src/bin/date.c
new file mode 100644
index 0000000..e39af8a
--- /dev/null
+++ b/src/bin/date.c
@@ -0,0 +1,47 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file date.c
21 * @brief Gets us the current date, like logstash does
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Gets us the current date, like logstash does
26 */
27
28#include "date.h"
29
30/**
31 * @fn char * timestamp_XML(char * date)
32 * @brief Gets us the current date, like logstash does
33 * @bug it doesnt get us date in UTC format, it gets us date on the system
34 *
35 * @param date (char *) Buffer where we will store the date
36 *
37 * @return 0
38 */
39char * timestamp_XML(char * date)
40{
41 time_t temps;
42 struct tm temp;
43 temps=time(NULL);
44 localtime_r(&temps,&temp);
45 sprintf(date,"%04d-%02d-%02dT%02d:%02d:%02d.000000Z",(temp.tm_year)+1900,(temp.tm_mon)+1,temp.tm_mday,temp.tm_hour,temp.tm_min,temp.tm_sec);
46 return(date);
47}
diff --git a/src/bin/date.h b/src/bin/date.h
new file mode 100644
index 0000000..64cc339
--- /dev/null
+++ b/src/bin/date.h
@@ -0,0 +1,31 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file date.h
21 * @brief Contains all includes and prototypes for date.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for date.c
26 */
27#include <time.h>
28#include <stdio.h>
29
30char * timestamp_XML(char * date);
31
diff --git a/src/bin/global.h b/src/bin/global.h
new file mode 100644
index 0000000..7728d68
--- /dev/null
+++ b/src/bin/global.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file global.h
21 * @brief Contains all global variables we need
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 * @todo It could be improved because not all structs are used everywhere.
25 *
26 * Contains all global variables we need
27 */
28#include <Eina.h>
29#include <Ecore.h>
30#include <Ecore_File.h>
31
32#ifndef GLOBALVARS
33#define GLOBALVARS
34char global_rulesdir[35], /**< Allows us to store the rules directory */
35 global_conf[35], /**< Allows us to store the configuration directory */
36 global_host[35], /**< Allows us to store the default hostname */
37 global_type[35], /**< Allows us to store the default type */
38 global_ESserver[128]; /**< Allows us to store ElasticSearch server adress */
39
40/**
41 * @struct rule
42 * @brief This structure can handle a rule described in the rule directory
43 */
44struct rule
45{
46 char *name, /**< Rule's name (Guessed using the filename of the rule inside the rules directory) */
47 *filename, /**< It is the filename of the logfile(s) that match this rule (see this as a condition) */
48 *message, /**< Regexp to apply to message we get from syslog, the match them (see this as a condition) */
49 *type, /**< Type we will apply to the matched log message (see this as an affectation) */
50 *source_host, /**< Host we will apply to the matched log message (see this as an affectation) */
51 *source_path, /**< Log path we will apply to the matched log message (its like renaming the log, without mv it) (see this as an affectation) */
52 *tags; /**< tags we will apply to the matched log message (see this as an affectation) */
53 int todel; /**< If set to something other than 0, every matched rule will not be indexed */
54};
55
56/**
57 * @struct logfile
58 * @brief This structure allows us to attach a cursor position to a logfile,
59 * which is necessary to find new log entries
60 */
61struct logfile
62{
63 char *name; /**< Name of the log file */
64 fpos_t cursor; /**< Position of the cursor inside this logfile */
65 unsigned long long int
66 filesize; /**< File size, only help to see if a logfile is truncated, as far as i know */
67};
68
69/**
70 * @struct logmessage
71 * @brief This structure Contains needed information about a logfile that is going
72 * to be JSONed for ES.
73 */
74struct logmessage
75{
76 char *source_host, /**< Hostname */
77 *source_path, /**< Name of the logfile from where this message comes from */
78 timestamp[30], /**< Date of the log */
79 *type, /**< Type of message */
80 *message; /**< Log message to index in ES */
81 Eina_List *list_tags; /**< List of tags associated to this message */
82 int todel; /**< If set to something other than 0, this message wont be indexed */
83};
84
85int einadom_rules, /**< Used for eina_log inside rules.c */
86 einadom_spy, /**< Used for eina_log inside spy.c */
87 einadom_logfiles, /**< Used for eina_log inside logfiles.c */
88 einadom_send, /**< Used for eina_log inside send.c */
89 einadom_conf; /**< Used for eina_log inside conf.c */
90
91Eina_List *list_rules; /**< Used to store all the rules in memory, in an eina list */
92Eina_List *list_logfiles; /**< Used to store all the logfiles watched, in an eina list */
93
94Ecore_File_Monitor *efm; /**< Used for file monitoring by ecore */
95
96#endif
diff --git a/src/bin/libconf.c b/src/bin/libconf.c
new file mode 100644
index 0000000..2ce1e5c
--- /dev/null
+++ b/src/bin/libconf.c
@@ -0,0 +1,232 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file libconf.c
21 * @brief Allows reading of a configuration file
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Allows reading of a configuration file.
26 * Every valid line of the configuration will be stored in an
27 * Eina list, and can be retrieved using callbacks
28 * @todo Being able to specify separation character between variable and value
29 *
30 */
31
32/**
33 * @page tutorial_libconf Libconf Documentation
34 * Libconf will allow you to parse basic configuration files of type :
35 *
36 * variable = value
37 *
38 *
39 * All you need to do is initialise the library, give fullpath to configuration
40 * file and read it.
41 *
42 * Example code :
43 * @code
44 * #include <libconf.h>
45 *
46 * int show_conf(char *variable, char *value)
47 * {
48 * printf("Variable=%s\tValue=%s\n", variable, value);
49 * return(0);
50 * }
51 *
52 * int main(int argc, char **argv)
53 * {
54 * if( argc < 2 ) return(1);
55 * struct libconfig myconf;
56 * eina_init();
57 * libconfig_init(argv[1], &myconf);
58 * libconfig_load(&myconf);
59 * libconfig_list(&myconf, show_conf);
60 * libconfig_free(&myconf);
61 * return(0);
62 * }
63 * @endcode
64 *
65 * @verbatim gcc -o main main.c `pkg-config --cflags libconf` `pkg-config --libs libconf` `pkg-config --cflags eina` @endverbatim
66 * @verbatim EINA_LOG_LEVEL=5 ./main /etc/docupack.conf@endverbatim
67 */
68#include "libconf.h"
69
70/**
71 * \fn int libconfig_init(char *file, struct libconfig *myconf)
72 * \brief Inits lib.
73 *
74 * \param file full path to configuration file
75 * \param myconf Pointer to a libconfig structure
76 * \return 0 if no error, 1 otherwise
77 */
78int libconfig_init(char *file, struct libconfig *myconf)
79{
80 strcpy(myconf->file, file);
81 myconf->lconfig = NULL;
82
83 ligconfig_einadom = eina_log_domain_register("Libconf", EINA_COLOR_ORANGE);
84
85 EINA_LOG_DOM_DBG(ligconfig_einadom, "Using configuration file %s", myconf->file);
86
87 return(0);
88}
89
90
91/**
92 * \fn int libconfig_load(struct libconfig *myconf)
93 * \brief Loads configuration file to store every variable into our Eina list
94 *
95 * \param myconf Pointer to a libconfig structure
96 * \return 0
97 */
98int libconfig_load(struct libconfig *myconf)
99{
100 FILE *fd;
101 char line[1024],
102 *ptr;
103 int nb;
104
105 EINA_LOG_DOM_DBG(ligconfig_einadom, "Loading configuration file");
106
107 fd = fopen(myconf->file, "r");
108 if( !fd )
109 {
110 EINA_LOG_DOM_ERR(ligconfig_einadom, "Can't open conf file \"%s\" : %s", myconf->file, strerror(errno));
111 return(-1);
112 }
113
114 while( 1 )
115 {
116 struct libconfig_entry *entrytmp;
117 int size;
118
119 nb = fscanf(fd, "%1024[^\n]\n", line);
120
121 // Did not got anything
122 if( nb != 1 )
123 break;
124
125 // Check if last char is '\r', if so we delete it
126 ptr = &line[strlen(line)-1];
127 if( ptr[0] == '\r' ) ptr[0] = 0;
128
129 // If this line is a comment, we go to next line
130 if( line[0] == '#' ) continue;
131
132 // We check that line has a '='
133 ptr = strchr(line, '=');
134 if( !ptr )
135 {
136 EINA_LOG_DOM_INFO(ligconfig_einadom, "Config entry is invalid : %s", line);
137 continue;
138 }
139
140 ptr[0] = 0;
141
142 ptr = &ptr[1];
143
144 // We delete undesired spaces
145 while( ( ptr[0] == 32 ) || ( ptr[0] == 9 ) )
146 ptr = &ptr[1];
147
148 size = strlen(ptr);
149 while( ( ptr[size-1] == 32 ) || ( ptr[size-1] == 9 ) )
150 {
151 ptr[size-1] = 0;
152 size = strlen(ptr);
153 }
154
155 size = strlen(line);
156 while( ( line[size-1] == 32 ) || ( line[size-1] == 9 ) )
157 {
158 line[size-1] = 0;
159 size = strlen(line);
160 }
161
162
163 entrytmp = malloc( sizeof(struct libconfig_entry) );
164
165 entrytmp->var = malloc( sizeof(char) * ( strlen(line) + 1 ) );
166 strcpy(entrytmp->var, line);
167
168 entrytmp->value = malloc( sizeof(char) * ( strlen(ptr) + 1 ) );
169 strcpy(entrytmp->value, ptr);
170
171 EINA_LOG_DOM_DBG(ligconfig_einadom, "Adding %s<->%s", entrytmp->var, entrytmp->value);
172 myconf->lconfig = eina_list_prepend(myconf->lconfig, entrytmp);
173 }
174
175 fclose(fd);
176
177 return(0);
178}
179
180/**
181 * \fn int libconfig_list(struct libconfig *myconf, int (*callback_function)(char *variable, char *value))
182 * \brief Will send to a callback every entry of the Eina list
183 *
184 * \param myconf Pointer to a libconfig structure
185 * \param callback_function Callback to call for each entry
186 * \return 0
187 */
188int libconfig_list(struct libconfig *myconf, int (*callback_function)(char *variable, char *value))
189{
190 Eina_List *l;
191 struct libconfig_entry *myentry;
192
193 EINA_LIST_FOREACH(myconf->lconfig, l, myentry)
194 callback_function(myentry->var, myentry->value);
195
196 return(0);
197}
198
199/**
200 * \fn int libconfig_free(struct libconfig *myconf)
201 * \brief Will free our eina list
202 *
203 * \param myconf Pointer to a libconfig structure
204 * \return 0
205 */
206int libconfig_free(struct libconfig *myconf)
207{
208 Eina_List *l;
209 struct libconfig_entry *myentry;
210
211 EINA_LIST_FOREACH(myconf->lconfig, l, myentry)
212 {
213 free(myentry->var);
214 free(myentry->value);
215 free(myentry);
216 }
217 eina_list_free(myconf->lconfig);
218 return(0);
219}
220
221/**
222 * @fn void libconfig_version(char *version)
223 * @brief Gets revision number of the library
224 *
225 * @param version buffer to use to store revision number
226 *
227 */
228void libconfig_version(char *version)
229{
230 strcpy(version, REVISION);
231 return;
232}
diff --git a/src/bin/libconf.h b/src/bin/libconf.h
new file mode 100644
index 0000000..a54a71e
--- /dev/null
+++ b/src/bin/libconf.h
@@ -0,0 +1,66 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file libconf.h
21 * @brief Contains structs and prototypes of libconf
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains structs and prototypes of libconf
26 *
27 */
28
29#include <string.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <unistd.h>
34#include <errno.h>
35#include <Eina.h>
36
37#ifndef LIBCONFVARS
38#define LIBCONFVARS
39/**
40 * \struct libconfig
41 * \brief Main structure
42 */
43struct libconfig
44{
45 char file[512]; /**< Name of config file */
46 Eina_List *lconfig; /**< List of variables */
47};
48
49/**
50 * \struct libconfig_entry
51 * \brief Structure containing information about one config entry
52 */
53struct libconfig_entry
54{
55 char *var, /**< Variable name */
56 *value; /**< Value for this variable */
57};
58
59int ligconfig_einadom; /**< Eina DOM to use for eina logs */
60#endif
61
62int libconfig_init(char *file, struct libconfig *myconf);
63int libconfig_load(struct libconfig *myconf);
64int libconfig_list(struct libconfig *myconf, int (*callback_function)(char *variable, char *value));
65int libconfig_free(struct libconfig *myconf);
66void libconfig_version(char *version);
diff --git a/src/bin/log.txt b/src/bin/log.txt
new file mode 100644
index 0000000..45d27e1
--- /dev/null
+++ b/src/bin/log.txt
@@ -0,0 +1,181 @@
1==22091== Memcheck, a memory error detector
2==22091== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
3==22091== Using Valgrind-3.6.0 and LibVEX; rerun with -h for copyright info
4==22091== Command: ./smman
5==22091==
6DBG<22091>:eina_module eina_module.c:709 eina_module_list_load() array 0x46b29b0, count 0
7DBG<22091>:eina_mempool eina_mempool.c:155 eina_mempool_register() be=0x42f2640, name=0x42ee351
8DBG<22091>:eina_mempool eina_mempool.c:155 eina_mempool_register() be=0x42f2660, name=0x42f15a3
9DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=list, options=
10DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=list, options=, mp=0x46b3020
11DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=list_accounting, options=
12DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=list_accounting, options=, mp=0x46b30e8
13DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=matrixsparse_cell, options=
14DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=matrixsparse_cell, options=, mp=0x46b4018
15DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=matrixsparse_row, options=
16DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=matrixsparse_row, options=, mp=0x46b40e8
17DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=rectangle-alloc, options=
18DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=rectangle-alloc, options=, mp=0x46b4338
19DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=rectangle, options=
20DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=rectangle, options=, mp=0x46b4408
21DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=QuadTree Item, options=
22DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=QuadTree Item, options=, mp=0x46b4550
23DBG<22091>:eina_mempool eina_mempool.c:337 eina_mempool_add() name=chained_mempool, context=QuadTree Root, options=
24DBG<22091>:eina_mempool eina_mempool.c:344 eina_mempool_add() name=chained_mempool, context=QuadTree Root, options=, mp=0x46b4620
25INF<22091>:ecore ecore_main.c:548 _ecore_main_loop_init() enter
26INF<22091>:ecore ecore_main.c:585 _ecore_main_loop_init() leave
27DBG<22091>:ecore ecore_time.c:152 _ecore_time_init() using CLOCK_MONOTONIC.
28DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626b0 (/usr/local/bin), slen=14
29DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626bf (/usr/bin), slen=8
30DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626c8 (/bin), slen=4
31DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626cd (/usr/local/sbin), slen=15
32DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626dd (/usr/sbin), slen=9
33DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626e7 (/sbin), slen=5
34DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626ed (/opt/java/jre/bin), slen=17
35DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed626ff (/usr/lib/perl5/vendor_perl/bin), slen=30
36DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed6271e (/usr/bin/core_perl), slen=18
37DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed62731 (/opt/qt/bin), slen=11
38DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed6273d (/usr/local/bin), slen=14
39DBG<22091>:eina_share eina_stringshare.c:658 eina_stringshare_add_length() str=0xbed6274c (/opt/e17/bin), slen=12
40INF<22091>:ecore ecore_main.c:193 _ecore_epoll_add() adding poll on 4 00000001
41DBG<22091>:Libconf libconf.c:85 libconfig_init() Using configuration file /etc/smman/smman.conf
42DBG<22091>:Libconf libconf.c:105 libconfig_load() Loading configuration file
43DBG<22091>:Libconf libconf.c:171 libconfig_load() Adding server<->http://localhost:9200/logstash/events/
44DBG<22091>:smman_conf conf.c:75 conf_load_var() Setting ES server to server
45DBG<22091>:smman_rules rules.c:55 rules_load() Found rule file tags_test
46DBG<22091>:Libconf libconf.c:85 libconfig_init() Using configuration file /etc/smman/rules.d/tags_test
47DBG<22091>:Libconf libconf.c:105 libconfig_load() Loading configuration file
48DBG<22091>:Libconf libconf.c:171 libconfig_load() Adding filename<->/var/log/slim.log
49DBG<22091>:Libconf libconf.c:171 libconfig_load() Adding tags<->test2,test3
50INF<22091>:smman_rules rules.c:191 rules_print()
51[tags_test]
52 filename = /var/log/slim.log
53 message = (null)
54 type = (null)
55 source_host = (null)
56 source_path = (null)
57 tags = test2,test3
58 delete = 0
59
60
61DBG<22091>:smman_spy spy.c:71 spy_addwatcher() Found 1 results for /var/log/slim.log
62INF<22091>:smman_logfiles logfiles.c:84 logfiles_print() Name = /var/log/slim.log Cursor = 100
63DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
64DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 100 !
65ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() ==22091== Use of uninitialised value of size 4
66==22091== at 0x43987B6: ??? (in /lib/libc-2.12.2.so)
67==22091== by 0x439BC48: vfprintf (in /lib/libc-2.12.2.so)
68==22091== by 0x439E3C1: ??? (in /lib/libc-2.12.2.so)
69==22091== by 0x4399312: vfprintf (in /lib/libc-2.12.2.so)
70==22091== by 0x42D561E: eina_log_print_cb_stderr (in /usr/lib/libeina.so.1.0.0)
71==22091== by 0x42D6CD3: eina_log_print (in /usr/lib/libeina.so.1.0.0)
72==22091== by 0x8049DA9: spy_extract_new_lines (spy.c:269)
73==22091== by 0x804A145: spy_event (spy.c:156)
74==22091== by 0x404F2CC: _ecore_file_monitor_inotify_handler (ecore_file_monitor_inotify.c:215)
75==22091== by 0x406E900: _ecore_main_loop_iterate_internal (ecore_main.c:1312)
76==22091== by 0x406EACE: ecore_main_loop_begin (ecore_main.c:663)
77==22091== by 0x80493A9: main (main.c:137)
78==22091==
79==22091== Conditional jump or move depends on uninitialised value(s)
80==22091== at 0x43987BE: ??? (in /lib/libc-2.12.2.so)
81==22091== by 0x439BC48: vfprintf (in /lib/libc-2.12.2.so)
82==22091== by 0x439E3C1: ??? (in /lib/libc-2.12.2.so)
83==22091== by 0x4399312: vfprintf (in /lib/libc-2.12.2.so)
84==22091== by 0x42D561E: eina_log_print_cb_stderr (in /usr/lib/libeina.so.1.0.0)
85==22091== by 0x42D6CD3: eina_log_print (in /usr/lib/libeina.so.1.0.0)
86==22091== by 0x8049DA9: spy_extract_new_lines (spy.c:269)
87==22091== by 0x804A145: spy_event (spy.c:156)
88==22091== by 0x404F2CC: _ecore_file_monitor_inotify_handler (ecore_file_monitor_inotify.c:215)
89==22091== by 0x406E900: _ecore_main_loop_iterate_internal (ecore_main.c:1312)
90==22091== by 0x406EACE: ecore_main_loop_begin (ecore_main.c:663)
91==22091== by 0x80493A9: main (main.c:137)
92==22091==
93==22091== Conditional jump or move depends on uninitialised value(s)
94==22091== at 0x439C1B0: vfprintf (in /lib/libc-2.12.2.so)
95==22091== by 0x439E3C1: ??? (in /lib/libc-2.12.2.so)
96==22091== by 0x4399312: vfprintf (in /lib/libc-2.12.2.so)
97==22091== by 0x42D561E: eina_log_print_cb_stderr (in /usr/lib/libeina.so.1.0.0)
98==22091== by 0x42D6CD3: eina_log_print (in /usr/lib/libeina.so.1.0.0)
99==22091== by 0x8049DA9: spy_extract_new_lines (spy.c:269)
100==22091== by 0x804A145: spy_event (spy.c:156)
101==22091== by 0x404F2CC: _ecore_file_monitor_inotify_handler (ecore_file_monitor_inotify.c:215)
102==22091== by 0x406E900: _ecore_main_loop_iterate_internal (ecore_main.c:1312)
103==22091== by 0x406EACE: ecore_main_loop_begin (ecore_main.c:663)
104==22091== by 0x80493A9: main (main.c:137)
105==22091==
106==22091== Conditional jump or move depends on uninitialised value(s)
107==22091== at 0x4399EAE: vfprintf (in /lib/libc-2.12.2.so)
108==22091== by 0x439E3C1: ??? (in /lib/libc-2.12.2.so)
109==22091== by 0x4399312: vfprintf (in /lib/libc-2.12.2.so)
110==22091== by 0x42D561E: eina_log_print_cb_stderr (in /usr/lib/libeina.so.1.0.0)
111==22091== by 0x42D6CD3: eina_log_print (in /usr/lib/libeina.so.1.0.0)
112==22091== by 0x8049DA9: spy_extract_new_lines (spy.c:269)
113==22091== by 0x804A145: spy_event (spy.c:156)
114==22091== by 0x404F2CC: _ecore_file_monitor_inotify_handler (ecore_file_monitor_inotify.c:215)
115==22091== by 0x406E900: _ecore_main_loop_iterate_internal (ecore_main.c:1312)
116==22091== by 0x406EACE: ecore_main_loop_begin (ecore_main.c:663)
117==22091== by 0x80493A9: main (main.c:137)
118==22091==
119FPOS 0 <-> 0
120DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
121DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:19.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
122DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
123DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 200 !
124ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
125DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
126DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:20.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
127DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
128DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 300 !
129ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
130DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
131DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:20.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
132DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
133DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 400 !
134ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
135DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
136DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:21.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
137DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
138DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 500 !
139ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
140DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
141DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:21.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
142DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
143DBG<22091>:smman_spy spy.c:148 spy_event() WTF TRUNC
144DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 0 !
145ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 74668116
146DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "", "@timestamp" : "2011-01-24T17:38:23.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
147DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
148DBG<22091>:smman_spy spy.c:148 spy_event() WTF TRUNC
149DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 0 !
150ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 74668116
151DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "", "@timestamp" : "2011-01-24T17:38:24.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
152DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
153DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 0 !
154ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
155DBG<22091>:smman_spy spy.c:293 spy_extract_new_lines() Empty line hack
156DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "** (gedit:6691): CRITICAL **: gedit_spell_checker_language_to_key: assertion `lang != NULL' failed", "@timestamp" : "2011-01-24T17:38:25.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
157DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
158DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 100 !
159ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
160DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "error 3: BadWindow (invalid Window parameter) request 20 minor 0 serial 13118263", "@timestamp" : "2011-01-24T17:38:33.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
161DBG<22091>:smman_spy spy.c:130 spy_event() Event on /var/log/slim.log ! 0x4735850 - 0x47358e0
162DBG<22091>:smman_spy spy.c:152 spy_event() Event on /var/log/slim.log - 678 !
163ERR<22091>:smman_spy spy.c:269 spy_extract_new_lines() FPOS 0 <-> 0
164DBG<22091>:smman_send send.c:74 send_logmessage() JSON : { "@source" : "file://Jetdail/var/log/slim.log", "@type" : "syslog", "@tags" : [ "test2","test3" ], "@fields" : { }, "@message" : "error 4: BadPixmap (invalid Pixmap parameter) request 54 minor 0 serial 13121431", "@timestamp" : "2011-01-24T17:38:33.000000Z", "@source_host" : "Jetdail", "@source_path" : "/var/log/slim.log"}
165==22091==
166==22091== HEAP SUMMARY:
167==22091== in use at exit: 80,900 bytes in 3,962 blocks
168==22091== total heap usage: 7,140 allocs, 3,178 frees, 622,324 bytes allocated
169==22091==
170==22091== LEAK SUMMARY:
171==22091== definitely lost: 0 bytes in 0 blocks
172==22091== indirectly lost: 0 bytes in 0 blocks
173==22091== possibly lost: 0 bytes in 0 blocks
174==22091== still reachable: 80,900 bytes in 3,962 blocks
175==22091== suppressed: 0 bytes in 0 blocks
176==22091== Reachable blocks (those to which a pointer was found) are not shown.
177==22091== To see them, rerun with: --leak-check=full --show-reachable=yes
178==22091==
179==22091== For counts of detected and suppressed errors, rerun with: -v
180==22091== Use --track-origins=yes to see where uninitialised values come from
181==22091== ERROR SUMMARY: 68 errors from 4 contexts (suppressed: 51 from 10)
diff --git a/src/bin/logfiles.c b/src/bin/logfiles.c
new file mode 100644
index 0000000..9865a7c
--- /dev/null
+++ b/src/bin/logfiles.c
@@ -0,0 +1,209 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file logfiles.c
21 * @brief Manages log files list
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Manages log files list
26 * @see logfile
27 * @see list_logfiles
28 */
29#include "logfiles.h"
30
31/**
32 * @fn int logfiles_exist(char *logfile)
33 * @brief Checks in the list of log files we are watching if we
34 * already watch a given logfile
35 *
36 * @param logfile (char *) Name of the logfile to check
37 *
38 * @return 0 if not found, 1 if found
39 */
40int logfiles_exist(char *logfile)
41{
42 Eina_List *l;
43 struct logfile *foundlogfile = NULL;
44
45 EINA_LIST_FOREACH(list_logfiles, l, foundlogfile)
46 {
47 if( !strcmp(foundlogfile->name, logfile) )
48 {
49 return(1);
50 }
51 }
52
53 return(0);
54}
55
56/**
57 * @fn int logfiles_add(struct logfile *new_logfile)
58 * @brief Adds a logfile struct inside the logfiles list
59 *
60 * @param new_logfile (struct logfile *) structure to add
61 *
62 * @return 0 if not found, 1 if found
63 */
64int logfiles_add(struct logfile *new_logfile)
65{
66 list_logfiles = eina_list_append(list_logfiles, new_logfile);
67 return(0);
68}
69
70/**
71 * @fn int logfiles_print(void)
72 * @brief Prints on stdout the list of logfiles. Only usefull for a bit of
73 * monitoring of what is going on
74 *
75 * @return 0 if not found, 1 if found
76 */
77int logfiles_print(void)
78{
79 Eina_List *l;
80 struct logfile *foundlogfile = NULL;
81
82 EINA_LIST_FOREACH(list_logfiles, l, foundlogfile)
83 {
84 EINA_LOG_DOM_INFO(einadom_logfiles, "Name = %s\tCursor = %d", foundlogfile->name, foundlogfile->cursor);
85 }
86 return(0);
87}
88
89/**
90 * @fn int logfiles_new(struct logfile **new_logfile, char *filename, fpos_t cursor, unsigned long long int filesize)
91 * @brief Will alloc a new logfile structure and set given values
92 *
93 * @param new_logfile (struct logfile *) structure to alloc
94 * @param filename (char *) Name of the logfile
95 * @param cursor (fpos_t) Position of the cursor
96 * @param filesize (unsigned long long int) Size of the file
97 *
98 * @return 0
99 */
100int logfiles_new(struct logfile **new_logfile, char *filename, fpos_t cursor, unsigned long long int filesize)
101{
102 *new_logfile = malloc(sizeof(struct logfile));
103 (*new_logfile)->name = malloc(sizeof(char) * ( strlen(filename) + 1 ) );
104 strcpy( (*new_logfile)->name, filename);
105 (*new_logfile)->cursor = cursor;
106 (*new_logfile)->filesize = filesize;
107
108 return(0);
109}
110
111/**
112 * @fn int logfiles_del(struct logfile **old_logfile)
113 * @brief This function will free an allocated logfile structure
114 *
115 * @param old_logfile (struct logfile **) structure to free
116 *
117 * @return 0
118 */
119int logfiles_del(struct logfile **old_logfile)
120{
121 if( !(*old_logfile) )
122 return(0);
123
124 if( (*old_logfile)->name )
125 free((*old_logfile)->name);
126
127 free((*old_logfile));
128 return(0);
129}
130
131/**
132 * @fn int logfiles_getend(char *logfile, fpos_t *pos_end)
133 * @brief This function will get a cursor to the end of the file
134 *
135 * @param logfile (char *) logfile involved
136 * @param pos_end (fpos_t *) pointer used to store the position
137 *
138 * @return 0 or -1 if an error occur
139 */
140int logfiles_getend(char *logfile, fpos_t *pos_end)
141{
142 FILE *fp;
143
144 // We get our cursor pos
145 fp = fopen(logfile, "r");
146 if( !fp )
147 {
148 EINA_LOG_DOM_ERR(einadom_logfiles, "Can't open %s : %s", logfile, strerror(errno));
149 return(-1);
150 }
151 fseek(fp, 0L, SEEK_END);
152 fgetpos(fp, pos_end);
153
154 fclose(fp);
155 return(0);
156}
157
158/**
159 * @fn int logfiles_getbegin(char *logfile, fpos_t *pos_begin)
160 * @brief This function will get a cursor to the begin of the file
161 *
162 * @param logfile (char *) logfile involved
163 * @param pos_begin (fpos_t *) pointer used to store the position
164 *
165 * @return 0 or -1 if an error occur
166 */
167int logfiles_getbegin(char *logfile, fpos_t *pos_begin)
168{
169 FILE *fp;
170
171 // We get our cursor pos
172 fp = fopen(logfile, "r");
173 if( !fp )
174 {
175 EINA_LOG_DOM_ERR(einadom_logfiles, "Can't open %s : %s", logfile, strerror(errno));
176 return(-1);
177 }
178 fgetpos(fp, pos_begin);
179
180 fclose(fp);
181 return(0);
182}
183
184/**
185 * @fn int logfiles_getsize(char *logfile, unsigned long long int *filesize)
186 * @brief This function will get the size of a file
187 *
188 * @param logfile (char *) logfile involved
189 * @param filesize (unsigned long long int) pointer used to store the size
190 *
191 * @return 0 or -1 if an error occur
192 */
193int logfiles_getsize(char *logfile, unsigned long long int *filesize)
194{
195 struct stat64 st_buffer;
196 int retour;
197
198 retour = stat64(logfile, &st_buffer);
199
200 if( retour )
201 {
202 EINA_LOG_DOM_ERR(einadom_logfiles, "Can't get size of %s : %s", logfile, strerror(errno));
203 return(-1);
204 }
205
206 *filesize = st_buffer.st_size;
207
208 return(0);
209}
diff --git a/src/bin/logfiles.h b/src/bin/logfiles.h
new file mode 100644
index 0000000..b0ae200
--- /dev/null
+++ b/src/bin/logfiles.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file logfiles.h
21 * @brief Contains all includes and prototypes for logfiles.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for logfiles.c
26 */
27#include <errno.h>
28#include <sys/stat.h>
29
30#include "global.h"
31
32int logfiles_exist(char *logfile);
33int logfiles_add(struct logfile *new_logfile);
34int logfiles_print(void);
35int logfiles_new(struct logfile **new_logfile, char *filename, fpos_t cursor, unsigned long long int filesize);
36int logfiles_del(struct logfile **old_logfile);
37int logfiles_getend(char *logfile, fpos_t *pos_end);
38int logfiles_getbegin(char *logfile, fpos_t *pos_begin);
39int logfiles_getsize(char *logfile, unsigned long long int *filesize);
40
diff --git a/src/bin/logmessages.c b/src/bin/logmessages.c
new file mode 100644
index 0000000..a128de8
--- /dev/null
+++ b/src/bin/logmessages.c
@@ -0,0 +1,184 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file logmessages.c
21 * @brief Contains functions that helps manipulating logmessage structure
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains functions that helps manipulating logmessage structure
26 */
27#include "logmessages.h"
28
29/**
30 * @fn int logmessages_new(struct logmessage **new_logmessage, char *message, char *logname)
31 * @brief This function will init a given logmessage structure with default values
32 *
33 * @param new_logmessage (struct logmessage **) struct to alloc
34 * @param message (char *) Log message to store in this structure
35 * @param logname (char *) Name of the log file
36 *
37 * @return 0
38 */
39int logmessages_new(struct logmessage **new_logmessage, char *message, char *logname)
40{
41 *new_logmessage = malloc(sizeof(struct logmessage));
42
43 if( message )
44 {
45 (*new_logmessage)->message = malloc( sizeof(char) * ( strlen(message) + 1) );
46 strcpy((*new_logmessage)->message, message);
47 }
48 else
49 {
50 (*new_logmessage)->message = malloc( sizeof(char) * (1) );
51 (*new_logmessage)->message[0] = 0;
52 }
53 (*new_logmessage)->source_path = malloc( sizeof(char) * ( strlen(logname) + 1 ) );
54 strcpy( (*new_logmessage)->source_path, logname);
55
56 (*new_logmessage)->source_host = malloc( sizeof(char) * ( strlen(global_host) + 1 ) );
57 strcpy( (*new_logmessage)->source_host, global_host);
58
59 (*new_logmessage)->type = malloc( sizeof(char) * ( strlen(global_type) + 1 ) );
60 strcpy( (*new_logmessage)->type, global_type);
61
62 timestamp_XML( (*new_logmessage)->timestamp);
63
64 (*new_logmessage)->list_tags = NULL;
65 (*new_logmessage)->todel = 0;
66 return(0);
67}
68
69/**
70 * @fn int logmessages_free(struct logmessage **old_logmessage)
71 * @brief This function will free everything allocated in the structure
72 *
73 * @param old_logmessage (struct logmessage **) struct to free
74 *
75 * @return 0
76 */
77int logmessages_free(struct logmessage **old_logmessage)
78{
79 char *ptr;
80 if( (*old_logmessage)->source_host )
81 free( (*old_logmessage)->source_host);
82 free( (*old_logmessage)->source_path);
83 free( (*old_logmessage)->type);
84 free( (*old_logmessage)->message);
85
86 EINA_LIST_FREE( (*old_logmessage)->list_tags, ptr)
87 free(ptr);
88 free( (*old_logmessage));
89 return(0);
90}
91
92/**
93 * @fn int logmessages_set_type(struct logmessage *mylog, char *type)
94 * @brief This function will set a given type to a given logmessage structure
95 *
96 * @param mylog (struct logmessage *) Structure to modify
97 * @param type (char *) Type to set
98 *
99 * @return 0
100 */
101int logmessages_set_type(struct logmessage *mylog, char *type)
102{
103 if( mylog->type )
104 free(mylog->type);
105
106 mylog->type = malloc( sizeof(char) * ( strlen(type) + 1 ) );
107 strcpy(mylog->type, type);
108 return(0);
109}
110
111/**
112 * @fn int logmessages_set_sourcehost(struct logmessage *mylog, char *source_host)
113 * @brief This function will set a given host to a given logmessage structure
114 *
115 * @param mylog (struct logmessage *) Structure to modify
116 * @param source_host (char *) Host to set
117 *
118 * @return 0
119 */
120int logmessages_set_sourcehost(struct logmessage *mylog, char *source_host)
121{
122 if( mylog->source_host )
123 free(mylog->source_host);
124
125 mylog->source_host = malloc( sizeof(char) * ( strlen(source_host) + 1 ) );
126 strcpy(mylog->source_host, source_host);
127 return(0);
128}
129
130/**
131 * @fn int logmessages_add_tag(struct logmessage *mylog, char *tag)
132 * @brief This function will add tags to the given logmessage structure.
133 * Tags has to be separated by a ","
134 *
135 * @param mylog (struct logmessage *) Structure to modify
136 * @param tag (char *) tag to add
137 *
138 * @return 0
139 */
140int logmessages_add_tag(struct logmessage *mylog, char *tag)
141{
142 char *ptr,
143 *ptr_delim;
144 int last = 0;
145 ptr = &tag[0];
146
147 while( 1 )
148 {
149 char *new_tag;
150 ptr_delim = strchr(ptr, ',');
151 if( !ptr_delim )
152 {
153 ptr_delim = &ptr[strlen(ptr)+1];
154 last = 1;
155 }
156 else ptr_delim[0] = 0;
157
158 new_tag = malloc( sizeof(char) * ( strlen(ptr) + 1 ) );
159 strcpy(new_tag, ptr);
160
161 mylog->list_tags = eina_list_append(mylog->list_tags, new_tag);
162
163 if( last ) break;
164 ptr_delim[0] = ',';
165 ptr = &ptr_delim[1];
166 }
167
168 return(0);
169}
170
171/**
172 * @fn int logmessages_set_todel(struct logmessage *mylog, int value)
173 * @brief This function will set a given value to the delete field
174 *
175 * @param mylog (struct logmessage *) Structure to modify
176 * @param value (int) value to set
177 *
178 * @return 0
179 */
180int logmessages_set_todel(struct logmessage *mylog, int value)
181{
182 mylog->todel = value;
183 return(0);
184}
diff --git a/src/bin/logmessages.h b/src/bin/logmessages.h
new file mode 100644
index 0000000..aacfcff
--- /dev/null
+++ b/src/bin/logmessages.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file logmessages.h
21 * @brief Contains all includes and prototypes for logmessages.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for logmessages.c
26 */
27#include "global.h"
28#include "date.h"
29
30int logmessages_new(struct logmessage **new_logmessage, char *message, char *logname);
31int logmessages_free(struct logmessage **old_logmessage);
32int logmessages_set_type(struct logmessage *mylog, char *type);
33int logmessages_set_sourcehost(struct logmessage *mylog, char *source_host);
34int logmessages_add_tag(struct logmessage *mylog, char *tag);
35int logmessages_set_todel(struct logmessage *mylog, int value);
36
diff --git a/src/bin/main.c b/src/bin/main.c
new file mode 100644
index 0000000..812314e
--- /dev/null
+++ b/src/bin/main.c
@@ -0,0 +1,178 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file main.c
21 * @brief Main functions
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * @todo make an exit if receiving SIGUSR1 so we never kill -9 it
26 * @todo Index all received messages in an EET file so we dont loose them
27 * if ES is down, if we have a network problem or if we get killed
28 *
29 * Main functions
30 *
31 */
32
33/**
34 * @mainpage Syslog Message MANager
35 *
36 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
37 *
38 * @section INTRODUCTION Introduction
39 * SMMan is gateway between syslog files and an <a href=www.elasticsearch.com>ElasticSearch</a> database.<br />
40 * SMMan has a few more interesting stuff : He can tag every log he sees by using defined rules on them.<br />
41 * SMMan uses a configuration file, and needs rules files that must be written by the user of SMMan.<br />
42 * SMMan will then use these rules to monitor all the specified logfiles (using inotify), and extract every new entry
43 * to filter it using the rules and then indexing it in the configured <a href=www.elasticsearch.com>ElasticSearch</a> database.
44 * <img src=intro.png>
45 *
46 * <br />
47 * @section CONFIGURATION Configuration
48 * The configuration file has to be in <b>/etc/smman/smman.conf</b><br />
49 * For now, there is only 3 configurable variables :
50 * @li @b server : URL to <a href=www.elasticsearch.com>ElasticSearch</a> database. SMMan speaks to <a href=www.elasticsearch.com>ElasticSearch</a> using JSON.
51 * @li @b host : Allows you to set a different host that the one returned by command hostname (optionnal).
52 * @li @b type : Default type for all logs (optionnal).
53 *
54 *
55 * Exemple of configuration file : <br />
56 * @code
57 * server = http://localhost:9200/logstash/logs/
58 * host = BlackStar
59 * type = syslog
60 * @endcode
61 *
62 * <br />
63 * @section RULES Writing rules
64 * Writing rules is quite easy. SMMan search for rules in <b>/etc/smman/rules.d/</b><br />
65 * Check the rules directory in the source code to see examples of rules.<br />
66 * Basically, rules allows you to write matches about filenames or messages (using globbing/regexp), and set informations like :
67 * @li source_host : Set a custom hostname
68 * @li type : Set a custom type
69 * @li tags : Add tags to the message
70 * @li delete : Do not index the log, just drop it
71 *
72 * <br />
73 * @section LOGSTASH Why not using logstash ?
74 * @li Its written in ruby and i know nothing to ruby (so i cant modify anything).
75 * @li I have been able to make it crash just by deleting a monitored file, or by
76 * sending chars like éàè.
77 * @li I seem to be too stupid to understand how to automatically tag messages (using Grok, which adds a dependancy seemed complicated to me).
78 */
79#include "main.h"
80
81/**
82 * @fn int main(int argc, char **argv)
83 * @brief Main function, will launch all needed functions
84 *
85 * @param argc args count
86 * @param argv args
87 *
88 * @return 0, exit should not happen
89 */
90int main(int argc, char **argv)
91{
92 int c;
93 eina_init();
94 ecore_init();
95 ecore_file_init();
96
97 while( 1 )
98 {
99 int option_index = 0;
100
101 static struct option long_options[] = {
102 {"version", 0, 0, 'v'},
103 {"help", 0, 0, 'h'},
104 {0, 0, 0, 0}
105 };
106
107 c = getopt_long(argc, argv, "vh", long_options, &option_index);
108 if (c == -1) break;
109
110 switch (c)
111 {
112 case 'v':
113 version(argv[0]);
114 exit(0);
115 case 'h':
116 usage(argv[0]);
117 exit(0);
118 default:
119 break;
120 }
121 }
122
123 // Read conf
124 conf_load();
125
126 // Load rules
127 rules_load();
128
129 // We show the list of loaded rules
130 // Unecessary
131 rules_print();
132
133 // Begin to spy files
134 spy_init();
135
136 // We show the list of files we will watch
137 // Unecessary
138 logfiles_print();
139
140 // We wait for events (new inserts in logfiles)
141 ecore_main_loop_begin();
142
143 return(0);
144}
145
146/**
147 * @fn void usage(char *progname)
148 * @brief displays basic usage
149 * http://patorjk.com/software/taag/ Cricket font
150 *
151 * @param progname (char *) Name of program
152 */
153void usage(char *progname)
154{
155 printf(" _______ \n");
156 printf(" | _ |.--------..--------..---.-..-----.\n");
157 printf(" | 1___|| || || _ || |\n");
158 printf(" |____ ||__|__|__||__|__|__||___._||__|__|\n");
159 printf(" |: 1 | \n");
160 printf(" |::.. . | Usage for %s : \n", progname);
161 printf(" `-------' \n");
162 printf("\t--help\t\t-h :\tShow this help screen\n");
163 printf("\t--version\t-v :\tShow revision version\n");
164 printf("\n");
165 printf("\tDebugging : \n");
166 printf("\t\tEINA_LOG_LEVEL=5 %s\n", progname);
167}
168
169/**
170 * @fn void version(char *progname)
171 * @brief Shows program revision
172 *
173 * @param progname (char *) Name of program
174 */
175void version(char *progname)
176{
177 printf("%s r%s\n", progname, REVISION);
178}
diff --git a/src/bin/main.h b/src/bin/main.h
new file mode 100644
index 0000000..5545c15
--- /dev/null
+++ b/src/bin/main.h
@@ -0,0 +1,42 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file main.h
21 * @brief Header file for main.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Header file for main.c
26 *
27 */
28
29#include <stdio.h>
30#include <Ecore.h>
31#include <Ecore_File.h>
32#include <getopt.h>
33
34#include "global.h"
35
36#include "rules.h"
37#include "spy.h"
38#include "conf.h"
39
40void usage(char *progname);
41void version(char *progname);
42
diff --git a/src/bin/rules.c b/src/bin/rules.c
new file mode 100644
index 0000000..8f7b66f
--- /dev/null
+++ b/src/bin/rules.c
@@ -0,0 +1,291 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file rules.c
21 * @brief Functions the manipulates rules
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * @bug : Better parsing of tags (we only escape double quotes right now)
26 *
27 * Functions the manipulates rules
28 *
29 */
30#include "rules.h"
31
32/**
33 * @fn int rules_load(void)
34 * @brief List the rules directory and loads every rule in it
35 *
36 * @return 0 if no error, -1 if can't open rules dir
37 */
38int rules_load(void)
39{
40 DIR *fd;
41 struct dirent * entree;
42
43 list_rules = NULL;
44
45 // For every rule in rules directory, we will load it
46 fd = opendir(global_rulesdir);
47 if( !fd )
48 {
49 EINA_LOG_DOM_ERR(einadom_rules, "Can't open rules directory %s : %s", global_rulesdir, strerror(errno));
50 return(-1);
51 }
52 while((entree = readdir(fd)) != NULL)
53 {
54 if( !strcmp(entree->d_name, ".") ) continue;
55 if( !strcmp(entree->d_name, "..") ) continue;
56
57 EINA_LOG_DOM_DBG(einadom_rules, "Found rule file %s", entree->d_name);
58
59 rules_load_rule(entree->d_name);
60 }
61
62 closedir(fd);
63 return(0);
64}
65
66/**
67 * @fn int rules_load_rule(char *rule_name)
68 * @brief This function receives the name of a rule file, and ask for libconf
69 * to analyze it
70 *
71 * @param rule_name (char *) name of the rule (filename)
72 *
73 * @return 0
74 */
75int rules_load_rule(char *rule_name)
76{
77 char full_path[512];
78 struct libconfig myconf;
79
80 sprintf(full_path, "%s%s", global_rulesdir, rule_name);
81
82 libconfig_init(full_path, &myconf);
83 libconfig_load(&myconf);
84
85 // We have to make a new rule struct
86 rules_temp = malloc(sizeof(struct rule));
87
88 rules_temp->name = malloc(sizeof(char) * ( strlen(rule_name) + 1 ) );
89 strcpy(rules_temp->name, rule_name);
90
91 // We init default values for our struct
92 rules_temp->filename = NULL;
93 rules_temp->message = NULL;
94 rules_temp->type = NULL;
95 rules_temp->source_host = NULL;
96 rules_temp->source_path = NULL;
97 rules_temp->tags = NULL;
98 rules_temp->todel = 0;
99
100 libconfig_list(&myconf, rules_load_rule_loadspec);
101
102 libconfig_free(&myconf);
103
104 // We insert our new rule in our eina rule list
105 list_rules = eina_list_append(list_rules, rules_temp);
106 return(0);
107}
108
109/**
110 * @fn int rules_load_rule_loadspec(char *variable, char *value)
111 * @brief This function is a callback used by libconf to send us
112 * every variable+value that libconf found in a rulefile
113 *
114 * @param variable (char *) variable's name
115 * @param value (char *) variable's value
116 *
117 * @return 0
118 */
119int rules_load_rule_loadspec(char *variable, char *value)
120{
121 if( !strcmp(variable, "filename") )
122 {
123 rules_temp->filename = malloc(sizeof(char) * ( strlen(value) + 1 ));
124 strcpy(rules_temp->filename, value);
125 }
126 else if( !strcmp(variable, "message") )
127 {
128 rules_temp->message = malloc(sizeof(char) * ( strlen(value) + 1 ));
129 strcpy(rules_temp->message, value);
130 }
131 else if( !strcmp(variable, "type") )
132 {
133 rules_temp->type = malloc(sizeof(char) * ( strlen(value) + 1 ));
134 strcpy(rules_temp->type, value);
135 }
136 else if( !strcmp(variable, "source_host") )
137 {
138 rules_temp->source_host = malloc(sizeof(char) * ( strlen(value) + 1 ));
139 strcpy(rules_temp->source_host, value);
140 }
141 else if( !strcmp(variable, "source_path") )
142 {
143 rules_temp->source_path = malloc(sizeof(char) * ( strlen(value) + 1 ));
144 strcpy(rules_temp->source_path, value);
145 }
146 else if( !strcmp(variable, "tags") )
147 {
148 rules_temp->tags = malloc(sizeof(char) * ( strlen(value) + 1 ));
149 strcpy(rules_temp->tags, value);
150 }
151 else if( !strcmp(variable, "delete") )
152 {
153 rules_temp->todel = atoi(value);
154 }
155 else
156 {
157 EINA_LOG_DOM_ERR(einadom_rules, "Unknown variable name %s", variable);
158 }
159 return(0);
160}
161
162
163/**
164 * @fn int rules_print(void)
165 * @brief This function will print to stdout every rules that is in
166 * the rules list.
167 *
168 * @return 0
169 */
170int rules_print(void)
171{
172 Eina_List *l;
173 struct rule *foundrule = NULL;
174
175 EINA_LIST_FOREACH(list_rules, l, foundrule)
176 {
177 EINA_LOG_DOM_INFO(einadom_rules,
178 "\n[%s]\n"
179 "\tfilename\t= %s\n"
180 "\tmessage\t\t= %s\n"
181 "\ttype\t\t= %s\n"
182 "\tsource_host\t= %s\n"
183 "\tsource_path\t= %s\n"
184 "\ttags\t\t= %s\n"
185 "\tdelete\t= %d\n\n",
186 foundrule->name,
187 foundrule->filename,
188 foundrule->message,
189 foundrule->type,
190 foundrule->source_host,
191 foundrule->source_path,
192 foundrule->tags,
193 foundrule->todel);
194 }
195 return(0);
196}
197
198/**
199 * @fn int rules_list(int (*callback)(struct rule *foundrule))
200 * @brief This function will list every rule in the list, to send each
201 * item to the given callback
202 *
203 * @param callback (int *) Callback that will receive all the items
204 *
205 * @return 0
206 */
207int rules_list(int (*callback)(struct rule *foundrule))
208{
209 Eina_List *l;
210 struct rule *foundrule = NULL;
211
212 EINA_LIST_FOREACH(list_rules, l, foundrule)
213 {
214 callback(foundrule);
215 }
216 return(0);
217}
218
219
220/**
221 * @fn int rules_filtermessage(struct logmessage *new_logmessage)
222 * @brief This function will get a log message, and apply all the rules
223 * on it before giving it back and filtered
224 *
225 * @param new_logmessage (struct logmessage *)
226 *
227 * @return 0
228 */
229int rules_filtermessage(struct logmessage *new_logmessage)
230{
231 Eina_List *l;
232 struct rule *foundrule = NULL;
233 int ret;
234
235 // We check each rules to see what we have to do
236 EINA_LIST_FOREACH(list_rules, l, foundrule)
237 {
238 // If filename is set, we check that our log is affected
239 // By this rule's filename
240 if( foundrule->filename )
241 {
242 ret = fnmatch(foundrule->filename, new_logmessage->source_path, FNM_NOESCAPE);
243 if( ret )
244 {
245 EINA_LOG_DOM_DBG(einadom_rules, "Log \"%s\" from \"%s\" is not affected by rule %s (filename exclude)", new_logmessage->message, new_logmessage->source_path, foundrule->name);
246 continue;
247 }
248 }
249
250 // Now we check for message filtering
251 if( foundrule->message )
252 {
253 regex_t preg;
254 size_t nmatch = 2;
255 regmatch_t pmatch[2];
256
257 ret = regcomp(&preg, foundrule->message, REG_EXTENDED);
258 if( ret )
259 {
260 EINA_LOG_DOM_ERR(einadom_rules, "Regcomp failed to compile regexp %s", foundrule->message);
261 regfree(&preg);
262 continue;
263 }
264
265 ret = regexec(&preg, new_logmessage->message,nmatch, pmatch, 0);
266 if( ret )
267 {
268 EINA_LOG_DOM_INFO(einadom_rules, "Log \"%s\" from \"%s\" is not affected by rule %s (message exclude)", new_logmessage->message, new_logmessage->source_path, foundrule->name);
269 regfree(&preg);
270 continue;
271 }
272 regfree(&preg);
273 }
274
275 // If we get here, then our log message have to be filtered
276
277 // If type is specified, then we have to override it
278 if( foundrule->type )
279 logmessages_set_type(new_logmessage, foundrule->type);
280
281 if( foundrule->source_host )
282 logmessages_set_sourcehost(new_logmessage, foundrule->source_host);
283
284 if( foundrule->tags )
285 logmessages_add_tag(new_logmessage, foundrule->tags);
286
287 if( foundrule->todel )
288 logmessages_set_todel(new_logmessage, 1);
289 }
290 return(0);
291}
diff --git a/src/bin/rules.h b/src/bin/rules.h
new file mode 100644
index 0000000..5f6e109
--- /dev/null
+++ b/src/bin/rules.h
@@ -0,0 +1,47 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file rules.h
21 * @brief Contains all includes and prototypes for rules.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for rules.c
26 */
27
28#include <dirent.h>
29#include <errno.h>
30#include <Eina.h>
31#include <fnmatch.h>
32#include <sys/types.h>
33#include <regex.h>
34
35#include "libconf.h"
36#include "global.h"
37#include "logmessages.h"
38
39struct rule *rules_temp; /**< Pointer to a rule, used so rules_load_rule_loadspec() knowns which rule rules_load_rule() is processing */
40
41int rules_load(void);
42int rules_load_rule(char *rule_name);
43int rules_load_rule_loadspec(char *variable, char *value);
44int rules_print(void);
45int rules_list(int (*callback)(struct rule *foundrule));
46int rules_filtermessage(struct logmessage *new_logmessage);
47
diff --git a/src/bin/send.c b/src/bin/send.c
new file mode 100644
index 0000000..76ef6e6
--- /dev/null
+++ b/src/bin/send.c
@@ -0,0 +1,239 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file send.c
21 * @brief Contains functions to send logs to ES
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains functions to send logs to ES
26 */
27
28#include "send.h"
29
30/**
31 * @fn int send_logmessage(struct logmessage *new_logmessage)
32 * @brief This function will receive a logmessage to index,
33 * convert it into JSON data and send it to <a href=www.elasticsearch.com>ES</a>
34 *
35 * @param new_logmessage (struct logmessage *) Log message to index
36 *
37 * @see send_convJSON()
38 * @see struct logmessage
39 * @see send_toES
40 *
41 * @return 0
42 */
43int send_logmessage(struct logmessage *new_logmessage)
44{
45 Eina_List *l;
46 char *tag = NULL,
47 *tags = NULL,
48 *jsondata = NULL;
49 unsigned int size = 0,
50 i = 0;
51
52 // We check how much space we need to store tags
53 EINA_LIST_FOREACH(new_logmessage->list_tags, l, tag)
54 {
55 size += strlen(tag) + 3;
56 }
57
58 tags = malloc( sizeof(char) * ( size + 1 ) );
59 memset(tags, 0, size + 1);
60
61 EINA_LIST_FOREACH(new_logmessage->list_tags, l, tag)
62 {
63 if( i > 0 )
64 strcat(tags, ",");
65
66 strcat(tags, "\"");
67 strcat(tags, tag);
68 strcat(tags, "\"");
69 i++;
70 }
71 // We will build our JSON object from these values
72 send_convJSON(new_logmessage->source_host, new_logmessage->source_path, new_logmessage->type, new_logmessage->message, tags, new_logmessage->timestamp, &jsondata);
73
74 EINA_LOG_DOM_DBG(einadom_send, "JSON : %s", jsondata);
75
76 send_toES(jsondata);
77
78 free(jsondata);
79 free(tags);
80 return(0);
81}
82
83/**
84 * @fn int send_convJSON(char *source_host, char *source_path, char *type, char *message, char *tags, char *timestamp, char **jsondata)
85 * @brief This Function receives all needed vars to build the JSON data for <a href=www.elasticsearch.com>ES</a>.
86 * @warning This function will malloc jsondata, so dont do it yourself, and dont forget to free it!
87 *
88 * @param source_host (char *) Host that sent the logfile
89 * @param source_path (char *) Logfile name
90 * @param type (char *) Type for this log message
91 * @param message (char *) Log message
92 * @param tags (char *) list of tags, they must be already parsed in format "Tag1","Tag2","Tag3"
93 * @param timestamp (char *) Timestamp for the message
94 * @param jsondata (char **) Buffer that we will malloc and fill with generated JSON message
95 *
96 * @return 0
97 */
98int send_convJSON(char *source_host, char *source_path, char *type, char *message, char *tags, char *timestamp, char **jsondata)
99{
100 char *Esource_host = NULL,
101 *Esource_path = NULL,
102 *Etype = NULL,
103 *Emessage = NULL;
104
105 send_escape(source_host, &Esource_host);
106 send_escape(source_path, &Esource_path);
107 send_escape(type, &Etype);
108 send_escape(message, &Emessage);
109
110 *jsondata = malloc( sizeof(char) * (200 + strlen(Esource_host)*2 + strlen(Esource_path)*2 + strlen(Etype) + strlen(Emessage) + strlen(tags) + 30 + 1) );
111 sprintf(*jsondata,
112 "{"
113 " \"@source\" : \"file://%s%s\","
114 " \"@type\" : \"%s\","
115 " \"@tags\" : [ %s ],"
116 " \"@fields\" : { },"
117 " \"@message\" : \"%s\","
118 " \"@timestamp\" : \"%s\","
119 " \"@source_host\" : \"%s\","
120 " \"@source_path\" : \"%s\""
121 "}",
122 Esource_host, Esource_path, Etype, tags, Emessage, timestamp, Esource_host, Esource_path);
123
124 free(Esource_host);
125 free(Esource_path);
126 free(Etype);
127 free(Emessage);
128
129 return(0);
130}
131
132
133/**
134 * @fn char *send_escape(char *src, char **dst)
135 * @brief This Function will escape all double quote so we dont get a parsing problem
136 * @warning This function will malloc dst, so dont do it yourself, and dont forget to free it!
137 *
138 * @param src (char *) buffer to escape
139 * @param dst (char **) Escaped buffer
140 *
141 * @return Pointer to escaped buffer
142 */
143char *send_escape(char *src, char **dst)
144{
145 unsigned i = 0,
146 j = 0,
147 len = strlen(src);
148 char tmp[len*2+1];
149
150 memset(tmp, 0, sizeof(tmp));
151
152 for( i = 0; i < len+1; i++)
153 {
154 if( src[i] == '"')
155 tmp[j++] = '\\';
156 tmp[j++] = src[i];
157 }
158 *dst = malloc( sizeof(char) * ( strlen(tmp) + 1 ) );
159 strcpy(*dst, tmp);
160 return(*dst);
161}
162
163/**
164 * @fn int send_toES(char *jsondata)
165 * @brief This function will send a given JSON data to the configured
166 * JSON server
167 *
168 * @param jsondata (char *)
169 *
170 * @return 0
171 */
172int send_toES(char *jsondata)
173{
174/* ecore_con_url_post doesnt return any error if it cant send
175 which sucks for us. Waiting for patch coming for EFLs 1.1
176 Ecore_Con_Url *ecu;
177 Eina_Bool ret;
178
179 ecore_con_url_init();
180 ecu = ecore_con_url_new(global_ESserver);
181 if( !ecu )
182 {
183 EINA_LOG_DOM_ERR(einadom_send, "Can't init ecore_con_url_new()");
184 ecore_con_url_shutdown();
185 return(-1);
186 }
187
188 ret = ecore_con_url_post(ecu, jsondata, -1, "text/xml");
189 if( ret == EINA_FALSE )
190 {
191 EINA_LOG_DOM_ERR(einadom_send, "Can't send jsondata to ES");
192 ecore_con_url_shutdown();
193 return(-1);
194 }
195
196 ecore_con_url_free(ecu);
197 ecore_con_url_shutdown();
198*/
199 CURL *curl;
200 CURLcode res;
201
202 curl = curl_easy_init();
203 if( !curl )
204 {
205 EINA_LOG_DOM_ERR(einadom_send, "Can't init curl.");
206 return(-1);
207 }
208 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, EINA_TRUE);
209 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, send_fromES);
210 curl_easy_setopt(curl, CURLOPT_URL, global_ESserver);
211 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsondata);
212
213 res = curl_easy_perform(curl);
214 if( res )
215 {
216 EINA_LOG_DOM_ERR(einadom_send, "Sending of JSON query failed, curl returned : %d", res);
217 }
218 curl_easy_cleanup(curl);
219 return(0);
220}
221
222/**
223 * @fn static size_t send_fromES(void *ptr, size_t size, size_t nmemb, void *data)
224 * @brief This fonction will get response from <a href=www.elasticsearch.com>ES</A>
225 * after sending our JSON data. This function is a callback used by libcurl
226 *
227 * @param ptr (void *) To be defined
228 * @param size (size_t) To be defined
229 * @param nmemb (size_t) To be defined
230 * @param data (void *) To be defined
231 *
232 * @return Number of bytes received
233 */
234size_t send_fromES(void *ptr, size_t size, size_t nmemb, void *data)
235{
236 if( strncmp((char *)ptr, "{\"ok\":", 6) )
237 EINA_LOG_DOM_ERR(einadom_send, "Indexing of JSON data failed");
238 return(size * nmemb);
239}
diff --git a/src/bin/send.h b/src/bin/send.h
new file mode 100644
index 0000000..2f1ab08
--- /dev/null
+++ b/src/bin/send.h
@@ -0,0 +1,38 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file send.h
21 * @brief Contains all includes and prototypes for send.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for send.c
26 */
27
28#include <Ecore_Con.h>
29#include <curl/curl.h>
30
31#include "global.h"
32
33int send_logmessage(struct logmessage *new_logmessage);
34int send_convJSON(char *source_host, char *source_path, char *type, char *message, char *tags, char *timestamp, char **jsondata);
35char *send_escape(char *src, char **dst);
36int send_toES(char *jsondata);
37size_t send_fromES(void *ptr, size_t size, size_t nmemb, void *data);
38
diff --git a/src/bin/spy.c b/src/bin/spy.c
new file mode 100644
index 0000000..9672d16
--- /dev/null
+++ b/src/bin/spy.c
@@ -0,0 +1,355 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file spy.c
21 * @brief Contains functions that monitors logfiles
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * @bug : In rules, use wildcards only for filenames, not directories
26 *
27 * Contains functions that monitors logfiles
28 */
29#include "spy.h"
30
31/**
32 * @fn int spy_init(void)
33 * @brief Will ask rules_list() to list all rules and tell spy_addwatcher()
34 * of every found rule so we can process it and monitor matching log files
35 *
36 * @return 0
37 */
38int spy_init(void)
39{
40 rules_list(spy_addwatcher);
41 return(0);
42}
43
44/**
45 * @fn int spy_addwatcher(struct rule *foundrule)
46 * @brief Gets a rule in param, and will check for every matching
47 * files on the system
48 *
49 * @param foundrule (struct rule *) Rule found by rules_list()
50 *
51 * @return 0 if no error, -1 if any error
52 */
53int spy_addwatcher(struct rule *foundrule)
54{
55 wordexp_t p;
56 int ret;
57 unsigned int i;
58 char *ptr,
59 tmp[512];
60
61 if( !foundrule->filename )
62 return(0);
63
64 // As filenames can contain wildcards, we have to test
65 // Globbing
66 ret = wordexp(foundrule->filename, &p, 0);
67 if( ret )
68 {
69 EINA_LOG_DOM_ERR(einadom_spy, "l utilisation de wordexp() a echoue, il a renvoye %d", ret);
70 return(-1);
71 }
72
73 EINA_LOG_DOM_DBG(einadom_spy, "Found %d results for %s", p.we_wordc, foundrule->filename);
74
75 // We now have a list of files (or a unique file) and we want to add them
76 // To our file list
77 for( i = 0; i < p.we_wordc; i++)
78 {
79 int exist = 0;
80
81 exist = logfiles_exist(p.we_wordv[i]);
82
83 if( !exist )
84 {
85 fpos_t pos_tmp;
86 struct logfile *new_logfile;
87 unsigned long long int filesize = 0;
88
89 // We get our cursor pos
90 logfiles_getend(p.we_wordv[i], &pos_tmp);
91 logfiles_getsize(p.we_wordv[i], &filesize);
92 logfiles_new(&new_logfile, p.we_wordv[i], pos_tmp, filesize);
93
94 logfiles_add(new_logfile);
95 efm = ecore_file_monitor_add(p.we_wordv[i],
96 (Ecore_File_Monitor_Cb)spy_event,
97 (void *)new_logfile);
98 }
99 }
100 wordfree(&p);
101
102 // We will check parent directory to see if a new file is created
103 // and matches one of the rules when a CREATE event is raised.
104 // This part sucks cause we only watch the last directory while
105 // The wildcard can englob multiple directories! (and so our code gets totally buggy)
106 strncpy(tmp, foundrule->filename, 512);
107 ptr = dirname(tmp);
108 efm = ecore_file_monitor_add(ptr,
109 (Ecore_File_Monitor_Cb)spy_event,
110 NULL);
111
112 return(0);
113}
114
115/**
116 * @fn int spy_event(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
117 * @brief ecore_main_loop() will call this function for every notification he gets from logfiles
118 * activity.
119 *
120 * @param data (void *) Data associated to the logfile in spy_addwatcher()
121 * @param em (Ecore_File_Monitor *) Not really used here.
122 * @param event (Ecore_File_Event) Event type
123 * @param path (const char *) Name of the file that raised the event
124 *
125 * @return ECORE_CALLBACK_RENEW
126 */
127int spy_event(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
128{
129 struct logmessage *new_logmessage;
130 char message[4096];
131
132 EINA_LOG_DOM_DBG(einadom_spy, "Event on %s ! %p - %p", path, data, em);
133 message[0] = 0;
134
135 if( event == ECORE_FILE_EVENT_MODIFIED )
136 {
137 struct logfile *log = data;
138 fpos_t new_pos;
139 unsigned long long int filesize;
140
141 if( !log )
142 return(ECORE_CALLBACK_RENEW);
143
144 // If logfile got trunc, than size is different
145 logfiles_getsize((char *)path, &filesize);
146
147 if( filesize < log->filesize )
148 {
149 // If event is that file has been truncated, then there is
150 // nothing to read, we just set cursor to beginning
151 logfiles_getbegin((char *)path, &(log->cursor));
152 log->filesize = filesize;
153 return(ECORE_CALLBACK_RENEW);
154 }
155 log->filesize = filesize;
156
157 EINA_LOG_DOM_DBG(einadom_spy, "Event on %s - %d !", path, log->cursor);
158
159 // We must take attention to the fact that the file might
160 // Have been truncated
161 spy_extract_new_lines(log->name, log->cursor, &new_pos, message);
162 log->cursor = new_pos;
163
164 // If nothing has been read, then file has been trunc and is empty
165 // So we do nothing
166 if( message[0] == 0 )
167 return(ECORE_CALLBACK_RENEW);
168
169 logmessages_new(&new_logmessage, message, log->name);
170
171
172 rules_filtermessage(new_logmessage);
173
174 // Now we only have to send this filtered message to ES
175 if( !new_logmessage->todel )
176 send_logmessage(new_logmessage);
177
178 // Message is sent, we can free our structure
179 logmessages_free(&new_logmessage);
180 }
181 else if( event == ECORE_FILE_EVENT_DELETED_SELF
182 || event == ECORE_FILE_EVENT_DELETED_DIRECTORY
183 || event == ECORE_FILE_EVENT_DELETED_FILE
184 )
185 {
186 struct logfile *log = data,
187 *foundlog;
188 Eina_List *l;
189 EINA_LOG_DOM_DBG(einadom_spy, "Logfile %s has been deleted!", path);
190
191 // If this file was one of the files we used to monitor,
192 // We must delete it from our list
193 EINA_LIST_FOREACH(list_logfiles, l, foundlog)
194 {
195 if( !strcmp(foundlog->name, path) )
196 {
197 list_logfiles = eina_list_remove(list_logfiles, log);
198 logfiles_del(&log);
199 break;
200 }
201 }
202 }
203 else if( event == ECORE_FILE_EVENT_CREATED_FILE
204 || event == ECORE_FILE_EVENT_CREATED_DIRECTORY
205 )
206 {
207 // A new log file has been made, we have to check if this file already is in our filelog
208 // And if a rule affects it.
209 // If so, we add it to our monitor
210 Eina_List *l;
211 struct rule *foundrule = NULL;
212 struct logfile *new_logfile = NULL;
213 fpos_t pos_tmp;
214 int ret,
215 got_it = 0;
216
217 EINA_LOG_DOM_DBG(einadom_spy, "Logfile %s has been created!", path);
218
219 // If we already monitor this file, then we ignore it
220 // Which might be a problem btw. This thing shouldnt happen
221 EINA_LIST_FOREACH(list_logfiles, l, new_logfile)
222 {
223 if( !strcmp(new_logfile->name, path) )
224 return(ECORE_CALLBACK_RENEW);
225
226 }
227
228 EINA_LIST_FOREACH(list_rules, l, foundrule)
229 {
230 if( foundrule->filename )
231 {
232 unsigned long long int filesize;
233 ret = fnmatch(foundrule->filename, path, FNM_NOESCAPE);
234 if( ret )
235 continue;
236
237 // We get our cursor pos
238 logfiles_getbegin((char *)path, &pos_tmp);
239 logfiles_getsize((char *)path, &filesize);
240 logfiles_new(&new_logfile, (char *)path, pos_tmp, filesize);
241
242 logfiles_add(new_logfile);
243 efm = ecore_file_monitor_add(path,
244 (Ecore_File_Monitor_Cb)spy_event,
245 (void *)new_logfile);
246
247 got_it = 1;
248 break;
249 }
250 }
251
252 if( got_it )
253 {
254 // We must take attention to the fact that the file might
255 // Have been truncated
256 spy_extract_new_lines(new_logfile->name, new_logfile->cursor, &new_logfile->cursor, message);
257
258 // If nothing has been read, then file has been trunc and is empty
259 // So we do nothing
260 if( message[0] == 0 )
261 return(ECORE_CALLBACK_RENEW);
262
263 logmessages_new(&new_logmessage, message, new_logfile->name);
264 rules_filtermessage(new_logmessage);
265
266 // Now we only have to send this filtered message to ES
267 if( !new_logmessage->todel )
268 send_logmessage(new_logmessage);
269
270 // Message is sent, we can free our structure
271 logmessages_free(&new_logmessage);
272 }
273 }
274 else
275 {
276 EINA_LOG_DOM_DBG(einadom_spy, "WTF event on %s !", path);
277
278 }
279 return(ECORE_CALLBACK_RENEW);
280}
281
282
283
284/**
285 * @fn int spy_extract_new_lines(char *filename, fpos_t pos_cur, fpos_t *pos_new, char *message)
286 * @brief Gets the new log message that has been inserted. This function kind of sucks and has to
287 * be improved to really extract all the messages and send them to a callback that will
288 * process them intead of taking only one (which can cause a problem if we don't get
289 * one inotify per message logged).
290 *
291 * @param filename (char *) File that raised an event and should be read
292 * @param pos_cur (fpos_t) current cursor position for this file
293 * @param pos_new (fpos_t *) New position of the cursor after extracting the new message
294 * @param message (char *) message extracted from the logfile
295 *
296 * @return 0 or -1 if there is an error
297 */
298int spy_extract_new_lines(char *filename, fpos_t pos_cur, fpos_t *pos_new, char *message)
299{
300 FILE *fp;
301 int ret;
302 fpos_t pos_begin;
303
304 fp = fopen(filename, "r");
305 if( !fp )
306 {
307 EINA_LOG_DOM_ERR(einadom_spy, "We haven't been able to open %s : %s", filename, strerror(errno));
308 return(-1);
309 }
310
311 fgetpos(fp, &pos_begin);
312
313
314 // If we can't set cursor, file has been truncated!
315 ret = fsetpos(fp, &pos_cur);
316 if( ret )
317 {
318 fsetpos(fp, &pos_begin);
319 *pos_new = pos_begin;
320 }
321 else *pos_new = pos_cur;
322
323 // This while is only here to avoid empty lines
324 while( 1 )
325 {
326 ret = fscanf(fp,"%4096[^\n]\n", message);
327
328 if( ret == EOF )
329 break;
330
331 // Didnt read anything
332 if( ret == 0)
333 {
334 char tmp[2];
335 EINA_LOG_DOM_DBG(einadom_spy, "Empty line hack");
336 ret = fread(tmp, 1, 1, fp);
337 if( ret != 1 )
338 EINA_LOG_DOM_DBG(einadom_spy, "WTF?!");
339 continue;
340 }
341 if( ret != 1 )
342 {
343 fgetpos(fp, pos_new);
344 EINA_LOG_DOM_DBG(einadom_spy, "Break! new_pos = %d", *pos_new);
345 break;
346 }
347 else
348 fgetpos(fp, pos_new);
349
350 // We have a message to log
351 }
352
353 fclose(fp);
354 return(0);
355}
diff --git a/src/bin/spy.h b/src/bin/spy.h
new file mode 100644
index 0000000..1c5b95c
--- /dev/null
+++ b/src/bin/spy.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright © 2011 ASP64 <guillaume.friloux@asp64.com>
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19/**
20 * @file spy.h
21 * @brief Contains all includes and prototypes for spy.c
22 * @author Guillaume Friloux <guillaume.friloux@asp64.com>
23 * @version 1.0
24 *
25 * Contains all includes and prototypes for spy.c
26 */
27#include <wordexp.h>
28
29#include "global.h"
30
31#include "rules.h"
32#include "logfiles.h"
33#include "send.h"
34#include "logmessages.h"
35
36int spy_init(void);
37int spy_addwatcher(struct rule *foundrule);
38int spy_event(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path);
39int spy_extract_new_lines(char *filename, fpos_t pos_cur, fpos_t *pos_new, char *message);
40