/* * Copyright (C) 2009 iptelorg GmbH * * This file is part of Kamailio, a free SIP server. * * Kamailio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * Kamailio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ #include /* hook prototypes */ #include "../../mem/shm_mem.h" #include "shm_regex.h" typedef void *(malloc_hook_t) (size_t, const void *); typedef void *(realloc_hook_t) (void *, size_t, const void *); typedef void (free_hook_t) (void *, const void *); /* The memory hooks are overwritten before calling regcomp(), regfree(), * and regexec(), and shared memory function are called * from the hooks instead of libc malloc/realloc/free. */ static void *shm_malloc_hook(size_t size, const void *caller) { return shm_malloc (size); } static void *shm_realloc_hook(void *p, size_t size, const void *caller) { return shm_realloc (p, size); } static void shm_free_hook(void *ptr, const void *caller) { if (ptr) shm_free (ptr); } #define replace_malloc_hooks() \ do { \ orig_malloc_hook = __malloc_hook; \ orig_realloc_hook = __realloc_hook; \ orig_free_hook = __free_hook; \ __malloc_hook = shm_malloc_hook; \ __realloc_hook = shm_realloc_hook; \ __free_hook = shm_free_hook; \ } while (0) #define restore_malloc_hooks() \ do { \ __malloc_hook = orig_malloc_hook; \ __realloc_hook = orig_realloc_hook; \ __free_hook = orig_free_hook; \ } while (0) int shm_regcomp(shm_regex_t *preg, const char *regex, int cflags) { malloc_hook_t *orig_malloc_hook; realloc_hook_t *orig_realloc_hook; free_hook_t *orig_free_hook; int ret; if(!lock_init(&preg->lock)) { return REG_EEND; } replace_malloc_hooks(); ret = regcomp(&preg->regexp, regex, cflags); restore_malloc_hooks(); if(ret) lock_destroy(&preg->lock); return ret; } void shm_regfree(shm_regex_t *preg) { malloc_hook_t *orig_malloc_hook; realloc_hook_t *orig_realloc_hook; free_hook_t *orig_free_hook; lock_destroy(&preg->lock); replace_malloc_hooks(); regfree(&preg->regexp); restore_malloc_hooks(); } int shm_regexec(shm_regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) { malloc_hook_t *orig_malloc_hook; realloc_hook_t *orig_realloc_hook; free_hook_t *orig_free_hook; int ret; /* regexec() allocates some memory for the pattern buffer * when it is successfully called for the first time, therefore * shared memory is required also here. * The drawback is that shared memory allocation is also used * needlessly for allocating the temporary space for * the elements of pmatch. -- Does not happen if pmatch and * nmatch are 0. * It is safe to call regexec() concurrently without locking, * because regexec() has its own locks. * (Miklos) * * Those locks, however, don't work with shm and multi-core hardware * causing a dead-lock. Tested with glibc 2.3.6. (skeller) */ lock_get(&preg->lock); replace_malloc_hooks(); ret = regexec(&preg->regexp, string, nmatch, pmatch, eflags); restore_malloc_hooks(); lock_release(&preg->lock); return ret; } size_t shm_regerror(int errcode, const shm_regex_t *preg, char *errbuf, size_t errbuf_size) { return regerror(errcode, &preg->regexp, errbuf, errbuf_size); }