1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 3*0Sstevel@tonic-gate * Use is subject to license terms. 4*0Sstevel@tonic-gate */ 5*0Sstevel@tonic-gate 6*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate /* 10*0Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public 11*0Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file 12*0Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of 13*0Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/ 14*0Sstevel@tonic-gate * 15*0Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS 16*0Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 17*0Sstevel@tonic-gate * implied. See the License for the specific language governing 18*0Sstevel@tonic-gate * rights and limitations under the License. 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released 21*0Sstevel@tonic-gate * March 31, 1998. 22*0Sstevel@tonic-gate * 23*0Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape 24*0Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are 25*0Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All 26*0Sstevel@tonic-gate * Rights Reserved. 27*0Sstevel@tonic-gate * 28*0Sstevel@tonic-gate * Contributor(s): 29*0Sstevel@tonic-gate */ 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate /* 32*0Sstevel@tonic-gate * Thread callback functions for libldap that use the NSPR (Netscape 33*0Sstevel@tonic-gate * Portable Runtime) thread API. 34*0Sstevel@tonic-gate * 35*0Sstevel@tonic-gate */ 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 38*0Sstevel@tonic-gate #include <thread.h> 39*0Sstevel@tonic-gate #include <synch.h> 40*0Sstevel@tonic-gate #include <prinit.h> 41*0Sstevel@tonic-gate #include <prthread.h> 42*0Sstevel@tonic-gate #include <syslog.h> 43*0Sstevel@tonic-gate #include <string.h> 44*0Sstevel@tonic-gate #include <sys/types.h> 45*0Sstevel@tonic-gate #include <signal.h> 46*0Sstevel@tonic-gate #include <errno.h> 47*0Sstevel@tonic-gate extern int errno; 48*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 49*0Sstevel@tonic-gate 50*0Sstevel@tonic-gate #include "ldappr-int.h" 51*0Sstevel@tonic-gate 52*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 53*0Sstevel@tonic-gate /* 54*0Sstevel@tonic-gate * Macros: 55*0Sstevel@tonic-gate */ 56*0Sstevel@tonic-gate /* 57*0Sstevel@tonic-gate * Grow thread private data arrays 10 elements at a time. 58*0Sstevel@tonic-gate */ 59*0Sstevel@tonic-gate #define PRLDAP_TPD_ARRAY_INCREMENT 10 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate /* 62*0Sstevel@tonic-gate * Structures and types: 63*0Sstevel@tonic-gate */ 64*0Sstevel@tonic-gate /* 65*0Sstevel@tonic-gate * Structure used by libldap thread callbacks to maintain error information. 66*0Sstevel@tonic-gate */ 67*0Sstevel@tonic-gate typedef struct prldap_errorinfo { 68*0Sstevel@tonic-gate int plei_lderrno; 69*0Sstevel@tonic-gate char *plei_matched; 70*0Sstevel@tonic-gate char *plei_errmsg; 71*0Sstevel@tonic-gate } PRLDAP_ErrorInfo; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate /* 74*0Sstevel@tonic-gate * Structure used to maintain thread-private data. At the present time, 75*0Sstevel@tonic-gate * only error info. is thread-private. One of these structures is allocated 76*0Sstevel@tonic-gate * for each thread. 77*0Sstevel@tonic-gate */ 78*0Sstevel@tonic-gate typedef struct prldap_tpd_header { 79*0Sstevel@tonic-gate int ptpdh_tpd_count; /* # of data items allocated */ 80*0Sstevel@tonic-gate void **ptpdh_dataitems; /* array of data items */ 81*0Sstevel@tonic-gate } PRLDAP_TPDHeader; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate /* 84*0Sstevel@tonic-gate * Structure used by associate a PRLDAP thread-private data index with an 85*0Sstevel@tonic-gate * LDAP session handle. One of these exists for each active LDAP session 86*0Sstevel@tonic-gate * handle. 87*0Sstevel@tonic-gate */ 88*0Sstevel@tonic-gate typedef struct prldap_tpd_map { 89*0Sstevel@tonic-gate LDAP *prtm_ld; /* non-NULL if in use */ 90*0Sstevel@tonic-gate PRUintn prtm_index; /* index into TPD array */ 91*0Sstevel@tonic-gate struct prldap_tpd_map *prtm_next; 92*0Sstevel@tonic-gate } PRLDAP_TPDMap; 93*0Sstevel@tonic-gate 94*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 95*0Sstevel@tonic-gate extern mutex_t inited_mutex; 96*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate /* 99*0Sstevel@tonic-gate * Static Variables: 100*0Sstevel@tonic-gate */ 101*0Sstevel@tonic-gate /* 102*0Sstevel@tonic-gate * prldap_map_list points to all of the PRLDAP_TPDMap structures 103*0Sstevel@tonic-gate * we have ever allocated. We recycle them as we open and close LDAP 104*0Sstevel@tonic-gate * sessions. 105*0Sstevel@tonic-gate */ 106*0Sstevel@tonic-gate static PRLDAP_TPDMap *prldap_map_list = NULL; 107*0Sstevel@tonic-gate 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* 110*0Sstevel@tonic-gate * The prldap_map_mutex is used to protect access to the prldap_map_list. 111*0Sstevel@tonic-gate */ 112*0Sstevel@tonic-gate static PRLock *prldap_map_mutex = NULL; 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate /* 115*0Sstevel@tonic-gate * The prldap_tpd_maxindex value is used to track the largest TPD array 116*0Sstevel@tonic-gate * index we have used. 117*0Sstevel@tonic-gate */ 118*0Sstevel@tonic-gate static PRInt32 prldap_tpd_maxindex = -1; 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate /* 121*0Sstevel@tonic-gate * prldap_tpdindex is an NSPR thread private data index we use to 122*0Sstevel@tonic-gate * maintain our own thread-private data. It is initialized inside 123*0Sstevel@tonic-gate * prldap_init_tpd(). 124*0Sstevel@tonic-gate */ 125*0Sstevel@tonic-gate static PRUintn prldap_tpdindex = 0; 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate /* 128*0Sstevel@tonic-gate * The prldap_callonce_init_tpd structure is used by NSPR to ensure 129*0Sstevel@tonic-gate * that prldap_init_tpd() is called at most once. 130*0Sstevel@tonic-gate */ 131*0Sstevel@tonic-gate static PRCallOnceType prldap_callonce_init_tpd = { 0, 0, 0 }; 132*0Sstevel@tonic-gate 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* 135*0Sstevel@tonic-gate * Private function prototypes: 136*0Sstevel@tonic-gate */ 137*0Sstevel@tonic-gate static void prldap_set_ld_error( int err, char *matched, char *errmsg, 138*0Sstevel@tonic-gate void *errorarg ); 139*0Sstevel@tonic-gate static int prldap_get_ld_error( char **matchedp, char **errmsgp, 140*0Sstevel@tonic-gate void *errorarg ); 141*0Sstevel@tonic-gate #endif 142*0Sstevel@tonic-gate static void *prldap_mutex_alloc( void ); 143*0Sstevel@tonic-gate static void prldap_mutex_free( void *mutex ); 144*0Sstevel@tonic-gate static int prldap_mutex_lock( void *mutex ); 145*0Sstevel@tonic-gate static int prldap_mutex_unlock( void *mutex ); 146*0Sstevel@tonic-gate static void *prldap_get_thread_id( void ); 147*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 148*0Sstevel@tonic-gate static PRStatus prldap_init_tpd( void ); 149*0Sstevel@tonic-gate static PRLDAP_TPDMap *prldap_allocate_map( LDAP *ld ); 150*0Sstevel@tonic-gate static void prldap_return_map( PRLDAP_TPDMap *map ); 151*0Sstevel@tonic-gate static PRUintn prldap_new_tpdindex( void ); 152*0Sstevel@tonic-gate static int prldap_set_thread_private( PRInt32 tpdindex, void *priv ); 153*0Sstevel@tonic-gate static void *prldap_get_thread_private( PRInt32 tpdindex ); 154*0Sstevel@tonic-gate static PRLDAP_TPDHeader *prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, 155*0Sstevel@tonic-gate int maxindex ); 156*0Sstevel@tonic-gate static void prldap_tsd_destroy( void *priv ); 157*0Sstevel@tonic-gate #endif 158*0Sstevel@tonic-gate 159*0Sstevel@tonic-gate 160*0Sstevel@tonic-gate /* 161*0Sstevel@tonic-gate * Install NSPR thread functions into ld (if ld is NULL, they are installed 162*0Sstevel@tonic-gate * as the default functions for new LDAP * handles). 163*0Sstevel@tonic-gate * 164*0Sstevel@tonic-gate * Returns 0 if all goes well and -1 if not. 165*0Sstevel@tonic-gate */ 166*0Sstevel@tonic-gate int 167*0Sstevel@tonic-gate prldap_install_thread_functions( LDAP *ld, int shared ) 168*0Sstevel@tonic-gate { 169*0Sstevel@tonic-gate struct ldap_thread_fns tfns; 170*0Sstevel@tonic-gate struct ldap_extra_thread_fns xtfns; 171*0Sstevel@tonic-gate 172*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 173*0Sstevel@tonic-gate if ( PR_CallOnce( &prldap_callonce_init_tpd, prldap_init_tpd ) 174*0Sstevel@tonic-gate != PR_SUCCESS ) { 175*0Sstevel@tonic-gate ldap_set_lderrno( ld, LDAP_LOCAL_ERROR, NULL, NULL ); 176*0Sstevel@tonic-gate return( -1 ); 177*0Sstevel@tonic-gate } 178*0Sstevel@tonic-gate #endif /* _SOLARIS_SDK */ 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate /* set thread function pointers */ 181*0Sstevel@tonic-gate memset( &tfns, '\0', sizeof(struct ldap_thread_fns) ); 182*0Sstevel@tonic-gate tfns.ltf_get_errno = prldap_get_system_errno; 183*0Sstevel@tonic-gate tfns.ltf_set_errno = prldap_set_system_errno; 184*0Sstevel@tonic-gate if ( shared ) { 185*0Sstevel@tonic-gate tfns.ltf_mutex_alloc = prldap_mutex_alloc; 186*0Sstevel@tonic-gate tfns.ltf_mutex_free = prldap_mutex_free; 187*0Sstevel@tonic-gate tfns.ltf_mutex_lock = prldap_mutex_lock; 188*0Sstevel@tonic-gate tfns.ltf_mutex_unlock = prldap_mutex_unlock; 189*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 190*0Sstevel@tonic-gate tfns.ltf_get_lderrno = NULL; 191*0Sstevel@tonic-gate tfns.ltf_set_lderrno = NULL; 192*0Sstevel@tonic-gate #else 193*0Sstevel@tonic-gate tfns.ltf_get_lderrno = prldap_get_ld_error; 194*0Sstevel@tonic-gate tfns.ltf_set_lderrno = prldap_set_ld_error; 195*0Sstevel@tonic-gate if ( ld != NULL ) { 196*0Sstevel@tonic-gate /* 197*0Sstevel@tonic-gate * If this is a real ld (i.e., we are not setting the global 198*0Sstevel@tonic-gate * defaults) allocate thread private data for error information. 199*0Sstevel@tonic-gate * If ld is NULL we do not do this here but it is done in 200*0Sstevel@tonic-gate * prldap_thread_new_handle(). 201*0Sstevel@tonic-gate */ 202*0Sstevel@tonic-gate if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) 203*0Sstevel@tonic-gate == NULL ) { 204*0Sstevel@tonic-gate return( -1 ); 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate } 207*0Sstevel@tonic-gate #endif 208*0Sstevel@tonic-gate } 209*0Sstevel@tonic-gate 210*0Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, 211*0Sstevel@tonic-gate (void *)&tfns ) != 0 ) { 212*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 213*0Sstevel@tonic-gate prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); 214*0Sstevel@tonic-gate #endif 215*0Sstevel@tonic-gate return( -1 ); 216*0Sstevel@tonic-gate } 217*0Sstevel@tonic-gate 218*0Sstevel@tonic-gate /* set extended thread function pointers */ 219*0Sstevel@tonic-gate memset( &xtfns, '\0', sizeof(struct ldap_extra_thread_fns) ); 220*0Sstevel@tonic-gate xtfns.ltf_threadid_fn = prldap_get_thread_id; 221*0Sstevel@tonic-gate if ( ldap_set_option( ld, LDAP_OPT_EXTRA_THREAD_FN_PTRS, 222*0Sstevel@tonic-gate (void *)&xtfns ) != 0 ) { 223*0Sstevel@tonic-gate return( -1 ); 224*0Sstevel@tonic-gate } 225*0Sstevel@tonic-gate 226*0Sstevel@tonic-gate return( 0 ); 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate static void * 231*0Sstevel@tonic-gate prldap_mutex_alloc( void ) 232*0Sstevel@tonic-gate { 233*0Sstevel@tonic-gate return( (void *)PR_NewLock()); 234*0Sstevel@tonic-gate } 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate 237*0Sstevel@tonic-gate static void 238*0Sstevel@tonic-gate prldap_mutex_free( void *mutex ) 239*0Sstevel@tonic-gate { 240*0Sstevel@tonic-gate PR_DestroyLock( (PRLock *)mutex ); 241*0Sstevel@tonic-gate } 242*0Sstevel@tonic-gate 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate static int 245*0Sstevel@tonic-gate prldap_mutex_lock( void *mutex ) 246*0Sstevel@tonic-gate { 247*0Sstevel@tonic-gate PR_Lock( (PRLock *)mutex ); 248*0Sstevel@tonic-gate return( 0 ); 249*0Sstevel@tonic-gate } 250*0Sstevel@tonic-gate 251*0Sstevel@tonic-gate 252*0Sstevel@tonic-gate static int 253*0Sstevel@tonic-gate prldap_mutex_unlock( void *mutex ) 254*0Sstevel@tonic-gate { 255*0Sstevel@tonic-gate if ( PR_Unlock( (PRLock *)mutex ) == PR_FAILURE ) { 256*0Sstevel@tonic-gate return( -1 ); 257*0Sstevel@tonic-gate } 258*0Sstevel@tonic-gate 259*0Sstevel@tonic-gate return( 0 ); 260*0Sstevel@tonic-gate } 261*0Sstevel@tonic-gate 262*0Sstevel@tonic-gate 263*0Sstevel@tonic-gate static void * 264*0Sstevel@tonic-gate prldap_get_thread_id( void ) 265*0Sstevel@tonic-gate { 266*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 267*0Sstevel@tonic-gate return ((void *)thr_self()); 268*0Sstevel@tonic-gate #else 269*0Sstevel@tonic-gate return( (void *)PR_GetCurrentThread()); 270*0Sstevel@tonic-gate #endif 271*0Sstevel@tonic-gate } 272*0Sstevel@tonic-gate 273*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 274*0Sstevel@tonic-gate static int 275*0Sstevel@tonic-gate prldap_get_ld_error( char **matchedp, char **errmsgp, void *errorarg ) 276*0Sstevel@tonic-gate { 277*0Sstevel@tonic-gate PRLDAP_TPDMap *map; 278*0Sstevel@tonic-gate PRLDAP_ErrorInfo *eip; 279*0Sstevel@tonic-gate 280*0Sstevel@tonic-gate if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL && ( eip = 281*0Sstevel@tonic-gate (PRLDAP_ErrorInfo *)prldap_get_thread_private( 282*0Sstevel@tonic-gate map->prtm_index )) != NULL ) { 283*0Sstevel@tonic-gate if ( matchedp != NULL ) { 284*0Sstevel@tonic-gate *matchedp = eip->plei_matched; 285*0Sstevel@tonic-gate } 286*0Sstevel@tonic-gate if ( errmsgp != NULL ) { 287*0Sstevel@tonic-gate *errmsgp = eip->plei_errmsg; 288*0Sstevel@tonic-gate } 289*0Sstevel@tonic-gate return( eip->plei_lderrno ); 290*0Sstevel@tonic-gate } else { 291*0Sstevel@tonic-gate if ( matchedp != NULL ) { 292*0Sstevel@tonic-gate *matchedp = NULL; 293*0Sstevel@tonic-gate } 294*0Sstevel@tonic-gate if ( errmsgp != NULL ) { 295*0Sstevel@tonic-gate *errmsgp = NULL; 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); /* punt */ 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate 302*0Sstevel@tonic-gate static void 303*0Sstevel@tonic-gate prldap_set_ld_error( int err, char *matched, char *errmsg, void *errorarg ) 304*0Sstevel@tonic-gate { 305*0Sstevel@tonic-gate PRLDAP_TPDMap *map; 306*0Sstevel@tonic-gate PRLDAP_ErrorInfo *eip; 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate if (( map = (PRLDAP_TPDMap *)errorarg ) != NULL ) { 309*0Sstevel@tonic-gate if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( 310*0Sstevel@tonic-gate map->prtm_index )) == NULL ) { 311*0Sstevel@tonic-gate /* 312*0Sstevel@tonic-gate * Error info. has not yet been allocated for this thread. 313*0Sstevel@tonic-gate * Do so now. Note that we free this memory only for the 314*0Sstevel@tonic-gate * thread that calls prldap_thread_dispose_handle(), which 315*0Sstevel@tonic-gate * should be the one that called ldap_unbind() -- see 316*0Sstevel@tonic-gate * prldap_return_map(). Not freeing the memory used by 317*0Sstevel@tonic-gate * other threads is deemed acceptable since it will be 318*0Sstevel@tonic-gate * recycled and used by other LDAP sessions. All of the 319*0Sstevel@tonic-gate * thread-private memory is freed when a thread exits 320*0Sstevel@tonic-gate * (inside the prldap_tsd_destroy() function). 321*0Sstevel@tonic-gate */ 322*0Sstevel@tonic-gate eip = (PRLDAP_ErrorInfo *)PR_Calloc( 1, 323*0Sstevel@tonic-gate sizeof( PRLDAP_ErrorInfo )); 324*0Sstevel@tonic-gate if ( eip == NULL ) { 325*0Sstevel@tonic-gate return; /* punt */ 326*0Sstevel@tonic-gate } 327*0Sstevel@tonic-gate (void)prldap_set_thread_private( map->prtm_index, eip ); 328*0Sstevel@tonic-gate } 329*0Sstevel@tonic-gate 330*0Sstevel@tonic-gate eip->plei_lderrno = err; 331*0Sstevel@tonic-gate if ( eip->plei_matched != NULL ) { 332*0Sstevel@tonic-gate ldap_memfree( eip->plei_matched ); 333*0Sstevel@tonic-gate } 334*0Sstevel@tonic-gate eip->plei_matched = matched; 335*0Sstevel@tonic-gate if ( eip->plei_errmsg != NULL ) { 336*0Sstevel@tonic-gate ldap_memfree( eip->plei_errmsg ); 337*0Sstevel@tonic-gate } 338*0Sstevel@tonic-gate eip->plei_errmsg = errmsg; 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate } 341*0Sstevel@tonic-gate #endif 342*0Sstevel@tonic-gate 343*0Sstevel@tonic-gate 344*0Sstevel@tonic-gate /* 345*0Sstevel@tonic-gate * Called when a new LDAP * session handle is allocated. 346*0Sstevel@tonic-gate * Allocate thread-private data for error information, but only if 347*0Sstevel@tonic-gate * it has not already been allocated and the get_ld_error callback has 348*0Sstevel@tonic-gate * been installed. If ld is not NULL when prldap_install_thread_functions() 349*0Sstevel@tonic-gate * is called, we will have already allocated the thread-private data there. 350*0Sstevel@tonic-gate */ 351*0Sstevel@tonic-gate int 352*0Sstevel@tonic-gate prldap_thread_new_handle( LDAP *ld, void *sessionarg ) 353*0Sstevel@tonic-gate { 354*0Sstevel@tonic-gate struct ldap_thread_fns tfns; 355*0Sstevel@tonic-gate 356*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 357*0Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, (void *)&tfns ) != 0 ) { 358*0Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 359*0Sstevel@tonic-gate } 360*0Sstevel@tonic-gate 361*0Sstevel@tonic-gate if ( tfns.ltf_lderrno_arg == NULL && tfns.ltf_get_lderrno != NULL ) { 362*0Sstevel@tonic-gate if (( tfns.ltf_lderrno_arg = (void *)prldap_allocate_map( ld )) == NULL 363*0Sstevel@tonic-gate || ldap_set_option( ld, LDAP_OPT_THREAD_FN_PTRS, 364*0Sstevel@tonic-gate (void *)&tfns ) != 0 ) { 365*0Sstevel@tonic-gate return( LDAP_LOCAL_ERROR ); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate } 368*0Sstevel@tonic-gate #endif 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate return( LDAP_SUCCESS ); 371*0Sstevel@tonic-gate } 372*0Sstevel@tonic-gate 373*0Sstevel@tonic-gate 374*0Sstevel@tonic-gate /* 375*0Sstevel@tonic-gate * Called when an LDAP * session handle is being destroyed. 376*0Sstevel@tonic-gate * Clean up our thread private data map. 377*0Sstevel@tonic-gate */ 378*0Sstevel@tonic-gate void 379*0Sstevel@tonic-gate prldap_thread_dispose_handle( LDAP *ld, void *sessionarg ) 380*0Sstevel@tonic-gate { 381*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 382*0Sstevel@tonic-gate struct ldap_thread_fns tfns; 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate if ( ldap_get_option( ld, LDAP_OPT_THREAD_FN_PTRS, 385*0Sstevel@tonic-gate (void *)&tfns ) == 0 && 386*0Sstevel@tonic-gate tfns.ltf_lderrno_arg != NULL ) { 387*0Sstevel@tonic-gate prldap_return_map( (PRLDAP_TPDMap *)tfns.ltf_lderrno_arg ); 388*0Sstevel@tonic-gate } 389*0Sstevel@tonic-gate #endif 390*0Sstevel@tonic-gate } 391*0Sstevel@tonic-gate 392*0Sstevel@tonic-gate 393*0Sstevel@tonic-gate #ifndef _SOLARIS_SDK 394*0Sstevel@tonic-gate static PRStatus 395*0Sstevel@tonic-gate prldap_init_tpd( void ) 396*0Sstevel@tonic-gate { 397*0Sstevel@tonic-gate if (( prldap_map_mutex = PR_NewLock()) == NULL || PR_NewThreadPrivateIndex( 398*0Sstevel@tonic-gate &prldap_tpdindex, prldap_tsd_destroy ) != PR_SUCCESS ) { 399*0Sstevel@tonic-gate return( PR_FAILURE ); 400*0Sstevel@tonic-gate } 401*0Sstevel@tonic-gate 402*0Sstevel@tonic-gate prldap_map_list = NULL; 403*0Sstevel@tonic-gate 404*0Sstevel@tonic-gate return( PR_SUCCESS ); 405*0Sstevel@tonic-gate } 406*0Sstevel@tonic-gate 407*0Sstevel@tonic-gate 408*0Sstevel@tonic-gate /* 409*0Sstevel@tonic-gate * Function: prldap_allocate_map() 410*0Sstevel@tonic-gate * Description: allocate a thread-private data map to use for a new 411*0Sstevel@tonic-gate * LDAP session handle. 412*0Sstevel@tonic-gate * Returns: a pointer to the TPD map or NULL if none available. 413*0Sstevel@tonic-gate */ 414*0Sstevel@tonic-gate static PRLDAP_TPDMap * 415*0Sstevel@tonic-gate prldap_allocate_map( LDAP *ld ) 416*0Sstevel@tonic-gate { 417*0Sstevel@tonic-gate PRLDAP_TPDMap *map, *prevmap; 418*0Sstevel@tonic-gate 419*0Sstevel@tonic-gate PR_Lock( prldap_map_mutex ); 420*0Sstevel@tonic-gate 421*0Sstevel@tonic-gate /* 422*0Sstevel@tonic-gate * first look for a map that is already allocated but free to be re-used 423*0Sstevel@tonic-gate */ 424*0Sstevel@tonic-gate prevmap = NULL; 425*0Sstevel@tonic-gate for ( map = prldap_map_list; map != NULL; map = map->prtm_next ) { 426*0Sstevel@tonic-gate if ( map->prtm_ld == NULL ) { 427*0Sstevel@tonic-gate break; 428*0Sstevel@tonic-gate } 429*0Sstevel@tonic-gate prevmap = map; 430*0Sstevel@tonic-gate } 431*0Sstevel@tonic-gate 432*0Sstevel@tonic-gate /* 433*0Sstevel@tonic-gate * if none we found (map == NULL), try to allocate a new one and add it 434*0Sstevel@tonic-gate * to the end of our global list. 435*0Sstevel@tonic-gate */ 436*0Sstevel@tonic-gate if ( map == NULL ) { 437*0Sstevel@tonic-gate PRUintn tpdindex; 438*0Sstevel@tonic-gate 439*0Sstevel@tonic-gate tpdindex = prldap_new_tpdindex(); 440*0Sstevel@tonic-gate map = (PRLDAP_TPDMap *)PR_Malloc( sizeof( PRLDAP_TPDMap )); 441*0Sstevel@tonic-gate if ( map != NULL ) { 442*0Sstevel@tonic-gate map->prtm_index = tpdindex; 443*0Sstevel@tonic-gate map->prtm_next = NULL; 444*0Sstevel@tonic-gate if ( prevmap == NULL ) { 445*0Sstevel@tonic-gate prldap_map_list = map; 446*0Sstevel@tonic-gate } else { 447*0Sstevel@tonic-gate prevmap->prtm_next = map; 448*0Sstevel@tonic-gate } 449*0Sstevel@tonic-gate } 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate 452*0Sstevel@tonic-gate if ( map != NULL ) { 453*0Sstevel@tonic-gate map->prtm_ld = ld; /* now marked as "in use" */ 454*0Sstevel@tonic-gate /* since we are reusing...reset */ 455*0Sstevel@tonic-gate /* to initial state */ 456*0Sstevel@tonic-gate (void)prldap_set_thread_private( map->prtm_index, NULL ); 457*0Sstevel@tonic-gate } 458*0Sstevel@tonic-gate 459*0Sstevel@tonic-gate PR_Unlock( prldap_map_mutex ); 460*0Sstevel@tonic-gate 461*0Sstevel@tonic-gate return( map ); 462*0Sstevel@tonic-gate } 463*0Sstevel@tonic-gate 464*0Sstevel@tonic-gate 465*0Sstevel@tonic-gate /* 466*0Sstevel@tonic-gate * Function: prldap_return_map() 467*0Sstevel@tonic-gate * Description: return a thread-private data map to the pool of ones 468*0Sstevel@tonic-gate * available for re-use. 469*0Sstevel@tonic-gate */ 470*0Sstevel@tonic-gate static void 471*0Sstevel@tonic-gate prldap_return_map( PRLDAP_TPDMap *map ) 472*0Sstevel@tonic-gate { 473*0Sstevel@tonic-gate PRLDAP_ErrorInfo *eip; 474*0Sstevel@tonic-gate 475*0Sstevel@tonic-gate PR_Lock( prldap_map_mutex ); 476*0Sstevel@tonic-gate 477*0Sstevel@tonic-gate /* 478*0Sstevel@tonic-gate * Dispose of thread-private LDAP error information. Note that this 479*0Sstevel@tonic-gate * only disposes of the memory consumed on THIS thread, but that is 480*0Sstevel@tonic-gate * okay. See the comment in prldap_set_ld_error() for the reason why. 481*0Sstevel@tonic-gate */ 482*0Sstevel@tonic-gate if (( eip = (PRLDAP_ErrorInfo *)prldap_get_thread_private( 483*0Sstevel@tonic-gate map->prtm_index )) != NULL && 484*0Sstevel@tonic-gate prldap_set_thread_private( map->prtm_index, NULL ) == 0 ) { 485*0Sstevel@tonic-gate if ( eip->plei_matched != NULL ) { 486*0Sstevel@tonic-gate ldap_memfree( eip->plei_matched ); 487*0Sstevel@tonic-gate } 488*0Sstevel@tonic-gate if ( eip->plei_errmsg != NULL ) { 489*0Sstevel@tonic-gate ldap_memfree( eip->plei_errmsg ); 490*0Sstevel@tonic-gate } 491*0Sstevel@tonic-gate 492*0Sstevel@tonic-gate PR_Free( eip ); 493*0Sstevel@tonic-gate } 494*0Sstevel@tonic-gate 495*0Sstevel@tonic-gate /* mark map as available for re-use */ 496*0Sstevel@tonic-gate map->prtm_ld = NULL; 497*0Sstevel@tonic-gate 498*0Sstevel@tonic-gate PR_Unlock( prldap_map_mutex ); 499*0Sstevel@tonic-gate } 500*0Sstevel@tonic-gate 501*0Sstevel@tonic-gate 502*0Sstevel@tonic-gate /* 503*0Sstevel@tonic-gate * Function: prldap_new_tpdindex() 504*0Sstevel@tonic-gate * Description: allocate a thread-private data index. 505*0Sstevel@tonic-gate * Returns: the new index. 506*0Sstevel@tonic-gate */ 507*0Sstevel@tonic-gate static PRUintn 508*0Sstevel@tonic-gate prldap_new_tpdindex( void ) 509*0Sstevel@tonic-gate { 510*0Sstevel@tonic-gate PRUintn tpdindex; 511*0Sstevel@tonic-gate 512*0Sstevel@tonic-gate tpdindex = (PRUintn)PR_AtomicIncrement( &prldap_tpd_maxindex ); 513*0Sstevel@tonic-gate return( tpdindex ); 514*0Sstevel@tonic-gate } 515*0Sstevel@tonic-gate 516*0Sstevel@tonic-gate 517*0Sstevel@tonic-gate /* 518*0Sstevel@tonic-gate * Function: prldap_set_thread_private() 519*0Sstevel@tonic-gate * Description: store a piece of thread-private data. 520*0Sstevel@tonic-gate * Returns: 0 if successful and -1 if not. 521*0Sstevel@tonic-gate */ 522*0Sstevel@tonic-gate static int 523*0Sstevel@tonic-gate prldap_set_thread_private( PRInt32 tpdindex, void *priv ) 524*0Sstevel@tonic-gate { 525*0Sstevel@tonic-gate PRLDAP_TPDHeader *tsdhdr; 526*0Sstevel@tonic-gate 527*0Sstevel@tonic-gate if ( tpdindex > prldap_tpd_maxindex ) { 528*0Sstevel@tonic-gate return( -1 ); /* bad index */ 529*0Sstevel@tonic-gate } 530*0Sstevel@tonic-gate 531*0Sstevel@tonic-gate tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); 532*0Sstevel@tonic-gate if ( tsdhdr == NULL || tpdindex >= tsdhdr->ptpdh_tpd_count ) { 533*0Sstevel@tonic-gate tsdhdr = prldap_tsd_realloc( tsdhdr, tpdindex ); 534*0Sstevel@tonic-gate if ( tsdhdr == NULL ) { 535*0Sstevel@tonic-gate return( -1 ); /* realloc failed */ 536*0Sstevel@tonic-gate } 537*0Sstevel@tonic-gate } 538*0Sstevel@tonic-gate 539*0Sstevel@tonic-gate tsdhdr->ptpdh_dataitems[ tpdindex ] = priv; 540*0Sstevel@tonic-gate return( 0 ); 541*0Sstevel@tonic-gate } 542*0Sstevel@tonic-gate 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* 545*0Sstevel@tonic-gate * Function: prldap_get_thread_private() 546*0Sstevel@tonic-gate * Description: retrieve a piece of thread-private data. If not set, 547*0Sstevel@tonic-gate * NULL is returned. 548*0Sstevel@tonic-gate * Returns: 0 if successful and -1 if not. 549*0Sstevel@tonic-gate */ 550*0Sstevel@tonic-gate static void * 551*0Sstevel@tonic-gate prldap_get_thread_private( PRInt32 tpdindex ) 552*0Sstevel@tonic-gate { 553*0Sstevel@tonic-gate PRLDAP_TPDHeader *tsdhdr; 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate tsdhdr = (PRLDAP_TPDHeader *)PR_GetThreadPrivate( prldap_tpdindex ); 556*0Sstevel@tonic-gate if ( tsdhdr == NULL ) { 557*0Sstevel@tonic-gate return( NULL ); /* no thread private data */ 558*0Sstevel@tonic-gate } 559*0Sstevel@tonic-gate 560*0Sstevel@tonic-gate if ( tpdindex >= tsdhdr->ptpdh_tpd_count 561*0Sstevel@tonic-gate || tsdhdr->ptpdh_dataitems == NULL ) { 562*0Sstevel@tonic-gate return( NULL ); /* fewer data items than requested index */ 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate 565*0Sstevel@tonic-gate return( tsdhdr->ptpdh_dataitems[ tpdindex ] ); 566*0Sstevel@tonic-gate } 567*0Sstevel@tonic-gate 568*0Sstevel@tonic-gate 569*0Sstevel@tonic-gate /* 570*0Sstevel@tonic-gate * Function: prldap_tsd_realloc() 571*0Sstevel@tonic-gate * Description: enlarge the thread-private data array. 572*0Sstevel@tonic-gate * Returns: the new PRLDAP_TPDHeader value (non-NULL if successful). 573*0Sstevel@tonic-gate * Note: tsdhdr can be NULL (allocates a new PRLDAP_TPDHeader). 574*0Sstevel@tonic-gate */ 575*0Sstevel@tonic-gate static PRLDAP_TPDHeader * 576*0Sstevel@tonic-gate prldap_tsd_realloc( PRLDAP_TPDHeader *tsdhdr, int maxindex ) 577*0Sstevel@tonic-gate { 578*0Sstevel@tonic-gate void *newdataitems = NULL; 579*0Sstevel@tonic-gate int count; 580*0Sstevel@tonic-gate 581*0Sstevel@tonic-gate if ( tsdhdr == NULL ) { 582*0Sstevel@tonic-gate /* allocate a new thread private data header */ 583*0Sstevel@tonic-gate if (( tsdhdr = PR_Calloc( 1, sizeof( PRLDAP_TPDHeader ))) == NULL ) { 584*0Sstevel@tonic-gate return( NULL ); 585*0Sstevel@tonic-gate } 586*0Sstevel@tonic-gate (void)PR_SetThreadPrivate( prldap_tpdindex, tsdhdr ); 587*0Sstevel@tonic-gate } 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* 590*0Sstevel@tonic-gate * Make the size of the new array the next highest multiple of 591*0Sstevel@tonic-gate * the array increment value that is greater than maxindex. 592*0Sstevel@tonic-gate */ 593*0Sstevel@tonic-gate count = PRLDAP_TPD_ARRAY_INCREMENT * 594*0Sstevel@tonic-gate ( 1 + ( maxindex / PRLDAP_TPD_ARRAY_INCREMENT )); 595*0Sstevel@tonic-gate 596*0Sstevel@tonic-gate /* increase the size of the data item array if necessary */ 597*0Sstevel@tonic-gate if ( count > tsdhdr->ptpdh_tpd_count ) { 598*0Sstevel@tonic-gate newdataitems = (PRLDAP_ErrorInfo *)PR_Calloc( count, sizeof( void * )); 599*0Sstevel@tonic-gate if ( newdataitems == NULL ) { 600*0Sstevel@tonic-gate return( NULL ); 601*0Sstevel@tonic-gate } 602*0Sstevel@tonic-gate if ( tsdhdr->ptpdh_dataitems != NULL ) { /* preserve old data */ 603*0Sstevel@tonic-gate memcpy( newdataitems, tsdhdr->ptpdh_dataitems, 604*0Sstevel@tonic-gate tsdhdr->ptpdh_tpd_count * sizeof( void * )); 605*0Sstevel@tonic-gate PR_Free( tsdhdr->ptpdh_dataitems ); 606*0Sstevel@tonic-gate } 607*0Sstevel@tonic-gate 608*0Sstevel@tonic-gate tsdhdr->ptpdh_tpd_count = count; 609*0Sstevel@tonic-gate tsdhdr->ptpdh_dataitems = newdataitems; 610*0Sstevel@tonic-gate } 611*0Sstevel@tonic-gate 612*0Sstevel@tonic-gate return( tsdhdr ); 613*0Sstevel@tonic-gate } 614*0Sstevel@tonic-gate 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate /* 617*0Sstevel@tonic-gate * Function: prldap_tsd_destroy() 618*0Sstevel@tonic-gate * Description: Free a thread-private data array. Installed as an NSPR TPD 619*0Sstevel@tonic-gate * destructor function 620*0Sstevel@tonic-gate * Returns: nothing. 621*0Sstevel@tonic-gate * Note: this function assumes that each TPD item installed at the PRLDAP 622*0Sstevel@tonic-gate * level can be freed with a call to PR_Free(). 623*0Sstevel@tonic-gate */ 624*0Sstevel@tonic-gate static void 625*0Sstevel@tonic-gate prldap_tsd_destroy( void *priv ) 626*0Sstevel@tonic-gate { 627*0Sstevel@tonic-gate PRLDAP_TPDHeader *tsdhdr; 628*0Sstevel@tonic-gate int i; 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate tsdhdr = (PRLDAP_TPDHeader *)priv; 631*0Sstevel@tonic-gate if ( tsdhdr != NULL ) { 632*0Sstevel@tonic-gate if ( tsdhdr->ptpdh_dataitems != NULL ) { 633*0Sstevel@tonic-gate for ( i = 0; i < tsdhdr->ptpdh_tpd_count; ++i ) { 634*0Sstevel@tonic-gate if ( tsdhdr->ptpdh_dataitems[ i ] != NULL ) { 635*0Sstevel@tonic-gate PR_Free( tsdhdr->ptpdh_dataitems[ i ] ); 636*0Sstevel@tonic-gate tsdhdr->ptpdh_dataitems[ i ] = NULL; 637*0Sstevel@tonic-gate } 638*0Sstevel@tonic-gate } 639*0Sstevel@tonic-gate PR_Free( tsdhdr->ptpdh_dataitems ); 640*0Sstevel@tonic-gate tsdhdr->ptpdh_dataitems = NULL; 641*0Sstevel@tonic-gate } 642*0Sstevel@tonic-gate PR_Free( tsdhdr ); 643*0Sstevel@tonic-gate } 644*0Sstevel@tonic-gate } 645*0Sstevel@tonic-gate #endif 646*0Sstevel@tonic-gate 647*0Sstevel@tonic-gate #ifdef _SOLARIS_SDK 648*0Sstevel@tonic-gate #pragma init(prldap_nspr_init) 649*0Sstevel@tonic-gate static mutex_t nspr_init_lock = DEFAULTMUTEX; 650*0Sstevel@tonic-gate static mutex_t nspr_idle_lock = DEFAULTMUTEX; 651*0Sstevel@tonic-gate static cond_t nspr_idle_cond = DEFAULTCV; 652*0Sstevel@tonic-gate static int nspr_pr_init_is_done = 0; 653*0Sstevel@tonic-gate static int nspr_initialized = 0; 654*0Sstevel@tonic-gate 655*0Sstevel@tonic-gate void * 656*0Sstevel@tonic-gate prldap_nspr_idle_primordial_thread(void *arg) { 657*0Sstevel@tonic-gate /* 658*0Sstevel@tonic-gate * Make sure PR_Init finishes before any other thread can continue 659*0Sstevel@tonic-gate */ 660*0Sstevel@tonic-gate (void) mutex_lock(&nspr_idle_lock); 661*0Sstevel@tonic-gate if (PR_Initialized() == PR_FALSE) 662*0Sstevel@tonic-gate PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 663*0Sstevel@tonic-gate nspr_pr_init_is_done = 1; 664*0Sstevel@tonic-gate (void) cond_signal(&nspr_idle_cond); 665*0Sstevel@tonic-gate (void) mutex_unlock(&nspr_idle_lock); 666*0Sstevel@tonic-gate 667*0Sstevel@tonic-gate /* Debug only */ 668*0Sstevel@tonic-gate syslog(LOG_DEBUG, "NSPR is initialized by the" 669*0Sstevel@tonic-gate "idle primordial thread tid %ld created by thread " 670*0Sstevel@tonic-gate "tid %ld", thr_self(), (long)arg); 671*0Sstevel@tonic-gate pause(); 672*0Sstevel@tonic-gate 673*0Sstevel@tonic-gate } 674*0Sstevel@tonic-gate 675*0Sstevel@tonic-gate /* 676*0Sstevel@tonic-gate * Initialize NSPR once 677*0Sstevel@tonic-gate * 678*0Sstevel@tonic-gate * Ideally this should be done in .init of NSPR. 679*0Sstevel@tonic-gate * This is a workaround so only main thread can initialize 680*0Sstevel@tonic-gate * NSPR but main() does not need to call PR_Init(). 681*0Sstevel@tonic-gate * The future direction is NSPR free so we don't want programs 682*0Sstevel@tonic-gate * to call PR_Init(). 683*0Sstevel@tonic-gate * 684*0Sstevel@tonic-gate * For most of cases, programs link libldap (-lldap) 685*0Sstevel@tonic-gate * and .init is executed before the control is transfered to 686*0Sstevel@tonic-gate * main(). 687*0Sstevel@tonic-gate * But for programs linking libnsl (-lnsl), libldap is loaded 688*0Sstevel@tonic-gate * via dlopen("nss_ldap.so.1", RTLD_LAZY) so the thread loads 689*0Sstevel@tonic-gate * libldap is not necessary a main or a primordial 690*0Sstevel@tonic-gate * thread. In the latter case, an idle primordial thread is created 691*0Sstevel@tonic-gate * to initialize NSPR so NSPR won't be initialized by non-primordial 692*0Sstevel@tonic-gate * threads. 693*0Sstevel@tonic-gate * libldap is built with "-z nodelete" so libldap and libnspr4.so 694*0Sstevel@tonic-gate * are persistent in the address space. 695*0Sstevel@tonic-gate */ 696*0Sstevel@tonic-gate void 697*0Sstevel@tonic-gate prldap_nspr_init(void) { 698*0Sstevel@tonic-gate struct sigaction action; 699*0Sstevel@tonic-gate 700*0Sstevel@tonic-gate /* 701*0Sstevel@tonic-gate * For performance reason, test it here first 702*0Sstevel@tonic-gate */ 703*0Sstevel@tonic-gate if (nspr_initialized != 0) 704*0Sstevel@tonic-gate return; 705*0Sstevel@tonic-gate 706*0Sstevel@tonic-gate (void) mutex_lock(&nspr_init_lock); 707*0Sstevel@tonic-gate /* Make sure PR_Init() is executed only once */ 708*0Sstevel@tonic-gate if (nspr_initialized == 0) { 709*0Sstevel@tonic-gate /* 710*0Sstevel@tonic-gate * PR_Init changes the signal handler of SIGPIPE to SIG_IGN. 711*0Sstevel@tonic-gate * Save the original and restore it after PR_Init. 712*0Sstevel@tonic-gate */ 713*0Sstevel@tonic-gate (void) sigaction(SIGPIPE, NULL, &action); 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate if (thr_self() == 1) { 716*0Sstevel@tonic-gate /* main thread */ 717*0Sstevel@tonic-gate if (PR_Initialized() == PR_FALSE) 718*0Sstevel@tonic-gate PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0); 719*0Sstevel@tonic-gate nspr_initialized = 1; 720*0Sstevel@tonic-gate } else { 721*0Sstevel@tonic-gate if (thr_create(NULL, NULL, 722*0Sstevel@tonic-gate prldap_nspr_idle_primordial_thread, 723*0Sstevel@tonic-gate (void *)thr_self(), THR_DETACHED, NULL) != 0) { 724*0Sstevel@tonic-gate syslog(LOG_ERR, 725*0Sstevel@tonic-gate "libldap:.init: Can't create thread. " 726*0Sstevel@tonic-gate "%s", strerror(errno)); 727*0Sstevel@tonic-gate } else { 728*0Sstevel@tonic-gate /* 729*0Sstevel@tonic-gate * Make sure PR_Init finishes before any other thread 730*0Sstevel@tonic-gate * can continue. 731*0Sstevel@tonic-gate * It's unlikely, but not impossible that this thread 732*0Sstevel@tonic-gate * finishes dlopen and starts to call 733*0Sstevel@tonic-gate * LDAP API when the idle thread still has not 734*0Sstevel@tonic-gate * finished PR_Init() yet. 735*0Sstevel@tonic-gate */ 736*0Sstevel@tonic-gate (void) mutex_lock(&nspr_idle_lock); 737*0Sstevel@tonic-gate while (nspr_pr_init_is_done == 0) { 738*0Sstevel@tonic-gate (void) cond_wait(&nspr_idle_cond, 739*0Sstevel@tonic-gate &nspr_idle_lock); 740*0Sstevel@tonic-gate 741*0Sstevel@tonic-gate } 742*0Sstevel@tonic-gate (void) mutex_unlock(&nspr_idle_lock); 743*0Sstevel@tonic-gate nspr_initialized = 1; 744*0Sstevel@tonic-gate } 745*0Sstevel@tonic-gate } 746*0Sstevel@tonic-gate /* 747*0Sstevel@tonic-gate * Restore signal handling attributes of SIGPIPE 748*0Sstevel@tonic-gate */ 749*0Sstevel@tonic-gate (void) sigaction(SIGPIPE, &action, NULL); 750*0Sstevel@tonic-gate 751*0Sstevel@tonic-gate } 752*0Sstevel@tonic-gate (void) mutex_unlock(&nspr_init_lock); 753*0Sstevel@tonic-gate } 754*0Sstevel@tonic-gate #endif 755