1 /**************************************************************************** 2 * Copyright (c) 1998-2015,2018 Free Software Foundation, Inc. * 3 * * 4 * Permission is hereby granted, free of charge, to any person obtaining a * 5 * copy of this software and associated documentation files (the * 6 * "Software"), to deal in the Software without restriction, including * 7 * without limitation the rights to use, copy, modify, merge, publish, * 8 * distribute, distribute with modifications, sublicense, and/or sell * 9 * copies of the Software, and to permit persons to whom the Software is * 10 * furnished to do so, subject to the following conditions: * 11 * * 12 * The above copyright notice and this permission notice shall be included * 13 * in all copies or substantial portions of the Software. * 14 * * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 18 * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 21 * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 22 * * 23 * Except as contained in this notice, the name(s) of the above copyright * 24 * holders shall not be used in advertising or otherwise to promote the * 25 * sale, use or other dealings in this Software without prior written * 26 * authorization. * 27 ****************************************************************************/ 28 29 /*************************************************************************** 30 * * 31 * Author : Juergen Pfeifer * 32 * * 33 ***************************************************************************/ 34 35 #include "form.priv.h" 36 37 MODULE_ID("$Id: fty_regex.c,v 1.27 2018/07/14 21:41:39 tom Exp $") 38 39 #if HAVE_REGEX_H_FUNCS || HAVE_LIB_PCRE2 /* We prefer POSIX regex */ 40 41 #if HAVE_PCRE2_POSIX_H 42 #include <pcre2-posix.h> 43 #elif HAVE_PCREPOSIX_H 44 #include <pcreposix.h> 45 #else 46 #include <regex.h> 47 #endif 48 49 typedef struct 50 { 51 regex_t *pRegExp; 52 unsigned long *refCount; 53 } 54 RegExp_Arg; 55 56 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 57 #undef RETURN 58 static int reg_errno; 59 60 static char * 61 RegEx_Init(char *instring) 62 { 63 reg_errno = 0; 64 return instring; 65 } 66 67 static char * 68 RegEx_Error(int code) 69 { 70 reg_errno = code; 71 return 0; 72 } 73 74 #define INIT register char *sp = RegEx_Init(instring); 75 #define GETC() (*sp++) 76 #define PEEKC() (*sp) 77 #define UNGETC(c) (--sp) 78 #define RETURN(c) return(c) 79 #define ERROR(c) return RegEx_Error(c) 80 81 #if HAVE_REGEXP_H_FUNCS 82 #include <regexp.h> 83 #else 84 #include <regexpr.h> 85 #endif 86 87 typedef struct 88 { 89 char *compiled_expression; 90 unsigned long *refCount; 91 } 92 RegExp_Arg; 93 94 /* Maximum Length we allow for a compiled regular expression */ 95 #define MAX_RX_LEN (2048) 96 #define RX_INCREMENT (256) 97 98 #endif 99 100 #if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 101 # define MAYBE_UNUSED 102 #else 103 # define MAYBE_UNUSED GCC_UNUSED 104 #endif 105 106 /*--------------------------------------------------------------------------- 107 | Facility : libnform 108 | Function : static void *Generic_RegularExpression_Type(void * arg) 109 | 110 | Description : Allocate structure for regex type argument. 111 | 112 | Return Values : Pointer to argument structure or NULL on error 113 +--------------------------------------------------------------------------*/ 114 static void * 115 Generic_RegularExpression_Type(void *arg MAYBE_UNUSED) 116 { 117 #if HAVE_REGEX_H_FUNCS 118 char *rx = (char *)arg; 119 RegExp_Arg *preg = (RegExp_Arg *)0; 120 121 if (rx) 122 { 123 preg = typeCalloc(RegExp_Arg, 1); 124 125 if (preg) 126 { 127 T((T_CREATE("RegExp_Arg %p"), (void *)preg)); 128 if (((preg->pRegExp = typeMalloc(regex_t, 1)) != 0) 129 && !regcomp(preg->pRegExp, rx, 130 (REG_EXTENDED | REG_NOSUB | REG_NEWLINE))) 131 { 132 T((T_CREATE("regex_t %p"), (void *)preg->pRegExp)); 133 if ((preg->refCount = typeMalloc(unsigned long, 1)) != 0) 134 *(preg->refCount) = 1; 135 } 136 else 137 { 138 if (preg->pRegExp) 139 free(preg->pRegExp); 140 free(preg); 141 preg = (RegExp_Arg *)0; 142 } 143 } 144 } 145 return ((void *)preg); 146 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 147 char *rx = (char *)arg; 148 RegExp_Arg *pArg = (RegExp_Arg *)0; 149 150 if (rx) 151 { 152 pArg = typeMalloc(RegExp_Arg, 1); 153 154 if (pArg) 155 { 156 int blen = RX_INCREMENT; 157 158 T((T_CREATE("RegExp_Arg %p"), pArg)); 159 pArg->compiled_expression = NULL; 160 if ((pArg->refCount = typeMalloc(unsigned long, 1)) != 0) 161 *(pArg->refCount) = 1; 162 163 do 164 { 165 char *buf = typeMalloc(char, blen); 166 167 if (buf) 168 { 169 #if HAVE_REGEXP_H_FUNCS 170 char *last_pos = compile(rx, buf, &buf[blen], '\0'); 171 172 #else /* HAVE_REGEXPR_H_FUNCS */ 173 char *last_pos = compile(rx, buf, &buf[blen]); 174 #endif 175 if (reg_errno) 176 { 177 free(buf); 178 if (reg_errno == 50) 179 blen += RX_INCREMENT; 180 else 181 { 182 free(pArg); 183 pArg = NULL; 184 break; 185 } 186 } 187 else 188 { 189 pArg->compiled_expression = buf; 190 break; 191 } 192 } 193 } 194 while (blen <= MAX_RX_LEN); 195 } 196 if (pArg && !pArg->compiled_expression) 197 { 198 free(pArg); 199 pArg = NULL; 200 } 201 } 202 return (void *)pArg; 203 #else 204 return 0; 205 #endif 206 } 207 208 /*--------------------------------------------------------------------------- 209 | Facility : libnform 210 | Function : static void *Make_RegularExpression_Type(va_list * ap) 211 | 212 | Description : Allocate structure for regex type argument. 213 | 214 | Return Values : Pointer to argument structure or NULL on error 215 +--------------------------------------------------------------------------*/ 216 static void * 217 Make_RegularExpression_Type(va_list *ap) 218 { 219 char *rx = va_arg(*ap, char *); 220 221 return Generic_RegularExpression_Type((void *)rx); 222 } 223 224 /*--------------------------------------------------------------------------- 225 | Facility : libnform 226 | Function : static void *Copy_RegularExpression_Type( 227 | const void * argp) 228 | 229 | Description : Copy structure for regex type argument. 230 | 231 | Return Values : Pointer to argument structure or NULL on error. 232 +--------------------------------------------------------------------------*/ 233 static void * 234 Copy_RegularExpression_Type(const void *argp MAYBE_UNUSED) 235 { 236 #if (HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS) 237 const RegExp_Arg *ap = (const RegExp_Arg *)argp; 238 const RegExp_Arg *result = (const RegExp_Arg *)0; 239 240 if (ap) 241 { 242 *(ap->refCount) += 1; 243 result = ap; 244 } 245 return (void *)result; 246 #else 247 return 0; 248 #endif 249 } 250 251 /*--------------------------------------------------------------------------- 252 | Facility : libnform 253 | Function : static void Free_RegularExpression_Type(void * argp) 254 | 255 | Description : Free structure for regex type argument. 256 | 257 | Return Values : - 258 +--------------------------------------------------------------------------*/ 259 static void 260 Free_RegularExpression_Type(void *argp MAYBE_UNUSED) 261 { 262 #if HAVE_REGEX_H_FUNCS | HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 263 RegExp_Arg *ap = (RegExp_Arg *)argp; 264 265 if (ap) 266 { 267 if (--(*(ap->refCount)) == 0) 268 { 269 #if HAVE_REGEX_H_FUNCS 270 if (ap->pRegExp) 271 { 272 free(ap->refCount); 273 regfree(ap->pRegExp); 274 free(ap->pRegExp); 275 } 276 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 277 if (ap->compiled_expression) 278 { 279 free(ap->refCount); 280 free(ap->compiled_expression); 281 } 282 #endif 283 free(ap); 284 } 285 } 286 #endif 287 } 288 289 /*--------------------------------------------------------------------------- 290 | Facility : libnform 291 | Function : static bool Check_RegularExpression_Field( 292 | FIELD * field, 293 | const void * argp) 294 | 295 | Description : Validate buffer content to be a valid regular expression 296 | 297 | Return Values : TRUE - field is valid 298 | FALSE - field is invalid 299 +--------------------------------------------------------------------------*/ 300 static bool 301 Check_RegularExpression_Field(FIELD *field MAYBE_UNUSED, 302 const void *argp MAYBE_UNUSED) 303 { 304 bool match = FALSE; 305 306 #if HAVE_REGEX_H_FUNCS 307 const RegExp_Arg *ap = (const RegExp_Arg *)argp; 308 309 if (ap && ap->pRegExp) 310 match = (regexec(ap->pRegExp, field_buffer(field, 0), 0, NULL, 0) 311 ? FALSE 312 : TRUE); 313 #elif HAVE_REGEXP_H_FUNCS | HAVE_REGEXPR_H_FUNCS 314 RegExp_Arg *ap = (RegExp_Arg *)argp; 315 316 if (ap && ap->compiled_expression) 317 match = (step(field_buffer(field, 0), ap->compiled_expression) 318 ? TRUE 319 : FALSE); 320 #endif 321 return match; 322 } 323 324 static FIELDTYPE typeREGEXP = 325 { 326 _HAS_ARGS | _RESIDENT, 327 1, /* this is mutable, so we can't be const */ 328 (FIELDTYPE *)0, 329 (FIELDTYPE *)0, 330 Make_RegularExpression_Type, 331 Copy_RegularExpression_Type, 332 Free_RegularExpression_Type, 333 INIT_FT_FUNC(Check_RegularExpression_Field), 334 INIT_FT_FUNC(NULL), 335 INIT_FT_FUNC(NULL), 336 INIT_FT_FUNC(NULL), 337 #if NCURSES_INTEROP_FUNCS 338 Generic_RegularExpression_Type 339 #endif 340 }; 341 342 NCURSES_EXPORT_VAR(FIELDTYPE*) TYPE_REGEXP = &typeREGEXP; 343 344 #if NCURSES_INTEROP_FUNCS 345 /* The next routines are to simplify the use of ncurses from 346 programming languages with restictions on interop with C level 347 constructs (e.g. variable access or va_list + ellipsis constructs) 348 */ 349 NCURSES_EXPORT(FIELDTYPE *) 350 _nc_TYPE_REGEXP(void) 351 { 352 return TYPE_REGEXP; 353 } 354 #endif 355 356 /* fty_regex.c ends here */ 357