1 /* -*-pgsql-c-*- */
2 /*
3 * $Header$
4 *
5 * pgpool: a language independent connection pool server for PostgreSQL
6 * written by Tatsuo Ishii
7 *
8 * Copyright (c) 2003-2016 PgPool Global Development Group
9 *
10 * Permission to use, copy, modify, and distribute this software and
11 * its documentation for any purpose and without fee is hereby
12 * granted, provided that the above copyright notice appear in all
13 * copies and that both that copyright notice and this permission
14 * notice appear in supporting documentation, and that the name of the
15 * author not be used in advertising or publicity pertaining to
16 * distribution of the software without specific, written prior
17 * permission. The author makes no representations about the
18 * suitability of this software for any purpose. It is provided "as
19 * is" without express or implied warranty.
20 *
21 */
22
23 /*
24 * This module handles regular expressio arrary.
25 */
26 #include <string.h>
27
28 #include "pool.h"
29 #include "pool_config.h"
30 #include "utils/regex_array.h"
31 #ifndef POOL_PRIVATE
32 #include "utils/elog.h"
33 #include "utils/palloc.h"
34 #else
35 #include "utils/fe_ports.h"
36 #endif
37
38 /*
39 * Create RegArray object
40 */
41 RegArray *
create_regex_array(void)42 create_regex_array(void)
43 {
44 RegArray *ar;
45
46 ar = palloc(sizeof(RegArray));
47 ar->pos = 0;
48 ar->size = AR_ALLOC_UNIT;
49 ar->regex = (regex_t **) palloc(sizeof(regex_t *) * ar->size);
50
51 return ar;
52 }
53
54 /*
55 * Add an regular expression pattern
56 */
57 int
add_regex_array(RegArray * ar,char * pattern)58 add_regex_array(RegArray * ar, char *pattern)
59 {
60 int regex_flags;
61 regex_t *regex;
62 char *pat;
63 int len;
64
65 if (ar == NULL)
66 {
67 ereport(WARNING,
68 (errmsg("failed to add regex pattern, regex array is NULL")));
69
70 return -1;
71 }
72
73 if (pattern == NULL)
74 {
75 ereport(WARNING,
76 (errmsg("failed to add regex pattern, regex pattern is NULL")));
77 return -1;
78 }
79
80 len = strlen(pattern);
81
82 /* Force case insensitive pattern matching */
83 regex_flags = REG_NOSUB;
84 regex_flags |= REG_ICASE;
85
86 /* Add extended regex search */
87 regex_flags |= REG_EXTENDED;
88
89 pat = palloc(sizeof(char) * (len + 3));
90 if (strncmp(pattern, "^", 1) != 0)
91 {
92 strncpy(pat, "^", 2);
93 strncat(pat, pattern, len + 1);
94 }
95 else
96 {
97 strncpy(pat, pattern, len + 1);
98 }
99
100 if (len == 0 || (len > 0 && pattern[len - 1] != '$'))
101 {
102 strncat(pat, "$", 2);
103 }
104
105 /* Compile our regex */
106 regex = palloc(sizeof(regex_t));
107 if (regcomp(regex, pat, regex_flags) != 0)
108 {
109 ereport(WARNING,
110 (errmsg("failed to add regex pattern, invalid regex pattern: \"%s\" (%s)", pattern, pat)));
111 pfree(regex);
112 pfree(pat);
113 return -1;
114 }
115 pfree(pat);
116
117 if (ar->pos == ar->size)
118 {
119 ar->size += AR_ALLOC_UNIT;
120 ar->regex = repalloc(ar->regex, sizeof(regex_t *) * ar->size);
121 }
122 ar->regex[ar->pos] = regex;
123 ar->pos++;
124
125 return 0;
126 }
127
128 /*
129 * Execute regex matching. Returns matched array index.
130 */
131 int
regex_array_match(RegArray * ar,char * pattern)132 regex_array_match(RegArray * ar, char *pattern)
133 {
134 int i;
135
136 if (ar == NULL)
137 {
138 ereport(WARNING,
139 (errmsg("failed to execute regex matching, regex array is NULL")));
140 return -1;
141 }
142
143 if (pattern == NULL)
144 {
145 ereport(WARNING,
146 (errmsg("failed to execute regex matching, pattern is NULL")));
147 return -1;
148 }
149
150 for (i = 0; i < ar->pos; i++)
151 {
152 if (regexec(ar->regex[i], pattern, 0, 0, 0) == 0)
153 return i;
154 }
155 return -1;
156 }
157
158 /*
159 * Destroy RegArray object
160 */
161 void
destroy_regex_arrary(RegArray * ar)162 destroy_regex_arrary(RegArray * ar)
163 {
164 pfree(ar->regex);
165 pfree(ar);
166 }
167
168 /*
169 * Create L-R token array
170 */
171 Left_right_tokens *
create_lrtoken_array(void)172 create_lrtoken_array(void)
173 {
174 Left_right_tokens *ar;
175
176 ar = palloc(sizeof(Left_right_tokens));
177 ar->pos = 0;
178 ar->size = AR_ALLOC_UNIT;
179 ar->token = (Left_right_token *) palloc(sizeof(Left_right_token) * ar->size);
180
181 return ar;
182 }
183
184 /*
185 * Extract tokens separated by delimi from str. Each token is separeted by delim2,
186 * and token lists are returned to left_tokens and right_tokens respectively.
187 * Nnumber of tokens is set to *n.
188 */
189 void
extract_string_tokens2(char * str,char * delimi,char delimi2,Left_right_tokens * lrtokens)190 extract_string_tokens2(char *str, char *delimi, char delimi2, Left_right_tokens * lrtokens)
191 {
192 char *token;
193 char *mystr;
194
195 mystr = pstrdup(str);
196
197 for (token = strtok(mystr, delimi); token != NULL; token = strtok(NULL, delimi))
198 {
199 int len;
200 char *left_token;
201 char *right_token;
202 char *weight_token = NULL;
203 int i,
204 j;
205
206 len = strlen(token) + 1;
207 left_token = palloc(len);
208 right_token = palloc(len);
209 weight_token = palloc(len);
210
211 for (i = 0; token[i] && token[i] != delimi2; i++)
212 left_token[i] = token[i];
213
214 left_token[i] = '\0';
215
216 if (i == len - 1)
217 {
218 pfree(left_token);
219 pfree(right_token);
220 pfree(mystr);
221 pfree(weight_token);
222 return;
223 }
224
225 /* Skip delimiter 2 */
226 i++;
227 j = 0;
228
229 for (; token[i] && token[i] != '('; i++)
230 right_token[j++] = token[i];
231
232 right_token[j] = '\0';
233
234 /* delimiter 3 */
235 int k = 0;
236
237 if (token[i] == '(')
238 {
239 i++;
240 for (; token[i] && token[i] != ')'; i++)
241 weight_token[k++] = token[i];
242 }
243 weight_token[k] = '\0';
244
245 if (lrtokens->pos == lrtokens->size)
246 {
247 lrtokens->size += AR_ALLOC_UNIT;
248 lrtokens->token = repalloc(lrtokens->token, sizeof(Left_right_token) * lrtokens->size);
249 }
250 lrtokens->token[lrtokens->pos].left_token = left_token;
251 lrtokens->token[lrtokens->pos].right_token = right_token;
252 if (weight_token[0] != '\0')
253 lrtokens->token[lrtokens->pos].weight_token = atof(weight_token);
254 else
255 lrtokens->token[lrtokens->pos].weight_token = 1.0;
256
257 lrtokens->pos++;
258 pfree(weight_token);
259 }
260 pfree(mystr);
261 }
262