/** * qsre.c: pcre expression match test tool * * See http://mod-qos.sourceforge.net/ for further * details. * * Copyright (C) 2023 Pascal Buchbinder * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ static const char revision[] = "$Id: qsre.c 2654 2022-05-13 09:12:42Z pbuchbinder $"; /* system */ #include #include #include #include #include /* apr */ #include #include #include #include #include #include #include #define PCRE2_CODE_UNIT_WIDTH 8 #include #include "qs_util.h" #define QS_OVECCOUNT 100 static void usage(const char *cmd, int man) { if(man) { //.TH [name of program] [section number] [center footer] [left footer] [center header] printf(".TH %s 1 \"%s\" \"mod_qos utilities %s\" \"%s man page\"\n", qs_CMD(cmd), man_date, man_version, cmd); } printf("\n"); if(man) { printf(".SH NAME\n"); } qs_man_print(man, "%s matches a regular expression against test strings.\n", cmd); printf("\n"); if(man) { printf(".SH SYNOPSIS\n"); } qs_man_print(man, "%s%s | |\n", man ? "" : "Usage: ", cmd); printf("\n"); if(man) { printf(".SH DESCRIPTION\n"); } else { printf("Summary\n"); } qs_man_print(man, "Regular expression test tool.\n"); qs_man_print(man, "The provided regular expression (pcre, caseless matching, \".\" matches anything\n"); qs_man_print(man, "incl. newline) is appplied against the provided test strings to verify if the\n"); qs_man_print(man, "pattern matches.\n"); printf("\n"); if(man) { printf(".SH OPTIONS\n"); } else { printf("Options\n"); } if(man) printf(".TP\n"); qs_man_print(man, " |\n"); if(man) printf("\n"); qs_man_print(man, " The first argument either defines a single test string of a path to\n"); qs_man_print(man, " a file containing either multiple test strings or a test pattern with\n"); qs_man_print(man, " newline characters (text).\n"); if(man) printf("\n.TP\n"); qs_man_print(man, " |\n"); if(man) printf("\n"); qs_man_print(man, " The second argument either defines a regular expression or a path to\n"); qs_man_print(man, " a file containing the expression.\n"); printf("\n"); if(man) { printf(".SH SEE ALSO\n"); 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"); printf(".SH AUTHOR\n"); printf("Pascal Buchbinder, http://mod-qos.sourceforge.net/\n"); } else { printf("See http://mod-qos.sourceforge.net/ for further details.\n"); } if(man) { exit(0); } else { exit(1); } } static int rmatch(const char *line, qs_regex_t *preg) { qs_regmatch_t regm[QS_MAX_REG_MATCH]; int rc_c = -1; do { int rc = qs_regexec_len(preg, line, strlen(line), QS_MAX_REG_MATCH, regm, 0); if(rc >= 0) { int ix; rc_c = 0; printf("[%.*s]", regm[0].rm_eo - regm[0].rm_so, &line[regm[0].rm_so]); for(ix = 1; ix < rc; ix++) { printf(" $%d=%.*s", ix, regm[ix].rm_eo - regm[ix].rm_so, &line[regm[ix].rm_so]); } line = &line[regm[0].rm_eo]; } else { line = NULL; } } while(line && line[0]); return rc_c; } int main(int argc, const char *const argv[]) { const char *errptr = NULL; int erroffset; qs_regex_t *preg; int rc_c = -1; const char *line; const char *in; const char *pattern; FILE *file; apr_pool_t *pool; char *raw = ""; int linenr = 0; const char *cmd = strrchr(argv[0], '/'); apr_app_initialize(&argc, &argv, NULL); apr_pool_create(&pool, NULL); if(cmd == NULL) { cmd = (char *)argv[0]; } else { cmd++; } argc--; argv++; if(argc != 2) { if(argc == 1 && strcmp(argv[0], "--man") == 0) { usage(cmd, 1); } else { usage(cmd, 0); } } in = argv[0]; pattern = argv[1]; file = fopen(pattern, "r"); if(file) { char readline[MAX_LINE]; if(fgets(readline, MAX_LINE-1, file) != NULL) { int len = strlen(readline); while(len > 0 && readline[len] < 32) { readline[len] = '\0'; len--; } pattern = apr_pstrdup(pool, readline); } fclose(file); } printf("expression: %s\n", pattern); preg = apr_palloc(pool, sizeof(qs_regex_t)); if(qs_regcomp(preg, pattern, PCRE2_DOTALL|PCRE2_CASELESS) != 0) { fprintf(stderr, "ERROR, rule <%s> could not compile regular expression\n", pattern); exit(1); } apr_pool_pre_cleanup_register(pool, preg, qs_pregfree); file = fopen(in, "r"); if(file) { char readline[MAX_LINE]; while(fgets(readline, MAX_LINE-1, file) != NULL) { int len = strlen(readline); linenr++; printf("line %.3d: ", linenr); raw = apr_pstrcat(pool, raw, readline, NULL); while(len > 0 && readline[len] < 32) { readline[len] = '\0'; len--; } if(readline[0] >= 32 && strlen(readline) > 0) { line = readline; rc_c = rmatch(line, preg); } printf("\n"); } fclose(file); printf("entire content match:\n"); rc_c = rmatch(raw, preg); printf("\n"); } else { line = in; rc_c = rmatch(line, preg); printf("\n"); } if(rc_c < 0) { printf("no match\n"); return 2; } return 0; }