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