1 /**
2 * qsre.c: pcre expression match test tool
3 *
4 * See http://mod-qos.sourceforge.net/ for further
5 * details.
6 *
7 * Copyright (C) 2020 Pascal Buchbinder
8 *
9 * Licensed to the Apache Software Foundation (ASF) under one or more
10 * contributor license agreements. See the NOTICE file distributed with
11 * this work for additional information regarding copyright ownership.
12 * The ASF licenses this file to You under the Apache License, Version 2.0
13 * (the "License"); you may not use this file except in compliance with
14 * the License. You may obtain a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21 * See the License for the specific language governing permissions and
22 * limitations under the License.
23 *
24 */
25
26 static const char revision[] = "$Id: qsre.c 2595 2020-01-03 06:19:53Z pbuchbinder $";
27
28 /* system */
29 #include <stdio.h>
30 #include <string.h>
31
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <time.h>
35
36 /* apr */
37 #include <pcre.h>
38 #include <apr.h>
39 #include <apr_strings.h>
40 #include <apr_time.h>
41 #include <apr_general.h>
42 #include <apr_lib.h>
43 #include <apr_portable.h>
44 #include <apr_support.h>
45
46 #include "qs_util.h"
47
48 #define QS_OVECCOUNT 100
49
50
usage(const char * cmd,int man)51 static void usage(const char *cmd, int man) {
52 if(man) {
53 //.TH [name of program] [section number] [center footer] [left footer] [center header]
54 printf(".TH %s 1 \"%s\" \"mod_qos utilities %s\" \"%s man page\"\n", qs_CMD(cmd), man_date,
55 man_version, cmd);
56 }
57 printf("\n");
58
59 if(man) {
60 printf(".SH NAME\n");
61 }
62 qs_man_print(man, "%s matches a regular expression against test strings.\n", cmd);
63 printf("\n");
64
65 if(man) {
66 printf(".SH SYNOPSIS\n");
67 }
68 qs_man_print(man, "%s%s <string>|<path> <pcre>|<path>\n", man ? "" : "Usage: ", cmd);
69 printf("\n");
70
71 if(man) {
72 printf(".SH DESCRIPTION\n");
73 } else {
74 printf("Summary\n");
75 }
76 qs_man_print(man, "Regular expression test tool.\n");
77 qs_man_print(man, "The provided regular expression (pcre, caseless matching, \".\" matches anything\n");
78 qs_man_print(man, "incl. newline) is appplied against the provided test strings to verify if the\n");
79 qs_man_print(man, "pattern matches.\n");
80 printf("\n");
81
82 if(man) {
83 printf(".SH OPTIONS\n");
84 } else {
85 printf("Options\n");
86 }
87 if(man) printf(".TP\n");
88 qs_man_print(man, " <string>|<path>\n");
89 if(man) printf("\n");
90 qs_man_print(man, " The first argument either defines a sinlge test string of a path to\n");
91 qs_man_print(man, " a file containing either multiple test strings or a test pattern with\n");
92 qs_man_print(man, " newline characters (text).\n");
93 if(man) printf("\n.TP\n");
94 qs_man_print(man, " <pcre>|<path>\n");
95 if(man) printf("\n");
96 qs_man_print(man, " The second argument either defines a regular expression or a path to\n");
97 qs_man_print(man, " a file containing the expression.\n");
98 printf("\n");
99
100 if(man) {
101 printf(".SH SEE ALSO\n");
102 printf("qsdt(1), qsexec(1), qsfilter2(1), qsgeo(1), qsgrep(1), qshead(1), qslog(1), qslogger(1), qspng(1), qsrespeed(1), qsrotate(1), qssign(1), qstail(1)\n");
103 printf(".SH AUTHOR\n");
104 printf("Pascal Buchbinder, http://mod-qos.sourceforge.net/\n");
105 } else {
106 printf("See http://mod-qos.sourceforge.net/ for further details.\n");
107 }
108 if(man) {
109 exit(0);
110 } else {
111 exit(1);
112 }
113 }
114
rmatch(const char * line,pcre * pcre)115 static int rmatch(const char *line, pcre *pcre) {
116 int ovector[QS_OVECCOUNT];
117 int rc_c = -1;
118 do {
119 int rc = pcre_exec(pcre, NULL, line, strlen(line), 0, 0, ovector, QS_OVECCOUNT);
120 if(rc >= 0) {
121 int ix;
122 rc_c = 0;
123 printf("[%.*s]", ovector[1] - ovector[0], &line[ovector[0]]);
124 for(ix = 1; ix < rc; ix++) {
125 printf(" $%d=%.*s", ix, ovector[ix*2+1] - ovector[ix*2], &line[ovector[ix*2]]);
126 }
127 line = &line[ovector[1]];
128 if(ovector[1] - ovector[0] == 0) {
129 line++;
130 }
131 } else {
132 line = NULL;
133 }
134 } while(line && line[0]);
135 return rc_c;
136 }
137
main(int argc,const char * const argv[])138 int main(int argc, const char *const argv[]) {
139 const char *errptr = NULL;
140 int erroffset;
141 pcre *pcre;
142 int rc_c = -1;
143 const char *line;
144 const char *in;
145 const char *pattern;
146 FILE *file;
147 apr_pool_t *pool;
148 char *raw = "";
149 int linenr = 0;
150
151 const char *cmd = strrchr(argv[0], '/');
152
153 apr_app_initialize(&argc, &argv, NULL);
154 apr_pool_create(&pool, NULL);
155
156 if(cmd == NULL) {
157 cmd = (char *)argv[0];
158 } else {
159 cmd++;
160 }
161
162 argc--;
163 argv++;
164 if(argc != 2) {
165 if(argc == 1 && strcmp(argv[0], "--man") == 0) {
166 usage(cmd, 1);
167 } else {
168 usage(cmd, 0);
169 }
170 }
171 in = argv[0];
172 pattern = argv[1];
173
174 file = fopen(pattern, "r");
175 if(file) {
176 char readline[MAX_LINE];
177 if(fgets(readline, MAX_LINE-1, file) != NULL) {
178 int len = strlen(readline);
179 while(len > 0 && readline[len] < 32) {
180 readline[len] = '\0';
181 len--;
182 }
183 pattern = apr_pstrdup(pool, readline);
184 }
185 fclose(file);
186 }
187 printf("expression: %s\n", pattern);
188
189 pcre = pcre_compile(pattern, PCRE_DOTALL|PCRE_CASELESS, &errptr, &erroffset, NULL);
190 if(pcre == NULL) {
191 fprintf(stderr, "ERROR, rule <%s> could not compile pcre at position %d,"
192 " reason: %s\n", pattern, erroffset, errptr);
193 exit(1);
194 }
195
196 file = fopen(in, "r");
197 if(file) {
198 char readline[MAX_LINE];
199 while(fgets(readline, MAX_LINE-1, file) != NULL) {
200 int len = strlen(readline);
201 linenr++;
202 printf("line %.3d: ", linenr);
203 raw = apr_pstrcat(pool, raw, readline, NULL);
204 while(len > 0 && readline[len] < 32) {
205 readline[len] = '\0';
206 len--;
207 }
208 if(readline[0] >= 32 && strlen(readline) > 0) {
209 line = readline;
210 rc_c = rmatch(line, pcre);
211 }
212 printf("\n");
213 }
214 fclose(file);
215 printf("entire content match:\n");
216 rc_c = rmatch(raw, pcre);
217 printf("\n");
218 } else {
219 line = in;
220 rc_c = rmatch(line, pcre);
221 printf("\n");
222 }
223 if(rc_c < 0) {
224 printf("no match\n");
225 return 2;
226 }
227 return 0;
228 }
229