/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "nscd_switch.h"
#include "nscd_log.h"
/*
* nscd_nsw_state_t list for each nss database. Protected
*/
static void
nscd_nsw_state_t *s)
{
int i;
(me, "freeing nsw state = %p\n", s);
if (s == NULL)
return;
/*
* an nsw state without base does not reference
* count the nsw config data (ie not using a
* shared one), so the one created for it should
* be freed
*/
else
for (i = 0; i < s->max_src; i++) {
continue;
}
}
for (i = 0; i < s->max_src; i++) {
continue;
if (s->getent == 1)
(void) NSS_INVOKE_DBOP(s->be[i],
NSS_DBOP_ENDENT, 0);
(void) NSS_INVOKE_DBOP(s->be[i],
NSS_DBOP_DESTRUCTOR, 0);
}
}
if (s->be_version_p != NULL)
free(s->be_version_p);
/* remove reference to the nsw state base */
}
(me, "nsw state %p freed \n", s);
free(s);
}
static void
{
int i;
return;
for (i = 0; i < 2; i++) {
if (i == 1)
else
while (s != NULL) {
s = ts;
}
}
}
void
{
int i;
(me, "freeing all db state base\n");
(void) rw_wrlock(&nscd_nsw_state_base_lock);
for (i = 0; i < NSCD_NUM_DB; i++) {
base = nscd_nsw_state_base[i];
continue;
nscd_nsw_state_base[i] = (nscd_nsw_state_base_t *)
}
(void) rw_unlock(&nscd_nsw_state_base_lock);
}
static nscd_nsw_state_t *
{
nscd_nsw_state_t *s;
(me, "creating nsw state...\n");
if (s == NULL) {
(me, "not able to allocate a nsw state\n");
return (NULL);
} else
(me, "nsw state %p allocated\n", s);
s->p = params->p;
(me, "not able to allocate s->be\n");
return (NULL);
} else {
}
sizeof (nss_backend_constr_t));
(me, "not able to allocate s->be_constr\n");
return (NULL);
} else {
}
if (s->be_version_p == NULL) {
(me, "not able to allocate s->be_version_p\n");
return (NULL);
} else {
}
(me, "not able to allocate s->be_db_pp\n");
return (NULL);
} else {
}
/* create the source:database backends */
for (i = 0; i < s->max_src; i++) {
int srci;
char *srcn;
const char *dbn;
if (i == 0)
else
(me, "error: lkp is NULL\n");
return (NULL);
}
return (NULL);
}
(const char *)dbn, NSCD_GET_FIRST_DB_ENTRY, 0);
(me, "no backend info or be_constr is NULL "
dbn);
} else {
NSCD_NSW_SRC_NAME(srci), 0);
s->recheck_be = nscd_true;
}
(me, "not able to init be for <%s : %s>\n",
continue;
}
nobe = 0;
}
if (nobe == 1) {
(me, "NO backend found, returning NULL\n");
return (NULL);
}
return (s);
}
/*
* Try to initialize the backend instances one more time
* in case the dependencies the backend libraries depend
* on are now available
*/
static void
nscd_nsw_state_t *s)
{
int i;
char *dbn;
char *srcn;
s->recheck_be = nscd_false;
for (i = 0; i < s->max_src; i++) {
if (i == 0)
else
return;
/*
* it is possible that 's->be[i]' could not be
* initialized earlier due to a dependency not
* yet available (e.g., nis on domain name),
* try to initialize one more time
*/
s->recheck_be = nscd_true;
}
}
}
static nscd_rc_t
{
int dbi;
/*
* no nsw state will be reused, if asked to use
* default config. So create the new structures
* used by the switch engine and the new nsw state
*/
if (rc != NSCD_SUCCESS)
return (rc);
(me, "no base nsw config created for %s (sources: %s)\n",
return (NSCD_CREATE_NSW_STATE_FAILED);
return (NSCD_SUCCESS);
}
/*
* if getting a nsw state for a request from the compat
* backend, create the new switch structures if this
* is the first time around for a passwd, shadow, group,
* or user_attr database
*/
dbi = i;
/*
* retrieve the pointer space which contains a
* pointer pointing to the nsswitch config
* structure for the compat backend
*/
(nscd_acc_data_t *)nscd_nsw_config[i]);
/*
* If nsswitch config structure not created yet,
* get the config string from the passwd_compat
* or group_compat DB and create the structure.
*/
/* Wait first if it's being created. */
(nscd_acc_data_t *)nscd_nsw_config[i]);
/* still not created yet */
/*
* get the nsswitch config string specified
* for passwd_compat or group_compat
*/
(nscd_acc_data_t *)
(me, "no nsw config for %s\n",
(void) _nscd_mutex_unlock(
(nscd_acc_data_t *)nswcfg2);
nswcfg);
return (NSCD_CREATE_NSW_STATE_FAILED);
}
if (rc == NSCD_SUCCESS) {
(me, "nsw config created for %s (%s)\n",
(*nswcfg1)->nsw_cfg_str);
} else {
(void) _nscd_mutex_unlock(
(nscd_acc_data_t *)nswcfg2);
nswcfg);
return (rc);
}
}
}
}
(void) rw_rdlock(&nscd_nsw_state_base_lock);
(void) rw_unlock(&nscd_nsw_state_base_lock);
/*
* If list is not empty, return the first one on list.
* Otherwise, create and return a new db state if the
* limit is not reached. if reacehed, wait for the 'one
* is available' signal.
*/
(nscd_acc_data_t *)base));
} else {
thread_only = 1;
}
}
wait_cond = 1;
wait_cond = 1;
if (wait_cond) {
while (wait_cond) {
if (!thread_only)
(me, "waiting for nsw state signal\n");
else
(me, "waiting for per thread "
"nsw state signal\n");
if (thread_only) {
if (base->used_by_thr == 0 &&
wait_cond = 0;
} else {
wait_cond = 0;
}
if (!thread_only)
(me, "woke from cond wait ...wait_cond = %d\n",
else
(me, "woke from cond wait (per thread) "
"...wait_cond = %d\n", wait_cond);
}
}
int geti;
/*
* for lookup calls from the compat backend
* uses the switch policy for passwd_compat
* or group_compat
*/
else
(me, "got a nsw config %p for index %d\n",
} else {
(me, "got a new per thread nsw_state %p\n",
}
} else {
(me, "error: unable to obtain a nsw state\n");
return (NSCD_CREATE_NSW_STATE_FAILED);
}
}
if (thread_only) {
"state %p: \n", ret);
}
}
else
/*
* reference count the nsswitch state base bfore handing out
* the nsswitch state
*/
return (NSCD_SUCCESS);
}
{
}
{
}
static void
nscd_nsw_state_t *s,
{
int thread_only = 0;
(me, "put back a nsw state\n");
if (s == NULL) {
(me, "nsw state is NULL, nothing to put back\n");
return;
}
/*
* no need to put back if the nsw state is not on any base
* but need to free the resources used
*/
(me, "no base nsw state, freeing resources ...\n");
return;
}
thread_only = 1;
/* base has been freed or no longer valid, free the nsw state */
(me, "nsw state base gone or no longer valid, freeing %p\n", s);
return;
}
if (thread_only)
else
}
} else {
}
/*
* Remove reference to the nsswitch state base.
*/
base->used_by_thr = 0;
}
}
}
}
(me, "done putting back nsw state %p, thread_only = %d\n",
s, thread_only);
}
void
nscd_nsw_state_t *s)
{
_put_nsw_state_int(s, NULL);
}
void
nscd_nsw_state_t *s)
{
_put_nsw_state_int(s, &tid);
}
int dbi,
int compat_basei,
int lock)
{
int cfgdbi;
if (lock)
(void) rw_rdlock(&nscd_nsw_state_base_lock);
sizeof (nscd_nsw_state_base_t),
(me, "not able to allocate a nsw state base\n");
if (lock)
(void) rw_unlock(&nscd_nsw_state_base_lock);
return (NSCD_NO_MEMORY);
}
/*
* initialize and activate the new nss_nsw_state base
*/
if (compat_basei != -1)
else
(nscd_acc_data_t *)base);
if (lock)
(void) rw_unlock(&nscd_nsw_state_base_lock);
return (NSCD_SUCCESS);
}
{
int i;
(void) rw_rdlock(&nscd_nsw_state_base_lock);
for (i = 0; i < NSCD_NUM_DB; i++) {
if (rc != NSCD_SUCCESS) {
(me, "not able to initialize a nsw db state "
"base (%d)\n", i);
(void) rw_unlock(&nscd_nsw_state_base_lock);
return (rc);
}
}
(me, "all nsw state base initialized\n");
(void) rw_unlock(&nscd_nsw_state_base_lock);
return (NSCD_SUCCESS);
}
{
(void) rw_rdlock(&nscd_nsw_state_base_lock);
sizeof (nscd_nsw_state_base_t *));
if (nscd_nsw_state_base == NULL) {
(void) rw_unlock(&nscd_nsw_state_base_lock);
return (NSCD_NO_MEMORY);
}
(void) rw_rdlock(&nscd_nsw_state_base_lock);
return (NSCD_SUCCESS);
}