Blame hooks/apr_hooks.c

Packit 383869
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 383869
 * contributor license agreements.  See the NOTICE file distributed with
Packit 383869
 * this work for additional information regarding copyright ownership.
Packit 383869
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 383869
 * (the "License"); you may not use this file except in compliance with
Packit 383869
 * the License.  You may obtain a copy of the License at
Packit 383869
 *
Packit 383869
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 383869
 *
Packit 383869
 * Unless required by applicable law or agreed to in writing, software
Packit 383869
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 383869
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 383869
 * See the License for the specific language governing permissions and
Packit 383869
 * limitations under the License.
Packit 383869
 */
Packit 383869
Packit 383869
#include <assert.h>
Packit 383869
#include <stdio.h>
Packit 383869
#include <stdlib.h>
Packit 383869
Packit 383869
#include "apr_pools.h"
Packit 383869
#include "apr_tables.h"
Packit 383869
#include "apr.h"
Packit 383869
#include "apr_hooks.h"
Packit 383869
#include "apr_hash.h"
Packit 383869
#include "apr_optional_hooks.h"
Packit 383869
#include "apr_optional.h"
Packit 383869
#define APR_WANT_MEMFUNC
Packit 383869
#define APR_WANT_STRFUNC
Packit 383869
#include "apr_want.h"
Packit 383869
Packit 383869
#if 0
Packit 383869
#define apr_palloc(pool,size)   malloc(size)
Packit 383869
#endif
Packit 383869
Packit 383869
APU_DECLARE_DATA apr_pool_t *apr_hook_global_pool = NULL;
Packit 383869
APU_DECLARE_DATA int apr_hook_debug_enabled = 0;
Packit 383869
APU_DECLARE_DATA const char *apr_hook_debug_current = NULL;
Packit 383869
Packit 383869
/** @deprecated @see apr_hook_global_pool */
Packit 383869
APU_DECLARE_DATA apr_pool_t *apr_global_hook_pool = NULL;
Packit 383869
Packit 383869
/** @deprecated @see apr_hook_debug_enabled */
Packit 383869
APU_DECLARE_DATA int apr_debug_module_hooks = 0;
Packit 383869
Packit 383869
/** @deprecated @see apr_hook_debug_current */
Packit 383869
APU_DECLARE_DATA const char *apr_current_hooking_module = NULL;
Packit 383869
Packit 383869
/* NB: This must echo the LINK_##name structure */
Packit 383869
typedef struct
Packit 383869
{
Packit 383869
    void (*dummy)(void *);
Packit 383869
    const char *szName;
Packit 383869
    const char * const *aszPredecessors;
Packit 383869
    const char * const *aszSuccessors;
Packit 383869
    int nOrder;
Packit 383869
} TSortData;
Packit 383869
Packit 383869
typedef struct tsort_
Packit 383869
{
Packit 383869
    void *pData;
Packit 383869
    int nPredecessors;
Packit 383869
    struct tsort_ **ppPredecessors;
Packit 383869
    struct tsort_ *pNext;
Packit 383869
} TSort;
Packit 383869
Packit 383869
#ifdef NETWARE
Packit 383869
#include "apr_private.h"
Packit 383869
#define get_apd                 APP_DATA* apd = (APP_DATA*)get_app_data(gLibId);
Packit 383869
#define s_aHooksToSort          ((apr_array_header_t *)(apd->gs_aHooksToSort))
Packit 383869
#define s_phOptionalHooks       ((apr_hash_t *)(apd->gs_phOptionalHooks))
Packit 383869
#define s_phOptionalFunctions   ((apr_hash_t *)(apd->gs_phOptionalFunctions))
Packit 383869
#endif
Packit 383869
Packit 383869
static int crude_order(const void *a_,const void *b_)
Packit 383869
{
Packit 383869
    const TSortData *a=a_;
Packit 383869
    const TSortData *b=b_;
Packit 383869
Packit 383869
    return a->nOrder-b->nOrder;
Packit 383869
}
Packit 383869
Packit 383869
static TSort *prepare(apr_pool_t *p,TSortData *pItems,int nItems)
Packit 383869
{
Packit 383869
    TSort *pData=apr_palloc(p,nItems*sizeof *pData);
Packit 383869
    int n;
Packit 383869
Packit 383869
    qsort(pItems,nItems,sizeof *pItems,crude_order);
Packit 383869
    for(n=0 ; n < nItems ; ++n) {
Packit 383869
        pData[n].nPredecessors=0;
Packit 383869
        pData[n].ppPredecessors=apr_pcalloc(p,nItems*sizeof *pData[n].ppPredecessors);
Packit 383869
        pData[n].pNext=NULL;
Packit 383869
        pData[n].pData=&pItems[n];
Packit 383869
    }
Packit 383869
Packit 383869
    for(n=0 ; n < nItems ; ++n) {
Packit 383869
        int i,k;
Packit 383869
Packit 383869
        for(i=0 ; pItems[n].aszPredecessors && pItems[n].aszPredecessors[i] ; ++i)
Packit 383869
            for(k=0 ; k < nItems ; ++k)
Packit 383869
                if(!strcmp(pItems[k].szName,pItems[n].aszPredecessors[i])) {
Packit 383869
                    int l;
Packit 383869
Packit 383869
                    for(l=0 ; l < pData[n].nPredecessors ; ++l)
Packit 383869
                        if(pData[n].ppPredecessors[l] == &pData[k])
Packit 383869
                            goto got_it;
Packit 383869
                    pData[n].ppPredecessors[pData[n].nPredecessors]=&pData[k];
Packit 383869
                    ++pData[n].nPredecessors;
Packit 383869
                got_it:
Packit 383869
                    break;
Packit 383869
                }
Packit 383869
        for(i=0 ; pItems[n].aszSuccessors && pItems[n].aszSuccessors[i] ; ++i)
Packit 383869
            for(k=0 ; k < nItems ; ++k)
Packit 383869
                if(!strcmp(pItems[k].szName,pItems[n].aszSuccessors[i])) {
Packit 383869
                    int l;
Packit 383869
Packit 383869
                    for(l=0 ; l < pData[k].nPredecessors ; ++l)
Packit 383869
                        if(pData[k].ppPredecessors[l] == &pData[n])
Packit 383869
                            goto got_it2;
Packit 383869
                    pData[k].ppPredecessors[pData[k].nPredecessors]=&pData[n];
Packit 383869
                    ++pData[k].nPredecessors;
Packit 383869
                got_it2:
Packit 383869
                    break;
Packit 383869
                }
Packit 383869
    }
Packit 383869
Packit 383869
    return pData;
Packit 383869
}
Packit 383869
Packit 383869
/* Topologically sort, dragging out-of-order items to the front. Note that
Packit 383869
   this tends to preserve things that want to be near the front better, and
Packit 383869
   changing that behaviour might compromise some of Apache's behaviour (in
Packit 383869
   particular, mod_log_forensic might otherwise get pushed to the end, and
Packit 383869
   core.c's log open function used to end up at the end when pushing items
Packit 383869
   to the back was the methedology). Also note that the algorithm could
Packit 383869
   go back to its original simplicity by sorting from the back instead of
Packit 383869
   the front.
Packit 383869
*/
Packit 383869
static TSort *tsort(TSort *pData,int nItems)
Packit 383869
{
Packit 383869
    int nTotal;
Packit 383869
    TSort *pHead=NULL;
Packit 383869
    TSort *pTail=NULL;
Packit 383869
Packit 383869
    for(nTotal=0 ; nTotal < nItems ; ++nTotal) {
Packit 383869
        int n,i,k;
Packit 383869
Packit 383869
        for(n=0 ; ; ++n) {
Packit 383869
            if(n == nItems)
Packit 383869
                assert(0);      /* we have a loop... */
Packit 383869
            if(!pData[n].pNext) {
Packit 383869
                if(pData[n].nPredecessors) {
Packit 383869
                    for(k=0 ; ; ++k) {
Packit 383869
                        assert(k < nItems);
Packit 383869
                        if(pData[n].ppPredecessors[k])
Packit 383869
                            break;
Packit 383869
                    }
Packit 383869
                    for(i=0 ; ; ++i) {
Packit 383869
                        assert(i < nItems);
Packit 383869
                        if(&pData[i] == pData[n].ppPredecessors[k]) {
Packit 383869
                            n=i-1;
Packit 383869
                            break;
Packit 383869
                        }
Packit 383869
                    }
Packit 383869
                } else
Packit 383869
                    break;
Packit 383869
            }
Packit 383869
        }
Packit 383869
        if(pTail)
Packit 383869
            pTail->pNext=&pData[n];
Packit 383869
        else
Packit 383869
            pHead=&pData[n];
Packit 383869
        pTail=&pData[n];
Packit 383869
        pTail->pNext=pTail;     /* fudge it so it looks linked */
Packit 383869
        for(i=0 ; i < nItems ; ++i)
Packit 383869
            for(k=0 ; k < nItems ; ++k)
Packit 383869
                if(pData[i].ppPredecessors[k] == &pData[n]) {
Packit 383869
                    --pData[i].nPredecessors;
Packit 383869
                    pData[i].ppPredecessors[k]=NULL;
Packit 383869
                    break;
Packit 383869
                }
Packit 383869
    }
Packit 383869
    pTail->pNext=NULL;  /* unfudge the tail */
Packit 383869
    return pHead;
Packit 383869
}
Packit 383869
Packit 383869
static apr_array_header_t *sort_hook(apr_array_header_t *pHooks,
Packit 383869
                                     const char *szName)
