1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  *
3*0Sstevel@tonic-gate  * Portions Copyright %G% Sun Microsystems, Inc.
4*0Sstevel@tonic-gate  * All Rights Reserved
5*0Sstevel@tonic-gate  *
6*0Sstevel@tonic-gate  */
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
9*0Sstevel@tonic-gate 
10*0Sstevel@tonic-gate /*
11*0Sstevel@tonic-gate  *  Copyright (c) 1994 Regents of the University of Michigan.
12*0Sstevel@tonic-gate  *  All rights reserved.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  *  getdn.c
15*0Sstevel@tonic-gate  */
16*0Sstevel@tonic-gate 
17*0Sstevel@tonic-gate #ifndef lint
18*0Sstevel@tonic-gate static char copyright[] = "@(#) Copyright (c) 1990 Regents of the University of Michigan.\nAll rights reserved.\n";
19*0Sstevel@tonic-gate #endif
20*0Sstevel@tonic-gate 
21*0Sstevel@tonic-gate #include <stdio.h>
22*0Sstevel@tonic-gate #include <ctype.h>
23*0Sstevel@tonic-gate #include <string.h>
24*0Sstevel@tonic-gate #include <stdlib.h> /* malloc(), realloc(), calloc() for Solaris */
25*0Sstevel@tonic-gate #ifdef MACOS
26*0Sstevel@tonic-gate #include <stdlib.h>
27*0Sstevel@tonic-gate #include "macos.h"
28*0Sstevel@tonic-gate #else /* MACOS */
29*0Sstevel@tonic-gate #if defined( DOS ) || defined( _WIN32 )
30*0Sstevel@tonic-gate #include <malloc.h>
31*0Sstevel@tonic-gate #include "msdos.h"
32*0Sstevel@tonic-gate #else /* DOS */
33*0Sstevel@tonic-gate #include <sys/types.h>
34*0Sstevel@tonic-gate #include <sys/socket.h>
35*0Sstevel@tonic-gate #endif /* DOS */
36*0Sstevel@tonic-gate #endif /* MACOS */
37*0Sstevel@tonic-gate 
38*0Sstevel@tonic-gate #include "lber.h"
39*0Sstevel@tonic-gate #include "ldap.h"
40*0Sstevel@tonic-gate #include "ldap-private.h"
41*0Sstevel@tonic-gate #include "ldap-int.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate char *
44*0Sstevel@tonic-gate ldap_get_dn( LDAP *ld, LDAPMessage *entry )
45*0Sstevel@tonic-gate {
46*0Sstevel@tonic-gate 	char		*dn;
47*0Sstevel@tonic-gate 	BerElement	tmp;
48*0Sstevel@tonic-gate 
49*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 181, "ldap_get_dn\n"), 0, 0, 0 );
50*0Sstevel@tonic-gate 
51*0Sstevel@tonic-gate 	if ( entry == NULL ) {
52*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_PARAM_ERROR;
53*0Sstevel@tonic-gate 		return( NULL );
54*0Sstevel@tonic-gate 	}
55*0Sstevel@tonic-gate 
56*0Sstevel@tonic-gate 	tmp = *entry->lm_ber;	/* struct copy */
57*0Sstevel@tonic-gate 	if ( ber_scanf( &tmp, "{a", &dn ) == LBER_ERROR ) {
58*0Sstevel@tonic-gate 		ld->ld_errno = LDAP_DECODING_ERROR;
59*0Sstevel@tonic-gate 		return( NULL );
60*0Sstevel@tonic-gate 	}
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	return( dn );
63*0Sstevel@tonic-gate }
64*0Sstevel@tonic-gate 
65*0Sstevel@tonic-gate char *
66*0Sstevel@tonic-gate ldap_dn2ufn( char *dn )
67*0Sstevel@tonic-gate {
68*0Sstevel@tonic-gate 	char	*p, *ufn, *r;
69*0Sstevel@tonic-gate 	int	state;
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 182, "ldap_dn2ufn\n"), 0, 0, 0 );
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate 	if ( ldap_is_dns_dn( dn ) || ( p = strchr( dn, '=' )) == NULL )
74*0Sstevel@tonic-gate 		return( strdup( dn ));
75*0Sstevel@tonic-gate 
76*0Sstevel@tonic-gate 	ufn = strdup( ++p );
77*0Sstevel@tonic-gate 
78*0Sstevel@tonic-gate #define INQUOTE		1
79*0Sstevel@tonic-gate #define OUTQUOTE	2
80*0Sstevel@tonic-gate 	state = OUTQUOTE;
81*0Sstevel@tonic-gate 	for ( p = ufn, r = ufn; *p; p++ ) {
82*0Sstevel@tonic-gate 		switch ( *p ) {
83*0Sstevel@tonic-gate 		case '\\':
84*0Sstevel@tonic-gate 			if ( *++p == '\0' )
85*0Sstevel@tonic-gate 				p--;
86*0Sstevel@tonic-gate 			else {
87*0Sstevel@tonic-gate 				*r++ = '\\';
88*0Sstevel@tonic-gate 				*r++ = *p;
89*0Sstevel@tonic-gate 			}
90*0Sstevel@tonic-gate 			break;
91*0Sstevel@tonic-gate 		case '"':
92*0Sstevel@tonic-gate 			if ( state == INQUOTE )
93*0Sstevel@tonic-gate 				state = OUTQUOTE;
94*0Sstevel@tonic-gate 			else
95*0Sstevel@tonic-gate 				state = INQUOTE;
96*0Sstevel@tonic-gate 			*r++ = *p;
97*0Sstevel@tonic-gate 			break;
98*0Sstevel@tonic-gate 		case ';':
99*0Sstevel@tonic-gate 		case ',':
100*0Sstevel@tonic-gate 			if ( state == OUTQUOTE )
101*0Sstevel@tonic-gate 				*r++ = ',';
102*0Sstevel@tonic-gate 			else
103*0Sstevel@tonic-gate 				*r++ = *p;
104*0Sstevel@tonic-gate 			break;
105*0Sstevel@tonic-gate 		case '=':
106*0Sstevel@tonic-gate 			if ( state == INQUOTE )
107*0Sstevel@tonic-gate 				*r++ = *p;
108*0Sstevel@tonic-gate 			else {
109*0Sstevel@tonic-gate 				char	*rsave = r;
110*0Sstevel@tonic-gate 
111*0Sstevel@tonic-gate 				*r-- = '\0';
112*0Sstevel@tonic-gate 				while ( !isspace( *r ) && *r != ';'
113*0Sstevel@tonic-gate 				    && *r != ',' && r > ufn )
114*0Sstevel@tonic-gate 					r--;
115*0Sstevel@tonic-gate 				r++;
116*0Sstevel@tonic-gate 
117*0Sstevel@tonic-gate 				if ( strcasecmp( r, "c" )
118*0Sstevel@tonic-gate 				    && strcasecmp( r, "o" )
119*0Sstevel@tonic-gate 				    && strcasecmp( r, "ou" )
120*0Sstevel@tonic-gate 				    && strcasecmp( r, "st" )
121*0Sstevel@tonic-gate 				    && strcasecmp( r, "l" )
122*0Sstevel@tonic-gate 				    && strcasecmp( r, "cn" ) ) {
123*0Sstevel@tonic-gate 					r = rsave;
124*0Sstevel@tonic-gate 					*r++ = '=';
125*0Sstevel@tonic-gate 				}
126*0Sstevel@tonic-gate 			}
127*0Sstevel@tonic-gate 			break;
128*0Sstevel@tonic-gate 		default:
129*0Sstevel@tonic-gate 			*r++ = *p;
130*0Sstevel@tonic-gate 			break;
131*0Sstevel@tonic-gate 		}
132*0Sstevel@tonic-gate 	}
133*0Sstevel@tonic-gate 	*r = '\0';
134*0Sstevel@tonic-gate 
135*0Sstevel@tonic-gate 	return( ufn );
136*0Sstevel@tonic-gate }
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate char **
139*0Sstevel@tonic-gate ldap_explode_dns( char *dn )
140*0Sstevel@tonic-gate {
141*0Sstevel@tonic-gate 	int	ncomps, maxcomps;
142*0Sstevel@tonic-gate 	char	*s;
143*0Sstevel@tonic-gate 	char	**rdns;
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 	if ( (rdns = (char **) malloc( 8 * sizeof(char *) )) == NULL ) {
146*0Sstevel@tonic-gate 		return( NULL );
147*0Sstevel@tonic-gate 	}
148*0Sstevel@tonic-gate 
149*0Sstevel@tonic-gate 	maxcomps = 8;
150*0Sstevel@tonic-gate 	ncomps = 0;
151*0Sstevel@tonic-gate 	for ( s = strtok( dn, "@." ); s != NULL; s = strtok( NULL, "@." ) ) {
152*0Sstevel@tonic-gate 		if ( ncomps == maxcomps ) {
153*0Sstevel@tonic-gate 			maxcomps *= 2;
154*0Sstevel@tonic-gate 			if ( (rdns = (char **) realloc( rdns, maxcomps *
155*0Sstevel@tonic-gate 			    sizeof(char *) )) == NULL ) {
156*0Sstevel@tonic-gate 				return( NULL );
157*0Sstevel@tonic-gate 			}
158*0Sstevel@tonic-gate 		}
159*0Sstevel@tonic-gate 		rdns[ncomps++] = strdup( s );
160*0Sstevel@tonic-gate 	}
161*0Sstevel@tonic-gate 	rdns[ncomps] = NULL;
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate 	return( rdns );
164*0Sstevel@tonic-gate }
165*0Sstevel@tonic-gate 
166*0Sstevel@tonic-gate char **
167*0Sstevel@tonic-gate ldap_explode_dn( char *dn, int notypes )
168*0Sstevel@tonic-gate {
169*0Sstevel@tonic-gate 	char	*p, *q, *rdnstart, **rdns = NULL;
170*0Sstevel@tonic-gate 	int	state, count = 0, endquote;
171*0Sstevel@tonic-gate 	ssize_t  len;
172*0Sstevel@tonic-gate 
173*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_dn\n"), 0, 0, 0 );
174*0Sstevel@tonic-gate 
175*0Sstevel@tonic-gate 	if ( ldap_is_dns_dn( dn ) ) {
176*0Sstevel@tonic-gate 		return( ldap_explode_dns( dn ) );
177*0Sstevel@tonic-gate 	}
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	rdnstart = dn;
180*0Sstevel@tonic-gate 	p = dn-1;
181*0Sstevel@tonic-gate 	state = OUTQUOTE;
182*0Sstevel@tonic-gate 
183*0Sstevel@tonic-gate 	do {
184*0Sstevel@tonic-gate 
185*0Sstevel@tonic-gate 		++p;
186*0Sstevel@tonic-gate 		switch ( *p ) {
187*0Sstevel@tonic-gate 		case '\\':
188*0Sstevel@tonic-gate 			if ( *++p == '\0' )
189*0Sstevel@tonic-gate 				p--;
190*0Sstevel@tonic-gate 			break;
191*0Sstevel@tonic-gate 		case '"':
192*0Sstevel@tonic-gate 			if ( state == INQUOTE )
193*0Sstevel@tonic-gate 				state = OUTQUOTE;
194*0Sstevel@tonic-gate 			else
195*0Sstevel@tonic-gate 				state = INQUOTE;
196*0Sstevel@tonic-gate 			break;
197*0Sstevel@tonic-gate 		case ';':
198*0Sstevel@tonic-gate 		case ',':
199*0Sstevel@tonic-gate 		case '\0':
200*0Sstevel@tonic-gate 			if ( state == OUTQUOTE ) {
201*0Sstevel@tonic-gate 				++count;
202*0Sstevel@tonic-gate 				if ( rdns == NULL ) {
203*0Sstevel@tonic-gate 					if (( rdns = (char **)malloc( 8
204*0Sstevel@tonic-gate 						 * sizeof( char *))) == NULL )
205*0Sstevel@tonic-gate 						return( NULL );
206*0Sstevel@tonic-gate 				} else if ( count >= 8 ) {
207*0Sstevel@tonic-gate 					if (( rdns = (char **)realloc( rdns,
208*0Sstevel@tonic-gate 						(count+1) * sizeof( char *)))
209*0Sstevel@tonic-gate 						== NULL )
210*0Sstevel@tonic-gate 						return( NULL );
211*0Sstevel@tonic-gate 				}
212*0Sstevel@tonic-gate 				rdns[ count ] = NULL;
213*0Sstevel@tonic-gate 				endquote = 0;
214*0Sstevel@tonic-gate 				if ( notypes ) {
215*0Sstevel@tonic-gate 					for ( q = rdnstart;
216*0Sstevel@tonic-gate 					    q < p && *q != '='; ++q ) {
217*0Sstevel@tonic-gate 						;
218*0Sstevel@tonic-gate 					}
219*0Sstevel@tonic-gate 					if ( q < p ) {
220*0Sstevel@tonic-gate 						rdnstart = ++q;
221*0Sstevel@tonic-gate 					}
222*0Sstevel@tonic-gate 					if ( *rdnstart == '"' ) {
223*0Sstevel@tonic-gate 						++rdnstart;
224*0Sstevel@tonic-gate 					}
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 					if ( *(p-1) == '"' ) {
227*0Sstevel@tonic-gate 						endquote = 1;
228*0Sstevel@tonic-gate 						--p;
229*0Sstevel@tonic-gate 					}
230*0Sstevel@tonic-gate 				}
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 				len = p - rdnstart;
233*0Sstevel@tonic-gate 				if (( rdns[ count-1 ] = (char *)calloc( 1,
234*0Sstevel@tonic-gate 				    len + 1 )) != NULL ) {
235*0Sstevel@tonic-gate 				    	(void) SAFEMEMCPY( rdns[ count-1 ], rdnstart,
236*0Sstevel@tonic-gate 					    len );
237*0Sstevel@tonic-gate 					rdns[ count-1 ][ len ] = '\0';
238*0Sstevel@tonic-gate 				}
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate 				/*
241*0Sstevel@tonic-gate 				 *  Don't forget to increment 'p' back to where
242*0Sstevel@tonic-gate 				 *  it should be.  If we don't, then we will
243*0Sstevel@tonic-gate 				 *  never get past an "end quote."
244*0Sstevel@tonic-gate 				 */
245*0Sstevel@tonic-gate 				if ( endquote == 1 )
246*0Sstevel@tonic-gate 					p++;
247*0Sstevel@tonic-gate 
248*0Sstevel@tonic-gate 				rdnstart = *p ? p + 1 : p;
249*0Sstevel@tonic-gate 				while ( isspace( *rdnstart ))
250*0Sstevel@tonic-gate 					++rdnstart;
251*0Sstevel@tonic-gate 			}
252*0Sstevel@tonic-gate 			break;
253*0Sstevel@tonic-gate 		}
254*0Sstevel@tonic-gate 	} while ( *p );
255*0Sstevel@tonic-gate 
256*0Sstevel@tonic-gate 	return( rdns );
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate int
261*0Sstevel@tonic-gate ldap_is_dns_dn( char *dn )
262*0Sstevel@tonic-gate {
263*0Sstevel@tonic-gate 	return( dn[ 0 ] != '\0' && strchr( dn, '=' ) == NULL &&
264*0Sstevel@tonic-gate 	    strchr( dn, ',' ) == NULL );
265*0Sstevel@tonic-gate }
266*0Sstevel@tonic-gate 
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate #if defined( ultrix ) || defined( NeXT )
269*0Sstevel@tonic-gate 
270*0Sstevel@tonic-gate char *strdup( char *s )
271*0Sstevel@tonic-gate {
272*0Sstevel@tonic-gate 	char	*p;
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate 	if ( (p = (char *) malloc( strlen( s ) + 1 )) == NULL )
275*0Sstevel@tonic-gate 		return( NULL );
276*0Sstevel@tonic-gate 
277*0Sstevel@tonic-gate 	strcpy( p, s );
278*0Sstevel@tonic-gate 
279*0Sstevel@tonic-gate 	return( p );
280*0Sstevel@tonic-gate }
281*0Sstevel@tonic-gate 
282*0Sstevel@tonic-gate #endif /* ultrix */
283*0Sstevel@tonic-gate 
284*0Sstevel@tonic-gate 
285*0Sstevel@tonic-gate /*
286*0Sstevel@tonic-gate  * Convert a DNS domain name into an X.500 distinguished name.
287*0Sstevel@tonic-gate  * For example, "sales.wiz.com" -> "dc=sales,dc=wiz,dc=com"
288*0Sstevel@tonic-gate  *
289*0Sstevel@tonic-gate  * If an error is encountered zero is returned, otherwise a string
290*0Sstevel@tonic-gate  * distinguished name and the number of nameparts is returned.
291*0Sstevel@tonic-gate  * The caller should free the returned string if it is non-zero.
292*0Sstevel@tonic-gate  */
293*0Sstevel@tonic-gate 
294*0Sstevel@tonic-gate char *
295*0Sstevel@tonic-gate ldap_dns_to_dn(
296*0Sstevel@tonic-gate 	char	*dns_name,
297*0Sstevel@tonic-gate 	int	*nameparts
298*0Sstevel@tonic-gate )
299*0Sstevel@tonic-gate {
300*0Sstevel@tonic-gate 	size_t	dns_len;
301*0Sstevel@tonic-gate 	char	*dn = 0;
302*0Sstevel@tonic-gate 	char	*cp;
303*0Sstevel@tonic-gate 
304*0Sstevel@tonic-gate 	/* check for NULL string, empty name and name ending in '.' */
305*0Sstevel@tonic-gate 	if (dns_name && (dns_len = strlen(dns_name)) &&
306*0Sstevel@tonic-gate 	    (dns_name[dns_len - 1] != '.')) {
307*0Sstevel@tonic-gate 		if (dn = (char *)malloc(dns_len * 3 + 1)) {
308*0Sstevel@tonic-gate 			*nameparts = 0;
309*0Sstevel@tonic-gate 			cp = dn;
310*0Sstevel@tonic-gate 			while (*dns_name) {
311*0Sstevel@tonic-gate 				*cp++ = 'd';
312*0Sstevel@tonic-gate 				*cp++ = 'c';
313*0Sstevel@tonic-gate 				*cp++ = '=';
314*0Sstevel@tonic-gate 
315*0Sstevel@tonic-gate 				while (*dns_name && (*dns_name != '.')) {
316*0Sstevel@tonic-gate 					*cp++ = *dns_name++;
317*0Sstevel@tonic-gate 				}
318*0Sstevel@tonic-gate 				if (*dns_name == '.') {
319*0Sstevel@tonic-gate 					dns_name++;
320*0Sstevel@tonic-gate 					*cp++ = ',';
321*0Sstevel@tonic-gate 				}
322*0Sstevel@tonic-gate 				(*nameparts)++;
323*0Sstevel@tonic-gate 			}
324*0Sstevel@tonic-gate 			*cp = '\0';
325*0Sstevel@tonic-gate 		}
326*0Sstevel@tonic-gate 	}
327*0Sstevel@tonic-gate 	return (dn);
328*0Sstevel@tonic-gate }
329*0Sstevel@tonic-gate 
330*0Sstevel@tonic-gate char **
331*0Sstevel@tonic-gate ldap_explode_rdn( char *rdn, int notypes )
332*0Sstevel@tonic-gate {
333*0Sstevel@tonic-gate 	char	*p, *q, *rdnstart, **rdncomps = NULL;
334*0Sstevel@tonic-gate 	int	state, count = 0, endquote;
335*0Sstevel@tonic-gate 	size_t  len;
336*0Sstevel@tonic-gate 
337*0Sstevel@tonic-gate 	Debug( LDAP_DEBUG_TRACE, catgets(slapdcat, 1, 183, "ldap_explode_rdn\n"), 0, 0, 0 );
338*0Sstevel@tonic-gate 
339*0Sstevel@tonic-gate 	rdnstart = rdn;
340*0Sstevel@tonic-gate 	p = rdn-1;
341*0Sstevel@tonic-gate 	state = OUTQUOTE;
342*0Sstevel@tonic-gate 
343*0Sstevel@tonic-gate 	do {
344*0Sstevel@tonic-gate 
345*0Sstevel@tonic-gate 		++p;
346*0Sstevel@tonic-gate 		switch ( *p ) {
347*0Sstevel@tonic-gate 		case '\\':
348*0Sstevel@tonic-gate 			if ( *++p == '\0' )
349*0Sstevel@tonic-gate 				p--;
350*0Sstevel@tonic-gate 			break;
351*0Sstevel@tonic-gate 		case '"':
352*0Sstevel@tonic-gate 			if ( state == INQUOTE )
353*0Sstevel@tonic-gate 				state = OUTQUOTE;
354*0Sstevel@tonic-gate 			else
355*0Sstevel@tonic-gate 				state = INQUOTE;
356*0Sstevel@tonic-gate 			break;
357*0Sstevel@tonic-gate 		case '+':
358*0Sstevel@tonic-gate 		case '\0':
359*0Sstevel@tonic-gate 			if ( state == OUTQUOTE ) {
360*0Sstevel@tonic-gate 				++count;
361*0Sstevel@tonic-gate 				if ( rdncomps == NULL ) {
362*0Sstevel@tonic-gate 					if (( rdncomps = (char **)malloc( 8 * sizeof( char *))) == NULL )
363*0Sstevel@tonic-gate 						return( NULL );
364*0Sstevel@tonic-gate 				} else if ( count >= 8 ) {
365*0Sstevel@tonic-gate 					if (( rdncomps = (char **)realloc( rdncomps,
366*0Sstevel@tonic-gate 						(count+1) * sizeof( char *)))
367*0Sstevel@tonic-gate 						== NULL )
368*0Sstevel@tonic-gate 						return( NULL );
369*0Sstevel@tonic-gate 				}
370*0Sstevel@tonic-gate 				rdncomps[ count ] = NULL;
371*0Sstevel@tonic-gate 				endquote = 0;
372*0Sstevel@tonic-gate 				if ( notypes ) {
373*0Sstevel@tonic-gate 					for ( q = rdnstart;
374*0Sstevel@tonic-gate 					    q < p && *q != '='; ++q ) {
375*0Sstevel@tonic-gate 						;
376*0Sstevel@tonic-gate 					}
377*0Sstevel@tonic-gate 					if ( q < p ) {
378*0Sstevel@tonic-gate 						rdnstart = ++q;
379*0Sstevel@tonic-gate 					}
380*0Sstevel@tonic-gate 					if ( *rdnstart == '"' ) {
381*0Sstevel@tonic-gate 						++rdnstart;
382*0Sstevel@tonic-gate 					}
383*0Sstevel@tonic-gate 
384*0Sstevel@tonic-gate 					if ( *(p-1) == '"' ) {
385*0Sstevel@tonic-gate 						endquote = 1;
386*0Sstevel@tonic-gate 						--p;
387*0Sstevel@tonic-gate 					}
388*0Sstevel@tonic-gate 				}
389*0Sstevel@tonic-gate 
390*0Sstevel@tonic-gate 				len = p - rdnstart;
391*0Sstevel@tonic-gate 				if (( rdncomps[ count-1 ] = (char *)calloc( 1, len + 1 )) != NULL ) {
392*0Sstevel@tonic-gate 				    	SAFEMEMCPY( rdncomps[ count-1 ], rdnstart,
393*0Sstevel@tonic-gate 					    len );
394*0Sstevel@tonic-gate 					rdncomps[ count-1 ][ len ] = '\0';
395*0Sstevel@tonic-gate 				}
396*0Sstevel@tonic-gate 
397*0Sstevel@tonic-gate 				/*
398*0Sstevel@tonic-gate 				 *  Don't forget to increment 'p' back to where
399*0Sstevel@tonic-gate 				 *  it should be.  If we don't, then we will
400*0Sstevel@tonic-gate 				 *  never get past an "end quote."
401*0Sstevel@tonic-gate 				 */
402*0Sstevel@tonic-gate 				if ( endquote == 1 )
403*0Sstevel@tonic-gate 					p++;
404*0Sstevel@tonic-gate 
405*0Sstevel@tonic-gate 				rdnstart = *p ? p + 1 : p;
406*0Sstevel@tonic-gate 				while ( isspace( *rdnstart ))
407*0Sstevel@tonic-gate 					++rdnstart;
408*0Sstevel@tonic-gate 			}
409*0Sstevel@tonic-gate 			break;
410*0Sstevel@tonic-gate 		}
411*0Sstevel@tonic-gate 	} while ( *p );
412*0Sstevel@tonic-gate 
413*0Sstevel@tonic-gate 	return( rdncomps );
414*0Sstevel@tonic-gate }
415