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 */
create_regex_array(void)41 RegArray *create_regex_array(void)
42 {
43 RegArray *ar;
44
45 ar = palloc(sizeof(RegArray));
46 ar->pos = 0;
47 ar->size = AR_ALLOC_UNIT;
48 ar->regex = (regex_t **)palloc(sizeof(regex_t *) * ar->size);
49
50 return ar;
51 }
52
53 /*
54 * Add an regular expression pattern
55 */
add_regex_array(RegArray * ar,char * pattern)56 int add_regex_array(RegArray *ar, char *pattern)
57 {
58 int regex_flags;
59 regex_t *regex;
60 char *pat;
61 int len;
62
63 if (ar == NULL)
64 {
65 ereport(WARNING,
66 (errmsg("failed to add regex pattern, regex array is NULL")));
67
68 return -1;
69 }
70
71 if (pattern == NULL)
72 {
73 ereport(WARNING,
74 (errmsg("failed to add regex pattern, regex pattern is NULL")));
75 return -1;
76 }
77
78 len = strlen(pattern);
79
80 /* Force case insensitive pattern matching */
81 regex_flags = REG_NOSUB;
82 regex_flags |= REG_ICASE;
83
84 /* Add extended regex search */
85 regex_flags |= REG_EXTENDED;
86
87 pat = palloc(sizeof(char)*(len+3));
88 if (strncmp(pattern, "^", 1) != 0)
89 {
90 strncpy(pat, "^", 2);
91 strncat(pat, pattern, len + 1);
92 }
93 else
94 {
95 strncpy(pat, pattern, len + 1);
96 }
97
98 if (len == 0 || (len > 0 && pattern[len - 1] != '$'))
99 {
100 strncat(pat, "$", 2);
101 }
102
103 /* Compile our regex */
104 regex = palloc(sizeof(regex_t));
105 if (regcomp(regex, pat, regex_flags) != 0)
106 {
107 ereport(WARNING,
108 (errmsg("failed to add regex pattern, invalid regex pattern: \"%s\" (%s)", pattern, pat)));
109 pfree(regex);
110 pfree(pat);
111 return -1;
112 }
113 pfree(pat);
114
115 if (ar->pos == ar->size)
116 {
117 ar->size += AR_ALLOC_UNIT;
118 ar->regex = repalloc(ar->regex, sizeof(regex_t *) * ar->size);
119 }
120 ar->regex[ar->pos] = regex;
121 ar->pos++;
122
123 return 0;
124 }
125
126 /*
127 * Execute regex matching. Returns matched array index.
128 */
regex_array_match(RegArray * ar,char * pattern)129 int regex_array_match(RegArray *ar, char *pattern)
130 {
131 int i;
132
133 if (ar == NULL)
134 {
135 ereport(WARNING,
136 (errmsg("failed to execute regex matching, regex array is NULL")));
137 return -1;
138 }
139
140 if (pattern == NULL)
141 {
142 ereport(WARNING,
143 (errmsg("failed to execute regex matching, pattern is NULL")));
144 return -1;
145 }
146
147 for (i=0;i<ar->pos;i++)
148 {
149 if (regexec(ar->regex[i], pattern, 0, 0, 0) == 0)
150 return i;
151 }
152 return -1;
153 }
154
155 /*
156 * Destroy RegArray object
157 */
destroy_regex_arrary(RegArray * ar)158 void destroy_regex_arrary(RegArray *ar)
159 {
160 pfree(ar->regex);
161 pfree(ar);
162 }
163
164 /*
165 * Create L-R token array
166 */
create_lrtoken_array(void)167 Left_right_tokens *create_lrtoken_array(void)
168 {
169 Left_right_tokens *ar;
170
171 ar = palloc(sizeof(Left_right_tokens));
172 ar->pos = 0;
173 ar->size = AR_ALLOC_UNIT;
174 ar->token = (Left_right_token *)palloc(sizeof(Left_right_token) * ar->size);
175
176 return ar;
177 }
178
179 /*
180 * Extract tokens separated by delimi from str. Each token is separeted by delim2,
181 * and token lists are returned to left_tokens and right_tokens respectively.
182 * Nnumber of tokens is set to *n.
183 */
extract_string_tokens2(char * str,char * delimi,char delimi2,Left_right_tokens * lrtokens)184 void extract_string_tokens2(char *str, char *delimi, char delimi2, Left_right_tokens *lrtokens)
185 {
186 char *token;
187 char *mystr;
188
189 mystr = pstrdup(str);
190
191 for (token = strtok(mystr, delimi); token != NULL; token = strtok(NULL, delimi))
192 {
193 int len;
194 char *left_token;
195 char *right_token;
196 int i,j;
197
198 len = strlen(token)+1;
199 left_token = palloc(len);
200 right_token = palloc(len);
201
202 for (i=0;token[i] && token[i] != delimi2;i++)
203 left_token[i] = token[i];
204
205 left_token[i] = '\0';
206
207 if (i == len -1)
208 {
209 pfree(left_token);
210 pfree(right_token);
211 pfree(mystr);
212 return;
213 }
214
215 /* Skip delimiter 2 */
216 i++;
217 j = 0;
218
219 for (;token[i];i++)
220 right_token[j++] = token[i];
221
222 right_token[j] = '\0';
223
224 if (lrtokens->pos == lrtokens->size)
225 {
226 lrtokens->size += AR_ALLOC_UNIT;
227 lrtokens->token = repalloc(lrtokens->token, sizeof(Left_right_token) * lrtokens->size);
228 }
229 lrtokens->token[lrtokens->pos].left_token = left_token;
230 lrtokens->token[lrtokens->pos].right_token = right_token;
231 lrtokens->pos++;
232 }
233 pfree(mystr);
234 }
235