Packit 383869
{
Packit 383869
    apr_pool_t *p;
Packit 383869
    TSort *pSort;
Packit 383869
    apr_array_header_t *pNew;
Packit 383869
    int n;
Packit 383869
Packit 383869
    apr_pool_create(&p, apr_hook_global_pool);
Packit 383869
    pSort=prepare(p,(TSortData *)pHooks->elts,pHooks->nelts);
Packit 383869
    pSort=tsort(pSort,pHooks->nelts);
Packit 383869
    pNew=apr_array_make(apr_hook_global_pool,pHooks->nelts,sizeof(TSortData));
Packit 383869
    if(apr_hook_debug_enabled)
Packit 383869
        printf("Sorting %s:",szName);
Packit 383869
    for(n=0 ; pSort ; pSort=pSort->pNext,++n) {
Packit 383869
        TSortData *pHook;
Packit 383869
        assert(n < pHooks->nelts);
Packit 383869
        pHook=apr_array_push(pNew);
Packit 383869
        memcpy(pHook,pSort->pData,sizeof *pHook);
Packit 383869
        if(apr_hook_debug_enabled)
Packit 383869
            printf(" %s",pHook->szName);
Packit 383869
    }
Packit 383869
    if(apr_hook_debug_enabled)
Packit 383869
        fputc('\n',stdout);
Packit 383869
Packit 383869
    /* destroy the pool - the sorted hooks were already copied */
Packit 383869
    apr_pool_destroy(p);
Packit 383869
Packit 383869
    return pNew;
Packit 383869
}
Packit 383869
Packit 383869
#ifndef NETWARE
Packit 383869
static apr_array_header_t *s_aHooksToSort;
Packit 383869
#endif
Packit 383869
Packit 383869
typedef struct
Packit 383869
{
Packit 383869
    const char *szHookName;
Packit 383869
    apr_array_header_t **paHooks;
Packit 383869
} HookSortEntry;
Packit 383869
Packit 383869
APU_DECLARE(void) apr_hook_sort_register(const char *szHookName,
Packit 383869
                                        apr_array_header_t **paHooks)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    HookSortEntry *pEntry;
