OpenSolaris_b135/cmd/nscd/nscd_init.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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
 * or http://www.opensolaris.org/os/licensing.
 * 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
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#include <locale.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include "nscd_common.h"
#include "nscd_config.h"
#include "nscd_log.h"
#include "nscd_switch.h"
#include "nscd_frontend.h"

static char	*cfgfile_save = NULL;
static mutex_t	time_mutex = DEFAULTMUTEX;
static time_t	start_time = 0;

void
_nscd_set_start_time(int reset)
{
	(void) mutex_lock(&time_mutex);
	if (start_time == 0 || reset == 1)
		start_time = time(NULL);
	(void) mutex_unlock(&time_mutex);
}

time_t
_nscd_get_start_time()
{
	return (start_time);
}

nscd_rc_t
_nscd_init(
	char			*cfgfile)
{
	char			*me = "nscd_init";
	nscd_rc_t		rc;
	nscd_cfg_error_t	*err;

	/*
	 * remember when main or forker nscd starts.
	 */
	_nscd_set_start_time(0);

	/*
	 * allocate the space for tables
	 */
	if ((rc = _nscd_alloc_nsw_config()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_service_state_table()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_nsw_state_base()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_nsw_be_info_db()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_getent_ctx_base()) != NSCD_SUCCESS)
		return (rc);

	/*
	 * allocate the space for local configuration
	 * and statistics
	 */
	if ((rc = _nscd_alloc_switch_cfg()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_frontend_cfg()) != NSCD_SUCCESS ||
	    (rc = _nscd_alloc_switch_stats()) != NSCD_SUCCESS)
		return (rc);

	/*
	 * Create and init the internal address database to keep
	 * track of the memory allocated by _nscd_alloc
	 */
	if (_nscd_create_int_addrDB() == NULL) {
		_NSCD_LOG(NSCD_LOG_INT_ADDR, NSCD_LOG_LEVEL_ERROR)
		(me, "_nscd_create_int_addrDB failed\n");
		return (NSCD_NO_MEMORY);
	}

	/*
	 * Create and init the internal context database to keep
	 * track of the getent context currently being used
	 */
	if (_nscd_create_getent_ctxDB() == NULL) {
		_NSCD_LOG(NSCD_LOG_GETENT_CTX, NSCD_LOG_LEVEL_ERROR)
		(me, "_nscd_create_getent_ctx_addrDB failed\n");
		return (NSCD_NO_MEMORY);
	}

	/*
	 * Create the backend info database for each possible source
	 */
	if ((rc = _nscd_init_all_nsw_be_info_db()) != NSCD_SUCCESS) {
		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
		(me, "_nscd_init_all_nsw_be_info_db failed (rc = %d)\n",
		    rc);
		return (rc);
	}

	/*
	 * Create the nscd_nsw_config_t for each possible nss database
	 */
	if ((rc = _nscd_init_all_nsw_config()) != NSCD_SUCCESS) {
		_NSCD_LOG(NSCD_LOG_NSW_STATE, NSCD_LOG_LEVEL_ERROR)
		(me, "_nscd_init_all_nsw_config failed (rc = %d)\n", rc);
		return (rc);
	}

	/*
	 * initialize config/stats management
	 */
	rc = _nscd_cfg_init(&err);
	if (rc != NSCD_SUCCESS) {
		if (err != NULL)
			_nscd_cfg_free_error(err);
		return (rc);
	}

	/*
	 * read in the nsswitch configuration
	 */
	rc = _nscd_cfg_read_nsswitch_file("/etc/nsswitch.conf", &err);
	if (rc != NSCD_SUCCESS) {
		(void) printf(
		gettext("reading config file %s failed with rc = %d, %s\n"),
		    "/etc/nsswitch.conf", rc, NSCD_ERR2MSG(err));
		if (err != NULL)
			_nscd_cfg_free_error(err);

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
	(me, "unable to read /etc/nsswitch.conf (rc = %d)\n", rc);
		return (rc);
	}
	/*
	 * remember which version of /etc/nsswitch.conf that was read
	 */
	_nscd_restart_if_cfgfile_changed();

	/*
	 * read in the nscd configuration
	 */
	if (cfgfile == NULL) {
		cfgfile = "/etc/nscd.conf";
		if (access(cfgfile, R_OK) != 0) {
			_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "unable to read /etc/nscd.conf (rc = %d)\n", rc);

			return (NSCD_CFG_FILE_ACCESS_ERROR);
		}
	}
	rc = _nscd_cfg_read_file(cfgfile, &err);
	if (rc != NSCD_SUCCESS) {
		(void) printf(
		gettext("reading config file %s failed with rc = %d, %s\n"),
		    cfgfile, rc, NSCD_ERR2MSG(err));
		if (err != NULL)
			_nscd_cfg_free_error(err);

		_NSCD_LOG(NSCD_LOG_FRONT_END, NSCD_LOG_LEVEL_ERROR)
		(me, "unable to read configuration from %s (rc = %d)\n",
		    cfgfile, rc);

		return (rc);
	}
	/*
	 * remember the name of the config file
	 * in case refresh is requested later
	 */
	if (cfgfile != NULL) {
		cfgfile_save = strdup(cfgfile);
		if (cfgfile_save == NULL)
			return (NSCD_NO_MEMORY);
	}

	return (NSCD_SUCCESS);
}

nscd_rc_t
_nscd_refresh()
{
	char			*me = "nscd_refresh";
	char			*cfgfile;
	nscd_rc_t		rc;
	nscd_cfg_error_t	*err;
	char			errmsg[1024];

	/*
	 * re-read the nscd configuration
	 */
	if (cfgfile_save == NULL)
		cfgfile = "/etc/nscd.conf";
	else
		cfgfile = cfgfile_save;

	if (access(cfgfile, R_OK) != 0) {
		(void) snprintf(errmsg, sizeof (errmsg),
		"unable to read the config file %s (rc = %d), %s\n",
		    cfgfile, NSCD_CFG_FILE_ACCESS_ERROR,
		    strerror(errno));

		goto error_exit;
	}

	rc = _nscd_cfg_read_file(cfgfile, &err);
	if (rc != NSCD_SUCCESS) {
		(void) snprintf(errmsg, sizeof (errmsg),
		    "unable to parse the config file %s (rc = %d), %s\n",
		    cfgfile, rc, NSCD_ERR2MSG(err));

		goto error_exit;
	}

	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ALL)
	(me, "nscd configuration refreshed successfully\n");

	return (NSCD_SUCCESS);

	error_exit:

	if (err != NULL)
		_nscd_cfg_free_error(err);

	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
	(me, "%s\n", errmsg);

	return (rc);
}