1N/A/*
1N/A * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
1N/A * Use is subject to license terms.
1N/A */
1N/A
1N/A#pragma ident "%Z%%M% %I% %E% SMI"
1N/A
1N/A
1N/A/*
1N/A * The contents of this file are subject to the Netscape Public
1N/A * License Version 1.1 (the "License"); you may not use this file
1N/A * except in compliance with the License. You may obtain a copy of
1N/A * the License at http://www.mozilla.org/NPL/
1N/A *
1N/A * Software distributed under the License is distributed on an "AS
1N/A * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
1N/A * implied. See the License for the specific language governing
1N/A * rights and limitations under the License.
1N/A *
1N/A * The Original Code is Mozilla Communicator client code, released
1N/A * March 31, 1998.
1N/A *
1N/A * The Initial Developer of the Original Code is Netscape
1N/A * Communications Corporation. Portions created by Netscape are
1N/A * Copyright (C) 1998-1999 Netscape Communications Corporation. All
1N/A * Rights Reserved.
1N/A *
1N/A * Contributor(s):
1N/A */
1N/A
1N/A/*
1N/A * Thread callback functions for libldap that use the NSPR (Netscape
1N/A * Portable Runtime) thread API.
1N/A *
1N/A */
1N/A
1N/A#ifdef _SOLARIS_SDK
1N/A#include <thread.h>
1N/A#include <synch.h>
1N/A#include <prinit.h>
1N/A#include <prthread.h>
1N/A#include <syslog.h>
1N/A#include <string.h>
1N/A#include <sys/types.h>
1N/A#include <signal.h>
1N/A#include <errno.h>
1N/Aextern int errno;
1N/A#endif /* _SOLARIS_SDK */
1N/A
1N/A#include "ldappr-int.h"
1N/A
1N/A#ifndef _SOLARIS_SDK
1N/A/*
1N/A * Macros:
1N/A */
1N/A/*
1N/A * Grow thread private data arrays 10 elements at a time.
1N/A */
1N/A#define PRLDAP_TPD_ARRAY_INCREMENT 10
1N/A
1N/A/*
1N/A * Structures and types:
1N/A */
1N/A/*
1N/A * Structure used by libldap thread callbacks to maintain error information.
1N/A */
1N/Atypedef struct prldap_errorinfo {
1N/A int plei_lderrno;
1N/A char *plei_matched;
1N/A char *plei_errmsg;
1N/A} PRLDAP_ErrorInfo;
1N/A
1N/A/*
1N/A * Structure used to maintain thread-private data. At the present time,
1N/A * only error info. is thread-private. One of these structures is allocated
1N/A * for each thread.
1N/A */
1N/Atypedef struct prldap_tpd_header {
1N/A int ptpdh_tpd_count; /* # of data items allocated */
1N/A void **ptpdh_dataitems; /* array of data items */
1N/A} PRLDAP_TPDHeader;
1N/A
1N/A/*
1N/A * Structure used by associate a PRLDAP thread-private data index with an
1N/A * LDAP session handle. One of these exists for each active LDAP session
1N/A * handle.
1N/A */
1N/Atypedef struct prldap_tpd_map {
1N/A LDAP *prtm_ld; /* non-NULL if in use */
1N/A PRUintn prtm_index; /* index into TPD array */
1N/A struct prldap_tpd_map *prtm_next;
1N/A} PRLDAP_TPDMap;
1N/A
1N/A#ifdef _SOLARIS_SDK
1N/Aextern mutex_t inited_mutex;
1N/A#endif /* _SOLARIS_SDK */
1N/A
1N/A/*
1N/A * Static Variables:
1N/A */
1N/A/*
1N/A * prldap_map_list points to all of the PRLDAP_TPDMap structures
1N/A * we have ever allocated. We recycle them as we open and close LDAP
1N/A * sessions.
1N/A */
1N/Astatic PRLDAP_TPDMap *prldap_map_list = NULL;
1N/A
1N/A
1N/A/*
1N/A * The prldap_map_mutex is used to protect access to the prldap_map_list.
1N/A */
1N/Astatic PRLock *prldap_map_mutex = NULL;
1N/A
1N/A/*
1N/A * The prldap_tpd_maxindex value is used to track the largest TPD array
1N/A * index we have used.
1N/A */
1N/Astatic PRInt32 prldap_tpd_maxindex = -1;
1N/A
1N/A/*
1N/A * prldap_tpdindex is an NSPR thread private data index we use to
1N/A * maintain our own thread-private data. It is initialized inside
1N/A * prldap_init_tpd().
1N/A */
1N/Astatic PRUintn prldap_tpdindex = 0;
1N/A
1N/A/*
1N/A * The prldap_callonce_init_tpd structure is used by NSPR to ensure
1N/A * that prldap_init_tpd() is called at most once.
1N/A */
1N/Astatic PRCallOnceType prldap_callonce_init_tpd = { 0, 0, 0 };
1N/A
1N/A
1N/A/*
1N/A * Private function prototypes:
1N/A */
1N/Astatic void prldap_set_ld_error( int err, char *matched, char *errmsg,
1N/A void *errorarg );
1N/Astatic int prldap_get_ld_error( char **matchedp, char **errmsgp,
1N/A void *errorarg );
1N/A#endif
1N/Astatic void *prldap_mutex_alloc( void );
1N/Astatic void prldap_mutex_free( void *mutex );
1N/Astatic int prldap_mutex_lock( void *mutex );
1N/Astatic int prldap_mutex_unlock( void *mutex );
1N/Astatic void *prldap_get_thread_id( void );
1N/A#ifndef _SOLARIS_SDK
1N/Astatic PRStatus prldap_init_tpd( void );
1N/Astatic PRLDAP_TPDMap *prldap_allocate_map( LDAP *ld );
1N/Astatic void prldap_return_map( PRLDAP_TPDMap *map );
1N/Astatic PRUintn prldap_new_tpdindex( void );
1N/Astatic int prldap_set_thread_private( PRInt32 tpdindex, void *priv );
1N/Astatic void *prldap_get_thread_private( PRInt32 tpdindex );
1N/Astatic PRLDAP_TPDHeader *prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr,
1N/A int maxindex );
1N/Astatic void prldap_tsd_destroy( void *priv );
1N/A#endif
1N/A
1N/A
1N/A/*
1N/A * Install NSPR thread functions into ld (if ld is NULL, they are installed
1N/A * as the default functions for new LDAP * handles).
1N/A *
1N/A * Returns 0 if all goes well and -1 if not.
1N/A */
1N/Aint
1N/Aprldap_install_thread_functions( LDAP *ld, int shared )
1N/A{
1N/A struct ldap_thread_fns tfns;
1N/A struct ldap_extra_thread_fns xtfns;
1N/A
1N/A#ifndef _SOLARIS_SDK
1N/A if ( PR_CallOnce( &prldap_callonce_init_tpd, prldap_init_tpd )
1N/A != PR_SUCCESS ) {
1N/A ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL );
1N/A return( -1 );
1N/A }
1N/A#endif /* _SOLARIS_SDK */
1N/A
1N/A /* set thread function pointers */
1N/A memset( &tfns, '\0', sizeof(struct ldap_thread_fns) );
1N/A tfns.ltf_get_errno = prldap_get_system_errno;
1N/A tfns.ltf_set_errno = prldap_set_system_errno;
1N/A if ( shared ) {
1N/A tfns.ltf_mutex_alloc = prldap_mutex_alloc;
1N/A tfns.ltf_mutex_free = prldap_mutex_free;
1N/A tfns.ltf_mutex_lock = prldap_mutex_lock;
1N/A tfns.ltf_mutex_unlock = prldap_mutex_unlock;
1N/A#ifdef _SOLARIS_SDK
1N/A tfns.ltf_get_lderrno = NULL;
1N/A tfns.ltf_set_lderrno = NULL;
1N/A#else
1N/A tfns.ltf_get_lderrno = prldap_get_ld_error;
1N/A tfns.ltf_set_lderrno = prldap_set_ld_error;
1N/A if ( ld != NULL ) {
1N/A /*
1N/A * If this is a real ld (i.e., we are not setting the global
1N/A * defaults) allocate thread private data for error information.
1N/A * If ld is NULL we do not do this here but it is done in
1N/A * prldap_thread_new_handle().
1N/A */
1N/A if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld ))
1N/A == NULL ) {
1N/A return( -1 );
1N/A }
1N/A }
1N/A#endif
1N/A }
1N/A
1N/A if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS,
1N/A (void *)&tfns ) != 0 ) {
1N/A#ifndef _SOLARIS_SDK
1N/A prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg );
1N/A#endif
1N/A return( -1 );
1N/A }
1N/A
1N/A /* set extended thread function pointers */
1N/A memset( &xtfns, '\0', sizeof(struct ldap_extra_thread_fns) );
1N/A xtfns.ltf_threadid_fn = prldap_get_thread_id;
1N/A if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS,
1N/A (void *)&xtfns ) != 0 ) {
1N/A return( -1 );
1N/A }
1N/A
1N/A return( 0 );
1N/A}
1N/A
1N/A
1N/Astatic void *
1N/Aprldap_mutex_alloc( void )
1N/A{
1N/A return( (void *)PR_NewLock());
1N/A}
1N/A
1N/A
1N/Astatic void
1N/Aprldap_mutex_free( void *mutex )
1N/A{
1N/A PR_DestroyLock( (PRLock *)mutex );
1N/A}
1N/A
1N/A
1N/Astatic int
1N/Aprldap_mutex_lock( void *mutex )
1N/A{
1N/A PR_Lock( (PRLock *)mutex );
1N/A return( 0 );
1N/A}
1N/A
1N/A
1N/Astatic int
1N/Aprldap_mutex_unlock( void *mutex )
1N/A{
1N/A if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) {
1N/A return( -1 );
1N/A }
1N/A
1N/A return( 0 );
1N/A}
1N/A
1N/A
1N/Astatic void *
1N/Aprldap_get_thread_id( void )
1N/A{
1N/A#ifdef _SOLARIS_SDK
1N/A return ((void *)thr_self());
1N/A#else
1N/A return( (void *)PR_GetCurrentThread());
1N/A#endif
1N/A}
1N/A
1N/A#ifndef _SOLARIS_SDK
1N/Astatic int
1N/Aprldap_get_ld_error( char **matchedp, char **errmsgp, void *errorarg )
1N/A{
1N/A PRLDAP_TPDMap *map;
1N/A PRLDAP_ErrorInfo *eip;
1N/A
1N/A if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL && ( eip =
1N/A (PRLDAP_ErrorInfo *)prldap_get_thread_private(
1N/A map->prtm_index )) != NULL ) {
1N/A if ( matchedp != NULL ) {
1N/A *matchedp = eip->plei_matched;
1N/A }
1N/A if ( errmsgp != NULL ) {
1N/A *errmsgp = eip->plei_errmsg;
1N/A }
1N/A return( eip->plei_lderrno );
1N/A } else {
1N/A if ( matchedp != NULL ) {
1N/A *matchedp = NULL;
1N/A }
1N/A if ( errmsgp != NULL ) {
1N/A *errmsgp = NULL;
1N/A }
1N/A return( LDAP_LOCAL_ERROR ); /* punt */
1N/A }
1N/A}
1N/A
1N/A
1N/Astatic void
1N/Aprldap_set_ld_error( int err, char *matched, char *errmsg, void *errorarg )
1N/A{
1N/A PRLDAP_TPDMap *map;
1N/A PRLDAP_ErrorInfo *eip;
1N/A
1N/A if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL ) {
1N/A if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private(
1N/A map->prtm_index )) == NULL ) {
1N/A /*
1N/A * Error info. has not yet been allocated for this thread.
1N/A * Do so now. Note that we free this memory only for the
1N/A * thread that calls prldap_thread_dispose_handle(), which
1N/A * should be the one that called ldap_unbind() -- see
1N/A * prldap_return_map(). Not freeing the memory used by
1N/A * other threads is deemed acceptable since it will be
1N/A * recycled and used by other LDAP sessions. All of the
1N/A * thread-private memory is freed when a thread exits
1N/A * (inside the prldap_tsd_destroy() function).
1N/A */
1N/A eip = (PRLDAP_ErrorInfo *)PR_Calloc( 1,
1N/A sizeof( PRLDAP_ErrorInfo ));
1N/A if ( eip == NULL ) {
1N/A return; /* punt */
1N/A }
1N/A (void)prldap_set_thread_private( map->prtm_index, eip );
1N/A }
1N/A
1N/A eip->plei_lderrno = err;
1N/A if ( eip->plei_matched != NULL ) {
1N/A ldap_memfree( eip->plei_matched );
1N/A }
1N/A eip->plei_matched = matched;
1N/A if ( eip->plei_errmsg != NULL ) {
1N/A ldap_memfree( eip->plei_errmsg );
1N/A }
1N/A eip->plei_errmsg = errmsg;
1N/A }
1N/A}
1N/A#endif
1N/A
1N/A
1N/A/*
1N/A * Called when a new LDAP * session handle is allocated.
1N/A * Allocate thread-private data for error information, but only if
1N/A * it has not already been allocated and the get_ld_error callback has
1N/A * been installed. If ld is not NULL when prldap_install_thread_functions()
1N/A * is called, we will have already allocated the thread-private data there.
1N/A */
1N/Aint
1N/Aprldap_thread_new_handle( LDAP *ld, void *sessionarg )
1N/A{
1N/A struct ldap_thread_fns tfns;
1N/A
1N/A#ifndef _SOLARIS_SDK
1N/A if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *)&tfns ) != 0 ) {
1N/A return( LDAP_LOCAL_ERROR );
1N/A }
1N/A
1N/A if ( tfns.ltf_lderrno_arg == NULL && tfns.ltf_get_lderrno != NULL ) {
1N/A if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) == NULL
1N/A || ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS,
1N/A (void *)&tfns ) != 0 ) {
1N/A return( LDAP_LOCAL_ERROR );
1N/A }
1N/A }
1N/A#endif
1N/A
1N/A return( LDAP_SUCCESS );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Called when an LDAP * session handle is being destroyed.
1N/A * Clean up our thread private data map.
1N/A */
1N/Avoid
1N/Aprldap_thread_dispose_handle( LDAP *ld, void *sessionarg )
1N/A{
1N/A#ifndef _SOLARIS_SDK
1N/A struct ldap_thread_fns tfns;
1N/A
1N/A if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS,
1N/A (void *)&tfns ) == 0 &&
1N/A tfns.ltf_lderrno_arg != NULL ) {
1N/A prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg );
1N/A }
1N/A#endif
1N/A}
1N/A
1N/A
1N/A#ifndef _SOLARIS_SDK
1N/Astatic PRStatus
1N/Aprldap_init_tpd( void )
1N/A{
1N/A if (( prldap_map_mutex = PR_NewLock()) == NULL || PR_NewThreadPrivateIndex(
1N/A &prldap_tpdindex, prldap_tsd_destroy ) != PR_SUCCESS ) {
1N/A return( PR_FAILURE );
1N/A }
1N/A
1N/A prldap_map_list = NULL;
1N/A
1N/A return( PR_SUCCESS );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_allocate_map()
1N/A * Description: allocate a thread-private data map to use for a new
1N/A * LDAP session handle.
1N/A * Returns: a pointer to the TPD map or NULL if none available.
1N/A */
1N/Astatic PRLDAP_TPDMap *
1N/Aprldap_allocate_map( LDAP *ld )
1N/A{
1N/A PRLDAP_TPDMap *map, *prevmap;
1N/A
1N/A PR_Lock( prldap_map_mutex );
1N/A
1N/A /*
1N/A * first look for a map that is already allocated but free to be re-used
1N/A */
1N/A prevmap = NULL;
1N/A for ( map = prldap_map_list; map != NULL; map = map->prtm_next ) {
1N/A if ( map->prtm_ld == NULL ) {
1N/A break;
1N/A }
1N/A prevmap = map;
1N/A }
1N/A
1N/A /*
1N/A * if none we found (map == NULL), try to allocate a new one and add it
1N/A * to the end of our global list.
1N/A */
1N/A if ( map == NULL ) {
1N/A PRUintn tpdindex;
1N/A
1N/A tpdindex = prldap_new_tpdindex();
1N/A map = (PRLDAP_TPDMap *)PR_Malloc( sizeof( PRLDAP_TPDMap ));
1N/A if ( map != NULL ) {
1N/A map->prtm_index = tpdindex;
1N/A map->prtm_next = NULL;
1N/A if ( prevmap == NULL ) {
1N/A prldap_map_list = map;
1N/A } else {
1N/A prevmap->prtm_next = map;
1N/A }
1N/A }
1N/A }
1N/A
1N/A if ( map != NULL ) {
1N/A map->prtm_ld = ld; /* now marked as "in use" */
1N/A /* since we are reusing...reset */
1N/A /* to initial state */
1N/A (void)prldap_set_thread_private( map->prtm_index, NULL );
1N/A }
1N/A
1N/A PR_Unlock( prldap_map_mutex );
1N/A
1N/A return( map );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_return_map()
1N/A * Description: return a thread-private data map to the pool of ones
1N/A * available for re-use.
1N/A */
1N/Astatic void
1N/Aprldap_return_map( PRLDAP_TPDMap *map )
1N/A{
1N/A PRLDAP_ErrorInfo *eip;
1N/A
1N/A PR_Lock( prldap_map_mutex );
1N/A
1N/A /*
1N/A * Dispose of thread-private LDAP error information. Note that this
1N/A * only disposes of the memory consumed on THIS thread, but that is
1N/A * okay. See the comment in prldap_set_ld_error() for the reason why.
1N/A */
1N/A if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private(
1N/A map->prtm_index )) != NULL &&
1N/A prldap_set_thread_private( map->prtm_index, NULL ) == 0 ) {
1N/A if ( eip->plei_matched != NULL ) {
1N/A ldap_memfree( eip->plei_matched );
1N/A }
1N/A if ( eip->plei_errmsg != NULL ) {
1N/A ldap_memfree( eip->plei_errmsg );
1N/A }
1N/A
1N/A PR_Free( eip );
1N/A }
1N/A
1N/A /* mark map as available for re-use */
1N/A map->prtm_ld = NULL;
1N/A
1N/A PR_Unlock( prldap_map_mutex );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_new_tpdindex()
1N/A * Description: allocate a thread-private data index.
1N/A * Returns: the new index.
1N/A */
1N/Astatic PRUintn
1N/Aprldap_new_tpdindex( void )
1N/A{
1N/A PRUintn tpdindex;
1N/A
1N/A tpdindex = (PRUintn)PR_AtomicIncrement( &prldap_tpd_maxindex );
1N/A return( tpdindex );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_set_thread_private()
1N/A * Description: store a piece of thread-private data.
1N/A * Returns: 0 if successful and -1 if not.
1N/A */
1N/Astatic int
1N/Aprldap_set_thread_private( PRInt32 tpdindex, void *priv )
1N/A{
1N/A PRLDAP_TPDHeader *tsdhdr;
1N/A
1N/A if ( tpdindex > prldap_tpd_maxindex ) {
1N/A return( -1 ); /* bad index */
1N/A }
1N/A
1N/A tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex );
1N/A if ( tsdhdr == NULL || tpdindex >= tsdhdr->ptpdh_tpd_count ) {
1N/A tsdhdr = prldap_tsd_realloc( tsdhdr, tpdindex );
1N/A if ( tsdhdr == NULL ) {
1N/A return( -1 ); /* realloc failed */
1N/A }
1N/A }
1N/A
1N/A tsdhdr->ptpdh_dataitems[ tpdindex ] = priv;
1N/A return( 0 );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_get_thread_private()
1N/A * Description: retrieve a piece of thread-private data. If not set,
1N/A * NULL is returned.
1N/A * Returns: 0 if successful and -1 if not.
1N/A */
1N/Astatic void *
1N/Aprldap_get_thread_private( PRInt32 tpdindex )
1N/A{
1N/A PRLDAP_TPDHeader *tsdhdr;
1N/A
1N/A tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex );
1N/A if ( tsdhdr == NULL ) {
1N/A return( NULL ); /* no thread private data */
1N/A }
1N/A
1N/A if ( tpdindex >= tsdhdr->ptpdh_tpd_count
1N/A || tsdhdr->ptpdh_dataitems == NULL ) {
1N/A return( NULL ); /* fewer data items than requested index */
1N/A }
1N/A
1N/A return( tsdhdr->ptpdh_dataitems[ tpdindex ] );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_tsd_realloc()
1N/A * Description: enlarge the thread-private data array.
1N/A * Returns: the new PRLDAP_TPDHeader value (non-NULL if successful).
1N/A * Note: tsdhdr can be NULL (allocates a new PRLDAP_TPDHeader).
1N/A */
1N/Astatic PRLDAP_TPDHeader *
1N/Aprldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, int maxindex )
1N/A{
1N/A void *newdataitems = NULL;
1N/A int count;
1N/A
1N/A if ( tsdhdr == NULL ) {
1N/A /* allocate a new thread private data header */
1N/A if (( tsdhdr = PR_Calloc( 1, sizeof( PRLDAP_TPDHeader ))) == NULL ) {
1N/A return( NULL );
1N/A }
1N/A (void)PR_SetThreadPrivate( prldap_tpdindex, tsdhdr );
1N/A }
1N/A
1N/A /*
1N/A * Make the size of the new array the next highest multiple of
1N/A * the array increment value that is greater than maxindex.
1N/A */
1N/A count = PRLDAP_TPD_ARRAY_INCREMENT *
1N/A ( 1 + ( maxindex / PRLDAP_TPD_ARRAY_INCREMENT ));
1N/A
1N/A /* increase the size of the data item array if necessary */
1N/A if ( count > tsdhdr->ptpdh_tpd_count ) {
1N/A newdataitems = (PRLDAP_ErrorInfo *)PR_Calloc( count, sizeof( void * ));
1N/A if ( newdataitems == NULL ) {
1N/A return( NULL );
1N/A }
1N/A if ( tsdhdr->ptpdh_dataitems != NULL ) { /* preserve old data */
1N/A memcpy( newdataitems, tsdhdr->ptpdh_dataitems,
1N/A tsdhdr->ptpdh_tpd_count * sizeof( void * ));
1N/A PR_Free( tsdhdr->ptpdh_dataitems );
1N/A }
1N/A
1N/A tsdhdr->ptpdh_tpd_count = count;
1N/A tsdhdr->ptpdh_dataitems = newdataitems;
1N/A }
1N/A
1N/A return( tsdhdr );
1N/A}
1N/A
1N/A
1N/A/*
1N/A * Function: prldap_tsd_destroy()
1N/A * Description: Free a thread-private data array. Installed as an NSPR TPD
1N/A * destructor function
1N/A * Returns: nothing.
1N/A * Note: this function assumes that each TPD item installed at the PRLDAP
1N/A * level can be freed with a call to PR_Free().
1N/A */
1N/Astatic void
1N/Aprldap_tsd_destroy( void *priv )
1N/A{
1N/A PRLDAP_TPDHeader *tsdhdr;
1N/A int i;
1N/A
1N/A tsdhdr = (PRLDAP_TPDHeader *)priv;
1N/A if ( tsdhdr != NULL ) {
1N/A if ( tsdhdr->ptpdh_dataitems != NULL ) {
1N/A for ( i = 0; i < tsdhdr->ptpdh_tpd_count; ++i ) {
1N/A if ( tsdhdr->ptpdh_dataitems[ i ] != NULL ) {
1N/A PR_Free( tsdhdr->ptpdh_dataitems[ i ] );
1N/A tsdhdr->ptpdh_dataitems[ i ] = NULL;
1N/A }
1N/A }
1N/A PR_Free( tsdhdr->ptpdh_dataitems );
1N/A tsdhdr->ptpdh_dataitems = NULL;
1N/A }
1N/A PR_Free( tsdhdr );
1N/A }
1N/A}
1N/A#endif
1N/A
1N/A#ifdef _SOLARIS_SDK
1N/A#pragma init(prldap_nspr_init)
1N/Astatic mutex_t nspr_init_lock = DEFAULTMUTEX;
1N/Astatic int nspr_initialized = 0;
1N/A
1N/A/*
1N/A * Initialize NSPR once
1N/A *
1N/A */
1N/Avoid
1N/Aprldap_nspr_init(void) {
1N/A struct sigaction action;
1N/A
1N/A /*
1N/A * For performance reason, test it here first
1N/A */
1N/A if (nspr_initialized != 0)
1N/A return;
1N/A
1N/A (void) mutex_lock(&nspr_init_lock);
1N/A /* Make sure PR_Init() is executed only once */
1N/A if (nspr_initialized == 0) {
1N/A /*
1N/A * PR_Init changes the signal handler of SIGPIPE to SIG_IGN.
1N/A * Save the original and restore it after PR_Init.
1N/A */
1N/A (void) sigaction(SIGPIPE, NULL, &action);
1N/A
1N/A if (PR_Initialized() == PR_FALSE) {
1N/A /*
1N/A * PR_Init() changes the current thread's
1N/A * priority. Save and restore the priority.
1N/A */
1N/A int priority;
1N/A (void) thr_getprio(thr_self(), &priority);
1N/A PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
1N/A (void) thr_setprio(thr_self(), priority);
1N/A }
1N/A nspr_initialized = 1;
1N/A /*
1N/A * Restore signal handling attributes of SIGPIPE
1N/A */
1N/A (void) sigaction(SIGPIPE, &action, NULL);
1N/A }
1N/A (void) mutex_unlock(&nspr_init_lock);
1N/A}
1N/A#endif