Packit 383869
Packit 383869
    if(!s_aHooksToSort)
Packit 383869
        s_aHooksToSort=apr_array_make(apr_hook_global_pool,1,sizeof(HookSortEntry));
Packit 383869
    pEntry=apr_array_push(s_aHooksToSort);
Packit 383869
    pEntry->szHookName=szHookName;
Packit 383869
    pEntry->paHooks=paHooks;
Packit 383869
}
Packit 383869
Packit 383869
APU_DECLARE(void) apr_hook_sort_all(void)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    int n;
Packit 383869
Packit 383869
    if (!s_aHooksToSort) {
Packit 383869
        s_aHooksToSort = apr_array_make(apr_hook_global_pool, 1, sizeof(HookSortEntry));
Packit 383869
    }
Packit 383869
Packit 383869
    for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
Packit 383869
        HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
Packit 383869
        *pEntry->paHooks=sort_hook(*pEntry->paHooks,pEntry->szHookName);
Packit 383869
    }
Packit 383869
}
Packit 383869
Packit 383869
#ifndef NETWARE
Packit 383869
static apr_hash_t *s_phOptionalHooks;
Packit 383869
static apr_hash_t *s_phOptionalFunctions;
Packit 383869
#endif
Packit 383869
Packit 383869
APU_DECLARE(void) apr_hook_deregister_all(void)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    int n;
Packit 383869
Packit 383869
    if (!s_aHooksToSort) {
Packit 383869
        return;
Packit 383869
    }
