xref: /titanic_44/usr/src/cmd/nscd/nscd_config.c (revision e37190e5b4531a897e4191a30b8f41678b582e25)
1cb5caa98Sdjl /*
2cb5caa98Sdjl  * CDDL HEADER START
3cb5caa98Sdjl  *
4cb5caa98Sdjl  * The contents of this file are subject to the terms of the
5cb5caa98Sdjl  * Common Development and Distribution License (the "License").
6cb5caa98Sdjl  * You may not use this file except in compliance with the License.
7cb5caa98Sdjl  *
8cb5caa98Sdjl  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9cb5caa98Sdjl  * or http://www.opensolaris.org/os/licensing.
10cb5caa98Sdjl  * See the License for the specific language governing permissions
11cb5caa98Sdjl  * and limitations under the License.
12cb5caa98Sdjl  *
13cb5caa98Sdjl  * When distributing Covered Code, include this CDDL HEADER in each
14cb5caa98Sdjl  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15cb5caa98Sdjl  * If applicable, add the following below this CDDL HEADER, with the
16cb5caa98Sdjl  * fields enclosed by brackets "[]" replaced with your own identifying
17cb5caa98Sdjl  * information: Portions Copyright [yyyy] [name of copyright owner]
18cb5caa98Sdjl  *
19cb5caa98Sdjl  * CDDL HEADER END
20cb5caa98Sdjl  */
21cb5caa98Sdjl /*
22cb5caa98Sdjl  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
23cb5caa98Sdjl  * Use is subject to license terms.
24cb5caa98Sdjl  */
25cb5caa98Sdjl 
26cb5caa98Sdjl #pragma ident	"%Z%%M%	%I%	%E% SMI"
27cb5caa98Sdjl 
28cb5caa98Sdjl #include <stdio.h>
29cb5caa98Sdjl #include <stdlib.h>
30cb5caa98Sdjl #include <locale.h>		/* gettext */
31cb5caa98Sdjl #include <dlfcn.h>
32cb5caa98Sdjl #include <string.h>
33cb5caa98Sdjl #include <sys/varargs.h>
34cb5caa98Sdjl #include <errno.h>
35cb5caa98Sdjl #include "nscd_db.h"
36cb5caa98Sdjl #include "nscd_config.h"
37cb5caa98Sdjl #include "nscd_cfgdef.h"
38cb5caa98Sdjl #include "nscd_log.h"
39cb5caa98Sdjl 
40cb5caa98Sdjl typedef struct {
41cb5caa98Sdjl 	rwlock_t	*global;
42cb5caa98Sdjl 	rwlock_t	*alldb;
43cb5caa98Sdjl 	rwlock_t	*nswdb;
44cb5caa98Sdjl } nscd_cfg_lock_t;
45cb5caa98Sdjl 
46cb5caa98Sdjl static rwlock_t		cfg_paramDB_rwlock = DEFAULTRWLOCK;
47cb5caa98Sdjl static nscd_db_t	*cfg_paramDB = NULL;
48cb5caa98Sdjl 
49cb5caa98Sdjl static	nscd_cfg_global_data_t 	*nscd_cfg_global_current;
50cb5caa98Sdjl static	nscd_cfg_nsw_db_data_t	*nscd_cfg_nsw_db_data_current;
51cb5caa98Sdjl static	nscd_cfg_nsw_db_data_t	*nscd_cfg_nsw_alldb_current;
52cb5caa98Sdjl static	rwlock_t		*nscd_cfg_global_rwlock;
53cb5caa98Sdjl static	rwlock_t		*nscd_cfg_nsw_db_data_rwlock;
54cb5caa98Sdjl static	rwlock_t		*nscd_cfg_nsw_alldb_rwlock;
55cb5caa98Sdjl 
56cb5caa98Sdjl extern	int			_nscd_cfg_num_nsw_src_all;
57cb5caa98Sdjl extern	nscd_cfg_id_t		*_nscd_cfg_nsw_src_all;
58cb5caa98Sdjl 
59cb5caa98Sdjl nscd_cfg_error_t *
60cb5caa98Sdjl _nscd_cfg_make_error(
61cb5caa98Sdjl 	nscd_rc_t	rc,
62cb5caa98Sdjl 	char		*msg)
63cb5caa98Sdjl {
64cb5caa98Sdjl 
65cb5caa98Sdjl 	nscd_cfg_error_t	*ret;
66cb5caa98Sdjl 	int			size, msglen;
67cb5caa98Sdjl 
68cb5caa98Sdjl 	msglen = (msg != NULL ? strlen(msg) + 1 : 0);
69cb5caa98Sdjl 
70cb5caa98Sdjl 	size = sizeof (nscd_cfg_error_t) + msglen;
71cb5caa98Sdjl 
72cb5caa98Sdjl 	ret = calloc(1, size);
73cb5caa98Sdjl 	if (ret == NULL)
74cb5caa98Sdjl 		return (NULL);
75cb5caa98Sdjl 
76cb5caa98Sdjl 	ret->rc = rc;
77cb5caa98Sdjl 	if (msg != NULL) {
78cb5caa98Sdjl 		ret->msg = (char *)ret +
79cb5caa98Sdjl 			sizeof (nscd_cfg_error_t);
80cb5caa98Sdjl 		(void) memcpy(ret->msg, msg, msglen);
81cb5caa98Sdjl 	}
82cb5caa98Sdjl 
83cb5caa98Sdjl 	return (ret);
84cb5caa98Sdjl }
85cb5caa98Sdjl 
86cb5caa98Sdjl static nscd_rc_t
87cb5caa98Sdjl _nscd_cfg_get_list(
88cb5caa98Sdjl 	nscd_cfg_list_t		**list,
89cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
90cb5caa98Sdjl {
91cb5caa98Sdjl 	char			*me = "_nscd_cfg_get_list";
92cb5caa98Sdjl 	int			i, num, size;
93cb5caa98Sdjl 	nscd_cfg_id_t		*l;
94cb5caa98Sdjl 	nscd_cfg_list_t 	*ret;
95cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pl;
96cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*sl;
97cb5caa98Sdjl 	void			*p;
98cb5caa98Sdjl 
99cb5caa98Sdjl 	if (list == NULL) {
100cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
101cb5caa98Sdjl 		(me, "invalid argument: list = %p\n", list);
102cb5caa98Sdjl 
103cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
104cb5caa98Sdjl 	}
105cb5caa98Sdjl 	*list = NULL;
106cb5caa98Sdjl 
107cb5caa98Sdjl 	switch (type) {
108cb5caa98Sdjl 	case NSCD_CFG_LIST_NSW_DB:
109cb5caa98Sdjl 
110cb5caa98Sdjl 		num = _nscd_cfg_num_nsw_db;
111cb5caa98Sdjl 		l = &_nscd_cfg_nsw_db[0];
112cb5caa98Sdjl 		break;
113cb5caa98Sdjl 
114cb5caa98Sdjl 	case NSCD_CFG_LIST_NSW_SRC:
115cb5caa98Sdjl 
116cb5caa98Sdjl 		num = _nscd_cfg_num_nsw_src_all;
117cb5caa98Sdjl 		l = _nscd_cfg_nsw_src_all;
118cb5caa98Sdjl 		break;
119cb5caa98Sdjl 
120cb5caa98Sdjl 	case NSCD_CFG_LIST_PARAM:
121cb5caa98Sdjl 
122cb5caa98Sdjl 		num = _nscd_cfg_num_param;
123cb5caa98Sdjl 		pl = &_nscd_cfg_param_desc[0];
124cb5caa98Sdjl 		break;
125cb5caa98Sdjl 
126cb5caa98Sdjl 	case NSCD_CFG_LIST_STAT:
127cb5caa98Sdjl 
128cb5caa98Sdjl 		num = _nscd_cfg_num_stat;
129cb5caa98Sdjl 		sl = &_nscd_cfg_stat_desc[0];
130cb5caa98Sdjl 		break;
131cb5caa98Sdjl 
132cb5caa98Sdjl 	default:
133cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
134cb5caa98Sdjl 		(me, "invalid argument: type (%d)\n", type);
135cb5caa98Sdjl 
136cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
137cb5caa98Sdjl 		break;
138cb5caa98Sdjl 	}
139cb5caa98Sdjl 
140cb5caa98Sdjl 	size =  sizeof (nscd_cfg_list_t) + sizeof (nscd_cfg_id_t *) * (num + 1);
141cb5caa98Sdjl 
142cb5caa98Sdjl 	ret = calloc(1, size);
143cb5caa98Sdjl 	if (ret == NULL)
144cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
145cb5caa98Sdjl 
146cb5caa98Sdjl 	ret->num = num;
147cb5caa98Sdjl 	p = (char *)ret + sizeof (nscd_cfg_list_t);
148cb5caa98Sdjl 	ret->list = (nscd_cfg_id_t **)p;
149cb5caa98Sdjl 
150cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_PARAM) {
151cb5caa98Sdjl 		for (i = 0; i <= num; i++)
152cb5caa98Sdjl 			ret->list[i] = (nscd_cfg_id_t *)&pl[i];
153cb5caa98Sdjl 	} else if (type == NSCD_CFG_LIST_STAT) {
154cb5caa98Sdjl 		for (i = 0; i <= num; i++)
155cb5caa98Sdjl 			ret->list[i] = (nscd_cfg_id_t *)&sl[i];
156cb5caa98Sdjl 	} else {
157cb5caa98Sdjl 		for (i = 0; i <= num; i++)
158cb5caa98Sdjl 			ret->list[i] = &l[i];
159cb5caa98Sdjl 	}
160cb5caa98Sdjl 
161cb5caa98Sdjl 	*list = ret;
162cb5caa98Sdjl 
163cb5caa98Sdjl 	return (NSCD_SUCCESS);
164cb5caa98Sdjl }
165cb5caa98Sdjl 
166cb5caa98Sdjl nscd_rc_t
167cb5caa98Sdjl _nscd_cfg_get_param_desc_list(
168cb5caa98Sdjl 	nscd_cfg_param_desc_list_t **list)
169cb5caa98Sdjl {
170cb5caa98Sdjl 	return (_nscd_cfg_get_list((nscd_cfg_list_t **)list,
171cb5caa98Sdjl 		NSCD_CFG_LIST_PARAM));
172cb5caa98Sdjl }
173cb5caa98Sdjl 
174cb5caa98Sdjl /* find function pointer in the executable via dlopen(0) */
175cb5caa98Sdjl static nscd_rc_t
176cb5caa98Sdjl _nscd_cfg_init_funcs(
177cb5caa98Sdjl 	char			*name,
178cb5caa98Sdjl 	void			**func_p,
179cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
180cb5caa98Sdjl {
181cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_funcs";
182cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
183cb5caa98Sdjl 	static void		*handle = NULL;
184cb5caa98Sdjl 	void			*sym;
185cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
186cb5caa98Sdjl 
187cb5caa98Sdjl 	if (name == NULL && handle != NULL) {
188cb5caa98Sdjl 		(void) dlclose(handle);
189cb5caa98Sdjl 		return (rc);
190cb5caa98Sdjl 	}
191cb5caa98Sdjl 	if (name == NULL)
192cb5caa98Sdjl 		return (rc);
193cb5caa98Sdjl 
194cb5caa98Sdjl 	if (handle == NULL) {
195cb5caa98Sdjl 		handle = dlopen((const char *)0, RTLD_LAZY);
196cb5caa98Sdjl 		if (handle == NULL) {
197cb5caa98Sdjl 
198cb5caa98Sdjl 			rc = NSCD_CFG_DLOPEN_ERROR;
199cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
200cb5caa98Sdjl 			gettext("unable to dlopen the nscd executable: %s"),
201cb5caa98Sdjl 				dlerror());
202cb5caa98Sdjl 			goto error_exit;
203cb5caa98Sdjl 		}
204cb5caa98Sdjl 	}
205cb5caa98Sdjl 
206cb5caa98Sdjl 	if (func_p) {
207cb5caa98Sdjl 		if ((sym = dlsym(handle, name)) == NULL) {
208cb5caa98Sdjl 
209cb5caa98Sdjl 			rc = NSCD_CFG_DLSYM_ERROR;
210cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
211cb5caa98Sdjl gettext("unable to get the address of a symbol in the nscd executable: %s"),
212cb5caa98Sdjl 				dlerror());
213cb5caa98Sdjl 			goto error_exit;
214cb5caa98Sdjl 		} else
215cb5caa98Sdjl 			(void) memcpy(func_p, &sym, sizeof (void *));
216cb5caa98Sdjl 	}
217cb5caa98Sdjl 
218cb5caa98Sdjl 	return (rc);
219cb5caa98Sdjl 
220cb5caa98Sdjl 	error_exit:
221cb5caa98Sdjl 
222cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
223cb5caa98Sdjl 	(me, "%s\n", msg);
224cb5caa98Sdjl 	if (errorp != NULL)
225cb5caa98Sdjl 		*errorp = _nscd_cfg_make_error(rc, msg);
226cb5caa98Sdjl 
227cb5caa98Sdjl 	return (rc);
228cb5caa98Sdjl }
229cb5caa98Sdjl 
230cb5caa98Sdjl 
231cb5caa98Sdjl /*
232cb5caa98Sdjl  * FUNCTION: _nscd_cfg_create_paramDB
233cb5caa98Sdjl  *
234cb5caa98Sdjl  * Create the internal config parameter database
235cb5caa98Sdjl  */
236cb5caa98Sdjl static nscd_db_t *
237cb5caa98Sdjl _nscd_cfg_create_paramDB()
238cb5caa98Sdjl {
239cb5caa98Sdjl 
240cb5caa98Sdjl 	nscd_db_t	*ret;
241cb5caa98Sdjl 
242cb5caa98Sdjl 	(void) rw_wrlock(&cfg_paramDB_rwlock);
243cb5caa98Sdjl 
244cb5caa98Sdjl 	ret = _nscd_alloc_db(NSCD_DB_SIZE_MEDIUM);
245cb5caa98Sdjl 
246cb5caa98Sdjl 	if (ret != NULL)
247cb5caa98Sdjl 		cfg_paramDB = ret;
248cb5caa98Sdjl 
249cb5caa98Sdjl 	(void) rw_unlock(&cfg_paramDB_rwlock);
250cb5caa98Sdjl 
251cb5caa98Sdjl 	return (ret);
252cb5caa98Sdjl }
253cb5caa98Sdjl 
254cb5caa98Sdjl /*
255cb5caa98Sdjl  * FUNCTION: _nscd_cfg_add_index_entry
256cb5caa98Sdjl  *
257cb5caa98Sdjl  * Add a config index entry (a name to index mapping)
258cb5caa98Sdjl  * to the internal configuration database.
259cb5caa98Sdjl  */
260cb5caa98Sdjl static nscd_rc_t
261cb5caa98Sdjl _nscd_cfg_add_index_entry(
262cb5caa98Sdjl 	char			*name,
263cb5caa98Sdjl 	int			index,
264cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
265cb5caa98Sdjl {
266cb5caa98Sdjl 	int		*idx;
267cb5caa98Sdjl 	int		size;
268cb5caa98Sdjl 	int		dbe_type;
269cb5caa98Sdjl 	nscd_db_entry_t	*db_entry;
270cb5caa98Sdjl 
271cb5caa98Sdjl 	if (name == NULL)
272cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
273cb5caa98Sdjl 
274cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_NSW_DB)
275cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
276cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_NSW_SRC)
277cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
278cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_PARAM)
279cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
280cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_STAT)
281cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_STAT_INDEX;
282cb5caa98Sdjl 
283cb5caa98Sdjl 	size = sizeof (int);
284cb5caa98Sdjl 
285cb5caa98Sdjl 	db_entry = _nscd_alloc_db_entry(dbe_type, (const char *)name,
286cb5caa98Sdjl 			size, 1, 1);
287cb5caa98Sdjl 	if (db_entry == NULL)
288cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
289cb5caa98Sdjl 
290cb5caa98Sdjl 	idx = (int *)*(db_entry->data_array);
291cb5caa98Sdjl 	*idx = index;
292cb5caa98Sdjl 
293cb5caa98Sdjl 	(void) rw_wrlock(&cfg_paramDB_rwlock);
294cb5caa98Sdjl 	(void) _nscd_add_db_entry(cfg_paramDB, name, db_entry,
295cb5caa98Sdjl 		NSCD_ADD_DB_ENTRY_FIRST);
296cb5caa98Sdjl 	(void) rw_unlock(&cfg_paramDB_rwlock);
297cb5caa98Sdjl 
298cb5caa98Sdjl 	return (NSCD_SUCCESS);
299cb5caa98Sdjl }
300cb5caa98Sdjl 
301cb5caa98Sdjl /*
302cb5caa98Sdjl  * FUNCTION: _nscd_cfg_get_index
303cb5caa98Sdjl  *
304cb5caa98Sdjl  * Get the index of a config data item by searching the internal config
305cb5caa98Sdjl  * database. Do not free the returned data.
306cb5caa98Sdjl  */
307cb5caa98Sdjl static int
308cb5caa98Sdjl _nscd_cfg_get_index(
309cb5caa98Sdjl 	char			*name,
310cb5caa98Sdjl 	nscd_cfg_list_type_t	type)
311cb5caa98Sdjl {
312cb5caa98Sdjl 	int			index = -1, dbe_type;
313cb5caa98Sdjl 	const nscd_db_entry_t	*db_entry;
314cb5caa98Sdjl 
315cb5caa98Sdjl 	if (name == NULL)
316cb5caa98Sdjl 		return (-1);
317cb5caa98Sdjl 
318cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_NSW_DB)
319cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_DB_INDEX;
320cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_NSW_SRC)
321cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_NSW_SRC_INDEX;
322cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_PARAM)
323cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_PARAM_INDEX;
324cb5caa98Sdjl 	else if (type == NSCD_CFG_LIST_STAT)
325cb5caa98Sdjl 		dbe_type = NSCD_DATA_CFG_STAT_INDEX;
326cb5caa98Sdjl 	else
327cb5caa98Sdjl 		return (-1);
328cb5caa98Sdjl 
329cb5caa98Sdjl 	db_entry = _nscd_get_db_entry(cfg_paramDB, dbe_type,
330cb5caa98Sdjl 		(const char *)name, NSCD_GET_FIRST_DB_ENTRY, 0);
331cb5caa98Sdjl 
332cb5caa98Sdjl 	if (db_entry != NULL)
333cb5caa98Sdjl 		index = *(int *)*(db_entry->data_array);
334cb5caa98Sdjl 
335cb5caa98Sdjl 	return (index);
336cb5caa98Sdjl }
337cb5caa98Sdjl 
338cb5caa98Sdjl static nscd_rc_t
339cb5caa98Sdjl _nscd_cfg_verify_group_info(
340cb5caa98Sdjl 	nscd_cfg_group_info_t	*g_info,
341cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc)
342cb5caa98Sdjl {
343cb5caa98Sdjl 
344cb5caa98Sdjl 	char			*me = "_nscd_cfg_verify_group_info";
345cb5caa98Sdjl 	void			*vp;
346cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
347cb5caa98Sdjl 
348cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(gdesc->pflag, NSCD_CFG_PFLAG_GLOBAL)) {
349cb5caa98Sdjl 		vp = (char *)&nscd_cfg_global_default +
350cb5caa98Sdjl 			gdesc->g_offset;
351cb5caa98Sdjl 		gi = (nscd_cfg_group_info_t *)vp;
352cb5caa98Sdjl 	} else {
353cb5caa98Sdjl 		vp = (char *)&nscd_cfg_nsw_db_data_default +
354cb5caa98Sdjl 			gdesc->g_offset;
355cb5caa98Sdjl 		gi = (nscd_cfg_group_info_t *)vp;
356cb5caa98Sdjl 
357cb5caa98Sdjl 	}
358cb5caa98Sdjl 
359cb5caa98Sdjl 	if (g_info->num_param == gi->num_param &&
360cb5caa98Sdjl 		_nscd_cfg_bitmap_is_equal(g_info->bitmap, gi->bitmap))
361cb5caa98Sdjl 		return (NSCD_SUCCESS);
362cb5caa98Sdjl 
363cb5caa98Sdjl 	_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
364cb5caa98Sdjl 	(me, "ERROR: group (%s) info mismatched: group info "
365cb5caa98Sdjl 	"(%d, %#6.4x) not equal to that of default configuration data "
366cb5caa98Sdjl 	"(%d, %#6.4x)\n", gdesc->id.name, g_info->num_param,
367cb5caa98Sdjl 	_nscd_cfg_bitmap_value(g_info->bitmap), gi->num_param,
368cb5caa98Sdjl 	_nscd_cfg_bitmap_value(gi->bitmap));
369cb5caa98Sdjl 
370cb5caa98Sdjl 	return (NSCD_CFG_PARAM_DESC_ERROR);
371cb5caa98Sdjl 
372cb5caa98Sdjl }
373cb5caa98Sdjl 
374cb5caa98Sdjl 
375cb5caa98Sdjl static nscd_rc_t
376cb5caa98Sdjl _nscd_cfg_init_nsw()
377cb5caa98Sdjl {
378cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_nsw";
379cb5caa98Sdjl 	int			i, j, idx, rc, num;
380cb5caa98Sdjl 	nscd_cfg_id_t		*id;
381cb5caa98Sdjl 	nscd_cfg_list_type_t	type[2] = { NSCD_CFG_LIST_NSW_DB,
382cb5caa98Sdjl 					NSCD_CFG_LIST_NSW_SRC };
383cb5caa98Sdjl 
384cb5caa98Sdjl 	nscd_cfg_id_t		*list[2] = { _nscd_cfg_nsw_db, NULL};
385cb5caa98Sdjl 
386cb5caa98Sdjl 	list[1] = _nscd_cfg_nsw_src_all;
387cb5caa98Sdjl 
388cb5caa98Sdjl 	for (j = 0; j < 2; j++) {
389cb5caa98Sdjl 
390cb5caa98Sdjl 		if (j == 0)
391cb5caa98Sdjl 			num = _nscd_cfg_num_nsw_db + 1;
392cb5caa98Sdjl 		else
393cb5caa98Sdjl 			num = _nscd_cfg_num_nsw_src_all;
394cb5caa98Sdjl 
395cb5caa98Sdjl 		for (i = 0; i < num; i++) {
396cb5caa98Sdjl 
397cb5caa98Sdjl 			/*
398cb5caa98Sdjl 			 * _nscd_cfg_nsw_alldb is the id for the
399cb5caa98Sdjl 			 * special ALLDB (defaults for all db)
400cb5caa98Sdjl 			 */
401cb5caa98Sdjl 			if (j == 0 && i == _nscd_cfg_num_nsw_db) {
402cb5caa98Sdjl 				id = &_nscd_cfg_nsw_alldb;
403cb5caa98Sdjl 				idx = NSCD_CFG_NSW_ALLDB_INDEX;
404cb5caa98Sdjl 			} else {
405cb5caa98Sdjl 				id = &(list[j])[i];
406cb5caa98Sdjl 				id->index = idx = i;
407cb5caa98Sdjl 			}
408cb5caa98Sdjl 
409cb5caa98Sdjl 			if (id->name == NULL)
410cb5caa98Sdjl 				continue;
411cb5caa98Sdjl 
412cb5caa98Sdjl 			if ((rc = _nscd_cfg_add_index_entry(id->name,
413cb5caa98Sdjl 				idx, type[j])) != NSCD_SUCCESS) {
414cb5caa98Sdjl 
415cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
416cb5caa98Sdjl 					NSCD_LOG_LEVEL_ERROR)
417cb5caa98Sdjl 				(me, "unable to add index entry for "
418cb5caa98Sdjl 				"nsswitch entry %s\n", id->name);
419cb5caa98Sdjl 
420cb5caa98Sdjl 				_nscd_free_db(cfg_paramDB);
421cb5caa98Sdjl 				return (rc);
422cb5caa98Sdjl 			}
423cb5caa98Sdjl 		}
424cb5caa98Sdjl 	}
425cb5caa98Sdjl 
426cb5caa98Sdjl 	return (NSCD_SUCCESS);
427cb5caa98Sdjl }
428cb5caa98Sdjl 
429cb5caa98Sdjl /*
430cb5caa98Sdjl  * get the address of a function in the nscd executable
431cb5caa98Sdjl  * and store it in where 'dest_p' points to
432cb5caa98Sdjl  */
433cb5caa98Sdjl static nscd_rc_t
434cb5caa98Sdjl _nscd_cfg_get_funcp(
435cb5caa98Sdjl 	char			*name,
436cb5caa98Sdjl 	void			*dest_p,
437cb5caa98Sdjl 	void			**gfunc_a,
438cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
439cb5caa98Sdjl {
440cb5caa98Sdjl 
441cb5caa98Sdjl 	void			*func;
442cb5caa98Sdjl 	nscd_rc_t		rc;
443cb5caa98Sdjl 
444cb5caa98Sdjl 	if (gfunc_a != NULL) {
445cb5caa98Sdjl 
446cb5caa98Sdjl 		if (strcmp(name, NSCD_CFG_FUNC_NAME_AS_GROUP) == 0)
447cb5caa98Sdjl 			(void) memcpy(dest_p, gfunc_a, sizeof (void *));
448cb5caa98Sdjl 
449cb5caa98Sdjl 		return (NSCD_SUCCESS);
450cb5caa98Sdjl 	}
451cb5caa98Sdjl 
452cb5caa98Sdjl 	rc = _nscd_cfg_init_funcs(name, &func, errorp);
453cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
454cb5caa98Sdjl 		return (rc);
455cb5caa98Sdjl 	(void) memcpy(dest_p, &func, sizeof (func));
456cb5caa98Sdjl 
457cb5caa98Sdjl 	return (NSCD_SUCCESS);
458cb5caa98Sdjl }
459cb5caa98Sdjl 
460cb5caa98Sdjl static nscd_rc_t
461cb5caa98Sdjl _nscd_cfg_init_param()
462cb5caa98Sdjl {
463cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_param";
464cb5caa98Sdjl 	int			i, gi, fn = 0;
465cb5caa98Sdjl 	nscd_cfg_id_t		*id;
466cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc, *gdesc = NULL;
467cb5caa98Sdjl 	nscd_cfg_group_info_t	g_info;
468cb5caa98Sdjl 	nscd_cfg_list_type_t	type = NSCD_CFG_LIST_PARAM;
469cb5caa98Sdjl 	nscd_rc_t		rc;
470cb5caa98Sdjl 	void			*nfunc, *vfunc;
471cb5caa98Sdjl 
472cb5caa98Sdjl 	if (_nscd_cfg_create_paramDB() == NULL)
473cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
474cb5caa98Sdjl 
475cb5caa98Sdjl 	desc = &_nscd_cfg_param_desc[0];
476cb5caa98Sdjl 
477cb5caa98Sdjl 	/*
478cb5caa98Sdjl 	 * need to loop to the last (+1) param description
479cb5caa98Sdjl 	 * which is a fake group and which marks the end
480cb5caa98Sdjl 	 * of list. It is used to signal the end of the
481cb5caa98Sdjl 	 * previous group so that the proper data will be
482cb5caa98Sdjl 	 * set for that group
483cb5caa98Sdjl 	 */
484cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param + 1; i++, desc++) {
485cb5caa98Sdjl 
486cb5caa98Sdjl 		id = (nscd_cfg_id_t *)desc;
487cb5caa98Sdjl 
488cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
489cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP)) {
490cb5caa98Sdjl 
491cb5caa98Sdjl 			if (gdesc != NULL) {
492cb5caa98Sdjl 				g_info.num_param = fn;
493cb5caa98Sdjl 				gdesc->p_fn = fn;
494cb5caa98Sdjl 
495cb5caa98Sdjl 				if ((rc = _nscd_cfg_verify_group_info(
496cb5caa98Sdjl 					&g_info, gdesc)) != NSCD_SUCCESS)
497cb5caa98Sdjl 					return (rc);
498cb5caa98Sdjl 			}
499cb5caa98Sdjl 
500cb5caa98Sdjl 			gi = i;
501cb5caa98Sdjl 			fn = 0;
502cb5caa98Sdjl 			gdesc = desc;
503cb5caa98Sdjl 			g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
504cb5caa98Sdjl 			nfunc = NULL;
505cb5caa98Sdjl 			vfunc = NULL;
506cb5caa98Sdjl 
507cb5caa98Sdjl 			/*
508cb5caa98Sdjl 			 * set the notify/verify functions
509cb5caa98Sdjl 			 */
510cb5caa98Sdjl 			if (gdesc->nfunc_name != NULL) {
511cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->nfunc_name,
512cb5caa98Sdjl 					&gdesc->notify, NULL, NULL);
513*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
514cb5caa98Sdjl 					return (rc);
515cb5caa98Sdjl 				nfunc = (void *)gdesc->notify;
516cb5caa98Sdjl 			}
517cb5caa98Sdjl 			if (gdesc->vfunc_name != NULL) {
518cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->vfunc_name,
519cb5caa98Sdjl 					&gdesc->verify, NULL, NULL);
520*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
521cb5caa98Sdjl 					return (rc);
522cb5caa98Sdjl 				vfunc = (void *)gdesc->verify;
523cb5caa98Sdjl 			}
524cb5caa98Sdjl 		} else {
525cb5caa98Sdjl 			if (i == 0) {
526cb5caa98Sdjl 
527cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
528cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
529cb5caa98Sdjl 				(me, "ERROR: first parameter "
530cb5caa98Sdjl 				"description is not for a group\n");
531cb5caa98Sdjl 
532cb5caa98Sdjl 				return (NSCD_CFG_PARAM_DESC_ERROR);
533cb5caa98Sdjl 			}
534cb5caa98Sdjl 
535cb5caa98Sdjl 			/*
536cb5caa98Sdjl 			 * set bitmap: the rightmost bit represents
537cb5caa98Sdjl 			 * the first member (index = 0) in the group,
538cb5caa98Sdjl 			 * the next bit is for the second member
539cb5caa98Sdjl 			 * (index = 1), and so on
540cb5caa98Sdjl 			 */
541cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
542cb5caa98Sdjl 
543cb5caa98Sdjl 			desc->p_fn = fn++;
544cb5caa98Sdjl 
545cb5caa98Sdjl 			/*
546cb5caa98Sdjl 			 * set the notify/verify functions
547cb5caa98Sdjl 			 */
548cb5caa98Sdjl 			if (desc->nfunc_name != NULL) {
549cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->nfunc_name,
550cb5caa98Sdjl 					&desc->notify, &nfunc, NULL);
551*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
552cb5caa98Sdjl 					return (rc);
553cb5caa98Sdjl 			}
554cb5caa98Sdjl 			if (desc->vfunc_name != NULL) {
555cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->vfunc_name,
556cb5caa98Sdjl 					&desc->verify, &vfunc, NULL);
557*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
558cb5caa98Sdjl 					return (rc);
559cb5caa98Sdjl 			}
560cb5caa98Sdjl 		}
561cb5caa98Sdjl 
562cb5caa98Sdjl 		/* if end of list reached, we are done */
563cb5caa98Sdjl 		if (i == _nscd_cfg_num_param)
564cb5caa98Sdjl 			break;
565cb5caa98Sdjl 
566cb5caa98Sdjl 		desc->g_index = gi;
567cb5caa98Sdjl 
568cb5caa98Sdjl 		id->index = i;
569cb5caa98Sdjl 
570cb5caa98Sdjl 		if ((rc = _nscd_cfg_add_index_entry(id->name,
571cb5caa98Sdjl 			i, type)) != NSCD_SUCCESS) {
572cb5caa98Sdjl 
573cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
574cb5caa98Sdjl 			(me, "unable to add index entry for parameter "
575cb5caa98Sdjl 			"%s\n", id->name);
576cb5caa98Sdjl 
577cb5caa98Sdjl 			_nscd_free_db(cfg_paramDB);
578cb5caa98Sdjl 			return (rc);
579cb5caa98Sdjl 		} else {
580cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
581cb5caa98Sdjl 			(me, "index entry for parameter "
582cb5caa98Sdjl 			"%s added\n", id->name);
583cb5caa98Sdjl 		}
584cb5caa98Sdjl 	}
585cb5caa98Sdjl 
586cb5caa98Sdjl 	return (_nscd_cfg_init_nsw());
587cb5caa98Sdjl }
588cb5caa98Sdjl 
589cb5caa98Sdjl static nscd_rc_t
590cb5caa98Sdjl _nscd_cfg_init_stat()
591cb5caa98Sdjl {
592cb5caa98Sdjl 	char			*me = "_nscd_cfg_init_stat";
593cb5caa98Sdjl 	int			i, gi, fn = 0;
594cb5caa98Sdjl 	nscd_cfg_id_t		*id;
595cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*desc, *gdesc = NULL;
596cb5caa98Sdjl 	nscd_cfg_group_info_t	g_info;
597cb5caa98Sdjl 	nscd_cfg_list_type_t	type = NSCD_CFG_LIST_STAT;
598cb5caa98Sdjl 	nscd_rc_t		rc;
599cb5caa98Sdjl 	void			*gsfunc;
600cb5caa98Sdjl 
601cb5caa98Sdjl 	desc = &_nscd_cfg_stat_desc[0];
602cb5caa98Sdjl 
603cb5caa98Sdjl 	/*
604cb5caa98Sdjl 	 * need to loop to the last (+1) stat description
605cb5caa98Sdjl 	 * which is a fake group and which marks the end
606cb5caa98Sdjl 	 * of list. It is used to signal the end of the
607cb5caa98Sdjl 	 * previous group so that the proper data will be
608cb5caa98Sdjl 	 * set for that group
609cb5caa98Sdjl 	 */
610cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_stat + 1; i++, desc++) {
611cb5caa98Sdjl 
612cb5caa98Sdjl 		id = (nscd_cfg_id_t *)desc;
613cb5caa98Sdjl 
614cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->sflag,
615cb5caa98Sdjl 			NSCD_CFG_SFLAG_GROUP)) {
616cb5caa98Sdjl 
617cb5caa98Sdjl 			if (gdesc != NULL) {
618cb5caa98Sdjl 				g_info.num_param = fn;
619cb5caa98Sdjl 				gdesc->s_fn = fn;
620cb5caa98Sdjl 
621cb5caa98Sdjl 				if (g_info.num_param !=
622cb5caa98Sdjl 					gdesc->gi.num_param ||
623cb5caa98Sdjl 					!_nscd_cfg_bitmap_is_equal(
624cb5caa98Sdjl 					g_info.bitmap, gdesc->gi.bitmap)) {
625cb5caa98Sdjl 
626cb5caa98Sdjl 					_NSCD_LOG(NSCD_LOG_CONFIG,
627cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
628cb5caa98Sdjl 					(me, "ERROR: group (%s) "
629cb5caa98Sdjl 					"info mismatched: "
630cb5caa98Sdjl 					"group info (%d, %#6.4x) not "
631cb5caa98Sdjl 					"equal to the predefined one "
632cb5caa98Sdjl 					"(%d, %#6.4x)\n", gdesc->id.name,
633cb5caa98Sdjl 					g_info.num_param,
634cb5caa98Sdjl 					_nscd_cfg_bitmap_value(g_info.bitmap),
635cb5caa98Sdjl 					gdesc->gi.num_param,
636cb5caa98Sdjl 					_nscd_cfg_bitmap_value(
637cb5caa98Sdjl 						gdesc->gi.bitmap));
638cb5caa98Sdjl 
639cb5caa98Sdjl 					exit(1);
640cb5caa98Sdjl 					return (NSCD_CFG_STAT_DESC_ERROR);
641cb5caa98Sdjl 				}
642cb5caa98Sdjl 			}
643cb5caa98Sdjl 
644cb5caa98Sdjl 			gi = i;
645cb5caa98Sdjl 			fn = 0;
646cb5caa98Sdjl 			gdesc = desc;
647cb5caa98Sdjl 			g_info.bitmap = NSCD_CFG_BITMAP_ZERO;
648cb5caa98Sdjl 			gsfunc = NULL;
649cb5caa98Sdjl 
650cb5caa98Sdjl 			/*
651cb5caa98Sdjl 			 * set the get_stat function
652cb5caa98Sdjl 			 */
653cb5caa98Sdjl 			if (gdesc->gsfunc_name != NULL) {
654cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(gdesc->gsfunc_name,
655cb5caa98Sdjl 					&gdesc->get_stat, NULL, NULL);
656*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
657cb5caa98Sdjl 					return (rc);
658cb5caa98Sdjl 				gsfunc = (void *)gdesc->get_stat;
659cb5caa98Sdjl 			}
660cb5caa98Sdjl 		} else {
661cb5caa98Sdjl 			if (i == 0) {
662cb5caa98Sdjl 
663cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
664cb5caa98Sdjl 						NSCD_LOG_LEVEL_ERROR)
665cb5caa98Sdjl 				(me, "ERROR: first stat "
666cb5caa98Sdjl 				"description is not for a group\n");
667cb5caa98Sdjl 
668cb5caa98Sdjl 				return (NSCD_CFG_STAT_DESC_ERROR);
669cb5caa98Sdjl 			}
670cb5caa98Sdjl 
671cb5caa98Sdjl 			/*
672cb5caa98Sdjl 			 * set bitmap: the rightmost bit represents
673cb5caa98Sdjl 			 * the first member (index = 0) in the group,
674cb5caa98Sdjl 			 * the next bit is for the second member
675cb5caa98Sdjl 			 * (index = 1), and so on
676cb5caa98Sdjl 			 */
677cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(g_info.bitmap, fn);
678cb5caa98Sdjl 
679cb5caa98Sdjl 			desc->s_fn = fn++;
680cb5caa98Sdjl 
681cb5caa98Sdjl 			/*
682cb5caa98Sdjl 			 * set the get_stat function
683cb5caa98Sdjl 			 */
684cb5caa98Sdjl 			if (desc->gsfunc_name != NULL) {
685cb5caa98Sdjl 				rc = _nscd_cfg_get_funcp(desc->gsfunc_name,
686cb5caa98Sdjl 					&desc->get_stat, &gsfunc, NULL);
687*e37190e5Smichen 				if (rc != NSCD_SUCCESS)
688cb5caa98Sdjl 					return (rc);
689cb5caa98Sdjl 			}
690cb5caa98Sdjl 		}
691cb5caa98Sdjl 
692cb5caa98Sdjl 		/* if end of list reached, we are done */
693cb5caa98Sdjl 		if (i == _nscd_cfg_num_stat)
694cb5caa98Sdjl 			break;
695cb5caa98Sdjl 
696cb5caa98Sdjl 		desc->g_index = gi;
697cb5caa98Sdjl 
698cb5caa98Sdjl 		id->index = i;
699cb5caa98Sdjl 
700cb5caa98Sdjl 		if ((rc = _nscd_cfg_add_index_entry(id->name,
701cb5caa98Sdjl 			i, type)) != NSCD_SUCCESS) {
702cb5caa98Sdjl 
703cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
704cb5caa98Sdjl 			(me, "unable to add index entry for stat "
705cb5caa98Sdjl 			"description %s\n", id->name);
706cb5caa98Sdjl 
707cb5caa98Sdjl 			_nscd_free_db(cfg_paramDB);
708cb5caa98Sdjl 			return (rc);
709cb5caa98Sdjl 		} else {
710cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
711cb5caa98Sdjl 			(me, "index entry for stat description "
712cb5caa98Sdjl 			"%s added\n", id->name);
713cb5caa98Sdjl 		}
714cb5caa98Sdjl 	}
715cb5caa98Sdjl 
716cb5caa98Sdjl 	return (NSCD_SUCCESS);
717cb5caa98Sdjl }
718cb5caa98Sdjl 
719cb5caa98Sdjl static nscd_rc_t
720cb5caa98Sdjl _nscd_cfg_copy_vlen_data(
721cb5caa98Sdjl 	void			*data,
722cb5caa98Sdjl 	void			**new_data_p,
723cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
724cb5caa98Sdjl 	int			*data_len,
725cb5caa98Sdjl 	nscd_bool_t		in)
726cb5caa98Sdjl {
727cb5caa98Sdjl 	int			len, dlen;
728cb5caa98Sdjl 	nscd_cfg_vlen_data_t	*v = NULL;
729cb5caa98Sdjl 
730cb5caa98Sdjl 	*new_data_p = NULL;
731cb5caa98Sdjl 	*data_len = 0;
732cb5caa98Sdjl 
733cb5caa98Sdjl 	/* it is OK if there is nothing to copy */
734cb5caa98Sdjl 	if (data == NULL)
735cb5caa98Sdjl 		return (NSCD_SUCCESS);
736cb5caa98Sdjl 
737cb5caa98Sdjl 	/*
738cb5caa98Sdjl 	 * if copy to the config store we need to allocate space
739cb5caa98Sdjl 	 * for the extra vlen header
740cb5caa98Sdjl 	 */
741cb5caa98Sdjl 	if (desc->type == NSCD_CFG_DATA_STRING) {
742cb5caa98Sdjl 		len = dlen = strlen((char *)data) + 1;
743cb5caa98Sdjl 		if (in == nscd_true)
744cb5caa98Sdjl 			len += sizeof (nscd_cfg_vlen_data_t);
745cb5caa98Sdjl 	} else {
746cb5caa98Sdjl 		/*
747cb5caa98Sdjl 		 * should not be here, since for now
748cb5caa98Sdjl 		 * only string variable length data
749cb5caa98Sdjl 		 * is supported
750cb5caa98Sdjl 		 */
751cb5caa98Sdjl 		*new_data_p = NULL;
752cb5caa98Sdjl 		return (NSCD_CFG_PARAM_DESC_ERROR);
753cb5caa98Sdjl 	}
754cb5caa98Sdjl 
755cb5caa98Sdjl 	v = calloc(1, len);
756cb5caa98Sdjl 	if (v == NULL) {
757cb5caa98Sdjl 		*new_data_p = NULL;
758cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
759cb5caa98Sdjl 	}
760cb5caa98Sdjl 
761cb5caa98Sdjl 	/*
762cb5caa98Sdjl 	 * if copy to the config store, set up
763cb5caa98Sdjl 	 * the extra vlen header in which the
764cb5caa98Sdjl 	 * pointer to, and length of, the real
765cb5caa98Sdjl 	 * data are kept. The pointer to the real
766cb5caa98Sdjl 	 * data, not the vlen header, is returned.
767cb5caa98Sdjl 	 */
768cb5caa98Sdjl 	if (in == nscd_true) {
769cb5caa98Sdjl 		v->ptr = (char *)v + sizeof (nscd_cfg_vlen_data_t);
770cb5caa98Sdjl 		v->len = dlen;
771cb5caa98Sdjl 		(void) memcpy(v->ptr, data, dlen);
772cb5caa98Sdjl 		*new_data_p = v->ptr;
773cb5caa98Sdjl 	} else {
774cb5caa98Sdjl 		(void) memcpy(v, data, dlen);
775cb5caa98Sdjl 		*new_data_p = v;
776cb5caa98Sdjl 	}
777cb5caa98Sdjl 	*data_len = dlen;
778cb5caa98Sdjl 
779cb5caa98Sdjl 	return (NSCD_SUCCESS);
780cb5caa98Sdjl }
781cb5caa98Sdjl 
782cb5caa98Sdjl static void
783cb5caa98Sdjl _nscd_cfg_free_vlen_data_int(
784cb5caa98Sdjl 	void	*data)
785cb5caa98Sdjl {
786cb5caa98Sdjl 	nscd_cfg_vlen_data_t	*v = NULL;
787cb5caa98Sdjl 	void			*p;
788cb5caa98Sdjl 
789cb5caa98Sdjl 	if (data == NULL)
790cb5caa98Sdjl 		return;
791cb5caa98Sdjl 
792cb5caa98Sdjl 	p = (char *)data - sizeof (nscd_cfg_vlen_data_t);
793cb5caa98Sdjl 	v = (nscd_cfg_vlen_data_t *)p;
794cb5caa98Sdjl 	if (v->ptr == data)
795cb5caa98Sdjl 		free(v);
796cb5caa98Sdjl }
797cb5caa98Sdjl 
798cb5caa98Sdjl static nscd_rc_t
799cb5caa98Sdjl _nscd_cfg_set_vlen_data_int(
800cb5caa98Sdjl 	void		*src,
801cb5caa98Sdjl 	void		*dest,
802cb5caa98Sdjl 	nscd_bool_t	global)
803cb5caa98Sdjl {
804cb5caa98Sdjl 	int			i, offset, dlen = 0;
805cb5caa98Sdjl 	void			*s, *d, *new;
806cb5caa98Sdjl 	void			*cptr;
807cb5caa98Sdjl 	nscd_rc_t		rc;
808cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
809cb5caa98Sdjl 
810cb5caa98Sdjl 	desc = &_nscd_cfg_param_desc[0];
811cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param; i++, desc++) {
812cb5caa98Sdjl 
813cb5caa98Sdjl 		if (global == nscd_true &&
814cb5caa98Sdjl 			_nscd_cfg_flag_is_not_set(desc->pflag,
815cb5caa98Sdjl 				NSCD_CFG_PFLAG_GLOBAL))
816cb5caa98Sdjl 			continue;
817cb5caa98Sdjl 		else if (global != nscd_true &&
818cb5caa98Sdjl 			_nscd_cfg_flag_is_set(desc->pflag,
819cb5caa98Sdjl 				NSCD_CFG_PFLAG_GLOBAL))
820cb5caa98Sdjl 			continue;
821cb5caa98Sdjl 
822cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
823cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
824cb5caa98Sdjl 
825cb5caa98Sdjl 			offset = desc->g_offset + desc->p_offset;
826cb5caa98Sdjl 
827cb5caa98Sdjl 			s = (char *)src + offset;
828cb5caa98Sdjl 			cptr = *(char **)s;
829cb5caa98Sdjl 
830cb5caa98Sdjl 			rc = _nscd_cfg_copy_vlen_data(cptr, &new,
831cb5caa98Sdjl 					desc, &dlen, nscd_true);
832cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
833cb5caa98Sdjl 				return (rc);
834cb5caa98Sdjl 
835cb5caa98Sdjl 			d = (char *)dest + offset;
836cb5caa98Sdjl 			/* free the old vlen data */
837cb5caa98Sdjl 			if (*(char **)d == NULL)
838cb5caa98Sdjl 				_nscd_cfg_free_vlen_data_int(*(char **)d);
839cb5caa98Sdjl 
840cb5caa98Sdjl 			*(char **)d = new;
841cb5caa98Sdjl 		}
842cb5caa98Sdjl 	}
843cb5caa98Sdjl 
844cb5caa98Sdjl 	return (NSCD_SUCCESS);
845cb5caa98Sdjl }
846cb5caa98Sdjl 
847cb5caa98Sdjl static void *
848cb5caa98Sdjl _nscd_cfg_locate_vlen_data(
849cb5caa98Sdjl 	void	*cfg_data,
850cb5caa98Sdjl 	int	*len)
851cb5caa98Sdjl {
852cb5caa98Sdjl 	void	*ptr, *ret;
853cb5caa98Sdjl 
854cb5caa98Sdjl 	ptr = *(char **)cfg_data;
855cb5caa98Sdjl 	ret = ptr;
856cb5caa98Sdjl 	if (ret == NULL) {
857cb5caa98Sdjl 		*len = 0;
858cb5caa98Sdjl 		return (NULL);
859cb5caa98Sdjl 	}
860cb5caa98Sdjl 	ptr = (char *)ptr - sizeof (nscd_cfg_vlen_data_t);
861cb5caa98Sdjl 	*len = ((nscd_cfg_vlen_data_t *)ptr)->len;
862cb5caa98Sdjl 
863cb5caa98Sdjl 	return (ret);
864cb5caa98Sdjl }
865cb5caa98Sdjl 
866cb5caa98Sdjl static void
867cb5caa98Sdjl _nscd_cfg_lock(
868cb5caa98Sdjl 	nscd_bool_t	is_read,
869cb5caa98Sdjl 	nscd_cfg_lock_t	*cfglock)
870cb5caa98Sdjl {
871cb5caa98Sdjl 
872cb5caa98Sdjl 	int	(*lockfunc)(rwlock_t *);
873cb5caa98Sdjl 
874cb5caa98Sdjl 	if (cfglock == NULL)
875cb5caa98Sdjl 		return;
876cb5caa98Sdjl 
877cb5caa98Sdjl 	if (is_read == nscd_true)
878cb5caa98Sdjl 		lockfunc = rw_rdlock;
879cb5caa98Sdjl 	else
880cb5caa98Sdjl 		lockfunc = rw_wrlock;
881cb5caa98Sdjl 
882cb5caa98Sdjl 	if (cfglock->global != NULL) {
883cb5caa98Sdjl 
884cb5caa98Sdjl 		(lockfunc)(cfglock->global);
885cb5caa98Sdjl 		return;
886cb5caa98Sdjl 	}
887cb5caa98Sdjl 
888cb5caa98Sdjl 	if (cfglock->alldb != NULL)
889cb5caa98Sdjl 		(lockfunc)(cfglock->alldb);
890cb5caa98Sdjl 
891cb5caa98Sdjl 	if (cfglock->nswdb != NULL)
892cb5caa98Sdjl 		(lockfunc)(cfglock->nswdb);
893cb5caa98Sdjl }
894cb5caa98Sdjl 
895cb5caa98Sdjl static void
896cb5caa98Sdjl _nscd_cfg_unlock(
897cb5caa98Sdjl 	nscd_cfg_lock_t	*cfglock)
898cb5caa98Sdjl {
899cb5caa98Sdjl 	if (cfglock == NULL)
900cb5caa98Sdjl 		return;
901cb5caa98Sdjl 
902cb5caa98Sdjl 	if (cfglock->global != NULL) {
903cb5caa98Sdjl 
904cb5caa98Sdjl 		(void) rw_unlock(cfglock->global);
905cb5caa98Sdjl 		free(cfglock);
906cb5caa98Sdjl 		return;
907cb5caa98Sdjl 	}
908cb5caa98Sdjl 
909cb5caa98Sdjl 	if (cfglock->nswdb != NULL)
910cb5caa98Sdjl 		(void) rw_unlock(cfglock->nswdb);
911cb5caa98Sdjl 
912cb5caa98Sdjl 	if (cfglock->alldb != NULL)
913cb5caa98Sdjl 		(void) rw_unlock(cfglock->alldb);
914cb5caa98Sdjl 
915cb5caa98Sdjl 	free(cfglock);
916cb5caa98Sdjl }
917cb5caa98Sdjl 
918cb5caa98Sdjl /*
919cb5caa98Sdjl  * If vlen_data_addr is given, it will be set to the
920cb5caa98Sdjl  * address of the pointer pointing to the vlen data.
921cb5caa98Sdjl  * 'cfglock' will be set to point to the reader/writer
922cb5caa98Sdjl  * lock(s) protecting the (group) configuration data.
923cb5caa98Sdjl  */
924cb5caa98Sdjl static nscd_rc_t
925cb5caa98Sdjl _nscd_cfg_locate_cfg_data(
926cb5caa98Sdjl 	void			**cfg_data,
927cb5caa98Sdjl 	nscd_bool_t		is_read,
928cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
929cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
930cb5caa98Sdjl 	nscd_bool_t		get_group,
931cb5caa98Sdjl 	void			**vlen_data_addr,
932cb5caa98Sdjl 	int			*len,
933cb5caa98Sdjl 	nscd_cfg_lock_t		**cfglock)
934cb5caa98Sdjl {
935cb5caa98Sdjl 	int		offset;
936cb5caa98Sdjl 
937cb5caa98Sdjl 	*cfg_data = NULL;
938cb5caa98Sdjl 	if (len != NULL)
939cb5caa98Sdjl 		*len = 0;
940cb5caa98Sdjl 	if (vlen_data_addr != NULL)
941cb5caa98Sdjl 		*vlen_data_addr = NULL;
942cb5caa98Sdjl 
943cb5caa98Sdjl 	if (cfglock != NULL) {
944cb5caa98Sdjl 		*cfglock = calloc(1, sizeof (nscd_cfg_lock_t));
945cb5caa98Sdjl 		if (*cfglock == NULL)
946cb5caa98Sdjl 			return (NSCD_NO_MEMORY);
947cb5caa98Sdjl 	}
948cb5caa98Sdjl 
949cb5caa98Sdjl 	/* assume if nswdb is NULL, the param is a global one */
950cb5caa98Sdjl 	if (nswdb == NULL) {
951cb5caa98Sdjl 
952cb5caa98Sdjl 		offset = desc->g_offset;
953cb5caa98Sdjl 		if (get_group != nscd_true)
954cb5caa98Sdjl 			offset += desc->p_offset;
955cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_global_current + offset;
956cb5caa98Sdjl 
957cb5caa98Sdjl 		if (cfglock != NULL)
958cb5caa98Sdjl 			(*cfglock)->global = nscd_cfg_global_rwlock;
959cb5caa98Sdjl 
960cb5caa98Sdjl 	} else if (nswdb->index == NSCD_CFG_NSW_ALLDB_INDEX) {
961cb5caa98Sdjl 
962cb5caa98Sdjl 		offset = desc->g_offset;
963cb5caa98Sdjl 		if (get_group != nscd_true)
964cb5caa98Sdjl 			offset += desc->p_offset;
965cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_nsw_alldb_current +
966cb5caa98Sdjl 			offset;
967cb5caa98Sdjl 
968cb5caa98Sdjl 		if (cfglock != NULL)
969cb5caa98Sdjl 			(*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
970cb5caa98Sdjl 
971cb5caa98Sdjl 	} else {
972cb5caa98Sdjl 
973cb5caa98Sdjl 		offset = nswdb->index *
974cb5caa98Sdjl 			(sizeof (nscd_cfg_nsw_db_data_t)) + desc->g_offset;
975cb5caa98Sdjl 		if (get_group != nscd_true)
976cb5caa98Sdjl 			offset += desc->p_offset;
977cb5caa98Sdjl 		*cfg_data = (char *)nscd_cfg_nsw_db_data_current +
978cb5caa98Sdjl 			offset;
979cb5caa98Sdjl 
980cb5caa98Sdjl 		if (cfglock != NULL) {
981cb5caa98Sdjl 			(*cfglock)->nswdb =
982cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_rwlock[nswdb->index];
983cb5caa98Sdjl 
984cb5caa98Sdjl 			(*cfglock)->alldb = nscd_cfg_nsw_alldb_rwlock;
985cb5caa98Sdjl 		}
986cb5caa98Sdjl 	}
987cb5caa98Sdjl 
988cb5caa98Sdjl 	/* lock the config data */
989cb5caa98Sdjl 	if (cfglock != NULL)
990cb5caa98Sdjl 		_nscd_cfg_lock(is_read, *cfglock);
991cb5caa98Sdjl 
992cb5caa98Sdjl 	if (get_group != nscd_true &&
993cb5caa98Sdjl 		_nscd_cfg_flag_is_not_set(desc->pflag,
994cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP) &&
995cb5caa98Sdjl 		(_nscd_cfg_flag_is_set(desc->pflag,
996cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA))) {
997cb5caa98Sdjl 		if (vlen_data_addr != NULL)
998cb5caa98Sdjl 			*vlen_data_addr = *cfg_data;
999cb5caa98Sdjl 		*cfg_data = _nscd_cfg_locate_vlen_data(*cfg_data, len);
1000cb5caa98Sdjl 		return (NSCD_SUCCESS);
1001cb5caa98Sdjl 	}
1002cb5caa98Sdjl 
1003cb5caa98Sdjl 	if (len != NULL) {
1004cb5caa98Sdjl 		if (get_group == nscd_true)
1005cb5caa98Sdjl 			*len = desc->g_size;
1006cb5caa98Sdjl 		else
1007cb5caa98Sdjl 			*len = desc->p_size;
1008cb5caa98Sdjl 	}
1009cb5caa98Sdjl 
1010cb5caa98Sdjl 	return (NSCD_SUCCESS);
1011cb5caa98Sdjl }
1012cb5caa98Sdjl 
1013cb5caa98Sdjl /*
1014cb5caa98Sdjl  * perform the preliminary (range) check on 'data' based on the
1015cb5caa98Sdjl  * datatype (desc->datatype) of the config parameter
1016cb5caa98Sdjl  */
1017cb5caa98Sdjl nscd_rc_t
1018cb5caa98Sdjl _nscd_cfg_prelim_check(
1019cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1020cb5caa98Sdjl 	void			*data,
1021cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1022cb5caa98Sdjl {
1023cb5caa98Sdjl 
1024cb5caa98Sdjl 	char			*me = "_nscd_cfg_prelim_check";
1025cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
1026cb5caa98Sdjl 	nscd_cfg_str_check_t	*sc;
1027cb5caa98Sdjl 	nscd_cfg_int_check_t	*ic;
1028cb5caa98Sdjl 	nscd_cfg_bitmap_check_t	*bmc;
1029cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_CFG_PRELIM_CHECK_FAILED;
1030cb5caa98Sdjl 
1031cb5caa98Sdjl 	if ((nscd_cfg_str_check_t *)desc->p_check == NULL)
1032cb5caa98Sdjl 		return (NSCD_SUCCESS);
1033cb5caa98Sdjl 
1034cb5caa98Sdjl 	switch (desc->type) {
1035cb5caa98Sdjl 
1036cb5caa98Sdjl 	case NSCD_CFG_DATA_STRING:
1037cb5caa98Sdjl 
1038cb5caa98Sdjl 		sc = (nscd_cfg_str_check_t *)desc->p_check;
1039cb5caa98Sdjl 		if (sc->must_not_null == nscd_true && data == NULL) {
1040cb5caa98Sdjl 
1041cb5caa98Sdjl 			if (errorp == NULL)
1042cb5caa98Sdjl 				break;
1043cb5caa98Sdjl 
1044cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1045cb5caa98Sdjl 			gettext("data must be specified for %s"),
1046cb5caa98Sdjl 			desc->id.name);
1047cb5caa98Sdjl 
1048cb5caa98Sdjl 			break;
1049cb5caa98Sdjl 		}
1050cb5caa98Sdjl 
1051cb5caa98Sdjl 		if (data == NULL) {
1052cb5caa98Sdjl 			rc = NSCD_SUCCESS;
1053cb5caa98Sdjl 			break;
1054cb5caa98Sdjl 		}
1055cb5caa98Sdjl 
1056cb5caa98Sdjl 		if (sc->maxlen != 0 &&
1057cb5caa98Sdjl 			strlen((char *)data) > sc->maxlen) {
1058cb5caa98Sdjl 
1059cb5caa98Sdjl 			if (errorp == NULL)
1060cb5caa98Sdjl 				break;
1061cb5caa98Sdjl 
1062cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1063cb5caa98Sdjl 		gettext("length of data (%s) for %s larger than %d"),
1064cb5caa98Sdjl 				(char *)data, desc->id.name, sc->maxlen);
1065cb5caa98Sdjl 			break;
1066cb5caa98Sdjl 		}
1067cb5caa98Sdjl 
1068cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1069cb5caa98Sdjl 
1070cb5caa98Sdjl 		break;
1071cb5caa98Sdjl 
1072cb5caa98Sdjl 	case NSCD_CFG_DATA_INTEGER:
1073cb5caa98Sdjl 
1074cb5caa98Sdjl 		ic = (nscd_cfg_int_check_t *)desc->p_check;
1075cb5caa98Sdjl 		if (*(int *)data > ic->max ||
1076cb5caa98Sdjl 			*(int *)data < ic->min) {
1077cb5caa98Sdjl 
1078cb5caa98Sdjl 			if (errorp == NULL)
1079cb5caa98Sdjl 				break;
1080cb5caa98Sdjl 
1081cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1082cb5caa98Sdjl 		gettext("data (%d) for %s out of range (%d - %d)"),
1083cb5caa98Sdjl 				*(int *)data, desc->id.name,
1084cb5caa98Sdjl 				ic->min, ic->max);
1085cb5caa98Sdjl 
1086cb5caa98Sdjl 			break;
1087cb5caa98Sdjl 		}
1088cb5caa98Sdjl 
1089cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1090cb5caa98Sdjl 
1091cb5caa98Sdjl 		break;
1092cb5caa98Sdjl 
1093cb5caa98Sdjl 	case NSCD_CFG_DATA_BITMAP:
1094cb5caa98Sdjl 
1095cb5caa98Sdjl 		bmc = (nscd_cfg_bitmap_check_t *)desc->p_check;
1096cb5caa98Sdjl 		if (_nscd_cfg_bitmap_value(*(nscd_cfg_bitmap_t *)data) &
1097cb5caa98Sdjl 			~(bmc->valid_bits)) {
1098cb5caa98Sdjl 
1099cb5caa98Sdjl 			if (errorp == NULL)
1100cb5caa98Sdjl 				break;
1101cb5caa98Sdjl 
1102cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1103cb5caa98Sdjl 		gettext("data (%#6.4x) for %s contain bit not in 0x%x"),
1104cb5caa98Sdjl 				_nscd_cfg_bitmap_value(
1105cb5caa98Sdjl 					*(nscd_cfg_bitmap_t *)data),
1106cb5caa98Sdjl 				desc->id.name,
1107cb5caa98Sdjl 				_nscd_cfg_bitmap_value(bmc->valid_bits));
1108cb5caa98Sdjl 			break;
1109cb5caa98Sdjl 		}
1110cb5caa98Sdjl 
1111cb5caa98Sdjl 		rc = NSCD_SUCCESS;
1112cb5caa98Sdjl 
1113cb5caa98Sdjl 		break;
1114cb5caa98Sdjl 	}
1115cb5caa98Sdjl 
1116cb5caa98Sdjl 	if (rc != NSCD_SUCCESS && errorp != NULL) {
1117cb5caa98Sdjl 		*errorp = _nscd_cfg_make_error(rc, msg);
1118cb5caa98Sdjl 
1119cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1120cb5caa98Sdjl 		(me, "invalid argument: %s\n", (*errorp)->msg);
1121cb5caa98Sdjl 	}
1122cb5caa98Sdjl 
1123cb5caa98Sdjl 	return (rc);
1124cb5caa98Sdjl }
1125cb5caa98Sdjl 
1126cb5caa98Sdjl static nscd_rc_t
1127cb5caa98Sdjl _nscd_cfg_notify_i(
1128cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1129cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
1130cb5caa98Sdjl 	int			*skip,
1131cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1132cb5caa98Sdjl {
1133cb5caa98Sdjl 
1134cb5caa98Sdjl 	char			*me = "_nscd_cfg_notify_i";
1135cb5caa98Sdjl 	int			i, num, skip_bk;
1136cb5caa98Sdjl 	void			*cfg_data, *cdata;
1137cb5caa98Sdjl 	void			*cookie = NULL;
1138cb5caa98Sdjl 	nscd_rc_t		rc;
1139cb5caa98Sdjl 	nscd_cfg_flag_t		dflag, dflag1;
1140cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap_c, bitmap_s, *bitmap_addr;
1141cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1142cb5caa98Sdjl 
1143cb5caa98Sdjl 	if (errorp != NULL)
1144cb5caa98Sdjl 		*errorp = NULL;
1145cb5caa98Sdjl 
1146cb5caa98Sdjl 	if (skip == NULL)
1147cb5caa98Sdjl 		skip = &skip_bk;
1148cb5caa98Sdjl 
1149cb5caa98Sdjl 	*skip = 0;
1150cb5caa98Sdjl 
1151cb5caa98Sdjl 	if (_nscd_cfg_flag_is_not_set(desc->pflag,
1152cb5caa98Sdjl 		NSCD_CFG_PFLAG_GROUP)) {
1153cb5caa98Sdjl 
1154cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1155cb5caa98Sdjl 		(me, "ERROR: expect parameter description for group, "
1156cb5caa98Sdjl 		"but receive parameter description is for %s\n",
1157cb5caa98Sdjl 		desc->id.name);
1158cb5caa98Sdjl 
1159cb5caa98Sdjl 		return (NSCD_CFG_PARAM_DESC_ERROR);
1160cb5caa98Sdjl 	}
1161cb5caa98Sdjl 
1162cb5caa98Sdjl 	/*
1163cb5caa98Sdjl 	 * Set data flag going with data to be sent to the
1164cb5caa98Sdjl 	 * verify/notify routines. Allowing the config flag
1165cb5caa98Sdjl 	 * be exipandable, set the bits one by one.
1166cb5caa98Sdjl 	 */
1167cb5caa98Sdjl 	dflag = NSCD_CFG_FLAG_ZERO;
1168cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
1169cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_INIT);
1170cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
1171cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
1172cb5caa98Sdjl 		NSCD_CFG_PFLAG_INIT_SET_ALL_DB))
1173cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag,
1174cb5caa98Sdjl 			NSCD_CFG_DFLAG_SET_ALL_DB);
1175cb5caa98Sdjl 
1176cb5caa98Sdjl 	/* get to the group data in the config store */
1177cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true,
1178cb5caa98Sdjl 			desc, nswdb, nscd_true, NULL, NULL, NULL);
1179cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1180cb5caa98Sdjl 		goto error;
1181cb5caa98Sdjl 
1182cb5caa98Sdjl 	/*
1183cb5caa98Sdjl 	 * the static bitmap associated with the group
1184cb5caa98Sdjl 	 * may be replaced before sending to the components,
1185cb5caa98Sdjl 	 * so save the bitmap for later use
1186cb5caa98Sdjl 	 */
1187cb5caa98Sdjl 	gi = _nscd_cfg_get_gi(cfg_data);
1188cb5caa98Sdjl 	bitmap_c = gi->bitmap;
1189cb5caa98Sdjl 	bitmap_addr = &(gi->bitmap);
1190cb5caa98Sdjl 
1191cb5caa98Sdjl 	/*
1192cb5caa98Sdjl 	 * the elements in this group will all be handled
1193cb5caa98Sdjl 	 * so the caller can skip them
1194cb5caa98Sdjl 	 */
1195cb5caa98Sdjl 	*skip = desc->p_fn;
1196cb5caa98Sdjl 
1197cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
1198cb5caa98Sdjl 			NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
1199cb5caa98Sdjl 		/* send the entire group just once */
1200cb5caa98Sdjl 		num = 1;
1201cb5caa98Sdjl 
1202cb5caa98Sdjl 	else { /* send individual members one by one */
1203cb5caa98Sdjl 
1204cb5caa98Sdjl 		num = desc->p_fn;
1205cb5caa98Sdjl 
1206cb5caa98Sdjl 		/*
1207cb5caa98Sdjl 		 * skip the first desc which is for the group
1208cb5caa98Sdjl 		 * and get to the desc for the first member
1209cb5caa98Sdjl 		 */
1210cb5caa98Sdjl 		desc++;
1211cb5caa98Sdjl 
1212cb5caa98Sdjl 		dflag = _nscd_cfg_flag_unset(dflag,
1213cb5caa98Sdjl 			NSCD_CFG_DFLAG_GROUP);
1214cb5caa98Sdjl 	}
1215cb5caa98Sdjl 
1216cb5caa98Sdjl 	dflag1 = dflag;
1217cb5caa98Sdjl 	for (i = 0; i < num; i++, desc++) {
1218cb5caa98Sdjl 
1219cb5caa98Sdjl 		dflag = dflag1;
1220cb5caa98Sdjl 
1221cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1222cb5caa98Sdjl 				NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
1223cb5caa98Sdjl 
1224cb5caa98Sdjl 			/* set the bitmap to select just this member */
1225cb5caa98Sdjl 			bitmap_s = NSCD_CFG_BITMAP_ZERO;
1226cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap_s, i);
1227cb5caa98Sdjl 			/* replace the bitmap in the cfg data */
1228cb5caa98Sdjl 			_nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
1229cb5caa98Sdjl 
1230cb5caa98Sdjl 			/*
1231cb5caa98Sdjl 			 * send the whole group but with only one
1232cb5caa98Sdjl 			 * member selected
1233cb5caa98Sdjl 			 */
1234cb5caa98Sdjl 			cdata = cfg_data;
1235cb5caa98Sdjl 
1236cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1237cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
1238cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1239cb5caa98Sdjl 				NSCD_CFG_DFLAG_BIT_SELECTED);
1240cb5caa98Sdjl 		} else {
1241cb5caa98Sdjl 			/*
1242cb5caa98Sdjl 			 * send param data or group data:
1243cb5caa98Sdjl 			 * param data - non-xero desc->p_offset
1244cb5caa98Sdjl 			 * group data - zero desc->p_offset
1245cb5caa98Sdjl 			 */
1246cb5caa98Sdjl 			cdata = (char *)cfg_data + desc->p_offset;
1247cb5caa98Sdjl 
1248cb5caa98Sdjl 			/*
1249cb5caa98Sdjl 			 * if variable length data, need to send pointer
1250cb5caa98Sdjl 			 * to the data (not the address of the pointer)
1251cb5caa98Sdjl 			 */
1252cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
1253cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
1254cb5caa98Sdjl 				cdata = *(char **)cdata;
1255cb5caa98Sdjl 		}
1256cb5caa98Sdjl 
1257cb5caa98Sdjl 		if (desc->verify != NULL) {
1258cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1259cb5caa98Sdjl 				NSCD_CFG_DFLAG_VERIFY);
1260cb5caa98Sdjl 			rc = desc->verify(cdata, desc, nswdb,
1261cb5caa98Sdjl 				dflag, errorp, &cookie);
1262cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
1263cb5caa98Sdjl 				goto error;
1264cb5caa98Sdjl 		}
1265cb5caa98Sdjl 
1266cb5caa98Sdjl 		if (desc->notify != NULL) {
1267cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
1268cb5caa98Sdjl 				NSCD_CFG_DFLAG_NOTIFY);
1269cb5caa98Sdjl 
1270cb5caa98Sdjl 			rc = desc->notify(cfg_data, desc, nswdb,
1271cb5caa98Sdjl 				dflag, errorp, cookie);
1272cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
1273cb5caa98Sdjl 				goto error;
1274cb5caa98Sdjl 		}
1275cb5caa98Sdjl 	}
1276cb5caa98Sdjl 
1277cb5caa98Sdjl 	rc = NSCD_SUCCESS;
1278cb5caa98Sdjl 
1279cb5caa98Sdjl 	/* restore the bitmap in the cfg data */
1280cb5caa98Sdjl 	_nscd_cfg_bitmap_set(bitmap_addr, bitmap_c);
1281cb5caa98Sdjl 
1282cb5caa98Sdjl 	error:
1283cb5caa98Sdjl 
1284cb5caa98Sdjl 	return (rc);
1285cb5caa98Sdjl 
1286cb5caa98Sdjl }
1287cb5caa98Sdjl 
1288cb5caa98Sdjl static nscd_rc_t
1289cb5caa98Sdjl _nscd_cfg_notify_init(
1290cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1291cb5caa98Sdjl {
1292cb5caa98Sdjl 	int			i, j, skip;
1293cb5caa98Sdjl 	nscd_rc_t		rc;
1294cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb = NULL;
1295cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1296cb5caa98Sdjl 
1297cb5caa98Sdjl 	if (errorp != NULL)
1298cb5caa98Sdjl 		*errorp = NULL;
1299cb5caa98Sdjl 
1300cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_param; i++) {
1301cb5caa98Sdjl 
1302cb5caa98Sdjl 		desc = &_nscd_cfg_param_desc[i];
1303cb5caa98Sdjl 
1304cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1305cb5caa98Sdjl 			NSCD_CFG_PFLAG_GLOBAL)) { /* global cfg data */
1306cb5caa98Sdjl 
1307cb5caa98Sdjl 			rc = _nscd_cfg_notify_i(desc, NULL, &skip, errorp);
1308cb5caa98Sdjl 		} else {
1309cb5caa98Sdjl 
1310cb5caa98Sdjl 			/*
1311cb5caa98Sdjl 			 * if use defaults for all nsswitch database,
1312cb5caa98Sdjl 			 * send the config data to verify/notify once
1313cb5caa98Sdjl 			 */
1314cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
1315cb5caa98Sdjl 				NSCD_CFG_PFLAG_INIT_SET_ALL_DB)) {
1316cb5caa98Sdjl 
1317cb5caa98Sdjl 				nswdb = &_nscd_cfg_nsw_alldb;
1318cb5caa98Sdjl 
1319cb5caa98Sdjl 				rc = _nscd_cfg_notify_i(desc, nswdb,
1320cb5caa98Sdjl 					&skip, errorp);
1321cb5caa98Sdjl 			} else { /* send data once for each nsw db */
1322cb5caa98Sdjl 
1323*e37190e5Smichen 				for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1324cb5caa98Sdjl 
1325cb5caa98Sdjl 					nswdb = &_nscd_cfg_nsw_db[j];
1326cb5caa98Sdjl 
1327cb5caa98Sdjl 					rc = _nscd_cfg_notify_i(desc,
1328cb5caa98Sdjl 						nswdb, &skip, errorp);
1329*e37190e5Smichen 
1330*e37190e5Smichen 					if (rc != NSCD_SUCCESS)
1331*e37190e5Smichen 						break;
1332cb5caa98Sdjl 				}
1333cb5caa98Sdjl 			}
1334cb5caa98Sdjl 		}
1335cb5caa98Sdjl 
1336cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
1337cb5caa98Sdjl 			return (rc);
1338cb5caa98Sdjl 
1339cb5caa98Sdjl 		i += skip;
1340cb5caa98Sdjl 	}
1341cb5caa98Sdjl 
1342cb5caa98Sdjl 	return (NSCD_SUCCESS);
1343cb5caa98Sdjl }
1344cb5caa98Sdjl 
1345cb5caa98Sdjl nscd_rc_t
1346cb5caa98Sdjl _nscd_cfg_init(
1347cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
1348cb5caa98Sdjl {
1349cb5caa98Sdjl 
1350cb5caa98Sdjl 	int				i, j, datalen;
1351cb5caa98Sdjl 	int				dbi = 0, dbj = 0;
1352cb5caa98Sdjl 	char				*dest, *src;
1353cb5caa98Sdjl 	char				*dbni = NULL, *dbnj = NULL;
1354cb5caa98Sdjl 	nscd_rc_t			rc;
1355cb5caa98Sdjl 	nscd_cfg_nsw_spc_default_t	*spc;
1356cb5caa98Sdjl 
1357cb5caa98Sdjl 	if (errorp != NULL)
1358cb5caa98Sdjl 		*errorp = NULL;
1359cb5caa98Sdjl 
1360cb5caa98Sdjl 	rc = _nscd_cfg_init_param();
1361cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1362cb5caa98Sdjl 		return (rc);
1363cb5caa98Sdjl 
1364cb5caa98Sdjl 	rc = _nscd_cfg_init_stat();
1365cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1366cb5caa98Sdjl 		return (rc);
1367cb5caa98Sdjl 
1368cb5caa98Sdjl 	nscd_cfg_global_current = calloc(1,
1369cb5caa98Sdjl 			sizeof (nscd_cfg_global_data_t));
1370cb5caa98Sdjl 	if (nscd_cfg_global_current == NULL)
1371cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1372cb5caa98Sdjl 
1373cb5caa98Sdjl 	nscd_cfg_nsw_alldb_current = calloc(1,
1374cb5caa98Sdjl 		sizeof (nscd_cfg_nsw_db_data_t));
1375cb5caa98Sdjl 	if (nscd_cfg_nsw_alldb_current == NULL)
1376cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1377cb5caa98Sdjl 
1378cb5caa98Sdjl 	nscd_cfg_nsw_db_data_current = calloc(_nscd_cfg_num_nsw_db,
1379cb5caa98Sdjl 		sizeof (nscd_cfg_nsw_db_data_t));
1380cb5caa98Sdjl 	if (nscd_cfg_nsw_db_data_current == NULL)
1381cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1382cb5caa98Sdjl 
1383cb5caa98Sdjl 	nscd_cfg_global_rwlock = calloc(1, sizeof (rwlock_t));
1384cb5caa98Sdjl 	if (nscd_cfg_global_rwlock == NULL)
1385cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1386cb5caa98Sdjl 	(void) rwlock_init(nscd_cfg_global_rwlock, NULL, NULL);
1387cb5caa98Sdjl 
1388cb5caa98Sdjl 	*nscd_cfg_global_current = nscd_cfg_global_default;
1389cb5caa98Sdjl 
1390cb5caa98Sdjl 	rc = _nscd_cfg_set_vlen_data_int(&nscd_cfg_global_default,
1391cb5caa98Sdjl 		nscd_cfg_global_current, nscd_true);
1392cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1393cb5caa98Sdjl 		return (rc);
1394cb5caa98Sdjl 
1395cb5caa98Sdjl 	nscd_cfg_nsw_db_data_rwlock = calloc(_nscd_cfg_num_nsw_db,
1396cb5caa98Sdjl 		sizeof (rwlock_t));
1397cb5caa98Sdjl 	if (nscd_cfg_nsw_db_data_rwlock == NULL)
1398cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1399cb5caa98Sdjl 
1400cb5caa98Sdjl 	/* set per switch db config to the default for all db's */
1401cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1402cb5caa98Sdjl 
1403cb5caa98Sdjl 		nscd_cfg_nsw_db_data_current[i] =
1404cb5caa98Sdjl 			nscd_cfg_nsw_db_data_default;
1405cb5caa98Sdjl 
1406cb5caa98Sdjl 		(void) rwlock_init(&nscd_cfg_nsw_db_data_rwlock[i],
1407cb5caa98Sdjl 			NULL, NULL);
1408cb5caa98Sdjl 	}
1409cb5caa98Sdjl 
1410cb5caa98Sdjl 	/* add db specific defaults */
1411cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_default; i++) {
1412cb5caa98Sdjl 
1413cb5caa98Sdjl 		if (_nscd_cfg_nsw_spc_default[i].data == NULL)
1414cb5caa98Sdjl 			continue;
1415cb5caa98Sdjl 
1416cb5caa98Sdjl 		if (_nscd_cfg_nsw_spc_default[i].db != dbni) {
1417cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1418cb5caa98Sdjl 
1419cb5caa98Sdjl 				if (strcmp(_nscd_cfg_nsw_db[j].name,
1420cb5caa98Sdjl 					_nscd_cfg_nsw_spc_default[i].db) != 0)
1421cb5caa98Sdjl 					continue;
1422cb5caa98Sdjl 
1423cb5caa98Sdjl 				dbi = _nscd_cfg_nsw_db[j].index;
1424cb5caa98Sdjl 				dbni = _nscd_cfg_nsw_db[j].name;
1425cb5caa98Sdjl 				break;
1426cb5caa98Sdjl 			}
1427cb5caa98Sdjl 		}
1428cb5caa98Sdjl 
1429cb5caa98Sdjl 		dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1430cb5caa98Sdjl 			_nscd_cfg_nsw_spc_default[i].group_off +
1431cb5caa98Sdjl 			_nscd_cfg_nsw_spc_default[i].param_off;
1432cb5caa98Sdjl 
1433cb5caa98Sdjl 		src = _nscd_cfg_nsw_spc_default[i].data;
1434cb5caa98Sdjl 		datalen = _nscd_cfg_nsw_spc_default[i].data_len;
1435cb5caa98Sdjl 
1436cb5caa98Sdjl 		(void) memcpy(dest, src, datalen);
1437cb5caa98Sdjl 	}
1438cb5caa98Sdjl 
1439cb5caa98Sdjl 	/* add db specific defaults via links */
1440cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
1441cb5caa98Sdjl 
1442cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
1443cb5caa98Sdjl 			continue;
1444cb5caa98Sdjl 
1445cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
1446cb5caa98Sdjl 
1447cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].db != dbni) {
1448cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1449cb5caa98Sdjl 
1450cb5caa98Sdjl 				if (strcmp(_nscd_cfg_nsw_db[j].name,
1451cb5caa98Sdjl 					_nscd_cfg_nsw_link_default[i].db) != 0)
1452cb5caa98Sdjl 					continue;
1453cb5caa98Sdjl 
1454cb5caa98Sdjl 				dbi = _nscd_cfg_nsw_db[j].index;
1455cb5caa98Sdjl 				dbni = _nscd_cfg_nsw_db[j].name;
1456cb5caa98Sdjl 				break;
1457cb5caa98Sdjl 			}
1458cb5caa98Sdjl 		}
1459cb5caa98Sdjl 
1460cb5caa98Sdjl 		dest = (char *)&nscd_cfg_nsw_db_data_current[dbi] +
1461cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off +
1462cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off;
1463cb5caa98Sdjl 
1464cb5caa98Sdjl 		if (_nscd_cfg_nsw_db[j].name != dbnj) {
1465cb5caa98Sdjl 			for (j = 0; j < _nscd_cfg_num_nsw_db; j++) {
1466cb5caa98Sdjl 
1467cb5caa98Sdjl 				if (strcmp(spc->db,
1468cb5caa98Sdjl 					_nscd_cfg_nsw_db[j].name) != 0)
1469cb5caa98Sdjl 					continue;
1470cb5caa98Sdjl 
1471cb5caa98Sdjl 				dbnj = _nscd_cfg_nsw_db[j].name;
1472cb5caa98Sdjl 				dbj = _nscd_cfg_nsw_db[j].index;
1473cb5caa98Sdjl 				break;
1474cb5caa98Sdjl 			}
1475cb5caa98Sdjl 		}
1476cb5caa98Sdjl 
1477cb5caa98Sdjl 		src = (char *)&nscd_cfg_nsw_db_data_current[dbj] +
1478cb5caa98Sdjl 				spc->group_off + spc->param_off;
1479cb5caa98Sdjl 		datalen = spc->data_len;
1480cb5caa98Sdjl 
1481cb5caa98Sdjl 		(void) memcpy(dest, src, datalen);
1482cb5caa98Sdjl 	}
1483cb5caa98Sdjl 
1484cb5caa98Sdjl 	/* fix up variable length fields */
1485cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
1486cb5caa98Sdjl 
1487cb5caa98Sdjl 		rc = _nscd_cfg_set_vlen_data_int(
1488cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_current[i],
1489cb5caa98Sdjl 			&nscd_cfg_nsw_db_data_current[i], nscd_false);
1490cb5caa98Sdjl 		if (rc != NSCD_SUCCESS)
1491cb5caa98Sdjl 			return (rc);
1492cb5caa98Sdjl 	}
1493cb5caa98Sdjl 
1494cb5caa98Sdjl 	nscd_cfg_nsw_alldb_rwlock = calloc(1, sizeof (rwlock_t));
1495cb5caa98Sdjl 	if (nscd_cfg_nsw_alldb_rwlock == NULL)
1496cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1497cb5caa98Sdjl 
1498cb5caa98Sdjl 	(void) rwlock_init(nscd_cfg_nsw_alldb_rwlock, NULL, NULL);
1499cb5caa98Sdjl 
1500cb5caa98Sdjl 	rc = _nscd_cfg_set_vlen_data_int(
1501cb5caa98Sdjl 		&nscd_cfg_nsw_db_data_default,
1502*e37190e5Smichen 		nscd_cfg_nsw_alldb_current, nscd_false);
1503cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1504cb5caa98Sdjl 		return (rc);
1505cb5caa98Sdjl 
1506cb5caa98Sdjl 	/*
1507cb5caa98Sdjl 	 * notify and send the configuration data to
1508cb5caa98Sdjl 	 * the nscd components
1509cb5caa98Sdjl 	 */
1510cb5caa98Sdjl 	rc = _nscd_cfg_notify_init(errorp);
1511cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1512cb5caa98Sdjl 		return (rc);
1513cb5caa98Sdjl 
1514cb5caa98Sdjl 	return (NSCD_SUCCESS);
1515cb5caa98Sdjl }
1516cb5caa98Sdjl 
1517cb5caa98Sdjl static nscd_rc_t
1518cb5caa98Sdjl _nscd_cfg_get_handle_common(
1519cb5caa98Sdjl 	nscd_cfg_list_type_t	type,
1520cb5caa98Sdjl 	char			*name,
1521cb5caa98Sdjl 	char			*nswdb_name,
1522cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1523cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1524cb5caa98Sdjl {
1525cb5caa98Sdjl 
1526cb5caa98Sdjl 	int			i, is_global;
1527cb5caa98Sdjl 	char			*desc_str;
1528cb5caa98Sdjl 	nscd_cfg_handle_t	*h;
1529cb5caa98Sdjl 	nscd_cfg_param_desc_t	*pdesc;
1530cb5caa98Sdjl 	nscd_cfg_stat_desc_t	*sdesc;
1531cb5caa98Sdjl 	char			*me = "_nscd_cfg_get_handle_common";
1532cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
1533cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_INVALID_ARGUMENT;
1534cb5caa98Sdjl 
1535cb5caa98Sdjl 	if (handle == NULL) {
1536cb5caa98Sdjl 
1537cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1538cb5caa98Sdjl 			gettext("address of handle not specified"));
1539cb5caa98Sdjl 		if (errorp)
1540cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1541cb5caa98Sdjl 
1542cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1543cb5caa98Sdjl 		(me, "invalid argument: %s\n", msg);
1544cb5caa98Sdjl 
1545cb5caa98Sdjl 		return (rc);
1546cb5caa98Sdjl 	}
1547cb5caa98Sdjl 
1548cb5caa98Sdjl 	*handle = NULL;
1549cb5caa98Sdjl 
1550cb5caa98Sdjl 	if (name == NULL) {
1551cb5caa98Sdjl 
1552cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1553cb5caa98Sdjl 			gettext("name not specified"));
1554cb5caa98Sdjl 		if (errorp)
1555cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1556cb5caa98Sdjl 
1557cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1558cb5caa98Sdjl 		(me, "invalid argument: %s\n");
1559cb5caa98Sdjl 
1560cb5caa98Sdjl 		return (rc);
1561cb5caa98Sdjl 	}
1562cb5caa98Sdjl 
1563cb5caa98Sdjl 	h = calloc(1, sizeof (nscd_cfg_handle_t));
1564cb5caa98Sdjl 	if (h == NULL)
1565cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
1566cb5caa98Sdjl 	h->type = type;
1567cb5caa98Sdjl 
1568cb5caa98Sdjl 	if (type == NSCD_CFG_LIST_PARAM)
1569cb5caa98Sdjl 		desc_str = gettext("configuration parameter");
1570cb5caa98Sdjl 	else
1571cb5caa98Sdjl 		desc_str = gettext("statistics");
1572cb5caa98Sdjl 
1573cb5caa98Sdjl 	/* get param or stat descriptor */
1574cb5caa98Sdjl 	i = _nscd_cfg_get_index(name, type);
1575cb5caa98Sdjl 	if (i != -1) {
1576cb5caa98Sdjl 
1577cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1578cb5caa98Sdjl 		(me, "%s: index of %s is %d\n", desc_str, name, i);
1579cb5caa98Sdjl 
1580cb5caa98Sdjl 		if (type == NSCD_CFG_LIST_PARAM) {
1581cb5caa98Sdjl 			pdesc = &_nscd_cfg_param_desc[i];
1582cb5caa98Sdjl 			(void) memcpy(&h->desc, &pdesc, sizeof (pdesc));
1583cb5caa98Sdjl 			is_global = _nscd_cfg_flag_is_set(
1584cb5caa98Sdjl 				pdesc->pflag, NSCD_CFG_PFLAG_GLOBAL);
1585cb5caa98Sdjl 
1586cb5caa98Sdjl 			/* hidden params are not exposed */
1587cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(
1588cb5caa98Sdjl 				pdesc->pflag, NSCD_CFG_PFLAG_HIDDEN))
1589cb5caa98Sdjl 				i = -1;
1590cb5caa98Sdjl 
1591cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(pdesc->pflag,
1592cb5caa98Sdjl 					NSCD_CFG_PFLAG_OBSOLETE)) {
1593cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG,
1594cb5caa98Sdjl 					NSCD_LOG_LEVEL_WARNING)
1595cb5caa98Sdjl 					(me,
1596cb5caa98Sdjl 			gettext("%s: %s is obsolete and will be ignored\n"),
1597cb5caa98Sdjl 					desc_str, name);
1598cb5caa98Sdjl 			}
1599cb5caa98Sdjl 		} else {
1600cb5caa98Sdjl 			sdesc = &_nscd_cfg_stat_desc[i];
1601cb5caa98Sdjl 			(void) memcpy(&h->desc, &sdesc, sizeof (sdesc));
1602cb5caa98Sdjl 			is_global = _nscd_cfg_flag_is_set(
1603cb5caa98Sdjl 				sdesc->sflag, NSCD_CFG_SFLAG_GLOBAL);
1604cb5caa98Sdjl 		}
1605cb5caa98Sdjl 	}
1606cb5caa98Sdjl 
1607cb5caa98Sdjl 	if (i == -1) {
1608cb5caa98Sdjl 
1609cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1610cb5caa98Sdjl 			gettext("%s: unknown name \"%s\""), desc_str, name);
1611cb5caa98Sdjl 		if (errorp)
1612cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1613cb5caa98Sdjl 
1614cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1615cb5caa98Sdjl 		(me, "%s\n", msg);
1616cb5caa98Sdjl 
1617cb5caa98Sdjl 		free(h);
1618cb5caa98Sdjl 		return (rc);
1619cb5caa98Sdjl 	}
1620cb5caa98Sdjl 
1621cb5caa98Sdjl 	/*
1622cb5caa98Sdjl 	 * if the param/stat is not a global one, we need to
1623cb5caa98Sdjl 	 * know which nsswitch database we are dealing with
1624cb5caa98Sdjl 	 */
1625cb5caa98Sdjl 	if (is_global == 0) {
1626cb5caa98Sdjl 		if (nswdb_name == NULL) {
1627cb5caa98Sdjl 
1628cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1629cb5caa98Sdjl 			gettext("%s: switch database name not specified"),
1630cb5caa98Sdjl 				desc_str);
1631cb5caa98Sdjl 			if (errorp)
1632cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
1633cb5caa98Sdjl 
1634cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1635cb5caa98Sdjl 			(me, "%s for non-global param or stat %s\n",
1636cb5caa98Sdjl 			msg, name);
1637cb5caa98Sdjl 
1638cb5caa98Sdjl 			free(h);
1639cb5caa98Sdjl 			return (rc);
1640cb5caa98Sdjl 		}
1641cb5caa98Sdjl 	} else {
1642cb5caa98Sdjl 
1643cb5caa98Sdjl 		if (nswdb_name != NULL) {
1644cb5caa98Sdjl 
1645cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
1646cb5caa98Sdjl 	gettext("%s: switch database specified for global data"),
1647cb5caa98Sdjl 				desc_str);
1648cb5caa98Sdjl 			if (errorp)
1649cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
1650cb5caa98Sdjl 
1651cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1652cb5caa98Sdjl 			(me, "%s %s\n", msg, name);
1653cb5caa98Sdjl 
1654cb5caa98Sdjl 			free(h);
1655cb5caa98Sdjl 			return (rc);
1656cb5caa98Sdjl 		}
1657cb5caa98Sdjl 
1658cb5caa98Sdjl 		*handle = h;
1659cb5caa98Sdjl 		return (NSCD_SUCCESS);
1660cb5caa98Sdjl 	}
1661cb5caa98Sdjl 
1662cb5caa98Sdjl 	/* get nsw DB id */
1663cb5caa98Sdjl 	i = _nscd_cfg_get_index(nswdb_name, NSCD_CFG_LIST_NSW_DB);
1664cb5caa98Sdjl 	if (i != -1) {
1665cb5caa98Sdjl 
1666cb5caa98Sdjl 		if (i == NSCD_CFG_NSW_ALLDB_INDEX)
1667cb5caa98Sdjl 			h->nswdb = &_nscd_cfg_nsw_alldb;
1668cb5caa98Sdjl 		else
1669cb5caa98Sdjl 			h->nswdb = &_nscd_cfg_nsw_db[i];
1670cb5caa98Sdjl 
1671cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_DEBUG)
1672cb5caa98Sdjl 		(me, "%s: index of %s is %d\n",
1673cb5caa98Sdjl 			desc_str, nswdb_name, i);
1674cb5caa98Sdjl 	} else {
1675cb5caa98Sdjl 
1676cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
1677cb5caa98Sdjl 			gettext("%s: unknown switch database name \"%s\""),
1678cb5caa98Sdjl 			desc_str, nswdb_name);
1679cb5caa98Sdjl 		if (errorp)
1680cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(rc, msg);
1681cb5caa98Sdjl 
1682cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1683cb5caa98Sdjl 		(me, "%s\n", msg);
1684cb5caa98Sdjl 
1685cb5caa98Sdjl 		free(h);
1686cb5caa98Sdjl 		return (NSCD_CFG_UNSUPPORTED_SWITCH_DB);
1687cb5caa98Sdjl 	}
1688cb5caa98Sdjl 
1689cb5caa98Sdjl 	*handle = h;
1690cb5caa98Sdjl 
1691cb5caa98Sdjl 	return (NSCD_SUCCESS);
1692cb5caa98Sdjl }
1693cb5caa98Sdjl 
1694cb5caa98Sdjl nscd_rc_t
1695cb5caa98Sdjl _nscd_cfg_get_handle(
1696cb5caa98Sdjl 	char			*param_name,
1697cb5caa98Sdjl 	char			*nswdb_name,
1698cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1699cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1700cb5caa98Sdjl {
1701cb5caa98Sdjl 
1702cb5caa98Sdjl 	return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_PARAM,
1703cb5caa98Sdjl 		param_name, nswdb_name, handle, errorp));
1704cb5caa98Sdjl }
1705cb5caa98Sdjl 
1706cb5caa98Sdjl nscd_rc_t
1707cb5caa98Sdjl _nscd_cfg_get_stat_handle(
1708cb5caa98Sdjl 	char			*stat_name,
1709cb5caa98Sdjl 	char			*nswdb_name,
1710cb5caa98Sdjl 	nscd_cfg_handle_t	**handle,
1711cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
1712cb5caa98Sdjl {
1713cb5caa98Sdjl 
1714cb5caa98Sdjl 	return (_nscd_cfg_get_handle_common(NSCD_CFG_LIST_STAT,
1715cb5caa98Sdjl 		stat_name, nswdb_name, handle, errorp));
1716cb5caa98Sdjl }
1717cb5caa98Sdjl 
1718cb5caa98Sdjl void
1719cb5caa98Sdjl _nscd_cfg_free_handle(
1720cb5caa98Sdjl 	nscd_cfg_handle_t	*handle)
1721cb5caa98Sdjl {
1722cb5caa98Sdjl 
1723cb5caa98Sdjl 	free(handle);
1724cb5caa98Sdjl 
1725cb5caa98Sdjl }
1726cb5caa98Sdjl 
1727cb5caa98Sdjl static void
1728cb5caa98Sdjl _nscd_cfg_free_vlen_data_group(
1729cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1730cb5caa98Sdjl 	void			*group_data,
1731cb5caa98Sdjl 	nscd_bool_t		in)
1732cb5caa98Sdjl {
1733cb5caa98Sdjl 	int			num;
1734cb5caa98Sdjl 	void			*dest, *ptr;
1735cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1736cb5caa98Sdjl 
1737cb5caa98Sdjl 	desc = gdesc;
1738cb5caa98Sdjl 
1739cb5caa98Sdjl 	num = ((nscd_cfg_group_info_t *)group_data)->num_param;
1740cb5caa98Sdjl 
1741cb5caa98Sdjl 	while (num-- > 0) {
1742cb5caa98Sdjl 
1743cb5caa98Sdjl 		desc++;
1744cb5caa98Sdjl 
1745cb5caa98Sdjl 		/* skip fixed length data */
1746cb5caa98Sdjl 		if (_nscd_cfg_flag_is_not_set(desc->pflag,
1747cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
1748cb5caa98Sdjl 			continue;
1749cb5caa98Sdjl 
1750cb5caa98Sdjl 		dest = (char *)group_data + desc->p_offset;
1751cb5caa98Sdjl 		ptr = *(char **)dest;
1752cb5caa98Sdjl 		if (ptr == NULL)
1753cb5caa98Sdjl 			continue;
1754cb5caa98Sdjl 		if (in == nscd_true)
1755cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(ptr);
1756cb5caa98Sdjl 		else
1757cb5caa98Sdjl 			free(ptr);
1758cb5caa98Sdjl 	}
1759cb5caa98Sdjl }
1760cb5caa98Sdjl 
1761cb5caa98Sdjl void
1762cb5caa98Sdjl _nscd_cfg_free_param_data(
1763cb5caa98Sdjl 	void			*data)
1764cb5caa98Sdjl {
1765cb5caa98Sdjl 
1766cb5caa98Sdjl 	if (data == NULL)
1767cb5caa98Sdjl 		return;
1768cb5caa98Sdjl 
1769cb5caa98Sdjl 	free(data);
1770cb5caa98Sdjl }
1771cb5caa98Sdjl 
1772cb5caa98Sdjl void
1773cb5caa98Sdjl _nscd_cfg_free_group_data(
1774cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
1775cb5caa98Sdjl 	void			*data)
1776cb5caa98Sdjl {
1777cb5caa98Sdjl 
1778cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1779cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1780cb5caa98Sdjl 
1781cb5caa98Sdjl 	if (handle == NULL || data == NULL)
1782cb5caa98Sdjl 		return;
1783cb5caa98Sdjl 
1784cb5caa98Sdjl 	desc = _nscd_cfg_get_desc(handle);
1785cb5caa98Sdjl 	gi = (nscd_cfg_group_info_t *)data;
1786cb5caa98Sdjl 	if (desc->p_fn != gi->num_param)
1787cb5caa98Sdjl 		return;
1788cb5caa98Sdjl 
1789cb5caa98Sdjl 	_nscd_cfg_free_vlen_data_group(desc, data, nscd_false);
1790cb5caa98Sdjl 
1791cb5caa98Sdjl 	free(data);
1792cb5caa98Sdjl }
1793cb5caa98Sdjl 
1794cb5caa98Sdjl void
1795cb5caa98Sdjl _nscd_cfg_free_error(
1796cb5caa98Sdjl 	nscd_cfg_error_t	*error)
1797cb5caa98Sdjl {
1798cb5caa98Sdjl 
1799cb5caa98Sdjl 	if (error == NULL)
1800cb5caa98Sdjl 		return;
1801cb5caa98Sdjl 
1802cb5caa98Sdjl 	free(error);
1803cb5caa98Sdjl }
1804cb5caa98Sdjl 
1805cb5caa98Sdjl static nscd_rc_t
1806cb5caa98Sdjl _nscd_cfg_copy_param_data(
1807cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
1808cb5caa98Sdjl 	void			*dest,
1809cb5caa98Sdjl 	void			*pdata,
1810cb5caa98Sdjl 	nscd_bool_t		in,
1811cb5caa98Sdjl 	nscd_bool_t		set_addr)
1812cb5caa98Sdjl {
1813cb5caa98Sdjl 
1814cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_param_data";
1815cb5caa98Sdjl 	void			*tmp;
1816cb5caa98Sdjl 	int			dlen;
1817cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
1818cb5caa98Sdjl 
1819cb5caa98Sdjl 	if (desc == NULL || dest == NULL) {
1820cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1821cb5caa98Sdjl 		(me, "input desc == %p, dest == %p\n", desc, dest);
1822cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
1823cb5caa98Sdjl 	}
1824cb5caa98Sdjl 
1825cb5caa98Sdjl 	/* fixed length data */
1826cb5caa98Sdjl 	if (_nscd_cfg_flag_is_not_set(desc->pflag,
1827cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA)) {
1828cb5caa98Sdjl 		(void) memcpy(dest, pdata, desc->p_size);
1829cb5caa98Sdjl 		goto done;
1830cb5caa98Sdjl 	}
1831cb5caa98Sdjl 
1832cb5caa98Sdjl 
1833cb5caa98Sdjl 	/* variable length data from this point on */
1834cb5caa98Sdjl 
1835cb5caa98Sdjl 	/* make a copy of the variable length data */
1836cb5caa98Sdjl 	rc = _nscd_cfg_copy_vlen_data(pdata, &tmp, desc, &dlen, in);
1837cb5caa98Sdjl 	if (rc != NSCD_SUCCESS)
1838cb5caa98Sdjl 		goto done;
1839cb5caa98Sdjl 
1840cb5caa98Sdjl 	if (in == nscd_true) { /* data to internal */
1841cb5caa98Sdjl 
1842cb5caa98Sdjl 		/* free the variable length data in the config store */
1843cb5caa98Sdjl 		if (*(char **)dest != NULL)
1844cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(*(char **)dest);
1845cb5caa98Sdjl 	}
1846cb5caa98Sdjl 
1847cb5caa98Sdjl 	if (set_addr == nscd_true) {
1848cb5caa98Sdjl 		/*
1849cb5caa98Sdjl 		 * set the addr of the vlen data
1850cb5caa98Sdjl 		 */
1851cb5caa98Sdjl 		*(char **)dest = tmp;
1852cb5caa98Sdjl 	} else {
1853cb5caa98Sdjl 		/*
1854cb5caa98Sdjl 		 * copy the data content (not address)
1855cb5caa98Sdjl 		 */
1856cb5caa98Sdjl 		(void) memcpy(dest, tmp, dlen);
1857cb5caa98Sdjl 	}
1858cb5caa98Sdjl 
1859cb5caa98Sdjl 	done:
1860cb5caa98Sdjl 
1861cb5caa98Sdjl 	return (rc);
1862cb5caa98Sdjl }
1863cb5caa98Sdjl 
1864cb5caa98Sdjl static nscd_rc_t
1865cb5caa98Sdjl _nscd_cfg_copy_group_data_in(
1866cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1867cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi,
1868cb5caa98Sdjl 	void			*group_dest,
1869cb5caa98Sdjl 	void			*group_src)
1870cb5caa98Sdjl {
1871cb5caa98Sdjl 	int			i, num;
1872cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1873cb5caa98Sdjl 	void			*src, *dest;
1874cb5caa98Sdjl 
1875cb5caa98Sdjl 	i = 0;
1876cb5caa98Sdjl 	num = gi->num_param;
1877cb5caa98Sdjl 	desc = gdesc;
1878cb5caa98Sdjl 
1879cb5caa98Sdjl 	while (num-- > 0) {
1880cb5caa98Sdjl 
1881cb5caa98Sdjl 		desc++;
1882cb5caa98Sdjl 
1883cb5caa98Sdjl 		/* if member not selected by bitmap, skip */
1884cb5caa98Sdjl 		if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++))
1885cb5caa98Sdjl 			continue;
1886cb5caa98Sdjl 
1887cb5caa98Sdjl 		src = (char *)group_src + desc->p_offset;
1888cb5caa98Sdjl 		dest = (char *)group_dest + desc->p_offset;
1889cb5caa98Sdjl 
1890cb5caa98Sdjl 		/*
1891cb5caa98Sdjl 		 * if variable length data, free and replace the old
1892cb5caa98Sdjl 		 * with the new
1893cb5caa98Sdjl 		 */
1894cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1895cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
1896cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_int(*(char **)dest);
1897cb5caa98Sdjl 			*(char **)dest = *(char **)src;
1898cb5caa98Sdjl 			*(char **)src = NULL;
1899cb5caa98Sdjl 		} else {
1900cb5caa98Sdjl 			/*
1901cb5caa98Sdjl 			 * fixed length data, just copy it
1902cb5caa98Sdjl 			 */
1903cb5caa98Sdjl 			(void) memcpy(dest, src, desc->p_size);
1904cb5caa98Sdjl 		}
1905cb5caa98Sdjl 	}
1906cb5caa98Sdjl 
1907cb5caa98Sdjl 	return (NSCD_SUCCESS);
1908cb5caa98Sdjl }
1909cb5caa98Sdjl 
1910cb5caa98Sdjl static nscd_rc_t
1911cb5caa98Sdjl _nscd_cfg_copy_group_data_out(
1912cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1913cb5caa98Sdjl 	void			*group_dest,
1914cb5caa98Sdjl 	void			*group_src)
1915cb5caa98Sdjl {
1916cb5caa98Sdjl 
1917cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_group_data_out";
1918cb5caa98Sdjl 	void			*src, *dest;
1919cb5caa98Sdjl 	int			dlen;
1920cb5caa98Sdjl 	int			num;
1921cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
1922cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
1923cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
1924cb5caa98Sdjl 
1925cb5caa98Sdjl 	if (group_dest == NULL) {
1926cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1927cb5caa98Sdjl 		(me, "input group_dest = NULL\n");
1928cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
1929cb5caa98Sdjl 	}
1930cb5caa98Sdjl 
1931cb5caa98Sdjl 	gi = _nscd_cfg_get_gi(group_src);
1932cb5caa98Sdjl 	num = gi->num_param;
1933cb5caa98Sdjl 	desc = gdesc;
1934cb5caa98Sdjl 
1935cb5caa98Sdjl 	while (num-- > 0) {
1936cb5caa98Sdjl 
1937cb5caa98Sdjl 		desc++;
1938cb5caa98Sdjl 
1939cb5caa98Sdjl 		dest = (char *)group_dest + desc->p_offset;
1940cb5caa98Sdjl 		src = (char *)group_src + desc->p_offset;
1941cb5caa98Sdjl 
1942cb5caa98Sdjl 		/*
1943cb5caa98Sdjl 		 * if variable length data, get the real
1944cb5caa98Sdjl 		 * address and length of the data
1945cb5caa98Sdjl 		 */
1946cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
1947cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA)) {
1948cb5caa98Sdjl 			src = _nscd_cfg_locate_vlen_data(src, &dlen);
1949cb5caa98Sdjl 			if (dlen == NULL)
1950cb5caa98Sdjl 				continue;
1951cb5caa98Sdjl 		}
1952cb5caa98Sdjl 
1953cb5caa98Sdjl 		/*
1954cb5caa98Sdjl 		 * The nscd_true asks _nscd_cfg_copy_param_data
1955cb5caa98Sdjl 		 * to set addr of the vlen data in 'dest' rather
1956cb5caa98Sdjl 		 * than copying the data content
1957cb5caa98Sdjl 		 */
1958cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, dest, src,
1959cb5caa98Sdjl 			nscd_false, nscd_true);
1960cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
1961cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
1962cb5caa98Sdjl 			(me, "unable to copy param data for %s\n",
1963cb5caa98Sdjl 				desc->id.name);
1964cb5caa98Sdjl 
1965cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
1966cb5caa98Sdjl 				group_dest, nscd_false);
1967cb5caa98Sdjl 
1968cb5caa98Sdjl 			free(group_dest);
1969cb5caa98Sdjl 
1970cb5caa98Sdjl 			return (rc);
1971cb5caa98Sdjl 		}
1972cb5caa98Sdjl 	}
1973cb5caa98Sdjl 
1974cb5caa98Sdjl 	/*
1975cb5caa98Sdjl 	 * set group bitmap
1976cb5caa98Sdjl 	 */
1977cb5caa98Sdjl 	(void) memcpy(group_dest, group_src,
1978cb5caa98Sdjl 		sizeof (nscd_cfg_group_info_t));
1979cb5caa98Sdjl 
1980cb5caa98Sdjl 	return (rc);
1981cb5caa98Sdjl }
1982cb5caa98Sdjl 
1983cb5caa98Sdjl 
1984cb5caa98Sdjl /*
1985cb5caa98Sdjl  * group_cfg is needed always; group_src may be NULL if
1986cb5caa98Sdjl  * param_index not zero and pdata not NULL; group_cfg and
1987cb5caa98Sdjl  * pdata should not be both non-NULL
1988cb5caa98Sdjl  */
1989cb5caa98Sdjl static nscd_rc_t
1990cb5caa98Sdjl _nscd_cfg_copy_group_data_merge(
1991cb5caa98Sdjl 	nscd_cfg_param_desc_t	*gdesc,
1992cb5caa98Sdjl 	void			**group_dest,
1993cb5caa98Sdjl 	void			*group_src,
1994cb5caa98Sdjl 	void			*group_cfg,
1995cb5caa98Sdjl 	int			param_index,
1996cb5caa98Sdjl 	void			*pdata)
1997cb5caa98Sdjl {
1998cb5caa98Sdjl 
1999cb5caa98Sdjl 	char			*me = "_nscd_cfg_copy_group_data_merge";
2000cb5caa98Sdjl 	void			*src, *dest, *tmp_dest = NULL;
2001cb5caa98Sdjl 	int			num, i = 0;
2002cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2003cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2004cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
2005cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap;
2006cb5caa98Sdjl 
2007cb5caa98Sdjl 	if (group_dest == NULL) {
2008cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2009cb5caa98Sdjl 		(me, "input **group_dest == NULL\n");
2010cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2011cb5caa98Sdjl 	}
2012cb5caa98Sdjl 
2013cb5caa98Sdjl 	if (group_cfg == NULL) {
2014cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2015cb5caa98Sdjl 		(me, "input **group_cfg == NULL\n");
2016cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2017cb5caa98Sdjl 	}
2018cb5caa98Sdjl 
2019cb5caa98Sdjl 	if (param_index != NULL && pdata == NULL) {
2020cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2021cb5caa98Sdjl 		(me, "param_index != NULL but pdata == %p\n", pdata);
2022cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2023cb5caa98Sdjl 	}
2024cb5caa98Sdjl 
2025cb5caa98Sdjl 	tmp_dest = calloc(1, gdesc->g_size);
2026cb5caa98Sdjl 	if (tmp_dest == NULL)
2027cb5caa98Sdjl 		return (NSCD_NO_MEMORY);
2028cb5caa98Sdjl 
2029cb5caa98Sdjl 	if (group_src != NULL)
2030cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(group_src);
2031cb5caa98Sdjl 	else {
2032cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(group_cfg);
2033cb5caa98Sdjl 		bitmap = NSCD_CFG_BITMAP_ZERO;
2034cb5caa98Sdjl 	}
2035cb5caa98Sdjl 
2036cb5caa98Sdjl 	num = gi->num_param;
2037cb5caa98Sdjl 	desc = gdesc;
2038cb5caa98Sdjl 
2039cb5caa98Sdjl 	while (num-- > 0) {
2040cb5caa98Sdjl 
2041cb5caa98Sdjl 		desc++;
2042cb5caa98Sdjl 
2043cb5caa98Sdjl 		dest = (char *)tmp_dest + desc->p_offset;
2044cb5caa98Sdjl 
2045cb5caa98Sdjl 		/*
2046cb5caa98Sdjl 		 * if member not selected by bitmap in group_src,
2047cb5caa98Sdjl 		 * get the member data in group_cfg
2048cb5caa98Sdjl 		 */
2049cb5caa98Sdjl 		if (_nscd_cfg_bitmap_is_not_set(gi->bitmap, i++) ||
2050cb5caa98Sdjl 				group_src == NULL) {
2051cb5caa98Sdjl 			src = (char *)group_cfg + desc->p_offset;
2052cb5caa98Sdjl 		} else
2053cb5caa98Sdjl 			src = (char *)group_src + desc->p_offset;
2054cb5caa98Sdjl 
2055cb5caa98Sdjl 		if (desc->id.index == param_index) {
2056cb5caa98Sdjl 
2057cb5caa98Sdjl 			/* use the param data in pdata if provided */
2058cb5caa98Sdjl 			src = pdata;
2059cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap, i);
2060cb5caa98Sdjl 		}
2061cb5caa98Sdjl 
2062cb5caa98Sdjl 		/*
2063cb5caa98Sdjl 		 * if variable length data, get to the data
2064cb5caa98Sdjl 		 * instead of pointer to the data
2065cb5caa98Sdjl 		 */
2066cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2067cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA))
2068cb5caa98Sdjl 				src = *(char **)src;
2069cb5caa98Sdjl 
2070cb5caa98Sdjl 		/*
2071cb5caa98Sdjl 		 * nscd_true asks _nscd_cfg_copy_param_data to
2072cb5caa98Sdjl 		 * set addr of the vlen data in 'dest' rather
2073cb5caa98Sdjl 		 * than copying the data content
2074cb5caa98Sdjl 		 */
2075cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, dest, src,
2076cb5caa98Sdjl 			nscd_true, nscd_true);
2077cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2078cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2079cb5caa98Sdjl 			(me, "unable to copy param data for %s\n",
2080cb5caa98Sdjl 				desc->id.name);
2081cb5caa98Sdjl 
2082cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
2083cb5caa98Sdjl 				tmp_dest, nscd_true);
2084cb5caa98Sdjl 
2085cb5caa98Sdjl 			free(tmp_dest);
2086cb5caa98Sdjl 
2087cb5caa98Sdjl 			return (rc);
2088cb5caa98Sdjl 		}
2089cb5caa98Sdjl 	}
2090cb5caa98Sdjl 
2091cb5caa98Sdjl 	*group_dest = tmp_dest;
2092cb5caa98Sdjl 
2093cb5caa98Sdjl 	/*
2094cb5caa98Sdjl 	 * set bitmap: if input is group data, use the one
2095cb5caa98Sdjl 	 * given; if input is param data, use the one computed
2096cb5caa98Sdjl 	 * above
2097cb5caa98Sdjl 	 */
2098cb5caa98Sdjl 	if (group_src != NULL)
2099cb5caa98Sdjl 		(void) memcpy(*group_dest, group_src,
2100cb5caa98Sdjl 			sizeof (nscd_cfg_group_info_t));
2101cb5caa98Sdjl 	else {
2102cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(*group_dest);
2103cb5caa98Sdjl 		_nscd_cfg_bitmap_set(&gi->bitmap, bitmap);
2104cb5caa98Sdjl 	}
2105cb5caa98Sdjl 
2106cb5caa98Sdjl 	return (rc);
2107cb5caa98Sdjl }
2108cb5caa98Sdjl 
2109cb5caa98Sdjl /* ARGSUSED */
2110cb5caa98Sdjl nscd_rc_t
2111cb5caa98Sdjl _nscd_cfg_get(
2112cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
2113cb5caa98Sdjl 	void			**data,
2114cb5caa98Sdjl 	int			*data_len,
2115cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2116cb5caa98Sdjl {
2117cb5caa98Sdjl 	char			*me = "_nscd_cfg_get";
2118cb5caa98Sdjl 	int			dlen;
2119cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2120cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb;
2121cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc;
2122cb5caa98Sdjl 	void			*cfg_data, *ptr = NULL;
2123cb5caa98Sdjl 	nscd_bool_t		get_group = nscd_false;
2124cb5caa98Sdjl 	nscd_bool_t		out = nscd_false;
2125cb5caa98Sdjl 	nscd_cfg_lock_t		*lock = NULL;
2126cb5caa98Sdjl 
2127cb5caa98Sdjl 	if (data_len != NULL)
2128cb5caa98Sdjl 		*data_len = 0;
2129cb5caa98Sdjl 
2130cb5caa98Sdjl 	if (data == NULL) {
2131cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2132cb5caa98Sdjl 		(me, "input data = %p\n", data);
2133cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2134cb5caa98Sdjl 	}
2135cb5caa98Sdjl 
2136cb5caa98Sdjl 	*data = NULL;
2137cb5caa98Sdjl 
2138cb5caa98Sdjl 	if (handle == NULL) {
2139cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2140cb5caa98Sdjl 		(me, "handle is NULL\n");
2141cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2142cb5caa98Sdjl 	}
2143cb5caa98Sdjl 
2144cb5caa98Sdjl 	nswdb = handle->nswdb;
2145cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2146cb5caa98Sdjl 
2147cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2148cb5caa98Sdjl 		get_group = nscd_true;
2149cb5caa98Sdjl 
2150cb5caa98Sdjl 	/*
2151cb5caa98Sdjl 	 * locate the current value of the param or group
2152cb5caa98Sdjl 	 * and lock the config data for reading
2153cb5caa98Sdjl 	 */
2154cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_true, desc,
2155cb5caa98Sdjl 		nswdb, get_group, NULL, &dlen, &lock);
2156cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2157cb5caa98Sdjl 
2158cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2159cb5caa98Sdjl 		(me, "unable to locate config data\n");
2160cb5caa98Sdjl 		return (rc);
2161cb5caa98Sdjl 
2162cb5caa98Sdjl 	} else if (cfg_data == NULL) /* NULL vlen data */
2163cb5caa98Sdjl 		goto done;
2164cb5caa98Sdjl 
2165cb5caa98Sdjl 	ptr = calloc(1, dlen);
2166cb5caa98Sdjl 	if (ptr == NULL) {
2167cb5caa98Sdjl 		rc = NSCD_NO_MEMORY;
2168cb5caa98Sdjl 		goto error_exit;
2169cb5caa98Sdjl 	}
2170cb5caa98Sdjl 
2171cb5caa98Sdjl 	if (get_group == nscd_true) {
2172cb5caa98Sdjl 
2173cb5caa98Sdjl 		rc = _nscd_cfg_copy_group_data_out(desc, ptr, cfg_data);
2174cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2175cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2176cb5caa98Sdjl 			(me, "unable to copy group data %p: "
2177cb5caa98Sdjl 			"error = %d\n", cfg_data, rc);
2178cb5caa98Sdjl 
2179cb5caa98Sdjl 			goto error_exit;
2180cb5caa98Sdjl 		}
2181cb5caa98Sdjl 	} else {
2182cb5caa98Sdjl 		/*
2183cb5caa98Sdjl 		 * nscd_false asks _nscd_cfg_copy_param_data to
2184cb5caa98Sdjl 		 * copy the data content rather than just setting
2185cb5caa98Sdjl 		 * the addr of the vlen data in 'ptr'
2186cb5caa98Sdjl 		 */
2187cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc, ptr, cfg_data,
2188cb5caa98Sdjl 			out, nscd_false);
2189cb5caa98Sdjl 
2190cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2191cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2192cb5caa98Sdjl 			(me, "unable to copy param data %p: "
2193cb5caa98Sdjl 			"error = %d\n", cfg_data, rc);
2194cb5caa98Sdjl 
2195cb5caa98Sdjl 			goto error_exit;
2196cb5caa98Sdjl 		}
2197cb5caa98Sdjl 	}
2198cb5caa98Sdjl 
2199cb5caa98Sdjl 	*data = ptr;
2200cb5caa98Sdjl 
2201cb5caa98Sdjl 	done:
2202cb5caa98Sdjl 
2203cb5caa98Sdjl 	if (data_len != NULL)
2204cb5caa98Sdjl 		*data_len = dlen;
2205cb5caa98Sdjl 
2206cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2207cb5caa98Sdjl 
2208cb5caa98Sdjl 	return (NSCD_SUCCESS);
2209cb5caa98Sdjl 
2210cb5caa98Sdjl 	error_exit:
2211cb5caa98Sdjl 
2212cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2213cb5caa98Sdjl 	if (ptr != NULL)
2214cb5caa98Sdjl 		free(ptr);
2215cb5caa98Sdjl 
2216cb5caa98Sdjl 	return (rc);
2217cb5caa98Sdjl }
2218cb5caa98Sdjl 
2219cb5caa98Sdjl /*
2220cb5caa98Sdjl  * three type of data:
2221cb5caa98Sdjl  * 1 - single param
2222cb5caa98Sdjl  * 	desc is that of the param
2223cb5caa98Sdjl  * 2 - single param to be sent in a group
2224cb5caa98Sdjl  *	a single bit is set in the bitmap,
2225cb5caa98Sdjl  * 	desc is that of the group
2226cb5caa98Sdjl  * 3 - group data
2227cb5caa98Sdjl  *	one of more bits are set in the bitmap,
2228cb5caa98Sdjl  * 	desc is that of the group
2229cb5caa98Sdjl  */
2230cb5caa98Sdjl static nscd_rc_t
2231cb5caa98Sdjl _nscd_cfg_notify_s(
2232cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
2233cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb,
2234cb5caa98Sdjl 	void			*data,
2235cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2236cb5caa98Sdjl {
2237cb5caa98Sdjl 	int			i, num, is_group = 0;
2238cb5caa98Sdjl 	void			*cookie = NULL;
2239cb5caa98Sdjl 	void			*cdata;
2240cb5caa98Sdjl 	nscd_rc_t		rc;
2241cb5caa98Sdjl 	nscd_cfg_flag_t		dflag, dflag1;
2242cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap_s, bitmap_in, *bitmap_addr = NULL;
2243cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2244cb5caa98Sdjl 
2245cb5caa98Sdjl 	if (errorp != NULL)
2246cb5caa98Sdjl 		*errorp = NULL;
2247cb5caa98Sdjl 
2248cb5caa98Sdjl 	/*
2249cb5caa98Sdjl 	 * Set data flag going with data to be sent to the
2250cb5caa98Sdjl 	 * verify/notify routines. To allow the config flag
2251cb5caa98Sdjl 	 * be exipandable, set the bits one by one.
2252cb5caa98Sdjl 	 */
2253cb5caa98Sdjl 	dflag = NSCD_CFG_FLAG_ZERO;
2254cb5caa98Sdjl 	dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_STATIC_DATA);
2255cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2256cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag, NSCD_CFG_DFLAG_GROUP);
2257cb5caa98Sdjl 		is_group = 1;
2258cb5caa98Sdjl 	}
2259cb5caa98Sdjl 	if (nswdb != NULL &&
2260cb5caa98Sdjl 		strcmp(NSCD_CFG_NSW_ALLDB, nswdb->name) == 0)
2261cb5caa98Sdjl 		dflag = _nscd_cfg_flag_set(dflag,
2262cb5caa98Sdjl 				NSCD_CFG_DFLAG_SET_ALL_DB);
2263cb5caa98Sdjl 
2264cb5caa98Sdjl 	/*
2265cb5caa98Sdjl 	 * the bitmap in the input data may be replaced before
2266cb5caa98Sdjl 	 * sending to the components, so save the bitmap for
2267cb5caa98Sdjl 	 * later use
2268cb5caa98Sdjl 	 */
2269cb5caa98Sdjl 	if (is_group == 1) {
2270cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(data);
2271cb5caa98Sdjl 		bitmap_in = gi->bitmap;
2272cb5caa98Sdjl 		bitmap_addr = &(gi->bitmap);
2273cb5caa98Sdjl 
2274cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2275cb5caa98Sdjl 			NSCD_CFG_PFLAG_INIT_SEND_WHOLE_GROUP))
2276cb5caa98Sdjl 			/* send the entire group just once */
2277cb5caa98Sdjl 			num = 1;
2278cb5caa98Sdjl 
2279cb5caa98Sdjl 		else { /* send individual members one by one */
2280cb5caa98Sdjl 
2281cb5caa98Sdjl 			num = desc->p_fn;
2282cb5caa98Sdjl 
2283cb5caa98Sdjl 			/*
2284cb5caa98Sdjl 			 * skip the first desc which is for the group
2285cb5caa98Sdjl 			 * and get to the desc for the first member
2286cb5caa98Sdjl 			 */
2287cb5caa98Sdjl 			desc++;
2288cb5caa98Sdjl 
2289cb5caa98Sdjl 			dflag = _nscd_cfg_flag_unset(dflag,
2290cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
2291cb5caa98Sdjl 		}
2292cb5caa98Sdjl 	} else {
2293cb5caa98Sdjl 		/* not group data, send the member once */
2294cb5caa98Sdjl 			num = 1;
2295cb5caa98Sdjl 	}
2296cb5caa98Sdjl 
2297cb5caa98Sdjl 	dflag1 = dflag;
2298cb5caa98Sdjl 	for (i = 0; i < num; i++, desc++) {
2299cb5caa98Sdjl 
2300cb5caa98Sdjl 		dflag = dflag1;
2301cb5caa98Sdjl 
2302cb5caa98Sdjl 		if (is_group == 0) {
2303cb5caa98Sdjl 			cdata = data;
2304cb5caa98Sdjl 			goto verify_data;
2305cb5caa98Sdjl 		}
2306cb5caa98Sdjl 
2307cb5caa98Sdjl 		if (_nscd_cfg_flag_is_set(desc->pflag,
2308cb5caa98Sdjl 				NSCD_CFG_PFLAG_SEND_BIT_SELECTED)) {
2309cb5caa98Sdjl 
2310cb5caa98Sdjl 			/* set the bitmap to select just this member */
2311cb5caa98Sdjl 			bitmap_s = NSCD_CFG_BITMAP_ZERO;
2312cb5caa98Sdjl 			_nscd_cfg_bitmap_set_nth(bitmap_s, i);
2313cb5caa98Sdjl 			/* replace the bitmap in the input data */
2314cb5caa98Sdjl 			_nscd_cfg_bitmap_set(bitmap_addr, bitmap_s);
2315cb5caa98Sdjl 
2316cb5caa98Sdjl 			/*
2317cb5caa98Sdjl 			 * send the whole group but with only one
2318cb5caa98Sdjl 			 * member selected
2319cb5caa98Sdjl 			 */
2320cb5caa98Sdjl 			cdata = data;
2321cb5caa98Sdjl 
2322cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2323cb5caa98Sdjl 				NSCD_CFG_DFLAG_GROUP);
2324cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2325cb5caa98Sdjl 				NSCD_CFG_DFLAG_BIT_SELECTED);
2326cb5caa98Sdjl 		} else {
2327cb5caa98Sdjl 			/*
2328cb5caa98Sdjl 			 * send param data or group data:
2329cb5caa98Sdjl 			 * param data - non-xero desc->p_offset
2330cb5caa98Sdjl 			 * group data - zero desc->p_offset
2331cb5caa98Sdjl 			 */
2332cb5caa98Sdjl 			cdata = (char *)data + desc->p_offset;
2333cb5caa98Sdjl 
2334cb5caa98Sdjl 			/*
2335cb5caa98Sdjl 			 * if variable length data, need to send pointer
2336cb5caa98Sdjl 			 * to the data (not the address of the pointer)
2337cb5caa98Sdjl 			 */
2338cb5caa98Sdjl 			if (_nscd_cfg_flag_is_set(desc->pflag,
2339cb5caa98Sdjl 				NSCD_CFG_PFLAG_VLEN_DATA))
2340cb5caa98Sdjl 				cdata = *(char **)cdata;
2341cb5caa98Sdjl 		}
2342cb5caa98Sdjl 
2343cb5caa98Sdjl 		verify_data:
2344cb5caa98Sdjl 
2345cb5caa98Sdjl 		if (desc->verify != NULL) {
2346cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2347cb5caa98Sdjl 				NSCD_CFG_DFLAG_VERIFY);
2348cb5caa98Sdjl 			rc = desc->verify(cdata, desc, nswdb,
2349cb5caa98Sdjl 				dflag, errorp, &cookie);
2350cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2351cb5caa98Sdjl 				goto error_exit;
2352cb5caa98Sdjl 		}
2353cb5caa98Sdjl 
2354cb5caa98Sdjl 		if (desc->notify != NULL) {
2355cb5caa98Sdjl 			dflag = _nscd_cfg_flag_set(dflag,
2356cb5caa98Sdjl 				NSCD_CFG_DFLAG_NOTIFY);
2357cb5caa98Sdjl 
2358cb5caa98Sdjl 			rc = desc->notify(data, desc, nswdb,
2359cb5caa98Sdjl 				dflag, errorp, cookie);
2360cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2361cb5caa98Sdjl 				goto error_exit;
2362cb5caa98Sdjl 		}
2363cb5caa98Sdjl 	}
2364cb5caa98Sdjl 
2365cb5caa98Sdjl 	rc = NSCD_SUCCESS;
2366cb5caa98Sdjl 
2367cb5caa98Sdjl 	error_exit:
2368cb5caa98Sdjl 
2369cb5caa98Sdjl 	/* restore the bitmap in the input data */
2370cb5caa98Sdjl 	if (bitmap_addr != NULL)
2371cb5caa98Sdjl 		_nscd_cfg_bitmap_set(bitmap_addr, bitmap_in);
2372cb5caa98Sdjl 
2373cb5caa98Sdjl 	return (rc);
2374cb5caa98Sdjl }
2375cb5caa98Sdjl 
2376cb5caa98Sdjl /*
2377cb5caa98Sdjl  * Convert string 'str' to data based on the data type in 'desc'.
2378cb5caa98Sdjl  * 'data' points to the buffer in which the converted data
2379cb5caa98Sdjl  * is placed. '*data_p' points to the buffer, or in the case
2380cb5caa98Sdjl  * of a string data type, points to the untoched string (i.e.,
2381cb5caa98Sdjl  * 'str').
2382cb5caa98Sdjl  */
2383cb5caa98Sdjl nscd_rc_t
2384cb5caa98Sdjl _nscd_cfg_str_to_data(
2385cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc,
2386cb5caa98Sdjl 	char			*str,
2387cb5caa98Sdjl 	void			*data,
2388cb5caa98Sdjl 	void			**data_p,
2389cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2390cb5caa98Sdjl {
2391cb5caa98Sdjl 
2392cb5caa98Sdjl 	char			*me = "_nscd_cfg_str_to_data";
2393cb5caa98Sdjl 	char			*c;
2394cb5caa98Sdjl 	nscd_cfg_bitmap_t	bitmap;
2395cb5caa98Sdjl 	char			msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2396cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_CFG_DATA_CONVERSION_FAILED;
2397cb5caa98Sdjl 
2398cb5caa98Sdjl 	if (desc == NULL || str == NULL || data == NULL) {
2399cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2400cb5caa98Sdjl 		(me, "ERROR: one of the following is NULL "
2401cb5caa98Sdjl 		"desc = %p, str = %p, data = %p, data_p = %p\n",
2402cb5caa98Sdjl 		desc, str, data, data_p);
2403cb5caa98Sdjl 
2404cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2405cb5caa98Sdjl 	}
2406cb5caa98Sdjl 	*data_p = data;
2407cb5caa98Sdjl 
2408cb5caa98Sdjl 	/* if description is that of a group, return error */
2409cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP)) {
2410cb5caa98Sdjl 
2411cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2412cb5caa98Sdjl 		gettext("single data specified for group %s"), desc->id.name);
2413cb5caa98Sdjl 
2414cb5caa98Sdjl 		if (errorp != NULL)
2415cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2416cb5caa98Sdjl 				msg);
2417cb5caa98Sdjl 
2418cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2419cb5caa98Sdjl 		(me, "ERROR: %s)\n", msg);
2420cb5caa98Sdjl 
2421cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2422cb5caa98Sdjl 
2423cb5caa98Sdjl 	}
2424cb5caa98Sdjl 
2425cb5caa98Sdjl 	if (desc->type == NSCD_CFG_DATA_STRING) {
2426cb5caa98Sdjl 		if (strcmp(str, NSCD_NULL) == 0)
2427cb5caa98Sdjl 			*(char **)data_p = NULL;
2428cb5caa98Sdjl 		else {
2429cb5caa98Sdjl 			/* remove the " char if quoted string */
2430cb5caa98Sdjl 			if (str[0] == '"') {
2431cb5caa98Sdjl 				c = str + strlen(str) - 1;
2432cb5caa98Sdjl 				if (*c == '"')
2433cb5caa98Sdjl 					*c = '\0';
2434cb5caa98Sdjl 				*(char **)data_p = str + 1;
2435cb5caa98Sdjl 			} else
2436cb5caa98Sdjl 				*(char **)data_p = str;
2437cb5caa98Sdjl 
2438cb5caa98Sdjl 		}
2439cb5caa98Sdjl 		return (NSCD_SUCCESS);
2440cb5caa98Sdjl 	}
2441cb5caa98Sdjl 
2442cb5caa98Sdjl 	if (str == NULL) {
2443cb5caa98Sdjl 
2444cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2445cb5caa98Sdjl 		gettext("data must be specified for %s"), desc->id.name);
2446cb5caa98Sdjl 
2447cb5caa98Sdjl 		if (errorp != NULL)
2448cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2449cb5caa98Sdjl 				msg);
2450cb5caa98Sdjl 
2451cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2452cb5caa98Sdjl 		(me, "ERROR: %s\n", msg);
2453cb5caa98Sdjl 
2454cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2455cb5caa98Sdjl 
2456cb5caa98Sdjl 	}
2457cb5caa98Sdjl 
2458cb5caa98Sdjl 	switch (desc->type) {
2459cb5caa98Sdjl 
2460cb5caa98Sdjl 	case NSCD_CFG_DATA_BOOLEAN:
2461cb5caa98Sdjl 
2462cb5caa98Sdjl 		if (strcasecmp(str, "yes") == 0)
2463cb5caa98Sdjl 			*(nscd_bool_t *)data = nscd_true;
2464cb5caa98Sdjl 		else if (strcasecmp(str, "no") == 0)
2465cb5caa98Sdjl 			*(nscd_bool_t *)data = nscd_false;
2466cb5caa98Sdjl 		else {
2467cb5caa98Sdjl 
2468cb5caa98Sdjl 		(void) snprintf(msg, sizeof (msg),
2469cb5caa98Sdjl 		gettext("data (%s) must be 'yes' or 'no' for %s"),
2470cb5caa98Sdjl 				str, desc->id.name);
2471cb5caa98Sdjl 
2472cb5caa98Sdjl 		if (errorp != NULL)
2473cb5caa98Sdjl 			*errorp = _nscd_cfg_make_error(NSCD_INVALID_ARGUMENT,
2474cb5caa98Sdjl 				msg);
2475cb5caa98Sdjl 
2476cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2477cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2478cb5caa98Sdjl 
2479cb5caa98Sdjl 			return (NSCD_INVALID_ARGUMENT);
2480cb5caa98Sdjl 		}
2481cb5caa98Sdjl 
2482cb5caa98Sdjl 		break;
2483cb5caa98Sdjl 
2484cb5caa98Sdjl 	case NSCD_CFG_DATA_INTEGER:
2485cb5caa98Sdjl 
2486cb5caa98Sdjl 		errno = 0;
2487cb5caa98Sdjl 		*(int *)data = (int)strtol(str, (char **)NULL, 10);
2488cb5caa98Sdjl 		if (errno != NULL) {
2489cb5caa98Sdjl 
2490cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2491cb5caa98Sdjl 			gettext("unable to convert data (%s) for %s"),
2492cb5caa98Sdjl 				str, desc->id.name);
2493cb5caa98Sdjl 
2494cb5caa98Sdjl 			if (errorp != NULL)
2495cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2496cb5caa98Sdjl 
2497cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2498cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2499cb5caa98Sdjl 
2500cb5caa98Sdjl 			return (rc);
2501cb5caa98Sdjl 		}
2502cb5caa98Sdjl 
2503cb5caa98Sdjl 		break;
2504cb5caa98Sdjl 
2505cb5caa98Sdjl 	case NSCD_CFG_DATA_BITMAP:
2506cb5caa98Sdjl 
2507cb5caa98Sdjl 		errno = 0;
2508cb5caa98Sdjl 		bitmap = (nscd_cfg_bitmap_t)strtol(str, (char **)NULL, 10);
2509cb5caa98Sdjl 		if (errno != NULL) {
2510cb5caa98Sdjl 
2511cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2512cb5caa98Sdjl 			gettext("unable to convert data (%s) for %s"),
2513cb5caa98Sdjl 				str, desc->id.name);
2514cb5caa98Sdjl 
2515cb5caa98Sdjl 			if (errorp != NULL)
2516cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2517cb5caa98Sdjl 
2518cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2519cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2520cb5caa98Sdjl 
2521cb5caa98Sdjl 			return (rc);
2522cb5caa98Sdjl 		}
2523cb5caa98Sdjl 
2524cb5caa98Sdjl 		_nscd_cfg_bitmap_set(data, bitmap);
2525cb5caa98Sdjl 
2526cb5caa98Sdjl 		break;
2527cb5caa98Sdjl 
2528cb5caa98Sdjl 	}
2529cb5caa98Sdjl 
2530cb5caa98Sdjl 	return (NSCD_SUCCESS);
2531cb5caa98Sdjl }
2532cb5caa98Sdjl 
2533cb5caa98Sdjl 
2534cb5caa98Sdjl nscd_rc_t
2535cb5caa98Sdjl _nscd_cfg_set(
2536cb5caa98Sdjl 	nscd_cfg_handle_t	*handle,
2537cb5caa98Sdjl 	void			*data,
2538cb5caa98Sdjl 	nscd_cfg_error_t	**errorp)
2539cb5caa98Sdjl {
2540cb5caa98Sdjl 	char			*me = "_nscd_cfg_set";
2541cb5caa98Sdjl 	int			dlen;
2542cb5caa98Sdjl 	nscd_cfg_id_t		*nswdb;
2543cb5caa98Sdjl 	nscd_cfg_param_desc_t	*desc, *gdesc;
2544cb5caa98Sdjl 	nscd_cfg_group_info_t	*gi;
2545cb5caa98Sdjl 	char			*nswdb_name, *param_name;
2546cb5caa98Sdjl 	void			*pdata = NULL;
2547cb5caa98Sdjl 	void			*cfg_data, *vdata_addr = NULL;
2548cb5caa98Sdjl 	nscd_bool_t		get_group = 0;
2549cb5caa98Sdjl 	nscd_bool_t		in = nscd_true;
2550cb5caa98Sdjl 	nscd_cfg_lock_t		*lock = NULL;
2551cb5caa98Sdjl 	nscd_rc_t		rc = NSCD_SUCCESS;
2552cb5caa98Sdjl 
2553cb5caa98Sdjl 	if (handle == NULL) {
2554cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2555cb5caa98Sdjl 		(me, "handle is NULL\n");
2556cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2557cb5caa98Sdjl 	}
2558cb5caa98Sdjl 
2559cb5caa98Sdjl 	nswdb = handle->nswdb;
2560cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2561cb5caa98Sdjl 	if (nswdb == NULL)
2562cb5caa98Sdjl 		nswdb_name = "global";
2563cb5caa98Sdjl 	else
2564cb5caa98Sdjl 		nswdb_name = nswdb->name;
2565cb5caa98Sdjl 	param_name = desc->id.name;
2566cb5caa98Sdjl 
2567cb5caa98Sdjl 	if (data == NULL && _nscd_cfg_flag_is_not_set(desc->pflag,
2568cb5caa98Sdjl 			NSCD_CFG_PFLAG_VLEN_DATA)) {
2569cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2570cb5caa98Sdjl 		(me, "data == NULL\n");
2571cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2572cb5caa98Sdjl 	}
2573cb5caa98Sdjl 
2574cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
2575cb5caa98Sdjl 			NSCD_CFG_PFLAG_UPDATE_SEND_WHOLE_GROUP) ||
2576cb5caa98Sdjl 		_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP))
2577cb5caa98Sdjl 		get_group = nscd_true;
2578cb5caa98Sdjl 
2579cb5caa98Sdjl 	/*
2580cb5caa98Sdjl 	 * locate the current value of the param or group
2581cb5caa98Sdjl 	 * and lock the config data for writing
2582cb5caa98Sdjl 	 */
2583cb5caa98Sdjl 	rc = _nscd_cfg_locate_cfg_data(&cfg_data, nscd_false, desc,
2584cb5caa98Sdjl 		nswdb, get_group, &vdata_addr, &dlen, &lock);
2585cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2586cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2587cb5caa98Sdjl 		(me, "unable to locate config data (rc = %d)\n", rc);
2588cb5caa98Sdjl 		return (rc);
2589cb5caa98Sdjl 	}
2590cb5caa98Sdjl 
2591cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag, NSCD_CFG_PFLAG_GROUP) &&
2592cb5caa98Sdjl 		((nscd_cfg_group_info_t *)cfg_data)->num_param !=
2593cb5caa98Sdjl 		((nscd_cfg_group_info_t *)data)->num_param) {
2594cb5caa98Sdjl 
2595cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2596cb5caa98Sdjl 		(me, "number of parameters in group <%s : %s> not equal: "
2597cb5caa98Sdjl 		"%d in input data, should be %d\n",
2598cb5caa98Sdjl 		NSCD_STR_OR_GLOBAL(nswdb_name),
2599cb5caa98Sdjl 		NSCD_STR_OR_NULL(param_name),
2600cb5caa98Sdjl 		((nscd_cfg_group_info_t *)data)->num_param,
2601cb5caa98Sdjl 		((nscd_cfg_group_info_t *)cfg_data)->num_param);
2602cb5caa98Sdjl 
2603cb5caa98Sdjl 		rc = NSCD_INVALID_ARGUMENT;
2604cb5caa98Sdjl 		goto error_exit;
2605cb5caa98Sdjl 	}
2606cb5caa98Sdjl 
2607cb5caa98Sdjl 	/*
2608cb5caa98Sdjl 	 * if variable length data, we want the address
2609cb5caa98Sdjl 	 * of the pointer pointing to the data
2610cb5caa98Sdjl 	 */
2611cb5caa98Sdjl 	if (vdata_addr != NULL)
2612cb5caa98Sdjl 		cfg_data = vdata_addr;
2613cb5caa98Sdjl 
2614cb5caa98Sdjl 	/*
2615cb5caa98Sdjl 	 * just copy in the specified data, if no need
2616cb5caa98Sdjl 	 * to verify the data or notify the associated
2617cb5caa98Sdjl 	 * component
2618cb5caa98Sdjl 	 */
2619cb5caa98Sdjl 		if (get_group == nscd_true) {
2620cb5caa98Sdjl 
2621cb5caa98Sdjl 			gdesc = &_nscd_cfg_param_desc[desc->g_index];
2622cb5caa98Sdjl 
2623cb5caa98Sdjl 			rc = _nscd_cfg_copy_group_data_merge(
2624cb5caa98Sdjl 				gdesc, &pdata, data, cfg_data,
2625cb5caa98Sdjl 				desc->id.index, data);
2626cb5caa98Sdjl 
2627cb5caa98Sdjl 			if (rc != NSCD_SUCCESS) {
2628cb5caa98Sdjl 				_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2629cb5caa98Sdjl 				(me, "unable to copy group data <%s : %s>\n",
2630cb5caa98Sdjl 				NSCD_STR_OR_GLOBAL(nswdb_name),
2631cb5caa98Sdjl 				NSCD_STR_OR_NULL(param_name));
2632cb5caa98Sdjl 
2633cb5caa98Sdjl 				goto error_exit;
2634cb5caa98Sdjl 			}
2635cb5caa98Sdjl 
2636cb5caa98Sdjl 			rc = _nscd_cfg_notify_s(gdesc, nswdb,
2637cb5caa98Sdjl 				pdata, errorp);
2638cb5caa98Sdjl 
2639cb5caa98Sdjl 		} else
2640cb5caa98Sdjl 			rc = _nscd_cfg_notify_s(desc, nswdb, data,
2641cb5caa98Sdjl 				errorp);
2642cb5caa98Sdjl 
2643cb5caa98Sdjl 		if (rc != NSCD_SUCCESS) {
2644cb5caa98Sdjl 
2645cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2646cb5caa98Sdjl 			(me, "verifying/notifying  of new configuration "
2647cb5caa98Sdjl 			"parameter <%s : %s> failed. %s\n",
2648cb5caa98Sdjl 			NSCD_STR_OR_GLOBAL(nswdb_name),
2649cb5caa98Sdjl 			param_name, (*errorp && (*errorp)->msg) ?
2650cb5caa98Sdjl 			(*errorp)->msg : "");
2651cb5caa98Sdjl 
2652cb5caa98Sdjl 			goto error_exit;
2653cb5caa98Sdjl 		}
2654cb5caa98Sdjl 
2655cb5caa98Sdjl 	/*
2656cb5caa98Sdjl 	 * Move the new config into the config store
2657cb5caa98Sdjl 	 */
2658cb5caa98Sdjl 	rc = NSCD_CFG_SET_PARAM_FAILED;
2659cb5caa98Sdjl 	if (_nscd_cfg_flag_is_set(desc->pflag,
2660cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP)) {
2661cb5caa98Sdjl 		gi = _nscd_cfg_get_gi(pdata);
2662cb5caa98Sdjl 		rc = _nscd_cfg_copy_group_data_in(gdesc, gi,
2663cb5caa98Sdjl 			cfg_data, pdata);
2664cb5caa98Sdjl 	} else {
2665cb5caa98Sdjl 		/*
2666cb5caa98Sdjl 		 * nscd_true asks _nscd_cfg_copy_param_data to
2667cb5caa98Sdjl 		 * set addr of the vlen data in 'cfg_data' rather
2668cb5caa98Sdjl 		 * than copying the data content
2669cb5caa98Sdjl 		 */
2670cb5caa98Sdjl 		if (pdata != NULL)
2671cb5caa98Sdjl 			_nscd_cfg_free_vlen_data_group(gdesc,
2672cb5caa98Sdjl 				pdata, in);
2673cb5caa98Sdjl 
2674cb5caa98Sdjl 		rc = _nscd_cfg_copy_param_data(desc,
2675cb5caa98Sdjl 			cfg_data, data, in, nscd_true);
2676cb5caa98Sdjl 	}
2677cb5caa98Sdjl 
2678cb5caa98Sdjl 	if (rc != NSCD_SUCCESS) {
2679cb5caa98Sdjl 
2680cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2681cb5caa98Sdjl 		(me, "unable to make new param data <%s : %s> current\n",
2682cb5caa98Sdjl 		NSCD_STR_OR_GLOBAL(nswdb_name),
2683cb5caa98Sdjl 		NSCD_STR_OR_NULL(param_name));
2684cb5caa98Sdjl 	}
2685cb5caa98Sdjl 
2686cb5caa98Sdjl 	error_exit:
2687cb5caa98Sdjl 
2688cb5caa98Sdjl 	_nscd_cfg_unlock(lock);
2689cb5caa98Sdjl 
2690cb5caa98Sdjl 	return (rc);
2691cb5caa98Sdjl }
2692cb5caa98Sdjl 
2693cb5caa98Sdjl nscd_rc_t
2694cb5caa98Sdjl _nscd_cfg_set_linked(
2695cb5caa98Sdjl 	nscd_cfg_handle_t		*handle,
2696cb5caa98Sdjl 	void				*data,
2697cb5caa98Sdjl 	nscd_cfg_error_t		**errorp)
2698cb5caa98Sdjl {
2699cb5caa98Sdjl 	char				*me = "_nscd_cfg_set_linked";
2700cb5caa98Sdjl 	nscd_cfg_id_t			*nswdb;
2701cb5caa98Sdjl 	nscd_cfg_handle_t		*hl;
2702cb5caa98Sdjl 	nscd_cfg_param_desc_t		*desc;
2703cb5caa98Sdjl 	char				*nswdb_name, *param_name, *dbl;
2704cb5caa98Sdjl 	nscd_rc_t			rc = NSCD_SUCCESS;
2705cb5caa98Sdjl 	nscd_cfg_nsw_spc_default_t	*spc;
2706cb5caa98Sdjl 	int				i;
2707cb5caa98Sdjl 	char				msg[NSCD_CFG_MAX_ERR_MSG_LEN];
2708cb5caa98Sdjl 
2709cb5caa98Sdjl 	if (handle == NULL) {
2710cb5caa98Sdjl 		_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2711cb5caa98Sdjl 		(me, "handle is NULL\n");
2712cb5caa98Sdjl 		return (NSCD_INVALID_ARGUMENT);
2713cb5caa98Sdjl 	}
2714cb5caa98Sdjl 
2715cb5caa98Sdjl 	nswdb = handle->nswdb;
2716cb5caa98Sdjl 	desc = (nscd_cfg_param_desc_t *)handle->desc;
2717cb5caa98Sdjl 
2718cb5caa98Sdjl 	/*
2719cb5caa98Sdjl 	 * no need to do the special linking thing,
2720cb5caa98Sdjl 	 * if a global param, or a group, or not a linked param
2721cb5caa98Sdjl 	 */
2722cb5caa98Sdjl 	if (nswdb == NULL || _nscd_cfg_flag_is_set(desc->pflag,
2723cb5caa98Sdjl 			NSCD_CFG_PFLAG_GROUP) ||
2724cb5caa98Sdjl 			_nscd_cfg_flag_is_not_set(desc->pflag,
2725cb5caa98Sdjl 			NSCD_CFG_PFLAG_LINKED))
2726cb5caa98Sdjl 		return (_nscd_cfg_set(handle, data, errorp));
2727cb5caa98Sdjl 	else
2728cb5caa98Sdjl 		nswdb_name = nswdb->name;
2729cb5caa98Sdjl 	param_name = desc->id.name;
2730cb5caa98Sdjl 
2731cb5caa98Sdjl 	/*
2732cb5caa98Sdjl 	 * if a param is linked to another, it can not be
2733cb5caa98Sdjl 	 * changed directly
2734cb5caa98Sdjl 	 */
2735cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2736cb5caa98Sdjl 
2737cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2738cb5caa98Sdjl 			continue;
2739cb5caa98Sdjl 
2740cb5caa98Sdjl 		if (strcmp(_nscd_cfg_nsw_link_default[i].db,
2741cb5caa98Sdjl 				nswdb_name) == 0 &&
2742cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off ==
2743cb5caa98Sdjl 				desc->g_offset &&
2744cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off ==
2745cb5caa98Sdjl 				desc->p_offset) {
2746cb5caa98Sdjl 
2747cb5caa98Sdjl 			rc = NSCD_CFG_READ_ONLY;
2748cb5caa98Sdjl 
2749cb5caa98Sdjl 			(void) snprintf(msg, sizeof (msg),
2750cb5caa98Sdjl gettext("vaule of \'%s\' not changeable, change that of \'%s\' instead"),
2751cb5caa98Sdjl 				nswdb->name, "passwd");
2752cb5caa98Sdjl 
2753cb5caa98Sdjl 			if (errorp != NULL)
2754cb5caa98Sdjl 				*errorp = _nscd_cfg_make_error(rc, msg);
2755cb5caa98Sdjl 
2756cb5caa98Sdjl 			_NSCD_LOG(NSCD_LOG_CONFIG, NSCD_LOG_LEVEL_ERROR)
2757cb5caa98Sdjl 			(me, "ERROR: %s\n", msg);
2758cb5caa98Sdjl 
2759cb5caa98Sdjl 			return (rc);
2760cb5caa98Sdjl 		}
2761cb5caa98Sdjl 	}
2762cb5caa98Sdjl 
2763cb5caa98Sdjl 	/*
2764cb5caa98Sdjl 	 * if a param is linked from another, it should be verify
2765cb5caa98Sdjl 	 * and changed first
2766cb5caa98Sdjl 	 */
2767cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2768cb5caa98Sdjl 
2769cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2770cb5caa98Sdjl 			continue;
2771cb5caa98Sdjl 
2772cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
2773cb5caa98Sdjl 
2774cb5caa98Sdjl 		if (strcmp(spc->db, nswdb_name) == 0 &&
2775cb5caa98Sdjl 			spc->group_off == desc->g_offset &&
2776cb5caa98Sdjl 			spc->param_off == desc->p_offset) {
2777cb5caa98Sdjl 
2778cb5caa98Sdjl 			rc = _nscd_cfg_set(handle, data, errorp);
2779cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2780cb5caa98Sdjl 				return (rc);
2781cb5caa98Sdjl 			break;
2782cb5caa98Sdjl 		}
2783cb5caa98Sdjl 	}
2784cb5caa98Sdjl 
2785cb5caa98Sdjl 	/*
2786cb5caa98Sdjl 	 * then change all those linked to the one that has been changed
2787cb5caa98Sdjl 	 */
2788cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_link_default; i++) {
2789cb5caa98Sdjl 
2790cb5caa98Sdjl 		if (_nscd_cfg_nsw_link_default[i].data == NULL)
2791cb5caa98Sdjl 			continue;
2792cb5caa98Sdjl 
2793cb5caa98Sdjl 		spc = _nscd_cfg_nsw_link_default[i].data;
2794cb5caa98Sdjl 
2795cb5caa98Sdjl 		if (strcmp(spc->db, nswdb_name) == 0 &&
2796cb5caa98Sdjl 			spc->group_off == desc->g_offset &&
2797cb5caa98Sdjl 			spc->param_off == desc->p_offset &&
2798cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].group_off ==
2799cb5caa98Sdjl 				desc->g_offset &&
2800cb5caa98Sdjl 			_nscd_cfg_nsw_link_default[i].param_off ==
2801cb5caa98Sdjl 				desc->p_offset) {
2802cb5caa98Sdjl 
2803cb5caa98Sdjl 			dbl = _nscd_cfg_nsw_link_default[i].db;
2804cb5caa98Sdjl 
2805cb5caa98Sdjl 			rc = _nscd_cfg_get_handle(param_name, dbl,
2806cb5caa98Sdjl 				&hl, errorp);
2807*e37190e5Smichen 			if (rc != NSCD_SUCCESS)
2808*e37190e5Smichen 				return (rc);
2809cb5caa98Sdjl 			rc = _nscd_cfg_set(hl, data, errorp);
2810cb5caa98Sdjl 			_nscd_cfg_free_handle(hl);
2811cb5caa98Sdjl 			if (rc != NSCD_SUCCESS)
2812cb5caa98Sdjl 				return (rc);
2813cb5caa98Sdjl 		}
2814cb5caa98Sdjl 	}
2815cb5caa98Sdjl 
2816cb5caa98Sdjl 	return (_nscd_cfg_set(handle, data, errorp));
2817cb5caa98Sdjl }
2818cb5caa98Sdjl 
2819cb5caa98Sdjl /*
2820cb5caa98Sdjl  * Return a list of space-separated database names that
2821cb5caa98Sdjl  * have at least one of the input sources appeared in the
2822cb5caa98Sdjl  * configured nsswitch policy string of the databases.
2823cb5caa98Sdjl  * The return string should be freed by the caller.
2824cb5caa98Sdjl  *
2825cb5caa98Sdjl  * For compat sources (compat_group and compat_passwd),
2826cb5caa98Sdjl  * "group" will be returned, if the policy string for
2827cb5caa98Sdjl  * compat_group contains one of the input sources. Same
2828cb5caa98Sdjl  * for compat_passwd and passwd.
2829cb5caa98Sdjl  */
2830cb5caa98Sdjl char *
2831cb5caa98Sdjl _nscd_srcs_in_db_nsw_policy(
2832cb5caa98Sdjl 	int			num_src,
2833cb5caa98Sdjl 	char			**srcs)
2834cb5caa98Sdjl {
2835cb5caa98Sdjl 	uint8_t			i, j, n = 0, nc = 0;
2836cb5caa98Sdjl 	uint8_t			compat_grp = 0, compat_pwd = 0;
2837cb5caa98Sdjl 	uint8_t			*db;
2838cb5caa98Sdjl 	uint8_t			*db_compat;
2839cb5caa98Sdjl 	int			dlen = 0;
2840cb5caa98Sdjl 	nscd_cfg_nsw_db_data_t	*dbcfg;
2841cb5caa98Sdjl 	nscd_cfg_switch_t	*sw;
2842cb5caa98Sdjl 	char			*outstr = NULL;
2843cb5caa98Sdjl 	char			*dbname;
2844cb5caa98Sdjl 
2845cb5caa98Sdjl 	db = (uint8_t *)calloc(_nscd_cfg_num_nsw_db, sizeof (uint8_t));
2846cb5caa98Sdjl 	if (db == NULL)
2847cb5caa98Sdjl 		return (NULL);
2848cb5caa98Sdjl 
2849cb5caa98Sdjl 	db_compat = (uint8_t *)calloc(_nscd_cfg_num_nsw_db,
2850cb5caa98Sdjl 		sizeof (uint8_t));
2851cb5caa98Sdjl 	if (db_compat == NULL) {
2852cb5caa98Sdjl 		free(db);
2853cb5caa98Sdjl 		return (NULL);
2854cb5caa98Sdjl 	}
2855cb5caa98Sdjl 
2856cb5caa98Sdjl 	for (i = 0; i < _nscd_cfg_num_nsw_db; i++) {
2857cb5caa98Sdjl 
2858cb5caa98Sdjl 		(void) rw_rdlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2859cb5caa98Sdjl 
2860cb5caa98Sdjl 		dbcfg = &nscd_cfg_nsw_db_data_current[i];
2861cb5caa98Sdjl 		sw = &dbcfg->sw;
2862cb5caa98Sdjl 		if (sw->nsw_config_string == NULL)
2863cb5caa98Sdjl 			continue;
2864cb5caa98Sdjl 
2865cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[i].name;
2866cb5caa98Sdjl 		for (j = 0; j < num_src; j++) {
2867cb5caa98Sdjl 			if (strstr(sw->nsw_config_string, srcs[j]) !=
2868cb5caa98Sdjl 				NULL) {
2869cb5caa98Sdjl 				db[n++] = i;
2870cb5caa98Sdjl 				dlen += strlen(dbname) + 1;
2871cb5caa98Sdjl 			} else if (strcmp(sw->nsw_config_string,
2872cb5caa98Sdjl 					"compat") == 0) {
2873cb5caa98Sdjl 				if (strcmp(dbname, "passwd") == 0) {
2874cb5caa98Sdjl 					compat_pwd = 1;
2875cb5caa98Sdjl 					dlen += 7;
2876cb5caa98Sdjl 				} else if (strcmp(dbname, "group") == 0) {
2877cb5caa98Sdjl 					compat_grp = 1;
2878cb5caa98Sdjl 					dlen += 6;
2879cb5caa98Sdjl 				} else {
2880cb5caa98Sdjl 					db_compat[nc++] = i;
2881cb5caa98Sdjl 				dlen += strlen(dbname) + 1;
2882cb5caa98Sdjl 
2883cb5caa98Sdjl 				}
2884cb5caa98Sdjl 			}
2885cb5caa98Sdjl 		}
2886cb5caa98Sdjl 		(void) rw_unlock(&nscd_cfg_nsw_db_data_rwlock[i]);
2887cb5caa98Sdjl 	}
2888cb5caa98Sdjl 
2889cb5caa98Sdjl 	if (dlen != NULL)
2890cb5caa98Sdjl 		outstr = (char *)calloc(1, dlen);
2891cb5caa98Sdjl 	if (outstr == NULL) {
2892cb5caa98Sdjl 		free(db_compat);
2893cb5caa98Sdjl 		free(db);
2894cb5caa98Sdjl 		return (NULL);
2895cb5caa98Sdjl 	}
2896cb5caa98Sdjl 
2897cb5caa98Sdjl 	for (j = 0; j < n; j++) {
2898cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[db[j]].name;
2899cb5caa98Sdjl 		if (strstr(dbname, "group_compat") != NULL) {
2900cb5caa98Sdjl 			if (compat_grp == 1)
2901cb5caa98Sdjl 				dbname = "group";
2902cb5caa98Sdjl 			else
2903cb5caa98Sdjl 				continue;
2904cb5caa98Sdjl 		} else if (strstr(dbname, "passwd_compat") != NULL) {
2905cb5caa98Sdjl 			if (compat_pwd == 1)
2906cb5caa98Sdjl 				dbname = "passwd";
2907cb5caa98Sdjl 			else
2908cb5caa98Sdjl 				continue;
2909cb5caa98Sdjl 		}
2910cb5caa98Sdjl 
2911cb5caa98Sdjl 		(void) strlcat(outstr, dbname, dlen);
2912cb5caa98Sdjl 		(void) strlcat(outstr, ",", dlen);
2913cb5caa98Sdjl 	}
2914cb5caa98Sdjl 
2915cb5caa98Sdjl 	for (j = 0; j < nc; j++) {
2916cb5caa98Sdjl 		dbname = _nscd_cfg_nsw_db[db_compat[j]].name;
2917cb5caa98Sdjl 		if (compat_pwd == 1) {
2918cb5caa98Sdjl 			(void) strlcat(outstr, dbname, dlen);
2919cb5caa98Sdjl 			(void) strlcat(outstr, " ", dlen);
2920cb5caa98Sdjl 		}
2921cb5caa98Sdjl 	}
2922cb5caa98Sdjl 
2923cb5caa98Sdjl 	free(db);
2924cb5caa98Sdjl 	free(db_compat);
2925cb5caa98Sdjl 	return (outstr);
2926cb5caa98Sdjl 
2927cb5caa98Sdjl }
2928