xref: /titanic_50/usr/src/lib/libnisdb/ldap_val.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2001-2003 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <lber.h>
30*7c478bd9Sstevel@tonic-gate #include <ldap.h>
31*7c478bd9Sstevel@tonic-gate #include <strings.h>
32*7c478bd9Sstevel@tonic-gate #include <errno.h>
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate #include "nisdb_mt.h"
35*7c478bd9Sstevel@tonic-gate 
36*7c478bd9Sstevel@tonic-gate #include "ldap_util.h"
37*7c478bd9Sstevel@tonic-gate #include "ldap_op.h"
38*7c478bd9Sstevel@tonic-gate #include "ldap_ruleval.h"
39*7c478bd9Sstevel@tonic-gate #include "ldap_attr.h"
40*7c478bd9Sstevel@tonic-gate #include "ldap_val.h"
41*7c478bd9Sstevel@tonic-gate #include "ldap_nisplus.h"
42*7c478bd9Sstevel@tonic-gate #include "ldap_ldap.h"
43*7c478bd9Sstevel@tonic-gate 
44*7c478bd9Sstevel@tonic-gate extern int yp2ldap;
45*7c478bd9Sstevel@tonic-gate 
46*7c478bd9Sstevel@tonic-gate 
47*7c478bd9Sstevel@tonic-gate __nis_mapping_format_t *
48*7c478bd9Sstevel@tonic-gate cloneMappingFormat(__nis_mapping_format_t *m) {
49*7c478bd9Sstevel@tonic-gate 	__nis_mapping_format_t	*new;
50*7c478bd9Sstevel@tonic-gate 	int			i, nf, err;
51*7c478bd9Sstevel@tonic-gate 	char			*myself = "cloneMappingFormat";
52*7c478bd9Sstevel@tonic-gate 
53*7c478bd9Sstevel@tonic-gate 	if (m == 0)
54*7c478bd9Sstevel@tonic-gate 		return (0);
55*7c478bd9Sstevel@tonic-gate 
56*7c478bd9Sstevel@tonic-gate 	for (nf = 0; m[nf].type != mmt_end; nf++);
57*7c478bd9Sstevel@tonic-gate 	nf++;
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate 	new = am(myself, nf * sizeof (new[0]));
60*7c478bd9Sstevel@tonic-gate 	if (new == 0)
61*7c478bd9Sstevel@tonic-gate 		return (0);
62*7c478bd9Sstevel@tonic-gate 
63*7c478bd9Sstevel@tonic-gate 	/* Copy the whole array */
64*7c478bd9Sstevel@tonic-gate 	memcpy(new, m, nf * sizeof (new[0]));
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate 	/* Make copies of allocated stuff */
67*7c478bd9Sstevel@tonic-gate 	for (i = 0, err = 0; i < nf; i++) {
68*7c478bd9Sstevel@tonic-gate 		switch (m[i].type) {
69*7c478bd9Sstevel@tonic-gate 		case mmt_string:
70*7c478bd9Sstevel@tonic-gate 			new[i].match.string = sdup(myself, T,
71*7c478bd9Sstevel@tonic-gate 							m[i].match.string);
72*7c478bd9Sstevel@tonic-gate 			if (new[i].match.string == 0 && m[i].match.string != 0)
73*7c478bd9Sstevel@tonic-gate 				err++;
74*7c478bd9Sstevel@tonic-gate 			break;
75*7c478bd9Sstevel@tonic-gate 		case mmt_single:
76*7c478bd9Sstevel@tonic-gate 			new[i].match.single.lo =
77*7c478bd9Sstevel@tonic-gate 				am(myself, m[i].match.single.numRange *
78*7c478bd9Sstevel@tonic-gate 					sizeof (new[i].match.single.lo[0]));
79*7c478bd9Sstevel@tonic-gate 			new[i].match.single.hi =
80*7c478bd9Sstevel@tonic-gate 				am(myself, m[i].match.single.numRange *
81*7c478bd9Sstevel@tonic-gate 					sizeof (new[i].match.single.hi[0]));
82*7c478bd9Sstevel@tonic-gate 			if (new[i].match.single.lo != 0)
83*7c478bd9Sstevel@tonic-gate 				memcpy(new[i].match.single.lo,
84*7c478bd9Sstevel@tonic-gate 					m[i].match.single.lo,
85*7c478bd9Sstevel@tonic-gate 					m[i].match.single.numRange);
86*7c478bd9Sstevel@tonic-gate 			else if (m[i].match.single.lo != 0)
87*7c478bd9Sstevel@tonic-gate 				err++;
88*7c478bd9Sstevel@tonic-gate 			if (new[i].match.single.hi != 0)
89*7c478bd9Sstevel@tonic-gate 				memcpy(new[i].match.single.hi,
90*7c478bd9Sstevel@tonic-gate 					m[i].match.single.hi,
91*7c478bd9Sstevel@tonic-gate 					m[i].match.single.numRange);
92*7c478bd9Sstevel@tonic-gate 			else if (m[i].match.single.hi != 0)
93*7c478bd9Sstevel@tonic-gate 				err++;
94*7c478bd9Sstevel@tonic-gate 			break;
95*7c478bd9Sstevel@tonic-gate 		case mmt_berstring:
96*7c478bd9Sstevel@tonic-gate 			new[i].match.berString = sdup(myself, T,
97*7c478bd9Sstevel@tonic-gate 							m[i].match.berString);
98*7c478bd9Sstevel@tonic-gate 			if (new[i].match.berString == 0 &&
99*7c478bd9Sstevel@tonic-gate 					m[i].match.berString != 0)
100*7c478bd9Sstevel@tonic-gate 				err++;
101*7c478bd9Sstevel@tonic-gate 			break;
102*7c478bd9Sstevel@tonic-gate 		case mmt_item:
103*7c478bd9Sstevel@tonic-gate 		case mmt_limit:
104*7c478bd9Sstevel@tonic-gate 		case mmt_any:
105*7c478bd9Sstevel@tonic-gate 		case mmt_begin:
106*7c478bd9Sstevel@tonic-gate 		case mmt_end:
107*7c478bd9Sstevel@tonic-gate 		default:
108*7c478bd9Sstevel@tonic-gate 			break;
109*7c478bd9Sstevel@tonic-gate 		}
110*7c478bd9Sstevel@tonic-gate 	}
111*7c478bd9Sstevel@tonic-gate 
112*7c478bd9Sstevel@tonic-gate 	/* If there were memory allocation errors, free the copy */
113*7c478bd9Sstevel@tonic-gate 	if (err > 0) {
114*7c478bd9Sstevel@tonic-gate 		freeMappingFormat(new);
115*7c478bd9Sstevel@tonic-gate 		new = 0;
116*7c478bd9Sstevel@tonic-gate 	}
117*7c478bd9Sstevel@tonic-gate 
118*7c478bd9Sstevel@tonic-gate 	return (new);
119*7c478bd9Sstevel@tonic-gate }
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate void
122*7c478bd9Sstevel@tonic-gate freeMappingFormat(__nis_mapping_format_t *m) {
123*7c478bd9Sstevel@tonic-gate 	int	i;
124*7c478bd9Sstevel@tonic-gate 
125*7c478bd9Sstevel@tonic-gate 	if (m == 0)
126*7c478bd9Sstevel@tonic-gate 		return;
127*7c478bd9Sstevel@tonic-gate 
128*7c478bd9Sstevel@tonic-gate 	for (i = 0; m[i].type != mmt_end; i++) {
129*7c478bd9Sstevel@tonic-gate 		switch (m[i].type) {
130*7c478bd9Sstevel@tonic-gate 		case mmt_string:
131*7c478bd9Sstevel@tonic-gate 			sfree(m[i].match.string);
132*7c478bd9Sstevel@tonic-gate 			break;
133*7c478bd9Sstevel@tonic-gate 		case mmt_single:
134*7c478bd9Sstevel@tonic-gate 			sfree(m[i].match.single.lo);
135*7c478bd9Sstevel@tonic-gate 			sfree(m[i].match.single.hi);
136*7c478bd9Sstevel@tonic-gate 			break;
137*7c478bd9Sstevel@tonic-gate 		case mmt_berstring:
138*7c478bd9Sstevel@tonic-gate 			sfree(m[i].match.berString);
139*7c478bd9Sstevel@tonic-gate 			break;
140*7c478bd9Sstevel@tonic-gate 		case mmt_item:
141*7c478bd9Sstevel@tonic-gate 		case mmt_limit:
142*7c478bd9Sstevel@tonic-gate 		case mmt_any:
143*7c478bd9Sstevel@tonic-gate 		case mmt_begin:
144*7c478bd9Sstevel@tonic-gate 		case mmt_end:
145*7c478bd9Sstevel@tonic-gate 		default:
146*7c478bd9Sstevel@tonic-gate 			break;
147*7c478bd9Sstevel@tonic-gate 		}
148*7c478bd9Sstevel@tonic-gate 	}
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate 	free(m);
151*7c478bd9Sstevel@tonic-gate }
152*7c478bd9Sstevel@tonic-gate 
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate void
155*7c478bd9Sstevel@tonic-gate copyIndex(__nis_index_t *old, __nis_index_t *new, int *err) {
156*7c478bd9Sstevel@tonic-gate 	int	i;
157*7c478bd9Sstevel@tonic-gate 	char	*myself = "copyIndex";
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	if (old == 0 || new == 0) {
160*7c478bd9Sstevel@tonic-gate 		*err = EINVAL;
161*7c478bd9Sstevel@tonic-gate 		return;
162*7c478bd9Sstevel@tonic-gate 	}
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < old->numIndexes; i++) {
165*7c478bd9Sstevel@tonic-gate 		new->name[i] = sdup(myself, T, old->name[i]);
166*7c478bd9Sstevel@tonic-gate 		if (new->name[i] == 0 && old->name[i] != 0) {
167*7c478bd9Sstevel@tonic-gate 			*err = ENOMEM;
168*7c478bd9Sstevel@tonic-gate 			return;
169*7c478bd9Sstevel@tonic-gate 		}
170*7c478bd9Sstevel@tonic-gate 		new->value[i] = cloneMappingFormat(old->value[i]);
171*7c478bd9Sstevel@tonic-gate 		if (new->value[i] == 0 && old->value[i] != 0) {
172*7c478bd9Sstevel@tonic-gate 			*err = ENOMEM;
173*7c478bd9Sstevel@tonic-gate 			return;
174*7c478bd9Sstevel@tonic-gate 		}
175*7c478bd9Sstevel@tonic-gate 	}
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 	new->numIndexes = old->numIndexes;
178*7c478bd9Sstevel@tonic-gate }
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate __nis_index_t *
181*7c478bd9Sstevel@tonic-gate cloneIndex(__nis_index_t *old) {
182*7c478bd9Sstevel@tonic-gate 	char		*myself = "cloneIndex";
183*7c478bd9Sstevel@tonic-gate 	int		err = 0;
184*7c478bd9Sstevel@tonic-gate 	__nis_index_t	*new = am(myself, sizeof (*new));
185*7c478bd9Sstevel@tonic-gate 
186*7c478bd9Sstevel@tonic-gate 	if (old == 0)
187*7c478bd9Sstevel@tonic-gate 		return (0);
188*7c478bd9Sstevel@tonic-gate 
189*7c478bd9Sstevel@tonic-gate 	if (new != 0) {
190*7c478bd9Sstevel@tonic-gate 		copyIndex(old, new, &err);
191*7c478bd9Sstevel@tonic-gate 		if (err != 0) {
192*7c478bd9Sstevel@tonic-gate 			freeIndex(new, 1);
193*7c478bd9Sstevel@tonic-gate 			new = 0;
194*7c478bd9Sstevel@tonic-gate 		}
195*7c478bd9Sstevel@tonic-gate 	}
196*7c478bd9Sstevel@tonic-gate 
197*7c478bd9Sstevel@tonic-gate 	return (new);
198*7c478bd9Sstevel@tonic-gate }
199*7c478bd9Sstevel@tonic-gate 
200*7c478bd9Sstevel@tonic-gate void
201*7c478bd9Sstevel@tonic-gate freeIndex(__nis_index_t *old, bool_t doFree) {
202*7c478bd9Sstevel@tonic-gate 	int	i;
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate 	if (old == 0)
205*7c478bd9Sstevel@tonic-gate 		return;
206*7c478bd9Sstevel@tonic-gate 
207*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < old->numIndexes; i++) {
208*7c478bd9Sstevel@tonic-gate 		sfree(old->name[i]);
209*7c478bd9Sstevel@tonic-gate 		freeMappingFormat(old->value[i]);
210*7c478bd9Sstevel@tonic-gate 	}
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate 	if (doFree)
213*7c478bd9Sstevel@tonic-gate 		free(old);
214*7c478bd9Sstevel@tonic-gate }
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate char **
217*7c478bd9Sstevel@tonic-gate cloneName(char **name, int numNames) {
218*7c478bd9Sstevel@tonic-gate 	char	**new;
219*7c478bd9Sstevel@tonic-gate 	int	i;
220*7c478bd9Sstevel@tonic-gate 	char	*myself = "cloneName";
221*7c478bd9Sstevel@tonic-gate 
222*7c478bd9Sstevel@tonic-gate 	if (name == 0 || numNames <= 0)
223*7c478bd9Sstevel@tonic-gate 		return (0);
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	new = am(myself, numNames * sizeof (new[0]));
226*7c478bd9Sstevel@tonic-gate 	if (new == 0)
227*7c478bd9Sstevel@tonic-gate 		return (0);
228*7c478bd9Sstevel@tonic-gate 
229*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < numNames; i++) {
230*7c478bd9Sstevel@tonic-gate 		if (name[i] != 0) {
231*7c478bd9Sstevel@tonic-gate 			new[i] = sdup(myself, T, name[i]);
232*7c478bd9Sstevel@tonic-gate 			if (new[i] == 0) {
233*7c478bd9Sstevel@tonic-gate 				for (i--; i >= 0; i--) {
234*7c478bd9Sstevel@tonic-gate 					sfree(new[i]);
235*7c478bd9Sstevel@tonic-gate 				}
236*7c478bd9Sstevel@tonic-gate 				sfree(new);
237*7c478bd9Sstevel@tonic-gate 				return (0);
238*7c478bd9Sstevel@tonic-gate 			}
239*7c478bd9Sstevel@tonic-gate 		} else {
240*7c478bd9Sstevel@tonic-gate 			new[i] = 0;
241*7c478bd9Sstevel@tonic-gate 		}
242*7c478bd9Sstevel@tonic-gate 	}
243*7c478bd9Sstevel@tonic-gate 
244*7c478bd9Sstevel@tonic-gate 	return (new);
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate void
248*7c478bd9Sstevel@tonic-gate freeValue(__nis_value_t *val, int count) {
249*7c478bd9Sstevel@tonic-gate 	int	c, i;
250*7c478bd9Sstevel@tonic-gate 
251*7c478bd9Sstevel@tonic-gate 	if (val == 0)
252*7c478bd9Sstevel@tonic-gate 		return;
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate 	for (c = 0; c < count; c++) {
255*7c478bd9Sstevel@tonic-gate 		if (val[c].val != 0) {
256*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < val[c].numVals; i++) {
257*7c478bd9Sstevel@tonic-gate 				sfree(val[c].val[i].value);
258*7c478bd9Sstevel@tonic-gate 			}
259*7c478bd9Sstevel@tonic-gate 			free(val[c].val);
260*7c478bd9Sstevel@tonic-gate 		}
261*7c478bd9Sstevel@tonic-gate 	}
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 	free(val);
264*7c478bd9Sstevel@tonic-gate }
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate __nis_value_t *
267*7c478bd9Sstevel@tonic-gate cloneValue(__nis_value_t *val, int count) {
268*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*n;
269*7c478bd9Sstevel@tonic-gate 	int		c, i;
270*7c478bd9Sstevel@tonic-gate 	char		*myself = "cloneValue";
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	if (count <= 0 || val == 0)
273*7c478bd9Sstevel@tonic-gate 		return (0);
274*7c478bd9Sstevel@tonic-gate 
275*7c478bd9Sstevel@tonic-gate 	n = am(myself, count * sizeof (*n));
276*7c478bd9Sstevel@tonic-gate 	if (n == 0)
277*7c478bd9Sstevel@tonic-gate 		return (0);
278*7c478bd9Sstevel@tonic-gate 
279*7c478bd9Sstevel@tonic-gate 	for (c = 0; c < count; c++) {
280*7c478bd9Sstevel@tonic-gate 		n[c].type = val[c].type;
281*7c478bd9Sstevel@tonic-gate 		n[c].repeat = val[c].repeat;
282*7c478bd9Sstevel@tonic-gate 		n[c].numVals = val[c].numVals;
283*7c478bd9Sstevel@tonic-gate 		if (n[c].numVals > 0) {
284*7c478bd9Sstevel@tonic-gate 			n[c].val = am(myself, n[c].numVals *
285*7c478bd9Sstevel@tonic-gate 						sizeof (n[c].val[0]));
286*7c478bd9Sstevel@tonic-gate 			if (n[c].val == 0) {
287*7c478bd9Sstevel@tonic-gate 				freeValue(n, c);
288*7c478bd9Sstevel@tonic-gate 				return (0);
289*7c478bd9Sstevel@tonic-gate 			}
290*7c478bd9Sstevel@tonic-gate 		} else {
291*7c478bd9Sstevel@tonic-gate 			n[c].val = 0;
292*7c478bd9Sstevel@tonic-gate 		}
293*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < n[c].numVals; i++) {
294*7c478bd9Sstevel@tonic-gate 			int	amlen = val[c].val[i].length;
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 			/*
297*7c478bd9Sstevel@tonic-gate 			 * The functions that create string values try to
298*7c478bd9Sstevel@tonic-gate 			 * make sure that there's a NUL at the end. However,
299*7c478bd9Sstevel@tonic-gate 			 * both NIS+ and LDAP have a tendency to store strings
300*7c478bd9Sstevel@tonic-gate 			 * without a NUL, so the value length may not include
301*7c478bd9Sstevel@tonic-gate 			 * the NUL (even though it's there). In order to
302*7c478bd9Sstevel@tonic-gate 			 * preserve that NUL, we add a byte to the length if
303*7c478bd9Sstevel@tonic-gate 			 * the type is vt_string, and there isn't already a
304*7c478bd9Sstevel@tonic-gate 			 * NUL at the end. The memory allocation function
305*7c478bd9Sstevel@tonic-gate 			 * (am()) will take care of actually putting the NUL
306*7c478bd9Sstevel@tonic-gate 			 * in place, since it allocates zero-initialized
307*7c478bd9Sstevel@tonic-gate 			 * memory.
308*7c478bd9Sstevel@tonic-gate 			 */
309*7c478bd9Sstevel@tonic-gate 			n[c].val[i].length = val[c].val[i].length;
310*7c478bd9Sstevel@tonic-gate 			if (n[c].type == vt_string && amlen > 0 &&
311*7c478bd9Sstevel@tonic-gate 				((char *)val[c].val[i].value)[amlen-1] !=
312*7c478bd9Sstevel@tonic-gate 					'\0') {
313*7c478bd9Sstevel@tonic-gate 				amlen++;
314*7c478bd9Sstevel@tonic-gate 			}
315*7c478bd9Sstevel@tonic-gate 			n[c].val[i].value = am(myself, amlen);
316*7c478bd9Sstevel@tonic-gate 			if (amlen > 0 && n[c].val[i].value == 0) {
317*7c478bd9Sstevel@tonic-gate 				freeValue(n, c);
318*7c478bd9Sstevel@tonic-gate 				return (0);
319*7c478bd9Sstevel@tonic-gate 			}
320*7c478bd9Sstevel@tonic-gate 			memcpy(n[c].val[i].value, val[c].val[i].value,
321*7c478bd9Sstevel@tonic-gate 				n[c].val[i].length);
322*7c478bd9Sstevel@tonic-gate 		}
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 
325*7c478bd9Sstevel@tonic-gate 	return (n);
326*7c478bd9Sstevel@tonic-gate }
327*7c478bd9Sstevel@tonic-gate 
328*7c478bd9Sstevel@tonic-gate /* Define LBER_USE_DER per ber_decode(3LDAP) */
329*7c478bd9Sstevel@tonic-gate #ifndef	LBER_USE_DER
330*7c478bd9Sstevel@tonic-gate #define	LBER_USE_DER	0x01
331*7c478bd9Sstevel@tonic-gate #endif	/* LBER_USE_DER */
332*7c478bd9Sstevel@tonic-gate 
333*7c478bd9Sstevel@tonic-gate /*
334*7c478bd9Sstevel@tonic-gate  * Return a copy of 'valIn' where each value has been replaced by the
335*7c478bd9Sstevel@tonic-gate  * BER encoded equivalent specified by 'berstring'. 'valIn' is unchanged.
336*7c478bd9Sstevel@tonic-gate  */
337*7c478bd9Sstevel@tonic-gate __nis_value_t *
338*7c478bd9Sstevel@tonic-gate berEncode(__nis_value_t *valIn, char *berstring) {
339*7c478bd9Sstevel@tonic-gate 	char		*myself = "berEncode";
340*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
341*7c478bd9Sstevel@tonic-gate 	int		i;
342*7c478bd9Sstevel@tonic-gate 
343*7c478bd9Sstevel@tonic-gate 	if (valIn == 0 || berstring == 0)
344*7c478bd9Sstevel@tonic-gate 		return (0);
345*7c478bd9Sstevel@tonic-gate 
346*7c478bd9Sstevel@tonic-gate 	val = cloneValue(valIn, 1);
347*7c478bd9Sstevel@tonic-gate 	if (val == 0)
348*7c478bd9Sstevel@tonic-gate 		return (0);
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < val->numVals; i++) {
351*7c478bd9Sstevel@tonic-gate 		BerElement	*ber = ber_alloc();
352*7c478bd9Sstevel@tonic-gate 		struct berval	*bv = 0;
353*7c478bd9Sstevel@tonic-gate 		int		ret;
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate 		if (ber == 0) {
356*7c478bd9Sstevel@tonic-gate 			logmsg(MSG_NOMEM, LOG_ERR, "%s: ber_alloc() => NULL",
357*7c478bd9Sstevel@tonic-gate 				myself);
358*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
359*7c478bd9Sstevel@tonic-gate 			return (0);
360*7c478bd9Sstevel@tonic-gate 		}
361*7c478bd9Sstevel@tonic-gate 
362*7c478bd9Sstevel@tonic-gate 		if ((strcmp("b", berstring) == 0 ||
363*7c478bd9Sstevel@tonic-gate 				strcmp("i", berstring) == 0)) {
364*7c478bd9Sstevel@tonic-gate 			if (val->val[i].length >= sizeof (int)) {
365*7c478bd9Sstevel@tonic-gate 				ret = ber_printf(ber, berstring,
366*7c478bd9Sstevel@tonic-gate 					*((int *)(val->val[i].value)));
367*7c478bd9Sstevel@tonic-gate 			} else {
368*7c478bd9Sstevel@tonic-gate 				ret = -1;
369*7c478bd9Sstevel@tonic-gate 			}
370*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("B", berstring) == 0) {
371*7c478bd9Sstevel@tonic-gate 			ret = ber_printf(ber, berstring,
372*7c478bd9Sstevel@tonic-gate 				val->val[i].value,
373*7c478bd9Sstevel@tonic-gate 				val->val[i].length * 8);
374*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("n", berstring) == 0) {
375*7c478bd9Sstevel@tonic-gate 			ret = ber_printf(ber, berstring);
376*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("o", berstring) == 0) {
377*7c478bd9Sstevel@tonic-gate 			ret = ber_printf(ber, berstring,
378*7c478bd9Sstevel@tonic-gate 				val->val[i].value, val->val[i].length);
379*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("s", berstring) == 0) {
380*7c478bd9Sstevel@tonic-gate 			char	*str = am(myself, val->val[i].length + 1);
381*7c478bd9Sstevel@tonic-gate 
382*7c478bd9Sstevel@tonic-gate 			if (str != 0) {
383*7c478bd9Sstevel@tonic-gate 				ret = ber_printf(ber, berstring, str);
384*7c478bd9Sstevel@tonic-gate 				free(str);
385*7c478bd9Sstevel@tonic-gate 			} else {
386*7c478bd9Sstevel@tonic-gate 				ret = -1;
387*7c478bd9Sstevel@tonic-gate 			}
388*7c478bd9Sstevel@tonic-gate 		} else {
389*7c478bd9Sstevel@tonic-gate 			ret = -1;
390*7c478bd9Sstevel@tonic-gate 		}
391*7c478bd9Sstevel@tonic-gate 
392*7c478bd9Sstevel@tonic-gate 		if (ret == -1) {
393*7c478bd9Sstevel@tonic-gate 			reportError(NPL_BERENCODE, "%s: BER encoding error",
394*7c478bd9Sstevel@tonic-gate 					myself);
395*7c478bd9Sstevel@tonic-gate 			ber_free(ber, 1);
396*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
397*7c478bd9Sstevel@tonic-gate 			return (0);
398*7c478bd9Sstevel@tonic-gate 		}
399*7c478bd9Sstevel@tonic-gate 
400*7c478bd9Sstevel@tonic-gate 		if (ber_flatten(ber, &bv) != 0 || bv == 0) {
401*7c478bd9Sstevel@tonic-gate 			reportError(NPL_BERENCODE, "%s: ber_flatten() error",
402*7c478bd9Sstevel@tonic-gate 					myself);
403*7c478bd9Sstevel@tonic-gate 			ber_free(ber, 1);
404*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
405*7c478bd9Sstevel@tonic-gate 			return (0);
406*7c478bd9Sstevel@tonic-gate 		}
407*7c478bd9Sstevel@tonic-gate 
408*7c478bd9Sstevel@tonic-gate 		sfree(val->val[i].value);
409*7c478bd9Sstevel@tonic-gate 		val->val[i].length = bv->bv_len;
410*7c478bd9Sstevel@tonic-gate 		val->val[i].value = bv->bv_val;
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 		ber_free(ber, 1);
413*7c478bd9Sstevel@tonic-gate 	}
414*7c478bd9Sstevel@tonic-gate 
415*7c478bd9Sstevel@tonic-gate 	val->type = vt_ber;
416*7c478bd9Sstevel@tonic-gate 
417*7c478bd9Sstevel@tonic-gate 	return (val);
418*7c478bd9Sstevel@tonic-gate }
419*7c478bd9Sstevel@tonic-gate 
420*7c478bd9Sstevel@tonic-gate __nis_value_t *
421*7c478bd9Sstevel@tonic-gate berDecode(__nis_value_t *valIn, char *berstring) {
422*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
423*7c478bd9Sstevel@tonic-gate 	int		i;
424*7c478bd9Sstevel@tonic-gate 	char		*myself = "berDecode";
425*7c478bd9Sstevel@tonic-gate 
426*7c478bd9Sstevel@tonic-gate 	if (valIn == 0 || berstring == 0)
427*7c478bd9Sstevel@tonic-gate 		return (0);
428*7c478bd9Sstevel@tonic-gate 
429*7c478bd9Sstevel@tonic-gate 	val = cloneValue(valIn, 1);
430*7c478bd9Sstevel@tonic-gate 	if (val == 0)
431*7c478bd9Sstevel@tonic-gate 		return (0);
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < val->numVals; i++) {
434*7c478bd9Sstevel@tonic-gate 		void		*v = 0;
435*7c478bd9Sstevel@tonic-gate 		int		ret, len = 0;
436*7c478bd9Sstevel@tonic-gate 		struct berval	bv;
437*7c478bd9Sstevel@tonic-gate 		BerElement	*ber;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 		if (val->val[i].value == 0 || val->val[i].length <= 0)
440*7c478bd9Sstevel@tonic-gate 			continue;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 		bv.bv_val = val->val[i].value;
443*7c478bd9Sstevel@tonic-gate 		bv.bv_len = val->val[i].length;
444*7c478bd9Sstevel@tonic-gate 		ber = ber_init(&bv);
445*7c478bd9Sstevel@tonic-gate 		if (ber == 0) {
446*7c478bd9Sstevel@tonic-gate 			reportError(NPL_BERDECODE, "%s: ber_init() error",
447*7c478bd9Sstevel@tonic-gate 				myself);
448*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
449*7c478bd9Sstevel@tonic-gate 			return (0);
450*7c478bd9Sstevel@tonic-gate 		}
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 		if ((strcmp("b", berstring) == 0 ||
453*7c478bd9Sstevel@tonic-gate 				strcmp("i", berstring) == 0)) {
454*7c478bd9Sstevel@tonic-gate 			len = sizeof (int);
455*7c478bd9Sstevel@tonic-gate 			v = am(myself, len);
456*7c478bd9Sstevel@tonic-gate 			if (v != 0) {
457*7c478bd9Sstevel@tonic-gate 				ret = ber_scanf(ber, berstring, v);
458*7c478bd9Sstevel@tonic-gate 			} else {
459*7c478bd9Sstevel@tonic-gate 				ret = -1;
460*7c478bd9Sstevel@tonic-gate 			}
461*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("B", berstring) == 0) {
462*7c478bd9Sstevel@tonic-gate 			long	llen;
463*7c478bd9Sstevel@tonic-gate 
464*7c478bd9Sstevel@tonic-gate 			ret = ber_scanf(ber, berstring, &v, &llen);
465*7c478bd9Sstevel@tonic-gate 			if (ret != -1) {
466*7c478bd9Sstevel@tonic-gate 				len = llen/8;
467*7c478bd9Sstevel@tonic-gate 			}
468*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("n", berstring) == 0) {
469*7c478bd9Sstevel@tonic-gate 			ret = 0;
470*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("o", berstring) == 0) {
471*7c478bd9Sstevel@tonic-gate 			struct berval	*bv = am(myself, sizeof (*bv));
472*7c478bd9Sstevel@tonic-gate 
473*7c478bd9Sstevel@tonic-gate 			if (bv != 0) {
474*7c478bd9Sstevel@tonic-gate 				ret = ber_scanf(ber, "O", &bv);
475*7c478bd9Sstevel@tonic-gate 				if (ret != -1 && bv != 0) {
476*7c478bd9Sstevel@tonic-gate 					v = bv->bv_val;
477*7c478bd9Sstevel@tonic-gate 					len = bv->bv_len;
478*7c478bd9Sstevel@tonic-gate 				} else {
479*7c478bd9Sstevel@tonic-gate 					ret = -1;
480*7c478bd9Sstevel@tonic-gate 				}
481*7c478bd9Sstevel@tonic-gate 				/* Only free 'bv' itself */
482*7c478bd9Sstevel@tonic-gate 				free(bv);
483*7c478bd9Sstevel@tonic-gate 			} else {
484*7c478bd9Sstevel@tonic-gate 				ret = -1;
485*7c478bd9Sstevel@tonic-gate 			}
486*7c478bd9Sstevel@tonic-gate 		} else if (strcmp("s", berstring) == 0) {
487*7c478bd9Sstevel@tonic-gate 			ret = ber_scanf(ber, "a", &v);
488*7c478bd9Sstevel@tonic-gate 			if (ret != -1) {
489*7c478bd9Sstevel@tonic-gate 				len = slen(v);
490*7c478bd9Sstevel@tonic-gate 			}
491*7c478bd9Sstevel@tonic-gate 		} else {
492*7c478bd9Sstevel@tonic-gate 			ret = -1;
493*7c478bd9Sstevel@tonic-gate 		}
494*7c478bd9Sstevel@tonic-gate 
495*7c478bd9Sstevel@tonic-gate 		if (ret == -1) {
496*7c478bd9Sstevel@tonic-gate 			reportError(NPL_BERDECODE, "%s: BER decoding error",
497*7c478bd9Sstevel@tonic-gate 					myself);
498*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
499*7c478bd9Sstevel@tonic-gate 			return (0);
500*7c478bd9Sstevel@tonic-gate 		}
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 		/* Free the old value, and replace it with the decoded one */
503*7c478bd9Sstevel@tonic-gate 		sfree(val->val[i].value);
504*7c478bd9Sstevel@tonic-gate 		val->val[i].value = v;
505*7c478bd9Sstevel@tonic-gate 		val->val[i].length = len;
506*7c478bd9Sstevel@tonic-gate 	}
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	return (val);
509*7c478bd9Sstevel@tonic-gate }
510*7c478bd9Sstevel@tonic-gate 
511*7c478bd9Sstevel@tonic-gate /*
512*7c478bd9Sstevel@tonic-gate  * Return the value of the specified item.
513*7c478bd9Sstevel@tonic-gate  */
514*7c478bd9Sstevel@tonic-gate __nis_value_t *
515*7c478bd9Sstevel@tonic-gate getMappingItemVal(__nis_mapping_item_t *item, __nis_mapping_item_type_t native,
516*7c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) {
517*7c478bd9Sstevel@tonic-gate 	__nis_value_t				*val = 0, *nameVal, *exVal = 0;
518*7c478bd9Sstevel@tonic-gate 	int					numName, caseInsens, cmp;
519*7c478bd9Sstevel@tonic-gate 	int					i, j, k;
520*7c478bd9Sstevel@tonic-gate 	char					**name;
521*7c478bd9Sstevel@tonic-gate 	enum {rvOnly, rvThenLookup, lookupOnly}	check;
522*7c478bd9Sstevel@tonic-gate 	unsigned char				fromldap = '\0';
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	if (item == 0)
525*7c478bd9Sstevel@tonic-gate 		return (0);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	/*
528*7c478bd9Sstevel@tonic-gate 	 * First, we decide if we should look for the value in 'rv',
529*7c478bd9Sstevel@tonic-gate 	 * directly from NIS+/LDAP, or both.
530*7c478bd9Sstevel@tonic-gate 	 */
531*7c478bd9Sstevel@tonic-gate 	switch (item->type) {
532*7c478bd9Sstevel@tonic-gate 	case mit_nisplus:
533*7c478bd9Sstevel@tonic-gate 		/* Do we have a valid index/object spec ? */
534*7c478bd9Sstevel@tonic-gate 		if (item->searchSpec.obj.index.numIndexes <= 0 &&
535*7c478bd9Sstevel@tonic-gate 				item->searchSpec.obj.name == 0) {
536*7c478bd9Sstevel@tonic-gate 			/*
537*7c478bd9Sstevel@tonic-gate 			 * No valid index/object. If we have a rule-value,
538*7c478bd9Sstevel@tonic-gate 			 * use it. Otherwise, return error.
539*7c478bd9Sstevel@tonic-gate 			 */
540*7c478bd9Sstevel@tonic-gate 			if (rv != 0) {
541*7c478bd9Sstevel@tonic-gate 				name = rv->colName;
542*7c478bd9Sstevel@tonic-gate 				nameVal = rv->colVal;
543*7c478bd9Sstevel@tonic-gate 				numName = rv->numColumns;
544*7c478bd9Sstevel@tonic-gate 				caseInsens = 0;
545*7c478bd9Sstevel@tonic-gate 				check = rvOnly;
546*7c478bd9Sstevel@tonic-gate 			} else {
547*7c478bd9Sstevel@tonic-gate 				return (0);
548*7c478bd9Sstevel@tonic-gate 			}
549*7c478bd9Sstevel@tonic-gate 		} else {
550*7c478bd9Sstevel@tonic-gate 			/*
551*7c478bd9Sstevel@tonic-gate 			 * Valid index, so skip the rule-value and do
552*7c478bd9Sstevel@tonic-gate 			 * a direct NIS+ lookup.
553*7c478bd9Sstevel@tonic-gate 			 */
554*7c478bd9Sstevel@tonic-gate 			check = lookupOnly;
555*7c478bd9Sstevel@tonic-gate 		}
556*7c478bd9Sstevel@tonic-gate 		break;
557*7c478bd9Sstevel@tonic-gate 	case mit_ldap:
558*7c478bd9Sstevel@tonic-gate 		if (rv != 0) {
559*7c478bd9Sstevel@tonic-gate 			name = rv->attrName;
560*7c478bd9Sstevel@tonic-gate 			nameVal = rv->attrVal;
561*7c478bd9Sstevel@tonic-gate 			numName = rv->numAttrs;
562*7c478bd9Sstevel@tonic-gate 			caseInsens = 1;
563*7c478bd9Sstevel@tonic-gate 			fromldap = '1';
564*7c478bd9Sstevel@tonic-gate 		}
565*7c478bd9Sstevel@tonic-gate 		/* Do we have a valid triple ? */
566*7c478bd9Sstevel@tonic-gate 		if (item->searchSpec.triple.scope == LDAP_SCOPE_UNKNOWN) {
567*7c478bd9Sstevel@tonic-gate 			/*
568*7c478bd9Sstevel@tonic-gate 			 * No valid triple. If we have a rule-value, use it.
569*7c478bd9Sstevel@tonic-gate 			 * Otherwise, return error.
570*7c478bd9Sstevel@tonic-gate 			 */
571*7c478bd9Sstevel@tonic-gate 			if (rv != 0) {
572*7c478bd9Sstevel@tonic-gate 				check = rvOnly;
573*7c478bd9Sstevel@tonic-gate 			} else {
574*7c478bd9Sstevel@tonic-gate 				return (0);
575*7c478bd9Sstevel@tonic-gate 			}
576*7c478bd9Sstevel@tonic-gate 		} else if (item->searchSpec.triple.base == 0 &&
577*7c478bd9Sstevel@tonic-gate 				item->searchSpec.triple.scope ==
578*7c478bd9Sstevel@tonic-gate 					LDAP_SCOPE_ONELEVEL &&
579*7c478bd9Sstevel@tonic-gate 				item->searchSpec.triple.attrs == 0 &&
580*7c478bd9Sstevel@tonic-gate 				item->searchSpec.triple.element == 0) {
581*7c478bd9Sstevel@tonic-gate 			/*
582*7c478bd9Sstevel@tonic-gate 			 * We have a valid triple, but it points to the
583*7c478bd9Sstevel@tonic-gate 			 * current LDAP container. Thus, first look in
584*7c478bd9Sstevel@tonic-gate 			 * the rule-value; if that fails, perform a direct
585*7c478bd9Sstevel@tonic-gate 			 * LDAP lookup.
586*7c478bd9Sstevel@tonic-gate 			 */
587*7c478bd9Sstevel@tonic-gate 			if (rv != 0) {
588*7c478bd9Sstevel@tonic-gate 				check = rvThenLookup;
589*7c478bd9Sstevel@tonic-gate 			} else {
590*7c478bd9Sstevel@tonic-gate 				check = lookupOnly;
591*7c478bd9Sstevel@tonic-gate 			}
592*7c478bd9Sstevel@tonic-gate 		} else {
593*7c478bd9Sstevel@tonic-gate 			/*
594*7c478bd9Sstevel@tonic-gate 			 * Valid triple, and it's not the current container
595*7c478bd9Sstevel@tonic-gate 			 * (at least not in the trivial sense). Hence, do
596*7c478bd9Sstevel@tonic-gate 			 * a direct LDAP lookup.
597*7c478bd9Sstevel@tonic-gate 			 */
598*7c478bd9Sstevel@tonic-gate 			check = lookupOnly;
599*7c478bd9Sstevel@tonic-gate 		}
600*7c478bd9Sstevel@tonic-gate 		break;
601*7c478bd9Sstevel@tonic-gate 	default:
602*7c478bd9Sstevel@tonic-gate 		return (0);
603*7c478bd9Sstevel@tonic-gate 	}
604*7c478bd9Sstevel@tonic-gate 
605*7c478bd9Sstevel@tonic-gate 	/* Check the rule-value */
606*7c478bd9Sstevel@tonic-gate 	if (check == rvOnly || check == rvThenLookup) {
607*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < numName; i++) {
608*7c478bd9Sstevel@tonic-gate 			if (caseInsens)
609*7c478bd9Sstevel@tonic-gate 				cmp = strcasecmp(item->name, name[i]);
610*7c478bd9Sstevel@tonic-gate 			else
611*7c478bd9Sstevel@tonic-gate 				cmp = strcmp(item->name, name[i]);
612*7c478bd9Sstevel@tonic-gate 			if (cmp == 0) {
613*7c478bd9Sstevel@tonic-gate 				if (nameVal[i].numVals <= 0)
614*7c478bd9Sstevel@tonic-gate 					break;
615*7c478bd9Sstevel@tonic-gate 				if (berstring == 0) {
616*7c478bd9Sstevel@tonic-gate 					val = cloneValue(&nameVal[i], 1);
617*7c478bd9Sstevel@tonic-gate 				} else if (yp2ldap && berstring[0] == 'a') {
618*7c478bd9Sstevel@tonic-gate 					val = cloneValue(&nameVal[i], 1);
619*7c478bd9Sstevel@tonic-gate 				} else {
620*7c478bd9Sstevel@tonic-gate 					val = berDecode(&nameVal[i],
621*7c478bd9Sstevel@tonic-gate 						berstring);
622*7c478bd9Sstevel@tonic-gate 				}
623*7c478bd9Sstevel@tonic-gate 				if (val != 0) {
624*7c478bd9Sstevel@tonic-gate 					val->repeat = item->repeat;
625*7c478bd9Sstevel@tonic-gate 					/*
626*7c478bd9Sstevel@tonic-gate 					 * If value for nis+ column is
627*7c478bd9Sstevel@tonic-gate 					 * passed with value, val is
628*7c478bd9Sstevel@tonic-gate 					 * manipulated in cloneValue().
629*7c478bd9Sstevel@tonic-gate 					 * To decide whether there are
630*7c478bd9Sstevel@tonic-gate 					 * enough nis+ column values
631*7c478bd9Sstevel@tonic-gate 					 * for rule to produce a value,
632*7c478bd9Sstevel@tonic-gate 					 * we need nis+ column values
633*7c478bd9Sstevel@tonic-gate 					 * as well as nis_mapping_element
634*7c478bd9Sstevel@tonic-gate 					 * from the rule. If we are here,
635*7c478bd9Sstevel@tonic-gate 					 * it indicates that the 'val has
636*7c478bd9Sstevel@tonic-gate 					 * an valid value for the column
637*7c478bd9Sstevel@tonic-gate 					 * item-> name. So set
638*7c478bd9Sstevel@tonic-gate 					 * NP_LDAP_MAP_SUCCESS
639*7c478bd9Sstevel@tonic-gate 					 * to np_ldap-stat.
640*7c478bd9Sstevel@tonic-gate 					 */
641*7c478bd9Sstevel@tonic-gate 
642*7c478bd9Sstevel@tonic-gate 					if (np_ldap_stat != NULL)
643*7c478bd9Sstevel@tonic-gate 						*np_ldap_stat =
644*7c478bd9Sstevel@tonic-gate 							NP_LDAP_MAP_SUCCESS;
645*7c478bd9Sstevel@tonic-gate 				}
646*7c478bd9Sstevel@tonic-gate 				break;
647*7c478bd9Sstevel@tonic-gate 			}
648*7c478bd9Sstevel@tonic-gate 		}
649*7c478bd9Sstevel@tonic-gate 	}
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	/* Do a direct lookup ? */
652*7c478bd9Sstevel@tonic-gate 	if (val == 0 && (check == rvThenLookup || check == lookupOnly)) {
653*7c478bd9Sstevel@tonic-gate 		if (item->type == mit_nisplus) {
654*7c478bd9Sstevel@tonic-gate 			val = lookupNisPlus(&item->searchSpec.obj, item->name,
655*7c478bd9Sstevel@tonic-gate 						rv);
656*7c478bd9Sstevel@tonic-gate 		} else if (item->type == mit_ldap) {
657*7c478bd9Sstevel@tonic-gate 			int	err = 0;
658*7c478bd9Sstevel@tonic-gate 			__nis_search_triple_t	triple;
659*7c478bd9Sstevel@tonic-gate 			char			*baseDN;
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 			/*
662*7c478bd9Sstevel@tonic-gate 			 * If item->searchSpec.triple.base is NULL, or ends
663*7c478bd9Sstevel@tonic-gate 			 * in a comma, append the current search base from
664*7c478bd9Sstevel@tonic-gate 			 * the TSD (put there by an upper layer).
665*7c478bd9Sstevel@tonic-gate 			 *
666*7c478bd9Sstevel@tonic-gate 			 * Special case for N2L mode:
667*7c478bd9Sstevel@tonic-gate 			 * if item->searchSpec.triple.base ends in a comma,
668*7c478bd9Sstevel@tonic-gate 			 * the current domain Context is used.
669*7c478bd9Sstevel@tonic-gate 			 */
670*7c478bd9Sstevel@tonic-gate 			if (yp2ldap && item->searchSpec.triple.base &&
671*7c478bd9Sstevel@tonic-gate 				strlen(item->searchSpec.triple.base) > 0) {
672*7c478bd9Sstevel@tonic-gate 				baseDN = __nisdb_get_tsd()->domainContext;
673*7c478bd9Sstevel@tonic-gate 			} else {
674*7c478bd9Sstevel@tonic-gate 				baseDN = __nisdb_get_tsd()->searchBase;
675*7c478bd9Sstevel@tonic-gate 			}
676*7c478bd9Sstevel@tonic-gate 			triple.base = appendBase(item->searchSpec.triple.base,
677*7c478bd9Sstevel@tonic-gate 				baseDN, &err, 0);
678*7c478bd9Sstevel@tonic-gate 			if (err == 0) {
679*7c478bd9Sstevel@tonic-gate 				triple.scope = item->searchSpec.triple.scope;
680*7c478bd9Sstevel@tonic-gate 				triple.attrs = item->searchSpec.triple.attrs;
681*7c478bd9Sstevel@tonic-gate 				triple.element =
682*7c478bd9Sstevel@tonic-gate 					item->searchSpec.triple.element;
683*7c478bd9Sstevel@tonic-gate 				val = lookupLDAP(&triple, item->name, rv, 0,
684*7c478bd9Sstevel@tonic-gate 					np_ldap_stat);
685*7c478bd9Sstevel@tonic-gate 				fromldap = '1';
686*7c478bd9Sstevel@tonic-gate 			} else {
687*7c478bd9Sstevel@tonic-gate 				val = 0;
688*7c478bd9Sstevel@tonic-gate 			}
689*7c478bd9Sstevel@tonic-gate 			sfree(triple.base);
690*7c478bd9Sstevel@tonic-gate 		}
691*7c478bd9Sstevel@tonic-gate 	}
692*7c478bd9Sstevel@tonic-gate 
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	/* Special processing for NIS to LDAP mode */
695*7c478bd9Sstevel@tonic-gate 	if (yp2ldap && val != 0) {
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 		/*
698*7c478bd9Sstevel@tonic-gate 		 * Escape special chars from dn before sending to DIT,
699*7c478bd9Sstevel@tonic-gate 		 * provided val is not ldap-based
700*7c478bd9Sstevel@tonic-gate 		 */
701*7c478bd9Sstevel@tonic-gate 		if (fromldap == '\0' && __nisdb_get_tsd()->escapeFlag == '1') {
702*7c478bd9Sstevel@tonic-gate 			if (escapeSpecialChars(val) < 0) {
703*7c478bd9Sstevel@tonic-gate 				freeValue(val, 1);
704*7c478bd9Sstevel@tonic-gate 				return (0);
705*7c478bd9Sstevel@tonic-gate 			}
706*7c478bd9Sstevel@tonic-gate 		} else if (__nisdb_get_tsd()->escapeFlag == '2') {
707*7c478bd9Sstevel@tonic-gate 			/* Remove escape chars from data received from DIT */
708*7c478bd9Sstevel@tonic-gate 			(void) removeEscapeChars(val);
709*7c478bd9Sstevel@tonic-gate 		}
710*7c478bd9Sstevel@tonic-gate 
711*7c478bd9Sstevel@tonic-gate 		/*
712*7c478bd9Sstevel@tonic-gate 		 * Remove from 'val', any values obtained using
713*7c478bd9Sstevel@tonic-gate 		 * the 'removespec' syntax
714*7c478bd9Sstevel@tonic-gate 		 */
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 		/* Obtain exVal */
717*7c478bd9Sstevel@tonic-gate 		if (item->exItem)
718*7c478bd9Sstevel@tonic-gate 			exVal = getMappingItemVal(item->exItem, native, rv,
719*7c478bd9Sstevel@tonic-gate 			    berstring, NULL);
720*7c478bd9Sstevel@tonic-gate 
721*7c478bd9Sstevel@tonic-gate 		/* delete */
722*7c478bd9Sstevel@tonic-gate 		if (exVal != 0) {
723*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < val->numVals; ) {
724*7c478bd9Sstevel@tonic-gate 				for (j = 0; j < exVal->numVals; j++) {
725*7c478bd9Sstevel@tonic-gate 					if (sstrncmp(val->val[i].value,
726*7c478bd9Sstevel@tonic-gate 							exVal->val[j].value,
727*7c478bd9Sstevel@tonic-gate 							MAX(val->val[i].length,
728*7c478bd9Sstevel@tonic-gate 							exVal->val[j].length))
729*7c478bd9Sstevel@tonic-gate 							== 0)
730*7c478bd9Sstevel@tonic-gate 						break;
731*7c478bd9Sstevel@tonic-gate 				}
732*7c478bd9Sstevel@tonic-gate 				if (j < exVal->numVals) {
733*7c478bd9Sstevel@tonic-gate 					sfree(val->val[i].value);
734*7c478bd9Sstevel@tonic-gate 					val->val[i].value = 0;
735*7c478bd9Sstevel@tonic-gate 					val->val[i].length = 0;
736*7c478bd9Sstevel@tonic-gate 					for (k = i; k < val->numVals - 1; k++) {
737*7c478bd9Sstevel@tonic-gate 						val->val[k] = val->val[k + 1];
738*7c478bd9Sstevel@tonic-gate 						val->val[k + 1].value = 0;
739*7c478bd9Sstevel@tonic-gate 						val->val[k + 1].length = 0;
740*7c478bd9Sstevel@tonic-gate 					}
741*7c478bd9Sstevel@tonic-gate 					val->numVals--;
742*7c478bd9Sstevel@tonic-gate 				} else
743*7c478bd9Sstevel@tonic-gate 					i++;
744*7c478bd9Sstevel@tonic-gate 			}
745*7c478bd9Sstevel@tonic-gate 
746*7c478bd9Sstevel@tonic-gate 			freeValue(exVal, 1);
747*7c478bd9Sstevel@tonic-gate 
748*7c478bd9Sstevel@tonic-gate 			/*
749*7c478bd9Sstevel@tonic-gate 			 * If val->numVals <= 0, then we have no val to
750*7c478bd9Sstevel@tonic-gate 			 * return. So free up stuff.
751*7c478bd9Sstevel@tonic-gate 			 */
752*7c478bd9Sstevel@tonic-gate 			if (val->numVals <= 0) {
753*7c478bd9Sstevel@tonic-gate 				free(val->val);
754*7c478bd9Sstevel@tonic-gate 				val->val = 0;
755*7c478bd9Sstevel@tonic-gate 				free(val);
756*7c478bd9Sstevel@tonic-gate 				return (0);
757*7c478bd9Sstevel@tonic-gate 			}
758*7c478bd9Sstevel@tonic-gate 		}
759*7c478bd9Sstevel@tonic-gate 	}
760*7c478bd9Sstevel@tonic-gate 
761*7c478bd9Sstevel@tonic-gate 	return (val);
762*7c478bd9Sstevel@tonic-gate }
763*7c478bd9Sstevel@tonic-gate 
764*7c478bd9Sstevel@tonic-gate __nis_value_t *
765*7c478bd9Sstevel@tonic-gate getMappingFormat(__nis_mapping_format_t *f, __nis_rule_value_t *rv,
766*7c478bd9Sstevel@tonic-gate 			__nis_format_arg_t at, void *a, int *numArg) {
767*7c478bd9Sstevel@tonic-gate 	char		*myself = "getMappingFormat";
768*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val = 0;
769*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
770*7c478bd9Sstevel@tonic-gate 	int		i;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	if (f == 0)
773*7c478bd9Sstevel@tonic-gate 		return (0);
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	if (rv == 0) {
776*7c478bd9Sstevel@tonic-gate 		val = am(myself, sizeof (*val));
777*7c478bd9Sstevel@tonic-gate 		if (val == 0)
778*7c478bd9Sstevel@tonic-gate 			return (0);
779*7c478bd9Sstevel@tonic-gate 
780*7c478bd9Sstevel@tonic-gate 		switch (f->type) {
781*7c478bd9Sstevel@tonic-gate 		case mmt_item:
782*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "%%s");
783*7c478bd9Sstevel@tonic-gate 			break;
784*7c478bd9Sstevel@tonic-gate 		case mmt_string:
785*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "%s", NIL(f->match.string));
786*7c478bd9Sstevel@tonic-gate 			break;
787*7c478bd9Sstevel@tonic-gate 		case mmt_single:
788*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "[");
789*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < f->match.single.numRange; i++) {
790*7c478bd9Sstevel@tonic-gate 				if (f->match.single.lo[i] ==
791*7c478bd9Sstevel@tonic-gate 						f->match.single.hi[i])
792*7c478bd9Sstevel@tonic-gate 					bp2buf(myself, &b, "%c",
793*7c478bd9Sstevel@tonic-gate 						f->match.single.lo[i]);
794*7c478bd9Sstevel@tonic-gate 				else
795*7c478bd9Sstevel@tonic-gate 					bp2buf(myself, &b, "%c-%c",
796*7c478bd9Sstevel@tonic-gate 						f->match.single.lo[i],
797*7c478bd9Sstevel@tonic-gate 						f->match.single.hi[i]);
798*7c478bd9Sstevel@tonic-gate 			}
799*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "]");
800*7c478bd9Sstevel@tonic-gate 			break;
801*7c478bd9Sstevel@tonic-gate 		case mmt_limit:
802*7c478bd9Sstevel@tonic-gate 			break;
803*7c478bd9Sstevel@tonic-gate 		case mmt_any:
804*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "*");
805*7c478bd9Sstevel@tonic-gate 			break;
806*7c478bd9Sstevel@tonic-gate 		case mmt_berstring:
807*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "%s", NIL(f->match.berString));
808*7c478bd9Sstevel@tonic-gate 			break;
809*7c478bd9Sstevel@tonic-gate 		case mmt_begin:
810*7c478bd9Sstevel@tonic-gate 		case mmt_end:
811*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "\"");
812*7c478bd9Sstevel@tonic-gate 			break;
813*7c478bd9Sstevel@tonic-gate 		default:
814*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "<unknown>");
815*7c478bd9Sstevel@tonic-gate 		}
816*7c478bd9Sstevel@tonic-gate 		val->type = vt_string;
817*7c478bd9Sstevel@tonic-gate 		val->numVals = 1;
818*7c478bd9Sstevel@tonic-gate 		val->val = am(myself, sizeof (val->val[0]));
819*7c478bd9Sstevel@tonic-gate 		if (val->val == 0) {
820*7c478bd9Sstevel@tonic-gate 			sfree(val);
821*7c478bd9Sstevel@tonic-gate 			return (0);
822*7c478bd9Sstevel@tonic-gate 		}
823*7c478bd9Sstevel@tonic-gate 		val->val[0].value = b.buf;
824*7c478bd9Sstevel@tonic-gate 		val->val[0].length = b.len;
825*7c478bd9Sstevel@tonic-gate 	} else {
826*7c478bd9Sstevel@tonic-gate 		switch (f->type) {
827*7c478bd9Sstevel@tonic-gate 		case mmt_item:
828*7c478bd9Sstevel@tonic-gate 		case mmt_berstring:
829*7c478bd9Sstevel@tonic-gate 			if (a != 0) {
830*7c478bd9Sstevel@tonic-gate 				if (at == fa_item) {
831*7c478bd9Sstevel@tonic-gate 					val = getMappingItemVal(
832*7c478bd9Sstevel@tonic-gate 						(__nis_mapping_item_t *)a,
833*7c478bd9Sstevel@tonic-gate 						mit_any, rv,
834*7c478bd9Sstevel@tonic-gate 		(f->type == mmt_berstring) ? f->match.berString : 0, NULL);
835*7c478bd9Sstevel@tonic-gate 					if (numArg != 0)
836*7c478bd9Sstevel@tonic-gate 						(*numArg)++;
837*7c478bd9Sstevel@tonic-gate 				} else {
838*7c478bd9Sstevel@tonic-gate 					val = cloneValue(
839*7c478bd9Sstevel@tonic-gate 						(__nis_value_t *)a, 1);
840*7c478bd9Sstevel@tonic-gate 					if (numArg != 0)
841*7c478bd9Sstevel@tonic-gate 						(*numArg)++;
842*7c478bd9Sstevel@tonic-gate 				}
843*7c478bd9Sstevel@tonic-gate 			}
844*7c478bd9Sstevel@tonic-gate 			break;
845*7c478bd9Sstevel@tonic-gate 		case mmt_string:
846*7c478bd9Sstevel@tonic-gate 			val = am(myself, sizeof (*val));
847*7c478bd9Sstevel@tonic-gate 			if (val == 0)
848*7c478bd9Sstevel@tonic-gate 				return (0);
849*7c478bd9Sstevel@tonic-gate 			val->type = vt_string;
850*7c478bd9Sstevel@tonic-gate 			val->numVals = 1;
851*7c478bd9Sstevel@tonic-gate 			val->val = am(myself, sizeof (val->val[0]));
852*7c478bd9Sstevel@tonic-gate 			if (val->val == 0) {
853*7c478bd9Sstevel@tonic-gate 				sfree(val);
854*7c478bd9Sstevel@tonic-gate 				return (0);
855*7c478bd9Sstevel@tonic-gate 			}
856*7c478bd9Sstevel@tonic-gate 			val->val[0].value = sdup(myself, T, f->match.string);
857*7c478bd9Sstevel@tonic-gate 			val->val[0].length = strlen(val->val[0].value);
858*7c478bd9Sstevel@tonic-gate 			break;
859*7c478bd9Sstevel@tonic-gate 		case mmt_single:
860*7c478bd9Sstevel@tonic-gate 		case mmt_limit:
861*7c478bd9Sstevel@tonic-gate 		case mmt_any:
862*7c478bd9Sstevel@tonic-gate 		case mmt_begin:
863*7c478bd9Sstevel@tonic-gate 		case mmt_end:
864*7c478bd9Sstevel@tonic-gate 			/* Not an error, so return an empty value */
865*7c478bd9Sstevel@tonic-gate 			val = am(myself, sizeof (*val));
866*7c478bd9Sstevel@tonic-gate 			if (val == 0)
867*7c478bd9Sstevel@tonic-gate 				return (0);
868*7c478bd9Sstevel@tonic-gate 			val->type = vt_string;
869*7c478bd9Sstevel@tonic-gate 			val->numVals = 0;
870*7c478bd9Sstevel@tonic-gate 			val->val = 0;
871*7c478bd9Sstevel@tonic-gate 			break;
872*7c478bd9Sstevel@tonic-gate 		default:
873*7c478bd9Sstevel@tonic-gate 			/* Do nothing */
874*7c478bd9Sstevel@tonic-gate 			val = 0;
875*7c478bd9Sstevel@tonic-gate 			break;
876*7c478bd9Sstevel@tonic-gate 		}
877*7c478bd9Sstevel@tonic-gate 	}
878*7c478bd9Sstevel@tonic-gate 	return (val);
879*7c478bd9Sstevel@tonic-gate }
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate /*
882*7c478bd9Sstevel@tonic-gate  * Used when evaluating an expression. Typically, the value of the
883*7c478bd9Sstevel@tonic-gate  * expression so far will be kept in 'v1', and 'v2' is the value
884*7c478bd9Sstevel@tonic-gate  * of the current component of the expression. In the general case,
885*7c478bd9Sstevel@tonic-gate  * both will be multi-valued, and the result is an "explosion"
886*7c478bd9Sstevel@tonic-gate  * resulting in N*M new values (if 'v1' had N values, and 'v2'
887*7c478bd9Sstevel@tonic-gate  * M ditto).
888*7c478bd9Sstevel@tonic-gate  *
889*7c478bd9Sstevel@tonic-gate  * For example, if v1 = {"ab", "cd", "ef"}, and v2 = {"gh", "ij", "kl"},
890*7c478bd9Sstevel@tonic-gate  * the result will be {"abgh", "abij", "abkl", "cdgh", "cdij", "cdkl",
891*7c478bd9Sstevel@tonic-gate  * "efgh", "efij", "efkl"}.
892*7c478bd9Sstevel@tonic-gate  *
893*7c478bd9Sstevel@tonic-gate  * There are special cases when v1->repeat and/or v2->repeat are set.
894*7c478bd9Sstevel@tonic-gate  * Repeat mostly makes sense with single values; for example, if
895*7c478bd9Sstevel@tonic-gate  * v1 = {"x="} with repeat on, and v2 = {"1", "2", "3"}, the result
896*7c478bd9Sstevel@tonic-gate  * is {"x=1", "x=2", "x=3"}.
897*7c478bd9Sstevel@tonic-gate  *
898*7c478bd9Sstevel@tonic-gate  * The result if v2 also had repeat on would be {"x=1x=2x=3"}. It's
899*7c478bd9Sstevel@tonic-gate  * not clear if there's a useful application for this, but the code's
900*7c478bd9Sstevel@tonic-gate  * there for the sake of orthogonality.
901*7c478bd9Sstevel@tonic-gate  */
902*7c478bd9Sstevel@tonic-gate __nis_value_t *
903*7c478bd9Sstevel@tonic-gate explodeValues(__nis_value_t *v1, __nis_value_t *v2) {
904*7c478bd9Sstevel@tonic-gate 	int		i1, i2, n, nv;
905*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*v;
906*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
907*7c478bd9Sstevel@tonic-gate 	char		*myself = "explodeValues";
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	if (v1 == 0 || v1->numVals <= 0)
910*7c478bd9Sstevel@tonic-gate 		return (cloneValue(v2, 1));
911*7c478bd9Sstevel@tonic-gate 	if (v2 == 0 || v2->numVals <= 0)
912*7c478bd9Sstevel@tonic-gate 		return (cloneValue(v1, 1));
913*7c478bd9Sstevel@tonic-gate 
914*7c478bd9Sstevel@tonic-gate 	/*
915*7c478bd9Sstevel@tonic-gate 	 * XXX What should we do if (v1->type != v2->type) ?
916*7c478bd9Sstevel@tonic-gate 	 * Policy: Just explode anyway, even though the result is
917*7c478bd9Sstevel@tonic-gate 	 * unlikely to be very useful.
918*7c478bd9Sstevel@tonic-gate 	 */
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate 	v = am(myself, sizeof (*v));
921*7c478bd9Sstevel@tonic-gate 	if (v == 0)
922*7c478bd9Sstevel@tonic-gate 		return (0);
923*7c478bd9Sstevel@tonic-gate 
924*7c478bd9Sstevel@tonic-gate 	if (!v1->repeat && !v2->repeat)
925*7c478bd9Sstevel@tonic-gate 		nv = v1->numVals * v2->numVals;
926*7c478bd9Sstevel@tonic-gate 	else if (v1->repeat && !v2->repeat)
927*7c478bd9Sstevel@tonic-gate 		nv = v2->numVals;
928*7c478bd9Sstevel@tonic-gate 	else if (!v1->repeat && v2->repeat)
929*7c478bd9Sstevel@tonic-gate 		nv = v1->numVals;
930*7c478bd9Sstevel@tonic-gate 	else /* v1->repeat && v2->repeat */
931*7c478bd9Sstevel@tonic-gate 		nv = 1;
932*7c478bd9Sstevel@tonic-gate 
933*7c478bd9Sstevel@tonic-gate 	v->val = am(myself, nv * sizeof (v->val[0]));
934*7c478bd9Sstevel@tonic-gate 	if (v->val == 0) {
935*7c478bd9Sstevel@tonic-gate 		free(v);
936*7c478bd9Sstevel@tonic-gate 		return (0);
937*7c478bd9Sstevel@tonic-gate 	}
938*7c478bd9Sstevel@tonic-gate 
939*7c478bd9Sstevel@tonic-gate 	/*
940*7c478bd9Sstevel@tonic-gate 	 * Four different cases, depending on the 'repeat' flags.
941*7c478bd9Sstevel@tonic-gate 	 */
942*7c478bd9Sstevel@tonic-gate 	if (!v1->repeat && !v2->repeat) {
943*7c478bd9Sstevel@tonic-gate 		for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
944*7c478bd9Sstevel@tonic-gate 			for (i2 = 0; i2 < v2->numVals; i2++) {
945*7c478bd9Sstevel@tonic-gate 				if (v1->type == vt_string)
946*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v1->val[i1].value,
947*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
948*7c478bd9Sstevel@tonic-gate 						&b);
949*7c478bd9Sstevel@tonic-gate 				else
950*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v1->val[i1].value,
951*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
952*7c478bd9Sstevel@tonic-gate 						&b);
953*7c478bd9Sstevel@tonic-gate 				if (v2->type == vt_string)
954*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v2->val[i2].value,
955*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
956*7c478bd9Sstevel@tonic-gate 						&b);
957*7c478bd9Sstevel@tonic-gate 				else
958*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v2->val[i2].value,
959*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
960*7c478bd9Sstevel@tonic-gate 						&b);
961*7c478bd9Sstevel@tonic-gate 				v->val[n].value = b.buf;
962*7c478bd9Sstevel@tonic-gate 				v->val[n].length = b.len;
963*7c478bd9Sstevel@tonic-gate 				n++;
964*7c478bd9Sstevel@tonic-gate 				b.buf = 0;
965*7c478bd9Sstevel@tonic-gate 				b.len = 0;
966*7c478bd9Sstevel@tonic-gate 			}
967*7c478bd9Sstevel@tonic-gate 		}
968*7c478bd9Sstevel@tonic-gate 	} else if (v1->repeat && !v2->repeat) {
969*7c478bd9Sstevel@tonic-gate 		for (i2 = 0; i2 < v2->numVals; i2++) {
970*7c478bd9Sstevel@tonic-gate 			for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
971*7c478bd9Sstevel@tonic-gate 				if (v1->type == vt_string)
972*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v1->val[i1].value,
973*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
974*7c478bd9Sstevel@tonic-gate 						&b);
975*7c478bd9Sstevel@tonic-gate 				else
976*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v1->val[i1].value,
977*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
978*7c478bd9Sstevel@tonic-gate 						&b);
979*7c478bd9Sstevel@tonic-gate 				if (v2->type == vt_string)
980*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v2->val[i2].value,
981*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
982*7c478bd9Sstevel@tonic-gate 						&b);
983*7c478bd9Sstevel@tonic-gate 				else
984*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v2->val[i2].value,
985*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
986*7c478bd9Sstevel@tonic-gate 						&b);
987*7c478bd9Sstevel@tonic-gate 			}
988*7c478bd9Sstevel@tonic-gate 			v->val[n].value = b.buf;
989*7c478bd9Sstevel@tonic-gate 			v->val[n].length = b.len;
990*7c478bd9Sstevel@tonic-gate 			n++;
991*7c478bd9Sstevel@tonic-gate 			b.buf = 0;
992*7c478bd9Sstevel@tonic-gate 			b.len = 0;
993*7c478bd9Sstevel@tonic-gate 		}
994*7c478bd9Sstevel@tonic-gate 	} else if (!v1->repeat && v2->repeat) {
995*7c478bd9Sstevel@tonic-gate 		for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
996*7c478bd9Sstevel@tonic-gate 			for (i2 = 0; i2 < v2->numVals; i2++) {
997*7c478bd9Sstevel@tonic-gate 				if (v1->type == vt_string)
998*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v1->val[i1].value,
999*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
1000*7c478bd9Sstevel@tonic-gate 						&b);
1001*7c478bd9Sstevel@tonic-gate 				else
1002*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v1->val[i1].value,
1003*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
1004*7c478bd9Sstevel@tonic-gate 						&b);
1005*7c478bd9Sstevel@tonic-gate 				if (v2->type == vt_string)
1006*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v2->val[i2].value,
1007*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
1008*7c478bd9Sstevel@tonic-gate 						&b);
1009*7c478bd9Sstevel@tonic-gate 				else
1010*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v2->val[i2].value,
1011*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
1012*7c478bd9Sstevel@tonic-gate 						&b);
1013*7c478bd9Sstevel@tonic-gate 			}
1014*7c478bd9Sstevel@tonic-gate 			v->val[n].value = b.buf;
1015*7c478bd9Sstevel@tonic-gate 			v->val[n].length = b.len;
1016*7c478bd9Sstevel@tonic-gate 			n++;
1017*7c478bd9Sstevel@tonic-gate 			b.buf = 0;
1018*7c478bd9Sstevel@tonic-gate 			b.len = 0;
1019*7c478bd9Sstevel@tonic-gate 		}
1020*7c478bd9Sstevel@tonic-gate 	} else { /* v1->repeat && v2->repeat */
1021*7c478bd9Sstevel@tonic-gate 		for (i1 = 0, n = 0; i1 < v1->numVals; i1++) {
1022*7c478bd9Sstevel@tonic-gate 			for (i2 = 0; i2 < v2->numVals; i2++) {
1023*7c478bd9Sstevel@tonic-gate 				if (v1->type == vt_string)
1024*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v1->val[i1].value,
1025*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
1026*7c478bd9Sstevel@tonic-gate 						&b);
1027*7c478bd9Sstevel@tonic-gate 				else
1028*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v1->val[i1].value,
1029*7c478bd9Sstevel@tonic-gate 						v1->val[i1].length,
1030*7c478bd9Sstevel@tonic-gate 						&b);
1031*7c478bd9Sstevel@tonic-gate 				if (v2->type == vt_string)
1032*7c478bd9Sstevel@tonic-gate 					sbc2buf(myself, v2->val[i2].value,
1033*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
1034*7c478bd9Sstevel@tonic-gate 						&b);
1035*7c478bd9Sstevel@tonic-gate 				else
1036*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, v2->val[i2].value,
1037*7c478bd9Sstevel@tonic-gate 						v2->val[i2].length,
1038*7c478bd9Sstevel@tonic-gate 						&b);
1039*7c478bd9Sstevel@tonic-gate 			}
1040*7c478bd9Sstevel@tonic-gate 		}
1041*7c478bd9Sstevel@tonic-gate 		v->val[n].value = b.buf;
1042*7c478bd9Sstevel@tonic-gate 		v->val[n].length = b.len;
1043*7c478bd9Sstevel@tonic-gate 		n++;
1044*7c478bd9Sstevel@tonic-gate 		b.buf = 0;
1045*7c478bd9Sstevel@tonic-gate 		b.len = 0;
1046*7c478bd9Sstevel@tonic-gate 	}
1047*7c478bd9Sstevel@tonic-gate 
1048*7c478bd9Sstevel@tonic-gate #ifdef	NISDB_LDAP_DEBUG
1049*7c478bd9Sstevel@tonic-gate 	/* Sanity check */
1050*7c478bd9Sstevel@tonic-gate 	if (n != nv)
1051*7c478bd9Sstevel@tonic-gate 		abort();
1052*7c478bd9Sstevel@tonic-gate #endif	/* NISD__LDAP_DEBUG */
1053*7c478bd9Sstevel@tonic-gate 
1054*7c478bd9Sstevel@tonic-gate 	v->type = (v1->type == vt_string) ?
1055*7c478bd9Sstevel@tonic-gate 			((v2->type == vt_string) ?
1056*7c478bd9Sstevel@tonic-gate 				vt_string : vt_ber) : vt_ber;
1057*7c478bd9Sstevel@tonic-gate 	v->repeat = 0;
1058*7c478bd9Sstevel@tonic-gate 	v->numVals = n;
1059*7c478bd9Sstevel@tonic-gate 
1060*7c478bd9Sstevel@tonic-gate 	return (v);
1061*7c478bd9Sstevel@tonic-gate }
1062*7c478bd9Sstevel@tonic-gate 
1063*7c478bd9Sstevel@tonic-gate __nis_value_t *
1064*7c478bd9Sstevel@tonic-gate getMappingFormatArray(__nis_mapping_format_t *a, __nis_rule_value_t *rv,
1065*7c478bd9Sstevel@tonic-gate 			__nis_format_arg_t at, int numArgs, void *arg) {
1066*7c478bd9Sstevel@tonic-gate 	int			i, ia = 0;
1067*7c478bd9Sstevel@tonic-gate 	__nis_value_t		*val, *v = 0;
1068*7c478bd9Sstevel@tonic-gate 	bool_t			moreFormat = (a != 0);
1069*7c478bd9Sstevel@tonic-gate 	bool_t			moreArgs = (numArgs > 0);
1070*7c478bd9Sstevel@tonic-gate 
1071*7c478bd9Sstevel@tonic-gate 	while (moreFormat && (arg == 0 || ia < numArgs)) {
1072*7c478bd9Sstevel@tonic-gate 		for (i = 0; moreFormat; i++) {
1073*7c478bd9Sstevel@tonic-gate 			moreFormat = (a[i].type != mmt_end);
1074*7c478bd9Sstevel@tonic-gate 			if (at == fa_item) {
1075*7c478bd9Sstevel@tonic-gate 				__nis_mapping_item_t *item = arg;
1076*7c478bd9Sstevel@tonic-gate 				val = getMappingFormat(&a[i], rv, at,
1077*7c478bd9Sstevel@tonic-gate 					((item != 0) ? &item[ia] : 0), &ia);
1078*7c478bd9Sstevel@tonic-gate 			} else {
1079*7c478bd9Sstevel@tonic-gate 				__nis_value_t **ival = arg;
1080*7c478bd9Sstevel@tonic-gate 				val = getMappingFormat(&a[i], rv, at,
1081*7c478bd9Sstevel@tonic-gate 					((ival != 0) ? ival[ia] : 0), &ia);
1082*7c478bd9Sstevel@tonic-gate 			}
1083*7c478bd9Sstevel@tonic-gate 			if (val != 0) {
1084*7c478bd9Sstevel@tonic-gate 				__nis_value_t	*new = explodeValues(v, val);
1085*7c478bd9Sstevel@tonic-gate 
1086*7c478bd9Sstevel@tonic-gate 				freeValue(v, 1);
1087*7c478bd9Sstevel@tonic-gate 				freeValue(val, 1);
1088*7c478bd9Sstevel@tonic-gate 				if (new == 0)
1089*7c478bd9Sstevel@tonic-gate 					return (0);
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate 				v = new;
1092*7c478bd9Sstevel@tonic-gate 			} else {
1093*7c478bd9Sstevel@tonic-gate 				freeValue(v, 1);
1094*7c478bd9Sstevel@tonic-gate 				return (0);
1095*7c478bd9Sstevel@tonic-gate 			}
1096*7c478bd9Sstevel@tonic-gate 			/*
1097*7c478bd9Sstevel@tonic-gate 			 * If we run out of arguments, but still have format
1098*7c478bd9Sstevel@tonic-gate 			 * remaining, repeat the last argument. Keep track of
1099*7c478bd9Sstevel@tonic-gate 			 * the fact that we've really consumed all arguments.
1100*7c478bd9Sstevel@tonic-gate 			 */
1101*7c478bd9Sstevel@tonic-gate 			if (moreFormat && ia >= numArgs) {
1102*7c478bd9Sstevel@tonic-gate 				ia = (numArgs > 0) ? numArgs - 1 : 0;
1103*7c478bd9Sstevel@tonic-gate 				moreArgs = FALSE;
1104*7c478bd9Sstevel@tonic-gate 			}
1105*7c478bd9Sstevel@tonic-gate 		}
1106*7c478bd9Sstevel@tonic-gate 		/*
1107*7c478bd9Sstevel@tonic-gate 		 * We've run out of format, so if we still have arguments
1108*7c478bd9Sstevel@tonic-gate 		 * left, start over on the format.
1109*7c478bd9Sstevel@tonic-gate 		 */
1110*7c478bd9Sstevel@tonic-gate 		if (ia < numArgs && moreArgs) {
1111*7c478bd9Sstevel@tonic-gate 			/*
1112*7c478bd9Sstevel@tonic-gate 			 * However, if we didn't consume any arguments going
1113*7c478bd9Sstevel@tonic-gate 			 * through the format once, abort to avoid an infinite
1114*7c478bd9Sstevel@tonic-gate 			 * loop.
1115*7c478bd9Sstevel@tonic-gate 			 */
1116*7c478bd9Sstevel@tonic-gate 			if (numArgs > 0 && ia <= 0) {
1117*7c478bd9Sstevel@tonic-gate 				freeValue(v, 1);
1118*7c478bd9Sstevel@tonic-gate 				return (0);
1119*7c478bd9Sstevel@tonic-gate 			}
1120*7c478bd9Sstevel@tonic-gate 			moreFormat = 1;
1121*7c478bd9Sstevel@tonic-gate 		}
1122*7c478bd9Sstevel@tonic-gate 	}
1123*7c478bd9Sstevel@tonic-gate 
1124*7c478bd9Sstevel@tonic-gate 	return (v);
1125*7c478bd9Sstevel@tonic-gate }
1126*7c478bd9Sstevel@tonic-gate 
1127*7c478bd9Sstevel@tonic-gate /*
1128*7c478bd9Sstevel@tonic-gate  * Returns a string representation (such as "[name=foo, value=bar]")
1129*7c478bd9Sstevel@tonic-gate  * of a nis_index_t.
1130*7c478bd9Sstevel@tonic-gate  */
1131*7c478bd9Sstevel@tonic-gate char *
1132*7c478bd9Sstevel@tonic-gate getIndex(__nis_index_t *i, int *len) {
1133*7c478bd9Sstevel@tonic-gate 	int		n;
1134*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
1135*7c478bd9Sstevel@tonic-gate 	char		*myself = "getIndex";
1136*7c478bd9Sstevel@tonic-gate 
1137*7c478bd9Sstevel@tonic-gate 	if (i == 0)
1138*7c478bd9Sstevel@tonic-gate 		return (0);
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 	if (i->numIndexes > 0) {
1141*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, "[");
1142*7c478bd9Sstevel@tonic-gate 		for (n = 0; n < i->numIndexes; n++) {
1143*7c478bd9Sstevel@tonic-gate 			__nis_value_t	*val;
1144*7c478bd9Sstevel@tonic-gate 			int		j;
1145*7c478bd9Sstevel@tonic-gate 
1146*7c478bd9Sstevel@tonic-gate 			val = getMappingFormatArray(i->value[n],
1147*7c478bd9Sstevel@tonic-gate 						0, fa_any, 0, 0);
1148*7c478bd9Sstevel@tonic-gate 			if (n > 0)
1149*7c478bd9Sstevel@tonic-gate 				bp2buf(myself, &b, ", ");
1150*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "%s=", i->name[n]);
1151*7c478bd9Sstevel@tonic-gate 			if (val != 0) {
1152*7c478bd9Sstevel@tonic-gate 				for (j = 0; j < val->numVals; j++) {
1153*7c478bd9Sstevel@tonic-gate 					bc2buf(myself, val->val[j].value,
1154*7c478bd9Sstevel@tonic-gate 						val->val[j].length, &b);
1155*7c478bd9Sstevel@tonic-gate 				}
1156*7c478bd9Sstevel@tonic-gate 			} else {
1157*7c478bd9Sstevel@tonic-gate 				bp2buf(myself, &b, "<no-vals>");
1158*7c478bd9Sstevel@tonic-gate 			}
1159*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
1160*7c478bd9Sstevel@tonic-gate 		}
1161*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, "]");
1162*7c478bd9Sstevel@tonic-gate 	}
1163*7c478bd9Sstevel@tonic-gate 	if (len != 0)
1164*7c478bd9Sstevel@tonic-gate 		*len = b.len;
1165*7c478bd9Sstevel@tonic-gate 	return (b.buf);
1166*7c478bd9Sstevel@tonic-gate }
1167*7c478bd9Sstevel@tonic-gate 
1168*7c478bd9Sstevel@tonic-gate char *
1169*7c478bd9Sstevel@tonic-gate getObjSpec(__nis_obj_spec_t *o, int *len) {
1170*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
1171*7c478bd9Sstevel@tonic-gate 	char		*myself = "getObjSpec";
1172*7c478bd9Sstevel@tonic-gate 
1173*7c478bd9Sstevel@tonic-gate 	if (o == 0)
1174*7c478bd9Sstevel@tonic-gate 		return (0);
1175*7c478bd9Sstevel@tonic-gate 
1176*7c478bd9Sstevel@tonic-gate 	b.buf = getIndex(&o->index, &b.len);
1177*7c478bd9Sstevel@tonic-gate 	sbc2buf(myself, o->name, slen(o->name), &b);
1178*7c478bd9Sstevel@tonic-gate 	if (len != 0)
1179*7c478bd9Sstevel@tonic-gate 		*len = b.len;
1180*7c478bd9Sstevel@tonic-gate 	return (b.buf);
1181*7c478bd9Sstevel@tonic-gate }
1182*7c478bd9Sstevel@tonic-gate 
1183*7c478bd9Sstevel@tonic-gate /*
1184*7c478bd9Sstevel@tonic-gate  * Returns a string representation of the LDAP scope. Note that the
1185*7c478bd9Sstevel@tonic-gate  * returned value is a static entity, and must be copied by the
1186*7c478bd9Sstevel@tonic-gate  * caller (but, obviously, must not be freed).
1187*7c478bd9Sstevel@tonic-gate  */
1188*7c478bd9Sstevel@tonic-gate char *
1189*7c478bd9Sstevel@tonic-gate getScope(int scope) {
1190*7c478bd9Sstevel@tonic-gate 	switch (scope) {
1191*7c478bd9Sstevel@tonic-gate 	case LDAP_SCOPE_BASE:
1192*7c478bd9Sstevel@tonic-gate 		return ("base");
1193*7c478bd9Sstevel@tonic-gate 	case LDAP_SCOPE_ONELEVEL:
1194*7c478bd9Sstevel@tonic-gate 		return ("one");
1195*7c478bd9Sstevel@tonic-gate 	case LDAP_SCOPE_SUBTREE:
1196*7c478bd9Sstevel@tonic-gate 		return ("sub");
1197*7c478bd9Sstevel@tonic-gate 	default:
1198*7c478bd9Sstevel@tonic-gate 		return ("one");
1199*7c478bd9Sstevel@tonic-gate 	}
1200*7c478bd9Sstevel@tonic-gate }
1201*7c478bd9Sstevel@tonic-gate 
1202*7c478bd9Sstevel@tonic-gate /*
1203*7c478bd9Sstevel@tonic-gate  * Return a string representation of an LDAP search triple (such as
1204*7c478bd9Sstevel@tonic-gate  * "ou=Hosts,dc=eng,dc=sun,dc=com?one?cn=xyzzy").
1205*7c478bd9Sstevel@tonic-gate  */
1206*7c478bd9Sstevel@tonic-gate char *
1207*7c478bd9Sstevel@tonic-gate getSearchTriple(__nis_search_triple_t *s, int *len) {
1208*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
1209*7c478bd9Sstevel@tonic-gate 	char		*a;
1210*7c478bd9Sstevel@tonic-gate 	int		l;
1211*7c478bd9Sstevel@tonic-gate 	char		*myself = "getSearchTriple";
1212*7c478bd9Sstevel@tonic-gate 
1213*7c478bd9Sstevel@tonic-gate 	/* If the scope is LDAP_SCOPE_UNKNOWN, the search triple is unused */
1214*7c478bd9Sstevel@tonic-gate 	if (s == 0 || s->scope == LDAP_SCOPE_UNKNOWN) {
1215*7c478bd9Sstevel@tonic-gate 		if (len != 0)
1216*7c478bd9Sstevel@tonic-gate 			*len = 0;
1217*7c478bd9Sstevel@tonic-gate 		return (0);
1218*7c478bd9Sstevel@tonic-gate 	}
1219*7c478bd9Sstevel@tonic-gate 
1220*7c478bd9Sstevel@tonic-gate 	if (s->base != 0)
1221*7c478bd9Sstevel@tonic-gate 		sbc2buf(myself, s->base, slen(s->base), &b);
1222*7c478bd9Sstevel@tonic-gate 	if (!(s->scope == LDAP_SCOPE_ONELEVEL &&
1223*7c478bd9Sstevel@tonic-gate 			(s->base == 0 || s->base[0] == '\0'))) {
1224*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, "?%s?", getScope(s->scope));
1225*7c478bd9Sstevel@tonic-gate 	}
1226*7c478bd9Sstevel@tonic-gate 	if ((l = slen(s->attrs)) > 0) {
1227*7c478bd9Sstevel@tonic-gate 		/*
1228*7c478bd9Sstevel@tonic-gate 		 * Remove white space from the filter/attribute list.
1229*7c478bd9Sstevel@tonic-gate 		 * The parser usually keeps any white space from the
1230*7c478bd9Sstevel@tonic-gate 		 * config file (or LDAP/command line), but we don't
1231*7c478bd9Sstevel@tonic-gate 		 * want it.
1232*7c478bd9Sstevel@tonic-gate 		 */
1233*7c478bd9Sstevel@tonic-gate 		a = am(myself, l+1);
1234*7c478bd9Sstevel@tonic-gate 		if (a != 0) {
1235*7c478bd9Sstevel@tonic-gate 			int	i, la;
1236*7c478bd9Sstevel@tonic-gate 
1237*7c478bd9Sstevel@tonic-gate 			for (i = 0, la = 0; i < l; i++) {
1238*7c478bd9Sstevel@tonic-gate 				if (s->attrs[i] != ' ' &&
1239*7c478bd9Sstevel@tonic-gate 						s->attrs[i] != '\t')
1240*7c478bd9Sstevel@tonic-gate 					a[la++] = s->attrs[i];
1241*7c478bd9Sstevel@tonic-gate 			}
1242*7c478bd9Sstevel@tonic-gate 			sbc2buf(myself, a, la, &b);
1243*7c478bd9Sstevel@tonic-gate 			sfree(a);
1244*7c478bd9Sstevel@tonic-gate 		} else {
1245*7c478bd9Sstevel@tonic-gate 			sbc2buf(myself, s->attrs, slen(s->attrs), &b);
1246*7c478bd9Sstevel@tonic-gate 		}
1247*7c478bd9Sstevel@tonic-gate 	}
1248*7c478bd9Sstevel@tonic-gate 
1249*7c478bd9Sstevel@tonic-gate 	if (len != 0)
1250*7c478bd9Sstevel@tonic-gate 		*len = b.len;
1251*7c478bd9Sstevel@tonic-gate 	return (b.buf);
1252*7c478bd9Sstevel@tonic-gate }
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate __nis_value_t *
1255*7c478bd9Sstevel@tonic-gate getMappingItem(__nis_mapping_item_t *i, __nis_mapping_item_type_t native,
1256*7c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv, char *berstring, int *np_ldap_stat) {
1257*7c478bd9Sstevel@tonic-gate 	char		*myself = "getMappingItem";
1258*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val = 0;
1259*7c478bd9Sstevel@tonic-gate 	__nis_buffer_t	b = {0, 0};
1260*7c478bd9Sstevel@tonic-gate 	int		len = 0;
1261*7c478bd9Sstevel@tonic-gate 	char		*buf;
1262*7c478bd9Sstevel@tonic-gate 
1263*7c478bd9Sstevel@tonic-gate 	if (i == 0)
1264*7c478bd9Sstevel@tonic-gate 		return (0);
1265*7c478bd9Sstevel@tonic-gate 
1266*7c478bd9Sstevel@tonic-gate 	if (rv != 0)
1267*7c478bd9Sstevel@tonic-gate 		return (getMappingItemVal(i, native, rv, berstring,
1268*7c478bd9Sstevel@tonic-gate 			np_ldap_stat));
1269*7c478bd9Sstevel@tonic-gate 
1270*7c478bd9Sstevel@tonic-gate 	val = am(myself, sizeof (*val));
1271*7c478bd9Sstevel@tonic-gate 	if (val == 0)
1272*7c478bd9Sstevel@tonic-gate 		return (0);
1273*7c478bd9Sstevel@tonic-gate 
1274*7c478bd9Sstevel@tonic-gate 	switch (i->type) {
1275*7c478bd9Sstevel@tonic-gate 	case mit_nisplus:
1276*7c478bd9Sstevel@tonic-gate 		if (native != mit_nisplus)
1277*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "nis+:");
1278*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, "%s", NIL(i->name));
1279*7c478bd9Sstevel@tonic-gate 		buf = getObjSpec(&i->searchSpec.obj, &len);
1280*7c478bd9Sstevel@tonic-gate 		if (buf != 0 && len > 0) {
1281*7c478bd9Sstevel@tonic-gate 			bc2buf(myself, ":", 1, &b);
1282*7c478bd9Sstevel@tonic-gate 			sbc2buf(myself, buf, len, &b);
1283*7c478bd9Sstevel@tonic-gate 		}
1284*7c478bd9Sstevel@tonic-gate 		sfree(buf);
1285*7c478bd9Sstevel@tonic-gate 		val->type = vt_string;
1286*7c478bd9Sstevel@tonic-gate 		val->repeat = i->repeat;
1287*7c478bd9Sstevel@tonic-gate 		val->numVals = 1;
1288*7c478bd9Sstevel@tonic-gate 		val->val = am(myself, sizeof (val->val[0]));
1289*7c478bd9Sstevel@tonic-gate 		if (val->val == 0) {
1290*7c478bd9Sstevel@tonic-gate 			sfree(b.buf);
1291*7c478bd9Sstevel@tonic-gate 			free(val);
1292*7c478bd9Sstevel@tonic-gate 			return (0);
1293*7c478bd9Sstevel@tonic-gate 		}
1294*7c478bd9Sstevel@tonic-gate 		val->val[0].value = b.buf;
1295*7c478bd9Sstevel@tonic-gate 		val->val[0].length = b.len;
1296*7c478bd9Sstevel@tonic-gate 		break;
1297*7c478bd9Sstevel@tonic-gate 	case mit_ldap:
1298*7c478bd9Sstevel@tonic-gate 		if (native != mit_ldap)
1299*7c478bd9Sstevel@tonic-gate 			bp2buf(myself, &b, "ldap:");
1300*7c478bd9Sstevel@tonic-gate 		bp2buf(myself, &b, "%s", NIL(i->name));
1301*7c478bd9Sstevel@tonic-gate 		buf = getSearchTriple(&i->searchSpec.triple, &len);
1302*7c478bd9Sstevel@tonic-gate 		if (buf != 0 && len > 0) {
1303*7c478bd9Sstevel@tonic-gate 			bc2buf(myself, ":", 1, &b);
1304*7c478bd9Sstevel@tonic-gate 			sbc2buf(myself, buf, len, &b);
1305*7c478bd9Sstevel@tonic-gate 		}
1306*7c478bd9Sstevel@tonic-gate 		sfree(buf);
1307*7c478bd9Sstevel@tonic-gate 		val->type = vt_string;
1308*7c478bd9Sstevel@tonic-gate 		val->repeat = i->repeat;
1309*7c478bd9Sstevel@tonic-gate 		val->numVals = 1;
1310*7c478bd9Sstevel@tonic-gate 		val->val = am(myself, sizeof (val->val[0]));
1311*7c478bd9Sstevel@tonic-gate 		if (val->val == 0) {
1312*7c478bd9Sstevel@tonic-gate 			sfree(b.buf);
1313*7c478bd9Sstevel@tonic-gate 			free(val);
1314*7c478bd9Sstevel@tonic-gate 			return (0);
1315*7c478bd9Sstevel@tonic-gate 		}
1316*7c478bd9Sstevel@tonic-gate 		val->val[0].value = b.buf;
1317*7c478bd9Sstevel@tonic-gate 		val->val[0].length = b.len;
1318*7c478bd9Sstevel@tonic-gate 		break;
1319*7c478bd9Sstevel@tonic-gate 	default:
1320*7c478bd9Sstevel@tonic-gate 		p2buf(myself, "<unknown>:");
1321*7c478bd9Sstevel@tonic-gate 		p2buf(myself, "%s", NIL(i->name));
1322*7c478bd9Sstevel@tonic-gate 		break;
1323*7c478bd9Sstevel@tonic-gate 	}
1324*7c478bd9Sstevel@tonic-gate 
1325*7c478bd9Sstevel@tonic-gate 	return (val);
1326*7c478bd9Sstevel@tonic-gate }
1327*7c478bd9Sstevel@tonic-gate 
1328*7c478bd9Sstevel@tonic-gate void
1329*7c478bd9Sstevel@tonic-gate copyObjSpec(__nis_obj_spec_t *old, __nis_obj_spec_t *new, int *err) {
1330*7c478bd9Sstevel@tonic-gate 	char	*myself = "copyObjSpec";
1331*7c478bd9Sstevel@tonic-gate 
1332*7c478bd9Sstevel@tonic-gate 	if (old == 0 || new == 0) {
1333*7c478bd9Sstevel@tonic-gate 		*err = EINVAL;
1334*7c478bd9Sstevel@tonic-gate 		return;
1335*7c478bd9Sstevel@tonic-gate 	}
1336*7c478bd9Sstevel@tonic-gate 
1337*7c478bd9Sstevel@tonic-gate 	if (new->index.name == 0) {
1338*7c478bd9Sstevel@tonic-gate 		new->index.name = am(myself, old->index.numIndexes *
1339*7c478bd9Sstevel@tonic-gate 						sizeof (new->index.name[0]));
1340*7c478bd9Sstevel@tonic-gate 		if (old->index.numIndexes > 0 && new->index.name == 0) {
1341*7c478bd9Sstevel@tonic-gate 			*err = ENOMEM;
1342*7c478bd9Sstevel@tonic-gate 			return;
1343*7c478bd9Sstevel@tonic-gate 		}
1344*7c478bd9Sstevel@tonic-gate 		new->index.value = am(myself, old->index.numIndexes *
1345*7c478bd9Sstevel@tonic-gate 						sizeof (new->index.value[0]));
1346*7c478bd9Sstevel@tonic-gate 		if (old->index.numIndexes > 0 && new->index.value == 0) {
1347*7c478bd9Sstevel@tonic-gate 			*err = ENOMEM;
1348*7c478bd9Sstevel@tonic-gate 			return;
1349*7c478bd9Sstevel@tonic-gate 		}
1350*7c478bd9Sstevel@tonic-gate 	}
1351*7c478bd9Sstevel@tonic-gate 	new->name = sdup(myself, T, old->name);
1352*7c478bd9Sstevel@tonic-gate 	if (new->name == 0 && old->name != 0) {
1353*7c478bd9Sstevel@tonic-gate 		*err = ENOMEM;
1354*7c478bd9Sstevel@tonic-gate 		return;
1355*7c478bd9Sstevel@tonic-gate 	}
1356*7c478bd9Sstevel@tonic-gate 	copyIndex(&old->index, &new->index, err);
1357*7c478bd9Sstevel@tonic-gate }
1358*7c478bd9Sstevel@tonic-gate 
1359*7c478bd9Sstevel@tonic-gate __nis_obj_spec_t *
1360*7c478bd9Sstevel@tonic-gate cloneObjSpec(__nis_obj_spec_t *old) {
1361*7c478bd9Sstevel@tonic-gate 	char			*myself = "cloneObjSpec";
1362*7c478bd9Sstevel@tonic-gate 	int			err = 0;
1363*7c478bd9Sstevel@tonic-gate 	__nis_obj_spec_t	*new = am(myself, sizeof (*new));
1364*7c478bd9Sstevel@tonic-gate 
1365*7c478bd9Sstevel@tonic-gate 	if (new != 0) {
1366*7c478bd9Sstevel@tonic-gate 		copyObjSpec(old, new, &err);
1367*7c478bd9Sstevel@tonic-gate 		if (err != 0) {
1368*7c478bd9Sstevel@tonic-gate 			freeObjSpec(new, 1);
1369*7c478bd9Sstevel@tonic-gate 			new = 0;
1370*7c478bd9Sstevel@tonic-gate 		}
1371*7c478bd9Sstevel@tonic-gate 	}
1372*7c478bd9Sstevel@tonic-gate 
1373*7c478bd9Sstevel@tonic-gate 	return (new);
1374*7c478bd9Sstevel@tonic-gate }
1375*7c478bd9Sstevel@tonic-gate 
1376*7c478bd9Sstevel@tonic-gate void
1377*7c478bd9Sstevel@tonic-gate freeObjSpec(__nis_obj_spec_t *old, bool_t doFree) {
1378*7c478bd9Sstevel@tonic-gate 
1379*7c478bd9Sstevel@tonic-gate 	if (old == 0)
1380*7c478bd9Sstevel@tonic-gate 		return;
1381*7c478bd9Sstevel@tonic-gate 
1382*7c478bd9Sstevel@tonic-gate 	sfree(old->name);
1383*7c478bd9Sstevel@tonic-gate 	freeIndex(&old->index, FALSE);
1384*7c478bd9Sstevel@tonic-gate 	if (doFree)
1385*7c478bd9Sstevel@tonic-gate 		free(old);
1386*7c478bd9Sstevel@tonic-gate }
1387*7c478bd9Sstevel@tonic-gate 
1388*7c478bd9Sstevel@tonic-gate void
1389*7c478bd9Sstevel@tonic-gate copySearchTriple(__nis_search_triple_t *old, __nis_search_triple_t *new,
1390*7c478bd9Sstevel@tonic-gate 		int *err) {
1391*7c478bd9Sstevel@tonic-gate 	char			*myself = "copySearchTriple";
1392*7c478bd9Sstevel@tonic-gate 
1393*7c478bd9Sstevel@tonic-gate 	*err = 0;
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	if (old == 0 || new == 0) {
1396*7c478bd9Sstevel@tonic-gate 		*err = EINVAL;
1397*7c478bd9Sstevel@tonic-gate 		return;
1398*7c478bd9Sstevel@tonic-gate 	}
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 	if (old->base != NULL)
1401*7c478bd9Sstevel@tonic-gate 		new->base = sdup(myself, T, old->base);
1402*7c478bd9Sstevel@tonic-gate 	else
1403*7c478bd9Sstevel@tonic-gate 		new->base = NULL;
1404*7c478bd9Sstevel@tonic-gate 	if (old->attrs != NULL)
1405*7c478bd9Sstevel@tonic-gate 		new->attrs = sdup(myself, T, old->attrs);
1406*7c478bd9Sstevel@tonic-gate 	else
1407*7c478bd9Sstevel@tonic-gate 		new->attrs = NULL;
1408*7c478bd9Sstevel@tonic-gate 	if ((new->base == 0 && old->base != 0) ||
1409*7c478bd9Sstevel@tonic-gate 			(new->attrs == 0 && old->attrs != 0)) {
1410*7c478bd9Sstevel@tonic-gate 		sfree(new->base);
1411*7c478bd9Sstevel@tonic-gate 		new->base = 0;
1412*7c478bd9Sstevel@tonic-gate 		sfree(new->attrs);
1413*7c478bd9Sstevel@tonic-gate 		new->attrs = 0;
1414*7c478bd9Sstevel@tonic-gate 		*err = ENOMEM;
1415*7c478bd9Sstevel@tonic-gate 		return;
1416*7c478bd9Sstevel@tonic-gate 	}
1417*7c478bd9Sstevel@tonic-gate 	new->scope = old->scope;
1418*7c478bd9Sstevel@tonic-gate 	/*
1419*7c478bd9Sstevel@tonic-gate 	 * XXX Really should have a cloneMappingElement() function.
1420*7c478bd9Sstevel@tonic-gate 	 * However, since whatever the 'element' field points to
1421*7c478bd9Sstevel@tonic-gate 	 * is allocated at parse time, and never is freed or modified,
1422*7c478bd9Sstevel@tonic-gate 	 * it's sufficient to copy the pointer value.
1423*7c478bd9Sstevel@tonic-gate 	 */
1424*7c478bd9Sstevel@tonic-gate 	new->element = old->element;
1425*7c478bd9Sstevel@tonic-gate }
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate __nis_search_triple_t *
1428*7c478bd9Sstevel@tonic-gate cloneSearchTriple(__nis_search_triple_t *old) {
1429*7c478bd9Sstevel@tonic-gate 	char			*myself = "cloneSearchTriple";
1430*7c478bd9Sstevel@tonic-gate 	int			err = 0;
1431*7c478bd9Sstevel@tonic-gate 	__nis_search_triple_t	*new = am(myself, sizeof (*new));
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 	if (new != 0) {
1434*7c478bd9Sstevel@tonic-gate 		copySearchTriple(old, new, &err);
1435*7c478bd9Sstevel@tonic-gate 		if (err != 0) {
1436*7c478bd9Sstevel@tonic-gate 			freeSearchTriple(new, 1);
1437*7c478bd9Sstevel@tonic-gate 			new = 0;
1438*7c478bd9Sstevel@tonic-gate 		}
1439*7c478bd9Sstevel@tonic-gate 	}
1440*7c478bd9Sstevel@tonic-gate 
1441*7c478bd9Sstevel@tonic-gate 	return (new);
1442*7c478bd9Sstevel@tonic-gate }
1443*7c478bd9Sstevel@tonic-gate 
1444*7c478bd9Sstevel@tonic-gate void
1445*7c478bd9Sstevel@tonic-gate freeSearchTriple(__nis_search_triple_t *old, bool_t doFree) {
1446*7c478bd9Sstevel@tonic-gate 
1447*7c478bd9Sstevel@tonic-gate 	if (old == 0)
1448*7c478bd9Sstevel@tonic-gate 		return;
1449*7c478bd9Sstevel@tonic-gate 
1450*7c478bd9Sstevel@tonic-gate 	sfree(old->base);
1451*7c478bd9Sstevel@tonic-gate 	sfree(old->attrs);
1452*7c478bd9Sstevel@tonic-gate 	/*
1453*7c478bd9Sstevel@tonic-gate 	 * Since we only copied the element pointer when this structure
1454*7c478bd9Sstevel@tonic-gate 	 * was created, we don't free old->element.
1455*7c478bd9Sstevel@tonic-gate 	 */
1456*7c478bd9Sstevel@tonic-gate 	if (doFree)
1457*7c478bd9Sstevel@tonic-gate 		free(old);
1458*7c478bd9Sstevel@tonic-gate }
1459*7c478bd9Sstevel@tonic-gate 
1460*7c478bd9Sstevel@tonic-gate void
1461*7c478bd9Sstevel@tonic-gate copyTripleOrObj(__nis_mapping_item_type_t type,
1462*7c478bd9Sstevel@tonic-gate 		__nis_triple_or_obj_t *old, __nis_triple_or_obj_t *new,
1463*7c478bd9Sstevel@tonic-gate 		int *err) {
1464*7c478bd9Sstevel@tonic-gate 
1465*7c478bd9Sstevel@tonic-gate 	*err = 0;
1466*7c478bd9Sstevel@tonic-gate 
1467*7c478bd9Sstevel@tonic-gate 	if (old == 0 || new == 0) {
1468*7c478bd9Sstevel@tonic-gate 		*err = EINVAL;
1469*7c478bd9Sstevel@tonic-gate 		return;
1470*7c478bd9Sstevel@tonic-gate 	}
1471*7c478bd9Sstevel@tonic-gate 
1472*7c478bd9Sstevel@tonic-gate 	if (type == mit_nisplus) {
1473*7c478bd9Sstevel@tonic-gate 		copyObjSpec(&old->obj, &new->obj, err);
1474*7c478bd9Sstevel@tonic-gate 	} else if (type == mit_ldap) {
1475*7c478bd9Sstevel@tonic-gate 		copySearchTriple(&old->triple, &new->triple, err);
1476*7c478bd9Sstevel@tonic-gate 	}
1477*7c478bd9Sstevel@tonic-gate }
1478*7c478bd9Sstevel@tonic-gate 
1479*7c478bd9Sstevel@tonic-gate __nis_triple_or_obj_t *
1480*7c478bd9Sstevel@tonic-gate cloneTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old) {
1481*7c478bd9Sstevel@tonic-gate 	char			*myself = "cloneTripleOrObj";
1482*7c478bd9Sstevel@tonic-gate 	int			err = 0;
1483*7c478bd9Sstevel@tonic-gate 	__nis_triple_or_obj_t	*new = am(myself, sizeof (*new));
1484*7c478bd9Sstevel@tonic-gate 
1485*7c478bd9Sstevel@tonic-gate 	if (new != 0) {
1486*7c478bd9Sstevel@tonic-gate 		copyTripleOrObj(type, old, new, &err);
1487*7c478bd9Sstevel@tonic-gate 		if (err != 0) {
1488*7c478bd9Sstevel@tonic-gate 			freeTripleOrObj(type, new, 1);
1489*7c478bd9Sstevel@tonic-gate 			new = 0;
1490*7c478bd9Sstevel@tonic-gate 		}
1491*7c478bd9Sstevel@tonic-gate 	}
1492*7c478bd9Sstevel@tonic-gate 
1493*7c478bd9Sstevel@tonic-gate 	return (new);
1494*7c478bd9Sstevel@tonic-gate }
1495*7c478bd9Sstevel@tonic-gate 
1496*7c478bd9Sstevel@tonic-gate void
1497*7c478bd9Sstevel@tonic-gate freeTripleOrObj(__nis_mapping_item_type_t type, __nis_triple_or_obj_t *old,
1498*7c478bd9Sstevel@tonic-gate 		bool_t doFree) {
1499*7c478bd9Sstevel@tonic-gate 
1500*7c478bd9Sstevel@tonic-gate 	if (old == 0)
1501*7c478bd9Sstevel@tonic-gate 		return;
1502*7c478bd9Sstevel@tonic-gate 
1503*7c478bd9Sstevel@tonic-gate 	if (type == mit_nisplus)
1504*7c478bd9Sstevel@tonic-gate 		freeObjSpec(&old->obj, doFree);
1505*7c478bd9Sstevel@tonic-gate 	else if (type == mit_ldap)
1506*7c478bd9Sstevel@tonic-gate 		freeSearchTriple(&old->triple, doFree);
1507*7c478bd9Sstevel@tonic-gate 
1508*7c478bd9Sstevel@tonic-gate 	if (doFree)
1509*7c478bd9Sstevel@tonic-gate 		free(old);
1510*7c478bd9Sstevel@tonic-gate }
1511*7c478bd9Sstevel@tonic-gate 
1512*7c478bd9Sstevel@tonic-gate void
1513*7c478bd9Sstevel@tonic-gate copyItem(__nis_mapping_item_t *old, __nis_mapping_item_t *new, int *err) {
1514*7c478bd9Sstevel@tonic-gate 
1515*7c478bd9Sstevel@tonic-gate 	*err = 0;
1516*7c478bd9Sstevel@tonic-gate 
1517*7c478bd9Sstevel@tonic-gate 	if (old == 0 || new == 0) {
1518*7c478bd9Sstevel@tonic-gate 		*err = EINVAL;
1519*7c478bd9Sstevel@tonic-gate 		return;
1520*7c478bd9Sstevel@tonic-gate 	}
1521*7c478bd9Sstevel@tonic-gate 
1522*7c478bd9Sstevel@tonic-gate 	new->type = old->type;
1523*7c478bd9Sstevel@tonic-gate 	new->repeat = old->repeat;
1524*7c478bd9Sstevel@tonic-gate 	if (old->name != 0) {
1525*7c478bd9Sstevel@tonic-gate 		new->name = strdup(old->name);
1526*7c478bd9Sstevel@tonic-gate 		if (new->name == 0) {
1527*7c478bd9Sstevel@tonic-gate 			*err = ENOMEM;
1528*7c478bd9Sstevel@tonic-gate 			return;
1529*7c478bd9Sstevel@tonic-gate 		}
1530*7c478bd9Sstevel@tonic-gate 	} else {
1531*7c478bd9Sstevel@tonic-gate 		new->name = 0;
1532*7c478bd9Sstevel@tonic-gate 	}
1533*7c478bd9Sstevel@tonic-gate 	if (old->type == mit_nisplus || old->type == mit_ldap)
1534*7c478bd9Sstevel@tonic-gate 		copyTripleOrObj(old->type, &old->searchSpec, &new->searchSpec,
1535*7c478bd9Sstevel@tonic-gate 				err);
1536*7c478bd9Sstevel@tonic-gate 	else
1537*7c478bd9Sstevel@tonic-gate 		memset(&new->searchSpec, 0, sizeof (new->searchSpec));
1538*7c478bd9Sstevel@tonic-gate }
1539*7c478bd9Sstevel@tonic-gate 
1540*7c478bd9Sstevel@tonic-gate __nis_mapping_item_t *
1541*7c478bd9Sstevel@tonic-gate cloneItem(__nis_mapping_item_t *old) {
1542*7c478bd9Sstevel@tonic-gate 	__nis_mapping_item_t	*new;
1543*7c478bd9Sstevel@tonic-gate 	int			err = 0;
1544*7c478bd9Sstevel@tonic-gate 	char			*myself = "cloneItem";
1545*7c478bd9Sstevel@tonic-gate 
1546*7c478bd9Sstevel@tonic-gate 	if (old == 0)
1547*7c478bd9Sstevel@tonic-gate 		return (0);
1548*7c478bd9Sstevel@tonic-gate 
1549*7c478bd9Sstevel@tonic-gate 	new = am(myself, sizeof (*new));
1550*7c478bd9Sstevel@tonic-gate 	if (new == 0)
1551*7c478bd9Sstevel@tonic-gate 		return (0);
1552*7c478bd9Sstevel@tonic-gate 
1553*7c478bd9Sstevel@tonic-gate 	copyItem(old, new, &err);
1554*7c478bd9Sstevel@tonic-gate 	if (err != 0) {
1555*7c478bd9Sstevel@tonic-gate 		freeMappingItem(new, 1);
1556*7c478bd9Sstevel@tonic-gate 		return (0);
1557*7c478bd9Sstevel@tonic-gate 	}
1558*7c478bd9Sstevel@tonic-gate 
1559*7c478bd9Sstevel@tonic-gate 	return (new);
1560*7c478bd9Sstevel@tonic-gate }
1561*7c478bd9Sstevel@tonic-gate 
1562*7c478bd9Sstevel@tonic-gate void
1563*7c478bd9Sstevel@tonic-gate freeMappingItem(__nis_mapping_item_t *item, int numItems) {
1564*7c478bd9Sstevel@tonic-gate 	int	i;
1565*7c478bd9Sstevel@tonic-gate 
1566*7c478bd9Sstevel@tonic-gate 	if (item == 0)
1567*7c478bd9Sstevel@tonic-gate 		return;
1568*7c478bd9Sstevel@tonic-gate 
1569*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < numItems; i++) {
1570*7c478bd9Sstevel@tonic-gate 		sfree(item[i].name);
1571*7c478bd9Sstevel@tonic-gate 		freeTripleOrObj(item[i].type, &item[i].searchSpec, FALSE);
1572*7c478bd9Sstevel@tonic-gate 	}
1573*7c478bd9Sstevel@tonic-gate 	sfree(item);
1574*7c478bd9Sstevel@tonic-gate }
1575*7c478bd9Sstevel@tonic-gate 
1576*7c478bd9Sstevel@tonic-gate __nis_mapping_item_t *
1577*7c478bd9Sstevel@tonic-gate concatenateMappingItem(__nis_mapping_item_t *old, int numItems,
1578*7c478bd9Sstevel@tonic-gate 		__nis_mapping_item_t *cat) {
1579*7c478bd9Sstevel@tonic-gate 	__nis_mapping_item_t	*new;
1580*7c478bd9Sstevel@tonic-gate 	int			i, err = 0;
1581*7c478bd9Sstevel@tonic-gate 	char			*myself = "concatenateMappingItem";
1582*7c478bd9Sstevel@tonic-gate 
1583*7c478bd9Sstevel@tonic-gate 	if (old == 0 || numItems < 1)
1584*7c478bd9Sstevel@tonic-gate 		return (cloneItem(cat));
1585*7c478bd9Sstevel@tonic-gate 
1586*7c478bd9Sstevel@tonic-gate 	new = am(myself, (numItems + 1) * sizeof (*new));
1587*7c478bd9Sstevel@tonic-gate 	if (new == 0)
1588*7c478bd9Sstevel@tonic-gate 		return (0);
1589*7c478bd9Sstevel@tonic-gate 
1590*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < numItems; i++) {
1591*7c478bd9Sstevel@tonic-gate 		copyItem(&old[i], &new[i], &err);
1592*7c478bd9Sstevel@tonic-gate 		if (err != 0) {
1593*7c478bd9Sstevel@tonic-gate 			freeMappingItem(new, i);
1594*7c478bd9Sstevel@tonic-gate 			return (0);
1595*7c478bd9Sstevel@tonic-gate 		}
1596*7c478bd9Sstevel@tonic-gate 	}
1597*7c478bd9Sstevel@tonic-gate 	copyItem(cat, &new[numItems], &err);
1598*7c478bd9Sstevel@tonic-gate 	if (err != 0) {
1599*7c478bd9Sstevel@tonic-gate 		freeMappingItem(new, numItems);
1600*7c478bd9Sstevel@tonic-gate 		new = 0;
1601*7c478bd9Sstevel@tonic-gate 	}
1602*7c478bd9Sstevel@tonic-gate 
1603*7c478bd9Sstevel@tonic-gate 	return (new);
1604*7c478bd9Sstevel@tonic-gate }
1605*7c478bd9Sstevel@tonic-gate 
1606*7c478bd9Sstevel@tonic-gate __nis_value_t *
1607*7c478bd9Sstevel@tonic-gate concatenateValues(__nis_value_t *v1, __nis_value_t *v2) {
1608*7c478bd9Sstevel@tonic-gate 	int		i, n, a;
1609*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*v;
1610*7c478bd9Sstevel@tonic-gate 	char		*myself = "concatenateValues";
1611*7c478bd9Sstevel@tonic-gate 
1612*7c478bd9Sstevel@tonic-gate 	if (v1 == 0 || v1->numVals <= 0)
1613*7c478bd9Sstevel@tonic-gate 		return (cloneValue(v2, 1));
1614*7c478bd9Sstevel@tonic-gate 	if (v2 == 0 || v2->numVals <= 0)
1615*7c478bd9Sstevel@tonic-gate 		return (cloneValue(v1, 1));
1616*7c478bd9Sstevel@tonic-gate 
1617*7c478bd9Sstevel@tonic-gate 	if (v1->type != v2->type)
1618*7c478bd9Sstevel@tonic-gate 		return (0);
1619*7c478bd9Sstevel@tonic-gate 
1620*7c478bd9Sstevel@tonic-gate 	n = v1->numVals + v2->numVals;
1621*7c478bd9Sstevel@tonic-gate 	v = am(myself, sizeof (*v));
1622*7c478bd9Sstevel@tonic-gate 	if (v == 0)
1623*7c478bd9Sstevel@tonic-gate 		return (0);
1624*7c478bd9Sstevel@tonic-gate 	v->val = am(myself, n * sizeof (v->val[0]));
1625*7c478bd9Sstevel@tonic-gate 	if (v->val == 0) {
1626*7c478bd9Sstevel@tonic-gate 		free(v);
1627*7c478bd9Sstevel@tonic-gate 		return (0);
1628*7c478bd9Sstevel@tonic-gate 	}
1629*7c478bd9Sstevel@tonic-gate 	v->type = v1->type;
1630*7c478bd9Sstevel@tonic-gate 	v->numVals = 0;
1631*7c478bd9Sstevel@tonic-gate 
1632*7c478bd9Sstevel@tonic-gate 	for (a = 0; a < 2; a++) {
1633*7c478bd9Sstevel@tonic-gate 		__nis_single_value_t	*val = (a == 0) ? v1->val : v2->val;
1634*7c478bd9Sstevel@tonic-gate 		int			numv = (a == 0) ? v1->numVals :
1635*7c478bd9Sstevel@tonic-gate 							v2->numVals;
1636*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < numv; i++) {
1637*7c478bd9Sstevel@tonic-gate 			int	clen, alen = val[i].length;
1638*7c478bd9Sstevel@tonic-gate 
1639*7c478bd9Sstevel@tonic-gate 			clen = alen;
1640*7c478bd9Sstevel@tonic-gate 
1641*7c478bd9Sstevel@tonic-gate 			/*
1642*7c478bd9Sstevel@tonic-gate 			 * Make sure there's a NUL at the end of a string,
1643*7c478bd9Sstevel@tonic-gate 			 * but avoid adding to the allocated length if there's
1644*7c478bd9Sstevel@tonic-gate 			 * already a NUL at the end.
1645*7c478bd9Sstevel@tonic-gate 			 */
1646*7c478bd9Sstevel@tonic-gate 			if (alen > 0 && v->type == vt_string &&
1647*7c478bd9Sstevel@tonic-gate 					((char *)val[i].value)[alen-1] != '\0')
1648*7c478bd9Sstevel@tonic-gate 				alen += 1;
1649*7c478bd9Sstevel@tonic-gate 			v->val[v->numVals].value = am(myself, alen);
1650*7c478bd9Sstevel@tonic-gate 			if (v->val[v->numVals].value == 0) {
1651*7c478bd9Sstevel@tonic-gate 				freeValue(v, 1);
1652*7c478bd9Sstevel@tonic-gate 				return (0);
1653*7c478bd9Sstevel@tonic-gate 			}
1654*7c478bd9Sstevel@tonic-gate 			memcpy(v->val[v->numVals].value, val[i].value, clen);
1655*7c478bd9Sstevel@tonic-gate 			v->val[v->numVals].length = val[i].length;
1656*7c478bd9Sstevel@tonic-gate 			v->numVals++;
1657*7c478bd9Sstevel@tonic-gate 		}
1658*7c478bd9Sstevel@tonic-gate 	}
1659*7c478bd9Sstevel@tonic-gate 
1660*7c478bd9Sstevel@tonic-gate 	return (v);
1661*7c478bd9Sstevel@tonic-gate }
1662*7c478bd9Sstevel@tonic-gate 
1663*7c478bd9Sstevel@tonic-gate __nis_value_t *
1664*7c478bd9Sstevel@tonic-gate splitMappingItem(__nis_mapping_item_t *item, char delim,
1665*7c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv) {
1666*7c478bd9Sstevel@tonic-gate 	__nis_value_t		*val = getMappingItem(item, mit_any,
1667*7c478bd9Sstevel@tonic-gate 			rv, 0, NULL);
1668*7c478bd9Sstevel@tonic-gate 	__nis_single_value_t	*nval;
1669*7c478bd9Sstevel@tonic-gate 	int			i, n, nv;
1670*7c478bd9Sstevel@tonic-gate 
1671*7c478bd9Sstevel@tonic-gate 	if (val == 0)
1672*7c478bd9Sstevel@tonic-gate 		return (0);
1673*7c478bd9Sstevel@tonic-gate 	else if (delim == 0 || val->val == 0 || val->numVals <= 0 ||
1674*7c478bd9Sstevel@tonic-gate 			val->type != vt_string) {
1675*7c478bd9Sstevel@tonic-gate 		freeValue(val, 1);
1676*7c478bd9Sstevel@tonic-gate 		return (0);
1677*7c478bd9Sstevel@tonic-gate 	}
1678*7c478bd9Sstevel@tonic-gate 
1679*7c478bd9Sstevel@tonic-gate 	nval = val->val;
1680*7c478bd9Sstevel@tonic-gate 	nv = val->numVals;
1681*7c478bd9Sstevel@tonic-gate 	val->repeat = FALSE;
1682*7c478bd9Sstevel@tonic-gate 	val->val = 0;
1683*7c478bd9Sstevel@tonic-gate 	val->numVals = 0;
1684*7c478bd9Sstevel@tonic-gate 
1685*7c478bd9Sstevel@tonic-gate 	/* In N2L, space and tab delimiters are treated the same */
1686*7c478bd9Sstevel@tonic-gate 	if (yp2ldap && delim == '\t')
1687*7c478bd9Sstevel@tonic-gate 		delim = ' ';
1688*7c478bd9Sstevel@tonic-gate 
1689*7c478bd9Sstevel@tonic-gate 	/* If the item has multiple values, we split each one independently */
1690*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nv; i++) {
1691*7c478bd9Sstevel@tonic-gate 		char			*str;
1692*7c478bd9Sstevel@tonic-gate 		int			s, e;
1693*7c478bd9Sstevel@tonic-gate 		char			*newstr;
1694*7c478bd9Sstevel@tonic-gate 		__nis_single_value_t	*newval;
1695*7c478bd9Sstevel@tonic-gate 
1696*7c478bd9Sstevel@tonic-gate 		if (yp2ldap && delim == ' ')
1697*7c478bd9Sstevel@tonic-gate 			nval[i].value = trimWhiteSpaces(nval[i].value,
1698*7c478bd9Sstevel@tonic-gate 							&nval[i].length, 1);
1699*7c478bd9Sstevel@tonic-gate 
1700*7c478bd9Sstevel@tonic-gate 		str = nval[i].value;
1701*7c478bd9Sstevel@tonic-gate 
1702*7c478bd9Sstevel@tonic-gate 		if (nval[i].value == 0)
1703*7c478bd9Sstevel@tonic-gate 			continue;
1704*7c478bd9Sstevel@tonic-gate 
1705*7c478bd9Sstevel@tonic-gate 		for (s = 0; s < nval[i].length; s = e+1) {
1706*7c478bd9Sstevel@tonic-gate 			/* Find the next delimiter, or end-of-string */
1707*7c478bd9Sstevel@tonic-gate 			for (e = s; str[e] != '\0' && str[e] != delim; e++);
1708*7c478bd9Sstevel@tonic-gate 			/*
1709*7c478bd9Sstevel@tonic-gate 			 * 'str[e]' is either a delimiter, or the concluding
1710*7c478bd9Sstevel@tonic-gate 			 * NUL. Make sure it's NUL.
1711*7c478bd9Sstevel@tonic-gate 			 */
1712*7c478bd9Sstevel@tonic-gate 			str[e] = '\0';
1713*7c478bd9Sstevel@tonic-gate 			/* Add to val->val */
1714*7c478bd9Sstevel@tonic-gate 			newstr = strdup(&str[s]);
1715*7c478bd9Sstevel@tonic-gate 			newval = realloc(val->val,
1716*7c478bd9Sstevel@tonic-gate 					(val->numVals+1) *
1717*7c478bd9Sstevel@tonic-gate 						sizeof (val->val[0]));
1718*7c478bd9Sstevel@tonic-gate 			if (newval != 0)
1719*7c478bd9Sstevel@tonic-gate 				val->val = newval;
1720*7c478bd9Sstevel@tonic-gate 			if (newstr == 0 || newval == 0) {
1721*7c478bd9Sstevel@tonic-gate 				freeValue(val, 1);
1722*7c478bd9Sstevel@tonic-gate 				for (n = i; n < nv; n++) {
1723*7c478bd9Sstevel@tonic-gate 					sfree(nval[n].value);
1724*7c478bd9Sstevel@tonic-gate 				}
1725*7c478bd9Sstevel@tonic-gate 				free(nval);
1726*7c478bd9Sstevel@tonic-gate 				sfree(newstr);
1727*7c478bd9Sstevel@tonic-gate 				return (0);
1728*7c478bd9Sstevel@tonic-gate 			}
1729*7c478bd9Sstevel@tonic-gate 			val->val[val->numVals].value = newstr;
1730*7c478bd9Sstevel@tonic-gate 			val->val[val->numVals].length = strlen(newstr) + 1;
1731*7c478bd9Sstevel@tonic-gate 			val->numVals++;
1732*7c478bd9Sstevel@tonic-gate 		}
1733*7c478bd9Sstevel@tonic-gate 		free(nval[i].value);
1734*7c478bd9Sstevel@tonic-gate 		nval[i].value = 0;
1735*7c478bd9Sstevel@tonic-gate 	}
1736*7c478bd9Sstevel@tonic-gate 	/* Already freed the nval[i].value's as we traversed nval */
1737*7c478bd9Sstevel@tonic-gate 	free(nval);
1738*7c478bd9Sstevel@tonic-gate 
1739*7c478bd9Sstevel@tonic-gate 	return (val);
1740*7c478bd9Sstevel@tonic-gate }
1741*7c478bd9Sstevel@tonic-gate 
1742*7c478bd9Sstevel@tonic-gate /*
1743*7c478bd9Sstevel@tonic-gate  * Match the format spec 'f[curf]' to the input value string 'str'.
1744*7c478bd9Sstevel@tonic-gate  *
1745*7c478bd9Sstevel@tonic-gate  * If successful, returns the updated position in the value string 'str'.
1746*7c478bd9Sstevel@tonic-gate  * Otherwise, NULL is returned.
1747*7c478bd9Sstevel@tonic-gate  *
1748*7c478bd9Sstevel@tonic-gate  * curf		Current index (i.e., the one we should look at) in 'f'
1749*7c478bd9Sstevel@tonic-gate  * nf		Number of elements in 'f', including 'mmt_end'
1750*7c478bd9Sstevel@tonic-gate  * str		The value string we're scanning
1751*7c478bd9Sstevel@tonic-gate  * val		Pointer to where an item value (if any) should be returned
1752*7c478bd9Sstevel@tonic-gate  *		Set to NULL if not an 'mmt_item'.
1753*7c478bd9Sstevel@tonic-gate  * fmtstart	If non-zero on entry, skip characters in 'str' until we find
1754*7c478bd9Sstevel@tonic-gate  *		the f[curf].type data, if doing so makes any sense. On exit,
1755*7c478bd9Sstevel@tonic-gate  *		set to the start of the fmt element data (which will be 'str',
1756*7c478bd9Sstevel@tonic-gate  *		unless we did skip characters)
1757*7c478bd9Sstevel@tonic-gate  * sepset	List of separators
1758*7c478bd9Sstevel@tonic-gate  */
1759*7c478bd9Sstevel@tonic-gate char *
1760*7c478bd9Sstevel@tonic-gate scanMappingFormat(__nis_mapping_format_t *f, int curf, int nf, char *str,
1761*7c478bd9Sstevel@tonic-gate 		char **val, char **fmtstart, char *sepset) {
1762*7c478bd9Sstevel@tonic-gate 	char	*mstr, *next, *start = 0, *tmpstr;
1763*7c478bd9Sstevel@tonic-gate 	int	i, len;
1764*7c478bd9Sstevel@tonic-gate 	bool_t	match;
1765*7c478bd9Sstevel@tonic-gate 	char	*myself = "scanMappingFormat";
1766*7c478bd9Sstevel@tonic-gate 	/* N2L variables */
1767*7c478bd9Sstevel@tonic-gate 	int	af, skipspaces = 0;
1768*7c478bd9Sstevel@tonic-gate 	bool_t	ipaddr = FALSE;
1769*7c478bd9Sstevel@tonic-gate 	char	*spacestr = " ", *emptystr = "";
1770*7c478bd9Sstevel@tonic-gate 
1771*7c478bd9Sstevel@tonic-gate 
1772*7c478bd9Sstevel@tonic-gate 	if (f == 0 || curf < 0 || nf <= 0 || str == 0)
1773*7c478bd9Sstevel@tonic-gate 		return (0);
1774*7c478bd9Sstevel@tonic-gate 
1775*7c478bd9Sstevel@tonic-gate 	/*
1776*7c478bd9Sstevel@tonic-gate 	 * If separator list is NULL (which will be the case for
1777*7c478bd9Sstevel@tonic-gate 	 * nis+2ldap), then simply use empty string
1778*7c478bd9Sstevel@tonic-gate 	 */
1779*7c478bd9Sstevel@tonic-gate 	if (sepset == 0)
1780*7c478bd9Sstevel@tonic-gate 		sepset = emptystr;
1781*7c478bd9Sstevel@tonic-gate 
1782*7c478bd9Sstevel@tonic-gate 	if (curf >= nf) {
1783*7c478bd9Sstevel@tonic-gate 		/* OK if the string also is exhausted */
1784*7c478bd9Sstevel@tonic-gate 		if (strchr(sepset, *str) != 0)
1785*7c478bd9Sstevel@tonic-gate 			return (str);
1786*7c478bd9Sstevel@tonic-gate 		else
1787*7c478bd9Sstevel@tonic-gate 			return (0);
1788*7c478bd9Sstevel@tonic-gate 	}
1789*7c478bd9Sstevel@tonic-gate 
1790*7c478bd9Sstevel@tonic-gate 	switch (f[curf].type) {
1791*7c478bd9Sstevel@tonic-gate 	case mmt_berstring:
1792*7c478bd9Sstevel@tonic-gate 		if (f[curf].match.berString[0] != 'a') {
1793*7c478bd9Sstevel@tonic-gate 			/* Not a matchable element */
1794*7c478bd9Sstevel@tonic-gate 			return (0);
1795*7c478bd9Sstevel@tonic-gate 		}
1796*7c478bd9Sstevel@tonic-gate 
1797*7c478bd9Sstevel@tonic-gate 		/*
1798*7c478bd9Sstevel@tonic-gate 		 * If here, it means it's an IP address (N2L case)
1799*7c478bd9Sstevel@tonic-gate 		 * So continue processing as if it was mmt_item
1800*7c478bd9Sstevel@tonic-gate 		 */
1801*7c478bd9Sstevel@tonic-gate 		ipaddr = TRUE;
1802*7c478bd9Sstevel@tonic-gate 
1803*7c478bd9Sstevel@tonic-gate 	case mmt_item:
1804*7c478bd9Sstevel@tonic-gate 		/*
1805*7c478bd9Sstevel@tonic-gate 		 * In order to find the end of the item value, we must look
1806*7c478bd9Sstevel@tonic-gate 		 * ahead and determine the start of the next formatting element.
1807*7c478bd9Sstevel@tonic-gate 		 * If successful, 'next' will be the start of the fmt element
1808*7c478bd9Sstevel@tonic-gate 		 * after the next one; we don't care about that, other than to
1809*7c478bd9Sstevel@tonic-gate 		 * check for error.
1810*7c478bd9Sstevel@tonic-gate 		 *
1811*7c478bd9Sstevel@tonic-gate 		 * Since an item match is somewhat like an any match, in that
1812*7c478bd9Sstevel@tonic-gate 		 * we don't know a priori if the first occurence of the next
1813*7c478bd9Sstevel@tonic-gate 		 * element really is the one we want, we have to scan ahead
1814*7c478bd9Sstevel@tonic-gate 		 * until we've reached the end.
1815*7c478bd9Sstevel@tonic-gate 		 */
1816*7c478bd9Sstevel@tonic-gate 		tmpstr = str;
1817*7c478bd9Sstevel@tonic-gate 		while ((next = scanMappingFormat(f, curf+1, nf, tmpstr, 0,
1818*7c478bd9Sstevel@tonic-gate 				&start, sepset)) != 0) {
1819*7c478bd9Sstevel@tonic-gate 			char	*tmp = next;
1820*7c478bd9Sstevel@tonic-gate 			int	cf;
1821*7c478bd9Sstevel@tonic-gate 
1822*7c478bd9Sstevel@tonic-gate 			for (cf = curf+2; cf < nf; cf++) {
1823*7c478bd9Sstevel@tonic-gate 				tmp = scanMappingFormat(f, cf, nf, tmp, 0,
1824*7c478bd9Sstevel@tonic-gate 					0, sepset);
1825*7c478bd9Sstevel@tonic-gate 				if (tmp == 0)
1826*7c478bd9Sstevel@tonic-gate 					break;
1827*7c478bd9Sstevel@tonic-gate 			}
1828*7c478bd9Sstevel@tonic-gate 			if (tmp == 0) {
1829*7c478bd9Sstevel@tonic-gate 				tmpstr = next;
1830*7c478bd9Sstevel@tonic-gate 			} else if (strchr(sepset, *tmp) != 0) {
1831*7c478bd9Sstevel@tonic-gate 				break;
1832*7c478bd9Sstevel@tonic-gate 			} else {
1833*7c478bd9Sstevel@tonic-gate 				return (0);
1834*7c478bd9Sstevel@tonic-gate 			}
1835*7c478bd9Sstevel@tonic-gate 
1836*7c478bd9Sstevel@tonic-gate 		}
1837*7c478bd9Sstevel@tonic-gate 		if (next == 0 || start == 0)
1838*7c478bd9Sstevel@tonic-gate 			return (0);
1839*7c478bd9Sstevel@tonic-gate 
1840*7c478bd9Sstevel@tonic-gate 		if (val != 0) {
1841*7c478bd9Sstevel@tonic-gate 			len = (int)((long)start - (long)str);
1842*7c478bd9Sstevel@tonic-gate 			*val = am(myself, len + 1);
1843*7c478bd9Sstevel@tonic-gate 			if (*val == 0)
1844*7c478bd9Sstevel@tonic-gate 				return (0);
1845*7c478bd9Sstevel@tonic-gate 			memcpy(*val, str, len);
1846*7c478bd9Sstevel@tonic-gate 			(*val)[len] = '\0';
1847*7c478bd9Sstevel@tonic-gate 
1848*7c478bd9Sstevel@tonic-gate 			if (ipaddr == TRUE) {
1849*7c478bd9Sstevel@tonic-gate 				/*
1850*7c478bd9Sstevel@tonic-gate 				 * In N2L, we need to check if *val is truly an
1851*7c478bd9Sstevel@tonic-gate 				 * IP address
1852*7c478bd9Sstevel@tonic-gate 				 */
1853*7c478bd9Sstevel@tonic-gate 				af = checkIPaddress(*val, len, &tmpstr);
1854*7c478bd9Sstevel@tonic-gate 
1855*7c478bd9Sstevel@tonic-gate 				if (af == -2) {
1856*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1857*7c478bd9Sstevel@tonic-gate 						"%s:Internal error while "
1858*7c478bd9Sstevel@tonic-gate 						"processing IPaddress %s",
1859*7c478bd9Sstevel@tonic-gate 						myself, *val);
1860*7c478bd9Sstevel@tonic-gate 					sfree(*val);
1861*7c478bd9Sstevel@tonic-gate 					return (0);
1862*7c478bd9Sstevel@tonic-gate 				} else if (af == -1) {
1863*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1864*7c478bd9Sstevel@tonic-gate 						"%s:%s is not an IP address",
1865*7c478bd9Sstevel@tonic-gate 						myself, *val);
1866*7c478bd9Sstevel@tonic-gate 					sfree(*val);
1867*7c478bd9Sstevel@tonic-gate 					return (0);
1868*7c478bd9Sstevel@tonic-gate 				} else if (af == 0) {
1869*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1870*7c478bd9Sstevel@tonic-gate 						"%s:IP address %s is not "
1871*7c478bd9Sstevel@tonic-gate 						"supported by rfc2307bis",
1872*7c478bd9Sstevel@tonic-gate 						myself, *val);
1873*7c478bd9Sstevel@tonic-gate 					sfree(*val);
1874*7c478bd9Sstevel@tonic-gate 					return (0);
1875*7c478bd9Sstevel@tonic-gate 				} else if (sstrncmp(*val, tmpstr, len) != 0) {
1876*7c478bd9Sstevel@tonic-gate 					logmsg(MSG_NOTIMECHECK, LOG_WARNING,
1877*7c478bd9Sstevel@tonic-gate 						"%s:IPaddress %s converted "
1878*7c478bd9Sstevel@tonic-gate 						"to %s", myself, *val, tmpstr);
1879*7c478bd9Sstevel@tonic-gate 				}
1880*7c478bd9Sstevel@tonic-gate 
1881*7c478bd9Sstevel@tonic-gate 				sfree(*val);
1882*7c478bd9Sstevel@tonic-gate 				*val = tmpstr;
1883*7c478bd9Sstevel@tonic-gate 			}
1884*7c478bd9Sstevel@tonic-gate 		}
1885*7c478bd9Sstevel@tonic-gate 
1886*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0)
1887*7c478bd9Sstevel@tonic-gate 			*fmtstart = str;
1888*7c478bd9Sstevel@tonic-gate 
1889*7c478bd9Sstevel@tonic-gate 		return (start);
1890*7c478bd9Sstevel@tonic-gate 
1891*7c478bd9Sstevel@tonic-gate 	case mmt_string:
1892*7c478bd9Sstevel@tonic-gate 		if ((mstr = f[curf].match.string) == 0 || *mstr == '\0') {
1893*7c478bd9Sstevel@tonic-gate 			/*
1894*7c478bd9Sstevel@tonic-gate 			 * Count this as a successful match of an empty
1895*7c478bd9Sstevel@tonic-gate 			 * string.
1896*7c478bd9Sstevel@tonic-gate 			 */
1897*7c478bd9Sstevel@tonic-gate 			if (fmtstart != 0)
1898*7c478bd9Sstevel@tonic-gate 				*fmtstart = str;
1899*7c478bd9Sstevel@tonic-gate 			return (str);
1900*7c478bd9Sstevel@tonic-gate 		}
1901*7c478bd9Sstevel@tonic-gate 
1902*7c478bd9Sstevel@tonic-gate 		/*
1903*7c478bd9Sstevel@tonic-gate 		 * In N2L, if the format string 'mstr' contains only
1904*7c478bd9Sstevel@tonic-gate 		 * whitespaces (spaces and tabs), then it should
1905*7c478bd9Sstevel@tonic-gate 		 * match one or more whitespaces from the input
1906*7c478bd9Sstevel@tonic-gate 		 * string 'str'.
1907*7c478bd9Sstevel@tonic-gate 		 */
1908*7c478bd9Sstevel@tonic-gate 		if (yp2ldap && strspn(mstr, " \t") == strlen(mstr)) {
1909*7c478bd9Sstevel@tonic-gate 				mstr = spacestr;
1910*7c478bd9Sstevel@tonic-gate 				skipspaces = 1;
1911*7c478bd9Sstevel@tonic-gate 				next = str + strcspn(str, " \t");
1912*7c478bd9Sstevel@tonic-gate 				/*
1913*7c478bd9Sstevel@tonic-gate 				 * Even if there is no whitespace in 'str',
1914*7c478bd9Sstevel@tonic-gate 				 * it's OK. This is to allow formats like
1915*7c478bd9Sstevel@tonic-gate 				 * "%s %s %s" to match inputs like "foo bar".
1916*7c478bd9Sstevel@tonic-gate 				 */
1917*7c478bd9Sstevel@tonic-gate 				if (*next == '\0')
1918*7c478bd9Sstevel@tonic-gate 					mstr = emptystr;
1919*7c478bd9Sstevel@tonic-gate 		} else {
1920*7c478bd9Sstevel@tonic-gate 			/* No match string in 'str' => failure */
1921*7c478bd9Sstevel@tonic-gate 			if ((next = strstr(str, mstr)) == 0)
1922*7c478bd9Sstevel@tonic-gate 				return (0);
1923*7c478bd9Sstevel@tonic-gate 		}
1924*7c478bd9Sstevel@tonic-gate 
1925*7c478bd9Sstevel@tonic-gate 		/* If 'fmtstart' == 0, we require 'next' == 'str' */
1926*7c478bd9Sstevel@tonic-gate 		if (fmtstart == 0 && next != str)
1927*7c478bd9Sstevel@tonic-gate 			return (0);
1928*7c478bd9Sstevel@tonic-gate 		/* Success; save start of match string if requested */
1929*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0)
1930*7c478bd9Sstevel@tonic-gate 			*fmtstart = next;
1931*7c478bd9Sstevel@tonic-gate 		/* Update position in the value string */
1932*7c478bd9Sstevel@tonic-gate 		str = (char *)((long)next + (long)strlen(mstr));
1933*7c478bd9Sstevel@tonic-gate 
1934*7c478bd9Sstevel@tonic-gate 		/* Skip whitespaces for N2L */
1935*7c478bd9Sstevel@tonic-gate 		if (skipspaces == 1)
1936*7c478bd9Sstevel@tonic-gate 			for (; *str == ' ' || *str == '\t'; str++);
1937*7c478bd9Sstevel@tonic-gate 
1938*7c478bd9Sstevel@tonic-gate 		return (str);
1939*7c478bd9Sstevel@tonic-gate 
1940*7c478bd9Sstevel@tonic-gate 	case mmt_single:
1941*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0) {
1942*7c478bd9Sstevel@tonic-gate 			match = FALSE;
1943*7c478bd9Sstevel@tonic-gate 			/* Skip ahead until we match */
1944*7c478bd9Sstevel@tonic-gate 			for (next = str; *next != '\0'; next++) {
1945*7c478bd9Sstevel@tonic-gate 				unsigned char	*lo = f[curf].match.single.lo;
1946*7c478bd9Sstevel@tonic-gate 				unsigned char	*hi = f[curf].match.single.hi;
1947*7c478bd9Sstevel@tonic-gate 
1948*7c478bd9Sstevel@tonic-gate 				for (i = 0; i < f[curf].match.single.numRange;
1949*7c478bd9Sstevel@tonic-gate 						i++) {
1950*7c478bd9Sstevel@tonic-gate 					if (*next >= lo[i] && *next <= hi[i]) {
1951*7c478bd9Sstevel@tonic-gate 						match = TRUE;
1952*7c478bd9Sstevel@tonic-gate 						break;
1953*7c478bd9Sstevel@tonic-gate 					}
1954*7c478bd9Sstevel@tonic-gate 				}
1955*7c478bd9Sstevel@tonic-gate 				if (match)
1956*7c478bd9Sstevel@tonic-gate 					break;
1957*7c478bd9Sstevel@tonic-gate 			}
1958*7c478bd9Sstevel@tonic-gate 			if (!match)
1959*7c478bd9Sstevel@tonic-gate 				return (0);
1960*7c478bd9Sstevel@tonic-gate 			*fmtstart = next;
1961*7c478bd9Sstevel@tonic-gate 			str = next;
1962*7c478bd9Sstevel@tonic-gate 		} else {
1963*7c478bd9Sstevel@tonic-gate 			match = FALSE;
1964*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < f[curf].match.single.numRange; i++) {
1965*7c478bd9Sstevel@tonic-gate 				if (*str >= f[curf].match.single.lo[i] &&
1966*7c478bd9Sstevel@tonic-gate 					*str <= f[curf].match.single.hi[i]) {
1967*7c478bd9Sstevel@tonic-gate 					match = TRUE;
1968*7c478bd9Sstevel@tonic-gate 					break;
1969*7c478bd9Sstevel@tonic-gate 				}
1970*7c478bd9Sstevel@tonic-gate 			}
1971*7c478bd9Sstevel@tonic-gate 			if (!match)
1972*7c478bd9Sstevel@tonic-gate 				return (0);
1973*7c478bd9Sstevel@tonic-gate 		}
1974*7c478bd9Sstevel@tonic-gate 		/* Step over the matched character */
1975*7c478bd9Sstevel@tonic-gate 		str++;
1976*7c478bd9Sstevel@tonic-gate 		return (str);
1977*7c478bd9Sstevel@tonic-gate 
1978*7c478bd9Sstevel@tonic-gate 	case mmt_any:
1979*7c478bd9Sstevel@tonic-gate 		/*
1980*7c478bd9Sstevel@tonic-gate 		 * Look ahead to find the beginning of the next element.
1981*7c478bd9Sstevel@tonic-gate 		 * Because a wildcard-match isn't necessarily uniquely
1982*7c478bd9Sstevel@tonic-gate 		 * determined until we've reached the end, we then continue
1983*7c478bd9Sstevel@tonic-gate 		 * to scan ahead.
1984*7c478bd9Sstevel@tonic-gate 		 */
1985*7c478bd9Sstevel@tonic-gate 		while ((next = scanMappingFormat(f, curf+1, nf, str, 0,
1986*7c478bd9Sstevel@tonic-gate 						&start, sepset)) != 0) {
1987*7c478bd9Sstevel@tonic-gate 			char	*tmp = next;
1988*7c478bd9Sstevel@tonic-gate 			int	cf;
1989*7c478bd9Sstevel@tonic-gate 
1990*7c478bd9Sstevel@tonic-gate 			for (cf = curf+2; cf < nf; cf++) {
1991*7c478bd9Sstevel@tonic-gate 				tmp = scanMappingFormat(f, cf, nf, tmp, 0,
1992*7c478bd9Sstevel@tonic-gate 					0, sepset);
1993*7c478bd9Sstevel@tonic-gate 				if (tmp == 0)
1994*7c478bd9Sstevel@tonic-gate 					break;
1995*7c478bd9Sstevel@tonic-gate 			}
1996*7c478bd9Sstevel@tonic-gate 			if (tmp == 0) {
1997*7c478bd9Sstevel@tonic-gate 				str = next;
1998*7c478bd9Sstevel@tonic-gate 			} else if (*tmp == '\0') {
1999*7c478bd9Sstevel@tonic-gate 				break;
2000*7c478bd9Sstevel@tonic-gate 			} else {
2001*7c478bd9Sstevel@tonic-gate 				return (0);
2002*7c478bd9Sstevel@tonic-gate 			}
2003*7c478bd9Sstevel@tonic-gate 		}
2004*7c478bd9Sstevel@tonic-gate 		if (next == 0 || start == 0)
2005*7c478bd9Sstevel@tonic-gate 			return (0);
2006*7c478bd9Sstevel@tonic-gate 
2007*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0)
2008*7c478bd9Sstevel@tonic-gate 			*fmtstart = str;
2009*7c478bd9Sstevel@tonic-gate 
2010*7c478bd9Sstevel@tonic-gate 		return (start);
2011*7c478bd9Sstevel@tonic-gate 
2012*7c478bd9Sstevel@tonic-gate 	case mmt_limit:
2013*7c478bd9Sstevel@tonic-gate 		if (f[curf].match.limit == eos) {
2014*7c478bd9Sstevel@tonic-gate 			if (fmtstart != 0) {
2015*7c478bd9Sstevel@tonic-gate 				/* Skip to the end */
2016*7c478bd9Sstevel@tonic-gate 				str = str + strcspn(str, sepset);
2017*7c478bd9Sstevel@tonic-gate 				*fmtstart = str;
2018*7c478bd9Sstevel@tonic-gate 			} else if (strchr(sepset, *str) == 0) {
2019*7c478bd9Sstevel@tonic-gate 				return (0);
2020*7c478bd9Sstevel@tonic-gate 			}
2021*7c478bd9Sstevel@tonic-gate 		}
2022*7c478bd9Sstevel@tonic-gate 		return (str);
2023*7c478bd9Sstevel@tonic-gate 
2024*7c478bd9Sstevel@tonic-gate 	case mmt_begin:
2025*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0)
2026*7c478bd9Sstevel@tonic-gate 			*fmtstart = str;
2027*7c478bd9Sstevel@tonic-gate 		return (str);
2028*7c478bd9Sstevel@tonic-gate 
2029*7c478bd9Sstevel@tonic-gate 	case mmt_end:
2030*7c478bd9Sstevel@tonic-gate 		if (fmtstart != 0) {
2031*7c478bd9Sstevel@tonic-gate 			/* Skip to the end */
2032*7c478bd9Sstevel@tonic-gate 			str = str + strcspn(str, sepset);
2033*7c478bd9Sstevel@tonic-gate 			*fmtstart = str;
2034*7c478bd9Sstevel@tonic-gate 			return (str);
2035*7c478bd9Sstevel@tonic-gate 		}
2036*7c478bd9Sstevel@tonic-gate 		/* No skipping, so we must be at the end of the value */
2037*7c478bd9Sstevel@tonic-gate 		if (strchr(sepset, *str) == 0)
2038*7c478bd9Sstevel@tonic-gate 			return (0);
2039*7c478bd9Sstevel@tonic-gate 		return (str);
2040*7c478bd9Sstevel@tonic-gate 
2041*7c478bd9Sstevel@tonic-gate 	default:
2042*7c478bd9Sstevel@tonic-gate 		break;
2043*7c478bd9Sstevel@tonic-gate 	}
2044*7c478bd9Sstevel@tonic-gate 
2045*7c478bd9Sstevel@tonic-gate 	return (0);
2046*7c478bd9Sstevel@tonic-gate }
2047*7c478bd9Sstevel@tonic-gate 
2048*7c478bd9Sstevel@tonic-gate /*
2049*7c478bd9Sstevel@tonic-gate  * Verify that the string 'str' matches the mapping format array 'f'.
2050*7c478bd9Sstevel@tonic-gate  * Returns 1 in case of a match, 0 otherwise.
2051*7c478bd9Sstevel@tonic-gate  */
2052*7c478bd9Sstevel@tonic-gate int
2053*7c478bd9Sstevel@tonic-gate verifyMappingMatch(__nis_mapping_format_t *f, char *str) {
2054*7c478bd9Sstevel@tonic-gate 	int			n, nf;
2055*7c478bd9Sstevel@tonic-gate 	__nis_mapping_format_t	*ftmp;
2056*7c478bd9Sstevel@tonic-gate 
2057*7c478bd9Sstevel@tonic-gate 	/* Count the number of format elements in the format */
2058*7c478bd9Sstevel@tonic-gate 	for (nf = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) {
2059*7c478bd9Sstevel@tonic-gate 		nf++;
2060*7c478bd9Sstevel@tonic-gate 	}
2061*7c478bd9Sstevel@tonic-gate 	/* Count the mmt_end as well */
2062*7c478bd9Sstevel@tonic-gate 	nf++;
2063*7c478bd9Sstevel@tonic-gate 
2064*7c478bd9Sstevel@tonic-gate 	for (n = 0; n < nf; n++) {
2065*7c478bd9Sstevel@tonic-gate 		str = scanMappingFormat(f, n, nf, str, 0, 0, 0);
2066*7c478bd9Sstevel@tonic-gate 		if (str == 0)
2067*7c478bd9Sstevel@tonic-gate 			break;
2068*7c478bd9Sstevel@tonic-gate 	}
2069*7c478bd9Sstevel@tonic-gate 
2070*7c478bd9Sstevel@tonic-gate 	return ((str != 0) ? 1 : 0);
2071*7c478bd9Sstevel@tonic-gate }
2072*7c478bd9Sstevel@tonic-gate 
2073*7c478bd9Sstevel@tonic-gate /*
2074*7c478bd9Sstevel@tonic-gate  * Perform a match operation. For example, given the rule
2075*7c478bd9Sstevel@tonic-gate  *	("{%s}%s", auth_name, public_data)=nisPublicKey
2076*7c478bd9Sstevel@tonic-gate  * and assuming that 'nisPublicKey' has the value "{dh640-0}abcdef12345",
2077*7c478bd9Sstevel@tonic-gate  * assign "dh640-0" to 'auth_name' and "abcdef12345" to 'public_data'.
2078*7c478bd9Sstevel@tonic-gate  *
2079*7c478bd9Sstevel@tonic-gate  * Note that this function doesn't perform the actual assignment. Rather,
2080*7c478bd9Sstevel@tonic-gate  * it returns an array of __nis_value_t's, with element zero of the value
2081*7c478bd9Sstevel@tonic-gate  * array being the new value of the first matched item, element one the
2082*7c478bd9Sstevel@tonic-gate  * value of the second matched item, etc. In the example above, we'd
2083*7c478bd9Sstevel@tonic-gate  * return a value array with two elements.
2084*7c478bd9Sstevel@tonic-gate  *
2085*7c478bd9Sstevel@tonic-gate  * If there is more than one input value (inVal->numVals > 1), the
2086*7c478bd9Sstevel@tonic-gate  * output array elements will also be multi-valued.
2087*7c478bd9Sstevel@tonic-gate  *
2088*7c478bd9Sstevel@tonic-gate  * f		The match format
2089*7c478bd9Sstevel@tonic-gate  * inVal	Input value(s)
2090*7c478bd9Sstevel@tonic-gate  * numVal	Number of elements in the output value array
2091*7c478bd9Sstevel@tonic-gate  * sepset	List of separators
2092*7c478bd9Sstevel@tonic-gate  * outstr	Points to the updated position upto which the
2093*7c478bd9Sstevel@tonic-gate  *		input string has been matched
2094*7c478bd9Sstevel@tonic-gate  */
2095*7c478bd9Sstevel@tonic-gate __nis_value_t **
2096*7c478bd9Sstevel@tonic-gate matchMappingItem(__nis_mapping_format_t *f, __nis_value_t *inVal,
2097*7c478bd9Sstevel@tonic-gate 		int *numVals, char *sepset, char **outstr) {
2098*7c478bd9Sstevel@tonic-gate 	__nis_value_t		**v = 0;
2099*7c478bd9Sstevel@tonic-gate 	int			i, n, ni, numItems, nf, nv = 0;
2100*7c478bd9Sstevel@tonic-gate 	char			*str, *valstr;
2101*7c478bd9Sstevel@tonic-gate 	__nis_mapping_format_t	*ftmp;
2102*7c478bd9Sstevel@tonic-gate 	char			*myself = "matchMappingItem";
2103*7c478bd9Sstevel@tonic-gate 
2104*7c478bd9Sstevel@tonic-gate 	if (f == 0 ||
2105*7c478bd9Sstevel@tonic-gate 		inVal == 0 || inVal->numVals < 1 || inVal->type != vt_string)
2106*7c478bd9Sstevel@tonic-gate 		return (0);
2107*7c478bd9Sstevel@tonic-gate 
2108*7c478bd9Sstevel@tonic-gate 	/* Count the number of format elements and items in the format */
2109*7c478bd9Sstevel@tonic-gate 	for (nf = numItems = 0, ftmp = f; ftmp->type != mmt_end; ftmp++) {
2110*7c478bd9Sstevel@tonic-gate 		nf++;
2111*7c478bd9Sstevel@tonic-gate 
2112*7c478bd9Sstevel@tonic-gate 		/*
2113*7c478bd9Sstevel@tonic-gate 		 * Count mmt_item and mmt_berstring (used by N2L to
2114*7c478bd9Sstevel@tonic-gate 		 * represent address %a)
2115*7c478bd9Sstevel@tonic-gate 		 */
2116*7c478bd9Sstevel@tonic-gate 		if (ftmp->type == mmt_item)
2117*7c478bd9Sstevel@tonic-gate 				numItems++;
2118*7c478bd9Sstevel@tonic-gate 		else if (ftmp->type == mmt_berstring && ftmp->match.berString &&
2119*7c478bd9Sstevel@tonic-gate 				ftmp->match.berString[0] == 'a')
2120*7c478bd9Sstevel@tonic-gate 				numItems++;
2121*7c478bd9Sstevel@tonic-gate 	}
2122*7c478bd9Sstevel@tonic-gate 	/* Count the mmt_end as well */
2123*7c478bd9Sstevel@tonic-gate 	nf++;
2124*7c478bd9Sstevel@tonic-gate 
2125*7c478bd9Sstevel@tonic-gate 	/*
2126*7c478bd9Sstevel@tonic-gate 	 * If no items, there will be no values. This isn't exactly an error
2127*7c478bd9Sstevel@tonic-gate 	 * from the limited point of view of this function, so we return a
2128*7c478bd9Sstevel@tonic-gate 	 * __nis_value_t with zero values.
2129*7c478bd9Sstevel@tonic-gate 	 */
2130*7c478bd9Sstevel@tonic-gate 	if (numItems <= 0) {
2131*7c478bd9Sstevel@tonic-gate 		v = am(myself, sizeof (v[0]));
2132*7c478bd9Sstevel@tonic-gate 		if (v == 0)
2133*7c478bd9Sstevel@tonic-gate 			return (0);
2134*7c478bd9Sstevel@tonic-gate 		v[0] = am(myself, sizeof (*v[0]));
2135*7c478bd9Sstevel@tonic-gate 		if (v[0] == 0) {
2136*7c478bd9Sstevel@tonic-gate 			sfree(v);
2137*7c478bd9Sstevel@tonic-gate 			return (0);
2138*7c478bd9Sstevel@tonic-gate 		}
2139*7c478bd9Sstevel@tonic-gate 		v[0]->type = vt_string;
2140*7c478bd9Sstevel@tonic-gate 		v[0]->numVals = 0;
2141*7c478bd9Sstevel@tonic-gate 		v[0]->val = 0;
2142*7c478bd9Sstevel@tonic-gate 		if (numVals != 0)
2143*7c478bd9Sstevel@tonic-gate 			*numVals = 1;
2144*7c478bd9Sstevel@tonic-gate 		return (v);
2145*7c478bd9Sstevel@tonic-gate 	}
2146*7c478bd9Sstevel@tonic-gate 
2147*7c478bd9Sstevel@tonic-gate 	/* Allocate and initialize the return array */
2148*7c478bd9Sstevel@tonic-gate 	v = am(myself, numItems * sizeof (v[0]));
2149*7c478bd9Sstevel@tonic-gate 	if (v == 0)
2150*7c478bd9Sstevel@tonic-gate 		return (0);
2151*7c478bd9Sstevel@tonic-gate 	for (n = 0; n < numItems; n++) {
2152*7c478bd9Sstevel@tonic-gate 		v[n] = am(myself, sizeof (*v[n]));
2153*7c478bd9Sstevel@tonic-gate 		if (v[n] == 0) {
2154*7c478bd9Sstevel@tonic-gate 			int	j;
2155*7c478bd9Sstevel@tonic-gate 
2156*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < n; j++)
2157*7c478bd9Sstevel@tonic-gate 				freeValue(v[j], 1);
2158*7c478bd9Sstevel@tonic-gate 			sfree(v);
2159*7c478bd9Sstevel@tonic-gate 			return (0);
2160*7c478bd9Sstevel@tonic-gate 		}
2161*7c478bd9Sstevel@tonic-gate 		v[n]->type = vt_string;
2162*7c478bd9Sstevel@tonic-gate 		v[n]->numVals = 0;
2163*7c478bd9Sstevel@tonic-gate 		v[n]->val = am(myself, inVal->numVals * sizeof (v[n]->val[0]));
2164*7c478bd9Sstevel@tonic-gate 		if (v[n]->val == 0) {
2165*7c478bd9Sstevel@tonic-gate 			int	j;
2166*7c478bd9Sstevel@tonic-gate 
2167*7c478bd9Sstevel@tonic-gate 			for (j = 0; j < n; j++)
2168*7c478bd9Sstevel@tonic-gate 				freeValue(v[j], 1);
2169*7c478bd9Sstevel@tonic-gate 			sfree(v);
2170*7c478bd9Sstevel@tonic-gate 			return (0);
2171*7c478bd9Sstevel@tonic-gate 		}
2172*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < inVal->numVals; i++) {
2173*7c478bd9Sstevel@tonic-gate 			v[n]->val[i].length = 0;
2174*7c478bd9Sstevel@tonic-gate 			v[n]->val[i].value = 0;
2175*7c478bd9Sstevel@tonic-gate 		}
2176*7c478bd9Sstevel@tonic-gate 	}
2177*7c478bd9Sstevel@tonic-gate 
2178*7c478bd9Sstevel@tonic-gate 	/* For each input value, perform the match operation */
2179*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < inVal->numVals; i++) {
2180*7c478bd9Sstevel@tonic-gate 		str = inVal->val[i].value;
2181*7c478bd9Sstevel@tonic-gate 		if (str == 0)
2182*7c478bd9Sstevel@tonic-gate 			continue;
2183*7c478bd9Sstevel@tonic-gate 		for (n = 0, ni = 0; n < nf; n++) {
2184*7c478bd9Sstevel@tonic-gate 			valstr = 0;
2185*7c478bd9Sstevel@tonic-gate 			str = scanMappingFormat(f, n, nf, str, &valstr,
2186*7c478bd9Sstevel@tonic-gate 				0, sepset);
2187*7c478bd9Sstevel@tonic-gate 			if (str == 0)
2188*7c478bd9Sstevel@tonic-gate 				break;
2189*7c478bd9Sstevel@tonic-gate 			if (valstr != 0 && ni < numItems &&
2190*7c478bd9Sstevel@tonic-gate 					v[ni]->numVals < inVal->numVals) {
2191*7c478bd9Sstevel@tonic-gate 				v[ni]->val[v[ni]->numVals].value = valstr;
2192*7c478bd9Sstevel@tonic-gate 				v[ni]->val[v[ni]->numVals].length =
2193*7c478bd9Sstevel@tonic-gate 							strlen(valstr) + 1;
2194*7c478bd9Sstevel@tonic-gate 				v[ni]->numVals++;
2195*7c478bd9Sstevel@tonic-gate 				ni++;
2196*7c478bd9Sstevel@tonic-gate 			} else if (valstr != 0) {
2197*7c478bd9Sstevel@tonic-gate 				sfree(valstr);
2198*7c478bd9Sstevel@tonic-gate 			}
2199*7c478bd9Sstevel@tonic-gate 		}
2200*7c478bd9Sstevel@tonic-gate 		if (str == 0) {
2201*7c478bd9Sstevel@tonic-gate 			for (n = 0; n < numItems; n++)
2202*7c478bd9Sstevel@tonic-gate 				freeValue(v[n], 1);
2203*7c478bd9Sstevel@tonic-gate 			sfree(v);
2204*7c478bd9Sstevel@tonic-gate 			return (0);
2205*7c478bd9Sstevel@tonic-gate 		}
2206*7c478bd9Sstevel@tonic-gate 	}
2207*7c478bd9Sstevel@tonic-gate 
2208*7c478bd9Sstevel@tonic-gate 	if (numVals != 0)
2209*7c478bd9Sstevel@tonic-gate 		*numVals = numItems;
2210*7c478bd9Sstevel@tonic-gate 
2211*7c478bd9Sstevel@tonic-gate 	/*
2212*7c478bd9Sstevel@tonic-gate 	 * Update the return string upto the point it has been matched
2213*7c478bd9Sstevel@tonic-gate 	 * This string will be used by the N2L code in its next call
2214*7c478bd9Sstevel@tonic-gate 	 * to this function
2215*7c478bd9Sstevel@tonic-gate 	 */
2216*7c478bd9Sstevel@tonic-gate 	if (outstr != 0)
2217*7c478bd9Sstevel@tonic-gate 		*outstr = str;
2218*7c478bd9Sstevel@tonic-gate 
2219*7c478bd9Sstevel@tonic-gate 	return (v);
2220*7c478bd9Sstevel@tonic-gate }
2221*7c478bd9Sstevel@tonic-gate 
2222*7c478bd9Sstevel@tonic-gate /*
2223*7c478bd9Sstevel@tonic-gate  * Perform an extract operation. For example, given the expression
2224*7c478bd9Sstevel@tonic-gate  *	(name, "%s.*")
2225*7c478bd9Sstevel@tonic-gate  * and assuming 'name' is an item with the value "some.thing", the
2226*7c478bd9Sstevel@tonic-gate  * value returned by the extract is "some".
2227*7c478bd9Sstevel@tonic-gate  */
2228*7c478bd9Sstevel@tonic-gate __nis_value_t *
2229*7c478bd9Sstevel@tonic-gate extractMappingItem(__nis_mapping_item_t *item, __nis_mapping_format_t *f,
2230*7c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv, int *stat) {
2231*7c478bd9Sstevel@tonic-gate 	__nis_value_t		*val = getMappingItem(item, mit_any,
2232*7c478bd9Sstevel@tonic-gate 			rv, 0, stat);
2233*7c478bd9Sstevel@tonic-gate 	__nis_single_value_t	*nval;
2234*7c478bd9Sstevel@tonic-gate 	int			i, n, nv, nf;
2235*7c478bd9Sstevel@tonic-gate 	__nis_mapping_format_t	*ftmp;
2236*7c478bd9Sstevel@tonic-gate 
2237*7c478bd9Sstevel@tonic-gate 	if (val == 0)
2238*7c478bd9Sstevel@tonic-gate 		return (0);
2239*7c478bd9Sstevel@tonic-gate 	else if (f == 0 || rv == 0 || val->val == 0 ||
2240*7c478bd9Sstevel@tonic-gate 			val->numVals <= 0 || val->type != vt_string) {
2241*7c478bd9Sstevel@tonic-gate 		freeValue(val, 1);
2242*7c478bd9Sstevel@tonic-gate 		return (0);
2243*7c478bd9Sstevel@tonic-gate 	}
2244*7c478bd9Sstevel@tonic-gate 
2245*7c478bd9Sstevel@tonic-gate 	/* Sanity check the format; it must have one and only one mmt_item */
2246*7c478bd9Sstevel@tonic-gate 	{
2247*7c478bd9Sstevel@tonic-gate 		int	numitem;
2248*7c478bd9Sstevel@tonic-gate 
2249*7c478bd9Sstevel@tonic-gate 		for (nf = numitem = 0, ftmp = f; ftmp->type != mmt_end;
2250*7c478bd9Sstevel@tonic-gate 				ftmp++) {
2251*7c478bd9Sstevel@tonic-gate 			nf++;
2252*7c478bd9Sstevel@tonic-gate 			if (ftmp->type == mmt_item)
2253*7c478bd9Sstevel@tonic-gate 				numitem++;
2254*7c478bd9Sstevel@tonic-gate 		}
2255*7c478bd9Sstevel@tonic-gate 		/* Count the mmt_end as well */
2256*7c478bd9Sstevel@tonic-gate 		nf++;
2257*7c478bd9Sstevel@tonic-gate 		if (numitem != 1) {
2258*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
2259*7c478bd9Sstevel@tonic-gate 			return (0);
2260*7c478bd9Sstevel@tonic-gate 		}
2261*7c478bd9Sstevel@tonic-gate 	}
2262*7c478bd9Sstevel@tonic-gate 
2263*7c478bd9Sstevel@tonic-gate 	nval = val->val;
2264*7c478bd9Sstevel@tonic-gate 	nv = val->numVals;
2265*7c478bd9Sstevel@tonic-gate 	val->repeat = FALSE;
2266*7c478bd9Sstevel@tonic-gate 	val->val = 0;
2267*7c478bd9Sstevel@tonic-gate 	val->numVals = 0;
2268*7c478bd9Sstevel@tonic-gate 
2269*7c478bd9Sstevel@tonic-gate 	/* If the item has multiple values, we extract each one independently */
2270*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < nv; i++) {
2271*7c478bd9Sstevel@tonic-gate 		char			*str = nval[i].value;
2272*7c478bd9Sstevel@tonic-gate 		char			*newstr = 0;
2273*7c478bd9Sstevel@tonic-gate 		__nis_single_value_t	*newval;
2274*7c478bd9Sstevel@tonic-gate 
2275*7c478bd9Sstevel@tonic-gate 		if (nval[i].value == 0)
2276*7c478bd9Sstevel@tonic-gate 			continue;
2277*7c478bd9Sstevel@tonic-gate 
2278*7c478bd9Sstevel@tonic-gate 		/*
2279*7c478bd9Sstevel@tonic-gate 		 * We match the whole string, even if we find a value for
2280*7c478bd9Sstevel@tonic-gate 		 * the item before exhausting all format elements. By doing
2281*7c478bd9Sstevel@tonic-gate 		 * this, we ensure that the string really matches the complete
2282*7c478bd9Sstevel@tonic-gate 		 * format specification.
2283*7c478bd9Sstevel@tonic-gate 		 */
2284*7c478bd9Sstevel@tonic-gate 		for (n = 0; n < nf; n++) {
2285*7c478bd9Sstevel@tonic-gate 			str = scanMappingFormat(f, n, nf, str, &newstr, 0, 0);
2286*7c478bd9Sstevel@tonic-gate 			if (str == 0)
2287*7c478bd9Sstevel@tonic-gate 				break;
2288*7c478bd9Sstevel@tonic-gate 		}
2289*7c478bd9Sstevel@tonic-gate 
2290*7c478bd9Sstevel@tonic-gate 		/*
2291*7c478bd9Sstevel@tonic-gate 		 * *str should now be NUL, meaning we've reached the end of
2292*7c478bd9Sstevel@tonic-gate 		 * the string (value), and it completely matched the format.
2293*7c478bd9Sstevel@tonic-gate 		 * If 'str' is NULL, there was an error, and if 'newstr' is
2294*7c478bd9Sstevel@tonic-gate 		 * 0, we somehow failed to obtain a value.
2295*7c478bd9Sstevel@tonic-gate 		 */
2296*7c478bd9Sstevel@tonic-gate 		if (str == 0 || *str != '\0' || newstr == 0 ||
2297*7c478bd9Sstevel@tonic-gate 				(newval = realloc(val->val,
2298*7c478bd9Sstevel@tonic-gate 					(val->numVals+1) *
2299*7c478bd9Sstevel@tonic-gate 					sizeof (val->val[0]))) == 0) {
2300*7c478bd9Sstevel@tonic-gate 			freeValue(val, 1);
2301*7c478bd9Sstevel@tonic-gate 			for (n = 0; n < nv; n++) {
2302*7c478bd9Sstevel@tonic-gate 				sfree(nval[n].value);
2303*7c478bd9Sstevel@tonic-gate 			}
2304*7c478bd9Sstevel@tonic-gate 			free(nval);
2305*7c478bd9Sstevel@tonic-gate 			sfree(newstr);
2306*7c478bd9Sstevel@tonic-gate 			return (0);
2307*7c478bd9Sstevel@tonic-gate 		}
2308*7c478bd9Sstevel@tonic-gate 
2309*7c478bd9Sstevel@tonic-gate 		val->val = newval;
2310*7c478bd9Sstevel@tonic-gate 		val->val[val->numVals].value = newstr;
2311*7c478bd9Sstevel@tonic-gate 		val->val[val->numVals].length = strlen(newstr) + 1;
2312*7c478bd9Sstevel@tonic-gate 		val->numVals++;
2313*7c478bd9Sstevel@tonic-gate 
2314*7c478bd9Sstevel@tonic-gate 		free(nval[i].value);
2315*7c478bd9Sstevel@tonic-gate 		nval[i].value = 0;
2316*7c478bd9Sstevel@tonic-gate 	}
2317*7c478bd9Sstevel@tonic-gate 	free(nval);
2318*7c478bd9Sstevel@tonic-gate 
2319*7c478bd9Sstevel@tonic-gate 	return (val);
2320*7c478bd9Sstevel@tonic-gate }
2321*7c478bd9Sstevel@tonic-gate 
2322*7c478bd9Sstevel@tonic-gate /*
2323*7c478bd9Sstevel@tonic-gate  * For each value in 'val', remove the last character, provided that
2324*7c478bd9Sstevel@tonic-gate  * it matches 'elide'.
2325*7c478bd9Sstevel@tonic-gate  */
2326*7c478bd9Sstevel@tonic-gate void
2327*7c478bd9Sstevel@tonic-gate stringElide(__nis_value_t *val, char elide) {
2328*7c478bd9Sstevel@tonic-gate 
2329*7c478bd9Sstevel@tonic-gate 	if (val != 0 && val->type == vt_string) {
2330*7c478bd9Sstevel@tonic-gate 		int	i;
2331*7c478bd9Sstevel@tonic-gate 
2332*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < val->numVals; i++) {
2333*7c478bd9Sstevel@tonic-gate 			int	end = val->val[i].length;
2334*7c478bd9Sstevel@tonic-gate 			char	*str = val->val[i].value;
2335*7c478bd9Sstevel@tonic-gate 
2336*7c478bd9Sstevel@tonic-gate 			if (str == 0 || end <= 0)
2337*7c478bd9Sstevel@tonic-gate 				continue;
2338*7c478bd9Sstevel@tonic-gate 
2339*7c478bd9Sstevel@tonic-gate 			/*
2340*7c478bd9Sstevel@tonic-gate 			 * If the NUL was counted in the length, step back
2341*7c478bd9Sstevel@tonic-gate 			 * over it.
2342*7c478bd9Sstevel@tonic-gate 			 */
2343*7c478bd9Sstevel@tonic-gate 			if (str[end-1] == '\0')
2344*7c478bd9Sstevel@tonic-gate 				end--;
2345*7c478bd9Sstevel@tonic-gate 			if (end > 0 && str[end-1] == elide) {
2346*7c478bd9Sstevel@tonic-gate 				str[end-1] = '\0';
2347*7c478bd9Sstevel@tonic-gate 				val->val[i].length--;
2348*7c478bd9Sstevel@tonic-gate 			}
2349*7c478bd9Sstevel@tonic-gate 		}
2350*7c478bd9Sstevel@tonic-gate 	}
2351*7c478bd9Sstevel@tonic-gate }
2352*7c478bd9Sstevel@tonic-gate 
2353*7c478bd9Sstevel@tonic-gate /*
2354*7c478bd9Sstevel@tonic-gate  * Obtain the value for the mapping sub-element 'e', given the input
2355*7c478bd9Sstevel@tonic-gate  * rule-value 'rv'.
2356*7c478bd9Sstevel@tonic-gate  */
2357*7c478bd9Sstevel@tonic-gate __nis_value_t *
2358*7c478bd9Sstevel@tonic-gate getMappingSubElement(__nis_mapping_sub_element_t *e,
2359*7c478bd9Sstevel@tonic-gate 	__nis_rule_value_t *rv, int *np_ldap_stat) {
2360*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val;
2361*7c478bd9Sstevel@tonic-gate 
2362*7c478bd9Sstevel@tonic-gate 	if (e == 0)
2363*7c478bd9Sstevel@tonic-gate 		return (0);
2364*7c478bd9Sstevel@tonic-gate 
2365*7c478bd9Sstevel@tonic-gate 	switch (e->type) {
2366*7c478bd9Sstevel@tonic-gate 	case me_item:
2367*7c478bd9Sstevel@tonic-gate 		val = getMappingItem(&e->element.item, mit_any, rv, 0,
2368*7c478bd9Sstevel@tonic-gate 			np_ldap_stat);
2369*7c478bd9Sstevel@tonic-gate 		break;
2370*7c478bd9Sstevel@tonic-gate 	case me_print:
2371*7c478bd9Sstevel@tonic-gate 		val = getMappingFormatArray(e->element.print.fmt, rv,
2372*7c478bd9Sstevel@tonic-gate 						fa_item,
2373*7c478bd9Sstevel@tonic-gate 						e->element.print.numItems,
2374*7c478bd9Sstevel@tonic-gate 						e->element.print.item);
2375*7c478bd9Sstevel@tonic-gate 		if (e->element.print.doElide)
2376*7c478bd9Sstevel@tonic-gate 			stringElide(val, e->element.print.elide);
2377*7c478bd9Sstevel@tonic-gate 		break;
2378*7c478bd9Sstevel@tonic-gate 	case me_split:
2379*7c478bd9Sstevel@tonic-gate 		val = splitMappingItem(&e->element.split.item,
2380*7c478bd9Sstevel@tonic-gate 					e->element.split.delim,
2381*7c478bd9Sstevel@tonic-gate 					rv);
2382*7c478bd9Sstevel@tonic-gate 		break;
2383*7c478bd9Sstevel@tonic-gate 	case me_extract:
2384*7c478bd9Sstevel@tonic-gate 		val = extractMappingItem(&e->element.extract.item,
2385*7c478bd9Sstevel@tonic-gate 					e->element.extract.fmt,
2386*7c478bd9Sstevel@tonic-gate 					rv, np_ldap_stat);
2387*7c478bd9Sstevel@tonic-gate 		break;
2388*7c478bd9Sstevel@tonic-gate 	case me_match:
2389*7c478bd9Sstevel@tonic-gate 	default:
2390*7c478bd9Sstevel@tonic-gate 		val = 0;
2391*7c478bd9Sstevel@tonic-gate 		break;
2392*7c478bd9Sstevel@tonic-gate 	}
2393*7c478bd9Sstevel@tonic-gate 
2394*7c478bd9Sstevel@tonic-gate 	return (val);
2395*7c478bd9Sstevel@tonic-gate }
2396*7c478bd9Sstevel@tonic-gate 
2397*7c478bd9Sstevel@tonic-gate /*
2398*7c478bd9Sstevel@tonic-gate  * Obtain the value of the mapping element 'e', given the input rule-
2399*7c478bd9Sstevel@tonic-gate  * value 'rv'. The 'native' mapping type is used when 'rv' is NULL,
2400*7c478bd9Sstevel@tonic-gate  * and the result is a string representation of the mapping element;
2401*7c478bd9Sstevel@tonic-gate  * in that case, items of the 'native' type are printed without their
2402*7c478bd9Sstevel@tonic-gate  * type designation ("nis+" or "ldap").
2403*7c478bd9Sstevel@tonic-gate  */
2404*7c478bd9Sstevel@tonic-gate __nis_value_t *
2405*7c478bd9Sstevel@tonic-gate getMappingElement(__nis_mapping_element_t *e, __nis_mapping_item_type_t native,
2406*7c478bd9Sstevel@tonic-gate 		__nis_rule_value_t *rv, int *stat) {
2407*7c478bd9Sstevel@tonic-gate 	__nis_value_t	*val, **tv;
2408*7c478bd9Sstevel@tonic-gate 	int		i, success = 0, novalue = 0;
2409*7c478bd9Sstevel@tonic-gate 	int *np_ldap_stat;
2410*7c478bd9Sstevel@tonic-gate 	char		*myself = "getMappingElement";
2411*7c478bd9Sstevel@tonic-gate 
2412*7c478bd9Sstevel@tonic-gate 	switch (e->type) {
2413*7c478bd9Sstevel@tonic-gate 	case me_item:
2414*7c478bd9Sstevel@tonic-gate 		val = getMappingItem(&e->element.item, native, rv, 0, NULL);
2415*7c478bd9Sstevel@tonic-gate 		break;
2416*7c478bd9Sstevel@tonic-gate 	case me_print:
2417*7c478bd9Sstevel@tonic-gate 		tv = am(myself, e->element.print.numSubElements *
2418*7c478bd9Sstevel@tonic-gate 			sizeof (tv[0]));
2419*7c478bd9Sstevel@tonic-gate 		np_ldap_stat = am(myself,
2420*7c478bd9Sstevel@tonic-gate 			e->element.print.numSubElements * sizeof (int));
2421*7c478bd9Sstevel@tonic-gate 		if ((e->element.print.numSubElements > 0) &&
2422*7c478bd9Sstevel@tonic-gate 				(tv == 0 || np_ldap_stat == 0)) {
2423*7c478bd9Sstevel@tonic-gate 			val = 0;
2424*7c478bd9Sstevel@tonic-gate 			sfree(tv);
2425*7c478bd9Sstevel@tonic-gate 			sfree(np_ldap_stat);
2426*7c478bd9Sstevel@tonic-gate 			break;
2427*7c478bd9Sstevel@tonic-gate 		}
2428*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < e->element.print.numSubElements; i++) {
2429*7c478bd9Sstevel@tonic-gate 			np_ldap_stat[i] = 0;
2430*7c478bd9Sstevel@tonic-gate 			tv[i] = getMappingSubElement(
2431*7c478bd9Sstevel@tonic-gate 				&e->element.print.subElement[i],
2432*7c478bd9Sstevel@tonic-gate 				rv, &np_ldap_stat[i]);
2433*7c478bd9Sstevel@tonic-gate 		}
2434*7c478bd9Sstevel@tonic-gate 		/*
2435*7c478bd9Sstevel@tonic-gate 		 * if we get NP_LDAP_NO_VALUE to any of the subelement
2436*7c478bd9Sstevel@tonic-gate 		 * and we get NP_LDAP_MAP_SUCCESS to all other subelement
2437*7c478bd9Sstevel@tonic-gate 		 * then we had enough nis+ column values which can
2438*7c478bd9Sstevel@tonic-gate 		 * produce value for this rule, but didn't. So return
2439*7c478bd9Sstevel@tonic-gate 		 * NP_LDAP_RULES_NO_VALUE to indicate to proceed to
2440*7c478bd9Sstevel@tonic-gate 		 * next database id.
2441*7c478bd9Sstevel@tonic-gate 		 */
2442*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < e->element.print.numSubElements; i++) {
2443*7c478bd9Sstevel@tonic-gate 			if (np_ldap_stat[i] == NP_LDAP_MAP_SUCCESS)
2444*7c478bd9Sstevel@tonic-gate 				success++;
2445*7c478bd9Sstevel@tonic-gate 			if (np_ldap_stat[i] == NP_LDAP_NO_VALUE)
2446*7c478bd9Sstevel@tonic-gate 				novalue++;
2447*7c478bd9Sstevel@tonic-gate 		}
2448*7c478bd9Sstevel@tonic-gate 		if (stat != NULL && novalue > 0 &&
2449*7c478bd9Sstevel@tonic-gate 				((novalue+success) ==
2450*7c478bd9Sstevel@tonic-gate 					e->element.print.numSubElements))
2451*7c478bd9Sstevel@tonic-gate 					    *stat = NP_LDAP_RULES_NO_VALUE;
2452*7c478bd9Sstevel@tonic-gate 		val = getMappingFormatArray(e->element.print.fmt, rv,
2453*7c478bd9Sstevel@tonic-gate 						fa_value,
2454*7c478bd9Sstevel@tonic-gate 						e->element.print.numSubElements,
2455*7c478bd9Sstevel@tonic-gate 						tv);
2456*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < e->element.print.numSubElements; i++) {
2457*7c478bd9Sstevel@tonic-gate 			freeValue(tv[i], 1);
2458*7c478bd9Sstevel@tonic-gate 		}
2459*7c478bd9Sstevel@tonic-gate 		sfree(tv);
2460*7c478bd9Sstevel@tonic-gate 		sfree(np_ldap_stat);
2461*7c478bd9Sstevel@tonic-gate 		if (e->element.print.doElide)
2462*7c478bd9Sstevel@tonic-gate 			stringElide(val, e->element.print.elide);
2463*7c478bd9Sstevel@tonic-gate 		break;
2464*7c478bd9Sstevel@tonic-gate 	case me_split:
2465*7c478bd9Sstevel@tonic-gate 		val = splitMappingItem(&e->element.split.item,
2466*7c478bd9Sstevel@tonic-gate 					e->element.split.delim,
2467*7c478bd9Sstevel@tonic-gate 					rv);
2468*7c478bd9Sstevel@tonic-gate 		break;
2469*7c478bd9Sstevel@tonic-gate 	case me_match:
2470*7c478bd9Sstevel@tonic-gate 		/*
2471*7c478bd9Sstevel@tonic-gate 		 * A match doesn't produce an assignable value per se,
2472*7c478bd9Sstevel@tonic-gate 		 * so we shouldn't get one here.
2473*7c478bd9Sstevel@tonic-gate 		 */
2474*7c478bd9Sstevel@tonic-gate 		val = 0;
2475*7c478bd9Sstevel@tonic-gate 		break;
2476*7c478bd9Sstevel@tonic-gate 	case me_extract:
2477*7c478bd9Sstevel@tonic-gate 		val = extractMappingItem(&e->element.extract.item,
2478*7c478bd9Sstevel@tonic-gate 					e->element.extract.fmt,
2479*7c478bd9Sstevel@tonic-gate 					rv, NULL);
2480*7c478bd9Sstevel@tonic-gate 		break;
2481*7c478bd9Sstevel@tonic-gate 	default:
2482*7c478bd9Sstevel@tonic-gate 		val = 0;
2483*7c478bd9Sstevel@tonic-gate 		break;
2484*7c478bd9Sstevel@tonic-gate 	}
2485*7c478bd9Sstevel@tonic-gate 
2486*7c478bd9Sstevel@tonic-gate 	return (val);
2487*7c478bd9Sstevel@tonic-gate }
2488