Packit 383869
Packit 383869
    for(n=0 ; n < s_aHooksToSort->nelts ; ++n) {
Packit 383869
        HookSortEntry *pEntry=&((HookSortEntry *)s_aHooksToSort->elts)[n];
Packit 383869
        *pEntry->paHooks=NULL;
Packit 383869
    }
Packit 383869
    s_aHooksToSort=NULL;
Packit 383869
    s_phOptionalHooks=NULL;
Packit 383869
    s_phOptionalFunctions=NULL;
Packit 383869
}
Packit 383869
Packit 383869
APU_DECLARE(void) apr_hook_debug_show(const char *szName,
Packit 383869
                                      const char * const *aszPre,
Packit 383869
                                      const char * const *aszSucc)
Packit 383869
{
Packit 383869
    int nFirst;
Packit 383869
Packit 383869
    printf("  Hooked %s",szName);
Packit 383869
    if(aszPre) {
Packit 383869
        fputs(" pre(",stdout);
Packit 383869
        nFirst=1;
Packit 383869
        while(*aszPre) {
Packit 383869
            if(!nFirst)
Packit 383869
                fputc(',',stdout);
Packit 383869
            nFirst=0;
Packit 383869
            fputs(*aszPre,stdout);
Packit 383869
            ++aszPre;
Packit 383869
        }
Packit 383869
        fputc(')',stdout);
Packit 383869
    }
Packit 383869
    if(aszSucc) {
Packit 383869
        fputs(" succ(",stdout);
Packit 383869
        nFirst=1;
Packit 383869
        while(*aszSucc) {
Packit 383869
            if(!nFirst)
Packit 383869
                fputc(',',stdout);
Packit 383869
            nFirst=0;
Packit 383869
            fputs(*aszSucc,stdout);
Packit 383869
            ++aszSucc;
Packit 383869
        }
Packit 383869
        fputc(')',stdout);
Packit 383869
    }
Packit 383869
    fputc('\n',stdout);
Packit 383869
}
Packit 383869
Packit 383869
/* Optional hook support */
Packit 383869
Packit 383869
APR_DECLARE_EXTERNAL_HOOK(apr,APU,void,_optional,(void))
Packit 383869
Packit 383869
APU_DECLARE(apr_array_header_t *) apr_optional_hook_get(const char *szName)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    apr_array_header_t **ppArray;
Packit 383869
Packit 383869
    if(!s_phOptionalHooks)
Packit 383869
        return NULL;
Packit 383869
    ppArray=apr_hash_get(s_phOptionalHooks,szName,strlen(szName));
