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