summaryrefslogtreecommitdiff
path: root/src/bin/spy.c
diff options
context:
space:
mode:
authorGuillaume Friloux <guillaume.friloux@gmail.com>2013-12-18 14:07:27 +0100
committerGuillaume Friloux <guillaume.friloux@gmail.com>2013-12-18 14:07:27 +0100
commitdbb099df5455a2932b9ed3b12258cff8faca513b (patch)
tree34ed6643ddf96c7864139bc6fd3e9f02def16139 /src/bin/spy.c
parent2c55710a9d04323fc698f49047432b3e231d2ca7 (diff)
Rewrite of smman.
Diffstat (limited to 'src/bin/spy.c')
-rw-r--r--src/bin/spy.c349
1 files changed, 0 insertions, 349 deletions
diff --git a/src/bin/spy.c b/src/bin/spy.c
deleted file mode 100644
index 6d27fde..0000000
--- a/src/bin/spy.c
+++ /dev/null
@@ -1,349 +0,0 @@
1/*
2 * Copyright © 2013 Guillaume Friloux <kuri@efl.so>
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#include "smman.h"
20#include <wordexp.h>
21
22
23/**
24 * @brief Will ask rules_list() to list all rules and tell spy_addwatcher()
25 * of every found rule so we can process it and monitor matching log files
26 *
27 * @return 0
28 */
29int spy_init(void)
30{
31 rules_list(spy_addwatcher);
32 return(0);
33}
34
35/**
36 * @brief Gets a rule in param, and will check for every matching
37 * files on the system
38 *
39 * @param foundrule (struct rule *) Rule found by rules_list()
40 *
41 * @return 0 if no error, -1 if any error
42 */
43int spy_addwatcher(struct rule *foundrule)
44{
45 wordexp_t p;
46 int ret;
47 unsigned int i;
48 char *ptr,
49 tmp[512];
50
51 if( !foundrule->filename )
52 return(0);
53
54 // As filenames can contain wildcards, we have to test
55 // Globbing
56 ret = wordexp(foundrule->filename, &p, 0);
57 if( ret )
58 {
59 EINA_LOG_DOM_ERR(einadom_spy, "l utilisation de wordexp() a echoue, il a renvoye %d", ret);
60 return(-1);
61 }
62
63 EINA_LOG_DOM_DBG(einadom_spy, "Found %zu results for %s", p.we_wordc, foundrule->filename);
64
65 // We now have a list of files (or a unique file) and we want to add them
66 // To our file list
67 for( i = 0; i < p.we_wordc; i++)
68 {
69 int exist = 0;
70
71 exist = logfiles_exist(p.we_wordv[i]);
72
73 if( !exist )
74 {
75 fpos_t pos_tmp;
76 struct logfile *new_logfile;
77 unsigned long long int filesize = 0;
78
79 // We get our cursor pos
80 logfiles_getend(p.we_wordv[i], &pos_tmp);
81 logfiles_getsize(p.we_wordv[i], &filesize);
82 logfiles_new(&new_logfile, p.we_wordv[i], pos_tmp, filesize);
83
84 logfiles_add(new_logfile);
85 efm = ecore_file_monitor_add(p.we_wordv[i],
86 (Ecore_File_Monitor_Cb)spy_event,
87 (void *)new_logfile);
88 }
89 }
90 wordfree(&p);
91
92 // We will check parent directory to see if a new file is created
93 // and matches one of the rules when a CREATE event is raised.
94 // This part sucks cause we only watch the last directory while
95 // The wildcard can englob multiple directories! (and so our code gets totally buggy)
96 strncpy(tmp, foundrule->filename, 512);
97 ptr = dirname(tmp);
98 efm = ecore_file_monitor_add(ptr,
99 (Ecore_File_Monitor_Cb)spy_event,
100 NULL);
101
102 return(0);
103}
104
105/**
106 * @brief ecore_main_loop() will call this function for every notification he gets from logfiles
107 * activity.
108 *
109 * @param data (void *) Data associated to the logfile in spy_addwatcher()
110 * @param em (Ecore_File_Monitor *) Not really used here.
111 * @param event (Ecore_File_Event) Event type
112 * @param path (const char *) Name of the file that raised the event
113 *
114 * @return ECORE_CALLBACK_RENEW
115 */
116int spy_event(void *data, Ecore_File_Monitor *em, Ecore_File_Event event, const char *path)
117{
118 struct logmessage *new_logmessage;
119 char message[4096];
120
121 EINA_LOG_DOM_DBG(einadom_spy, "Event on %s ! %p - %p", path, data, em);
122 message[0] = 0;
123
124 if( event == ECORE_FILE_EVENT_MODIFIED )
125 {
126 struct logfile *log = data;
127 fpos_t new_pos;
128 unsigned long long int filesize;
129 Eina_Counter *counter;
130 char *counterresult;
131 if( !log )
132 return(ECORE_CALLBACK_RENEW);
133 counter = eina_counter_new("MessageProcessingTime");
134 eina_counter_start(counter);
135 // If logfile got trunc, than size is different
136 logfiles_getsize((char *)path, &filesize);
137
138 if( filesize < log->filesize )
139 {
140 // If event is that file has been truncated, then there is
141 // nothing to read, we just set cursor to beginning
142 logfiles_getbegin((char *)path, &(log->cursor));
143 log->filesize = filesize;
144 return(ECORE_CALLBACK_RENEW);
145 }
146 log->filesize = filesize;
147
148 EINA_LOG_DOM_DBG(einadom_spy, "Event on %s !", path);
149
150 // We must take attention to the fact that the file might
151 // Have been truncated
152 spy_extract_new_lines(log->name, log->cursor, &new_pos, message);
153 log->cursor = new_pos;
154
155 // If nothing has been read, then file has been trunc and is empty
156 // So we do nothing
157 if( message[0] == 0 )
158 return(ECORE_CALLBACK_RENEW);
159
160 logmessages_new(&new_logmessage, message, log->name);
161
162 rules_filtermessage(new_logmessage);
163
164 // Now we only have to send this filtered message to ES
165 if( !new_logmessage->todel )
166 send_logmessage(new_logmessage);
167
168 // Message is sent, we can free our structure
169 logmessages_free(&new_logmessage);
170 eina_counter_stop(counter, 1);
171
172 counterresult = eina_counter_dump(counter);
173 EINA_LOG_DOM_DBG(einadom_spy, "Message processing time :\n%s", counterresult);
174 free(counterresult);
175 eina_counter_free(counter);
176 }
177 else if( event == ECORE_FILE_EVENT_DELETED_SELF
178 || event == ECORE_FILE_EVENT_DELETED_DIRECTORY
179 || event == ECORE_FILE_EVENT_DELETED_FILE
180 )
181 {
182 struct logfile *log = data,
183 *foundlog;
184 Eina_List *l;
185 EINA_LOG_DOM_DBG(einadom_spy, "Logfile %s has been deleted!", path);
186
187 // If this file was one of the files we used to monitor,
188 // We must delete it from our list
189 EINA_LIST_FOREACH(list_logfiles, l, foundlog)
190 {
191 if( !strcmp(foundlog->name, path) )
192 {
193 list_logfiles = eina_list_remove(list_logfiles, log);
194 logfiles_del(&log);
195 break;
196 }
197 }
198 }
199 else if( event == ECORE_FILE_EVENT_CREATED_FILE
200 || event == ECORE_FILE_EVENT_CREATED_DIRECTORY
201 )
202 {
203 // A new log file has been made, we have to check if this file already is in our filelog
204 // And if a rule affects it.
205 // If so, we add it to our monitor
206 Eina_List *l;
207 struct rule *foundrule = NULL;
208 struct logfile *new_logfile = NULL;
209 fpos_t pos_tmp;
210 int ret,
211 got_it = 0;
212
213 EINA_LOG_DOM_DBG(einadom_spy, "Logfile %s has been created!", path);
214
215 // If we already monitor this file, then we ignore it
216 // Which might be a problem btw. This thing shouldnt happen
217 EINA_LIST_FOREACH(list_logfiles, l, new_logfile)
218 {
219 if( !strcmp(new_logfile->name, path) )
220 return(ECORE_CALLBACK_RENEW);
221 }
222
223 EINA_LIST_FOREACH(list_rules, l, foundrule)
224 {
225 if( foundrule->filename )
226 {
227 unsigned long long int filesize;
228 ret = fnmatch(foundrule->filename, path, FNM_NOESCAPE);
229 if( ret )
230 continue;
231
232 // We get our cursor pos
233 logfiles_getbegin((char *)path, &pos_tmp);
234 logfiles_getsize((char *)path, &filesize);
235 logfiles_new(&new_logfile, (char *)path, pos_tmp, filesize);
236
237 logfiles_add(new_logfile);
238 efm = ecore_file_monitor_add(path,
239 (Ecore_File_Monitor_Cb)spy_event,
240 (void *)new_logfile);
241
242 got_it = 1;
243 break;
244 }
245 }
246
247 if( got_it )
248 {
249 // We must take attention to the fact that the file might
250 // Have been truncated
251 spy_extract_new_lines(new_logfile->name, new_logfile->cursor, &new_logfile->cursor, message);
252
253 // If nothing has been read, then file has been trunc and is empty
254 // So we do nothing
255 if( message[0] == 0 )
256 return(ECORE_CALLBACK_RENEW);
257
258 logmessages_new(&new_logmessage, message, new_logfile->name);
259 rules_filtermessage(new_logmessage);
260
261 // Now we only have to send this filtered message to ES
262 if( !new_logmessage->todel )
263 send_logmessage(new_logmessage);
264
265 // Message is sent, we can free our structure
266 logmessages_free(&new_logmessage);
267 }
268 }
269 else
270 {
271 EINA_LOG_DOM_DBG(einadom_spy, "WTF event on %s !", path);
272
273 }
274 return(ECORE_CALLBACK_RENEW);
275}
276
277
278
279/**
280 * @brief Gets the new log message that has been inserted. This function kind of sucks and has to
281 * be improved to really extract all the messages and send them to a callback that will
282 * process them intead of taking only one (which can cause a problem if we don't get
283 * one inotify per message logged).
284 *
285 * @param filename (char *) File that raised an event and should be read
286 * @param pos_cur (fpos_t) current cursor position for this file
287 * @param pos_new (fpos_t *) New position of the cursor after extracting the new message
288 * @param message (char *) message extracted from the logfile
289 *
290 * @return 0 or -1 if there is an error
291 */
292int spy_extract_new_lines(char *filename, fpos_t pos_cur, fpos_t *pos_new, char *message)
293{
294 FILE *fp;
295 int ret;
296 fpos_t pos_begin;
297
298 fp = fopen(filename, "r");
299 if( !fp )
300 {
301 EINA_LOG_DOM_ERR(einadom_spy, "We haven't been able to open %s : %s", filename, strerror(errno));
302 return(-1);
303 }
304
305 fgetpos(fp, &pos_begin);
306
307
308 // If we can't set cursor, file has been truncated!
309 ret = fsetpos(fp, &pos_cur);
310 if( ret )
311 {
312 fsetpos(fp, &pos_begin);
313 *pos_new = pos_begin;
314 }
315 else *pos_new = pos_cur;
316
317 // This while is only here to avoid empty lines
318 while( 1 )
319 {
320 ret = fscanf(fp,"%4096[^\n]\n", message);
321
322 if( ret == EOF )
323 break;
324
325 // Didnt read anything
326 if( ret == 0)
327 {
328 char tmp[2];
329 EINA_LOG_DOM_DBG(einadom_spy, "Empty line hack");
330 ret = fread(tmp, 1, 1, fp);
331 if( ret != 1 )
332 EINA_LOG_DOM_DBG(einadom_spy, "WTF?!");
333 continue;
334 }
335 if( ret != 1 )
336 {
337 fgetpos(fp, pos_new);
338 break;
339 }
340 else
341 fgetpos(fp, pos_new);
342
343 // We have a message to log
344 break;
345 }
346
347 fclose(fp);
348 return(0);
349}