forked from jordansissel/grok
-
Notifications
You must be signed in to change notification settings - Fork 0
/
grok_pattern.c
139 lines (109 loc) · 3.81 KB
/
grok_pattern.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <assert.h>
#include <string.h>
#include <errno.h>
#include "grok.h"
#include "grok_pattern.h"
TCLIST *grok_pattern_name_list(const grok_t *grok) {
TCLIST *names;
const void *data;
int datalen;
TCTREE *patterns = grok->patterns;
names = tclistnew();
tctreeiterinit(patterns);
while ((data = tctreeiternext(patterns, &datalen)) != NULL) {
tclistpush(names, data, datalen);
}
return names;
}
int grok_pattern_add(const grok_t *grok, const char *name, size_t name_len,
const char *regexp, size_t regexp_len) {
TCTREE *patterns = grok->patterns;
grok_log(grok, LOG_PATTERNS, "Adding new pattern '%.*s' => '%.*s'",
name_len, name, regexp_len, regexp);
tctreeput(patterns, name, name_len, regexp, regexp_len);
return GROK_OK;
}
int grok_pattern_find(const grok_t *grok, const char *name, size_t name_len,
const char **regexp, size_t *regexp_len) {
TCTREE *patterns = grok->patterns;
*regexp = tctreeget(patterns, name, name_len, (int*) regexp_len);
grok_log(grok, LOG_PATTERNS, "Searching for pattern '%s' (%s): %.*s",
name, *regexp == NULL ? "not found" : "found", *regexp_len, *regexp);
if (*regexp == NULL) {
grok_log(grok, LOG_PATTERNS, "pattern '%s': not found", name);
*regexp = NULL;
*regexp_len = 0;
return GROK_ERROR_PATTERN_NOT_FOUND;
}
return GROK_OK;
}
int grok_patterns_import_from_file(const grok_t *grok, const char *filename) {
FILE *patfile = NULL;
size_t filesize = 0;
size_t bytes = 0;
char *buffer = NULL;
grok_log(grok, LOG_PATTERNS, "Importing pattern file: '%s'", filename);
patfile = fopen(filename, "r");
if (patfile == NULL) {
grok_log(grok, LOG_PATTERNS, "Unable to open '%s' for reading: %s",
filename, strerror(errno));
return GROK_ERROR_FILE_NOT_ACCESSIBLE;
}
fseek(patfile, 0, SEEK_END);
filesize = ftell(patfile);
fseek(patfile, 0, SEEK_SET);
buffer = calloc(1, filesize + 1);
if (buffer == NULL) {
fprintf(stderr, "Fatal: calloc(1, %zd) failed while trying to read '%s'",
filesize, filename);
abort();
}
memset(buffer, 0, filesize);
bytes = fread(buffer, 1, filesize, patfile);
if (bytes != filesize) {
grok_log(grok, LOG_PATTERNS, "Unable to open '%s' for reading: %s",
filename, strerror(errno));
fprintf(stderr, "Expected %zd bytes, but read %zd.", filesize, bytes);
return GROK_ERROR_UNEXPECTED_READ_SIZE;
}
grok_patterns_import_from_string(grok, buffer);
free(buffer);
fclose(patfile);
return GROK_OK;
}
int grok_patterns_import_from_string(const grok_t *grok, const char *buffer) {
char *tokctx = NULL;
char *tok = NULL;
char *strptr = NULL;
char *dupbuf = NULL;
grok_log(grok, LOG_PATTERNS, "Importing patterns from string");
dupbuf = strdup(buffer);
strptr = dupbuf;
while ((tok = strtok_r(strptr, "\n", &tokctx)) != NULL) {
const char *name, *regexp;
size_t name_len, regexp_len;
strptr = NULL;
/* skip leading whitespace */
tok += strspn(tok, " \t");
/* If first non-whitespace is a '#', then this is a comment. */
if (*tok == '#') continue;
_pattern_parse_string(tok, &name, &name_len, ®exp, ®exp_len);
(void) grok_pattern_add(grok, name, name_len, regexp, regexp_len);
}
free(dupbuf);
return GROK_OK;
}
void _pattern_parse_string(const char *line,
const char **name, size_t *name_len,
const char **regexp, size_t *regexp_len) {
size_t offset;
/* Skip leading whitespace */
offset = strspn(line, " \t");
*name = line + offset;
/* Find the first whitespace */
offset += strcspn(line + offset, " \t");
*name_len = offset - (*name - line);
offset += strspn(line + offset, " \t");
*regexp = line + offset;
*regexp_len = strlen(line) - (*regexp - line);
}