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