Packit 383869
    if(!ppArray)
Packit 383869
        return NULL;
Packit 383869
    return *ppArray;
Packit 383869
}
Packit 383869
Packit 383869
APU_DECLARE(void) apr_optional_hook_add(const char *szName,void (*pfn)(void),
Packit 383869
                                        const char * const *aszPre,
Packit 383869
                                        const char * const *aszSucc,int nOrder)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    apr_array_header_t *pArray=apr_optional_hook_get(szName);
Packit 383869
    apr_LINK__optional_t *pHook;
Packit 383869
Packit 383869
    if(!pArray) {
Packit 383869
        apr_array_header_t **ppArray;
Packit 383869
Packit 383869
        pArray=apr_array_make(apr_hook_global_pool,1,
Packit 383869
                              sizeof(apr_LINK__optional_t));
Packit 383869
        if(!s_phOptionalHooks)
Packit 383869
            s_phOptionalHooks=apr_hash_make(apr_hook_global_pool);
Packit 383869
        ppArray=apr_palloc(apr_hook_global_pool,sizeof *ppArray);
Packit 383869
        *ppArray=pArray;
Packit 383869
        apr_hash_set(s_phOptionalHooks,szName,strlen(szName),ppArray);
Packit 383869
        apr_hook_sort_register(szName,ppArray);
Packit 383869
    }
Packit 383869
    pHook=apr_array_push(pArray);
Packit 383869
    pHook->pFunc=pfn;
Packit 383869
    pHook->aszPredecessors=aszPre;
Packit 383869
    pHook->aszSuccessors=aszSucc;
Packit 383869
    pHook->nOrder=nOrder;
Packit 383869
    pHook->szName=apr_hook_debug_current;
Packit 383869
    if(apr_hook_debug_enabled)
Packit 383869
        apr_hook_debug_show(szName,aszPre,aszSucc);
Packit 383869
}
Packit 383869
Packit 383869
/* optional function support */
Packit 383869
Packit 383869
APU_DECLARE(apr_opt_fn_t *) apr_dynamic_fn_retrieve(const char *szName)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    if(!s_phOptionalFunctions)
Packit 383869
        return NULL;
Packit 383869
    return (void(*)(void))apr_hash_get(s_phOptionalFunctions,szName,strlen(szName));
Packit 383869
}
Packit 383869
Packit 383869
/* Deprecated */
Packit 383869
APU_DECLARE_NONSTD(void) apr_dynamic_fn_register(const char *szName,
Packit 383869
                                                  apr_opt_fn_t *pfn)
Packit 383869
{
Packit 383869
#ifdef NETWARE
Packit 383869
    get_apd
Packit 383869
#endif
Packit 383869
    if(!s_phOptionalFunctions)
Packit 383869
        s_phOptionalFunctions=apr_hash_make(apr_hook_global_pool);
Packit 383869
    apr_hash_set(s_phOptionalFunctions,szName,strlen(szName),(void *)pfn);
Packit 383869
}
Packit 383869
Packit 383869
#if 0
Packit 383869
void main()
Packit 383869
{
Packit 383869
    const char *aszAPre[]={"b","c",NULL};
Packit 383869
    const char *aszBPost[]={"a",NULL};
Packit 383869
    const char *aszCPost[]={"b",NULL};
Packit 383869
    TSortData t1[]=
Packit 383869
    {
Packit 383869
        { "a",aszAPre,NULL },
Packit 383869
        { "b",NULL,aszBPost },
Packit 383869
        { "c",NULL,aszCPost }
Packit 383869
    };
Packit 383869
    TSort *pResult;
Packit 383869
Packit 383869
    pResult=prepare(t1,3);
Packit 383869
    pResult=tsort(pResult,3);
Packit 383869
Packit 383869
    for( ; pResult ; pResult=pResult->pNext)
Packit 383869
        printf("%s\n",pResult->pData->szName);
Packit 383869
}
Packit 383869
#endif