xref: /onnv-gate/usr/src/lib/libldap5/sources/ldap/common/srchpref.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
2*0Sstevel@tonic-gate 
3*0Sstevel@tonic-gate /*
4*0Sstevel@tonic-gate  * The contents of this file are subject to the Netscape Public
5*0Sstevel@tonic-gate  * License Version 1.1 (the "License"); you may not use this file
6*0Sstevel@tonic-gate  * except in compliance with the License. You may obtain a copy of
7*0Sstevel@tonic-gate  * the License at http://www.mozilla.org/NPL/
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * Software distributed under the License is distributed on an "AS
10*0Sstevel@tonic-gate  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
11*0Sstevel@tonic-gate  * implied. See the License for the specific language governing
12*0Sstevel@tonic-gate  * rights and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * The Original Code is Mozilla Communicator client code, released
15*0Sstevel@tonic-gate  * March 31, 1998.
16*0Sstevel@tonic-gate  *
17*0Sstevel@tonic-gate  * The Initial Developer of the Original Code is Netscape
18*0Sstevel@tonic-gate  * Communications Corporation. Portions created by Netscape are
19*0Sstevel@tonic-gate  * Copyright (C) 1998-1999 Netscape Communications Corporation. All
20*0Sstevel@tonic-gate  * Rights Reserved.
21*0Sstevel@tonic-gate  *
22*0Sstevel@tonic-gate  * Contributor(s):
23*0Sstevel@tonic-gate  */
24*0Sstevel@tonic-gate /*
25*0Sstevel@tonic-gate  * Copyright (c) 1993, 1994 Regents of the University of Michigan.
26*0Sstevel@tonic-gate  * All rights reserved.
27*0Sstevel@tonic-gate  *
28*0Sstevel@tonic-gate  * Redistribution and use in source and binary forms are permitted
29*0Sstevel@tonic-gate  * provided that this notice is preserved and that due credit is given
30*0Sstevel@tonic-gate  * to the University of Michigan at Ann Arbor. The name of the University
31*0Sstevel@tonic-gate  * may not be used to endorse or promote products derived from this
32*0Sstevel@tonic-gate  * software without specific prior written permission. This software
33*0Sstevel@tonic-gate  * is provided ``as is'' without express or implied warranty.
34*0Sstevel@tonic-gate  *
35*0Sstevel@tonic-gate  */
36*0Sstevel@tonic-gate /*
37*0Sstevel@tonic-gate  * searchpref.c:  search preferences library routines for LDAP clients
38*0Sstevel@tonic-gate  */
39*0Sstevel@tonic-gate 
40*0Sstevel@tonic-gate #include "ldap-int.h"
41*0Sstevel@tonic-gate #include "srchpref.h"
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate static void free_searchobj( struct ldap_searchobj *so );
44*0Sstevel@tonic-gate static int read_next_searchobj( char **bufp, long *blenp,
45*0Sstevel@tonic-gate 	struct ldap_searchobj **sop, int soversion );
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate 
48*0Sstevel@tonic-gate static char		*sobjoptions[] = {
49*0Sstevel@tonic-gate     "internal",
50*0Sstevel@tonic-gate     NULL
51*0Sstevel@tonic-gate };
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate 
54*0Sstevel@tonic-gate static unsigned long	sobjoptvals[] = {
55*0Sstevel@tonic-gate     LDAP_SEARCHOBJ_OPT_INTERNAL,
56*0Sstevel@tonic-gate };
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate 
59*0Sstevel@tonic-gate int
60*0Sstevel@tonic-gate LDAP_CALL
61*0Sstevel@tonic-gate ldap_init_searchprefs( char *file, struct ldap_searchobj **solistp )
62*0Sstevel@tonic-gate {
63*0Sstevel@tonic-gate     FILE	*fp;
64*0Sstevel@tonic-gate     char	*buf;
65*0Sstevel@tonic-gate     long	rlen, len;
66*0Sstevel@tonic-gate     int		rc, eof;
67*0Sstevel@tonic-gate 
68*0Sstevel@tonic-gate     if (( fp = fopen( file, "r" )) == NULL ) {
69*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_FILE );
70*0Sstevel@tonic-gate     }
71*0Sstevel@tonic-gate 
72*0Sstevel@tonic-gate     if ( fseek( fp, 0L, SEEK_END ) != 0 ) {	/* move to end to get len */
73*0Sstevel@tonic-gate 	fclose( fp );
74*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_FILE );
75*0Sstevel@tonic-gate     }
76*0Sstevel@tonic-gate 
77*0Sstevel@tonic-gate     len = ftell( fp );
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate     if ( fseek( fp, 0L, SEEK_SET ) != 0 ) {	/* back to start of file */
80*0Sstevel@tonic-gate 	fclose( fp );
81*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_FILE );
82*0Sstevel@tonic-gate     }
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate     if (( buf = NSLDAPI_MALLOC( (size_t)len )) == NULL ) {
85*0Sstevel@tonic-gate 	fclose( fp );
86*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_MEM );
87*0Sstevel@tonic-gate     }
88*0Sstevel@tonic-gate 
89*0Sstevel@tonic-gate     rlen = fread( buf, 1, (size_t)len, fp );
90*0Sstevel@tonic-gate     eof = feof( fp );
91*0Sstevel@tonic-gate     fclose( fp );
92*0Sstevel@tonic-gate 
93*0Sstevel@tonic-gate     if ( rlen != len && !eof ) {	/* error:  didn't get the whole file */
94*0Sstevel@tonic-gate 	NSLDAPI_FREE( buf );
95*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_FILE );
96*0Sstevel@tonic-gate     }
97*0Sstevel@tonic-gate 
98*0Sstevel@tonic-gate     rc = ldap_init_searchprefs_buf( buf, rlen, solistp );
99*0Sstevel@tonic-gate     NSLDAPI_FREE( buf );
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate     return( rc );
102*0Sstevel@tonic-gate }
103*0Sstevel@tonic-gate 
104*0Sstevel@tonic-gate 
105*0Sstevel@tonic-gate int
106*0Sstevel@tonic-gate LDAP_CALL
107*0Sstevel@tonic-gate ldap_init_searchprefs_buf( char *buf, long buflen,
108*0Sstevel@tonic-gate 	struct ldap_searchobj **solistp )
109*0Sstevel@tonic-gate {
110*0Sstevel@tonic-gate     int				rc = 0, version;
111*0Sstevel@tonic-gate     char			**toks;
112*0Sstevel@tonic-gate     struct ldap_searchobj	*prevso, *so;
113*0Sstevel@tonic-gate 
114*0Sstevel@tonic-gate     *solistp = prevso = NULLSEARCHOBJ;
115*0Sstevel@tonic-gate 
116*0Sstevel@tonic-gate     if ( ldap_next_line_tokens( &buf, &buflen, &toks ) != 2 ||
117*0Sstevel@tonic-gate 	    strcasecmp( toks[ 0 ], "version" ) != 0 ) {
118*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
119*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
120*0Sstevel@tonic-gate     }
121*0Sstevel@tonic-gate     version = atoi( toks[ 1 ] );
122*0Sstevel@tonic-gate     ldap_free_strarray( toks );
123*0Sstevel@tonic-gate     if ( version != LDAP_SEARCHPREF_VERSION &&
124*0Sstevel@tonic-gate 	    version != LDAP_SEARCHPREF_VERSION_ZERO ) {
125*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_VERSION );
126*0Sstevel@tonic-gate     }
127*0Sstevel@tonic-gate 
128*0Sstevel@tonic-gate     while ( buflen > 0 && ( rc = read_next_searchobj( &buf, &buflen, &so,
129*0Sstevel@tonic-gate 	    version )) == 0 && so != NULLSEARCHOBJ ) {
130*0Sstevel@tonic-gate 	if ( prevso == NULLSEARCHOBJ ) {
131*0Sstevel@tonic-gate 	    *solistp = so;
132*0Sstevel@tonic-gate 	} else {
133*0Sstevel@tonic-gate 	    prevso->so_next = so;
134*0Sstevel@tonic-gate 	}
135*0Sstevel@tonic-gate 	prevso = so;
136*0Sstevel@tonic-gate     }
137*0Sstevel@tonic-gate 
138*0Sstevel@tonic-gate     if ( rc != 0 ) {
139*0Sstevel@tonic-gate 	ldap_free_searchprefs( *solistp );
140*0Sstevel@tonic-gate     }
141*0Sstevel@tonic-gate 
142*0Sstevel@tonic-gate     return( rc );
143*0Sstevel@tonic-gate }
144*0Sstevel@tonic-gate 
145*0Sstevel@tonic-gate 
146*0Sstevel@tonic-gate 
147*0Sstevel@tonic-gate void
148*0Sstevel@tonic-gate LDAP_CALL
149*0Sstevel@tonic-gate ldap_free_searchprefs( struct ldap_searchobj *solist )
150*0Sstevel@tonic-gate {
151*0Sstevel@tonic-gate     struct ldap_searchobj	*so, *nextso;
152*0Sstevel@tonic-gate 
153*0Sstevel@tonic-gate     if ( solist != NULL ) {
154*0Sstevel@tonic-gate 	for ( so = solist; so != NULL; so = nextso ) {
155*0Sstevel@tonic-gate 	    nextso = so->so_next;
156*0Sstevel@tonic-gate 	    free_searchobj( so );
157*0Sstevel@tonic-gate 	}
158*0Sstevel@tonic-gate     }
159*0Sstevel@tonic-gate     /* XXX XXX need to do some work here */
160*0Sstevel@tonic-gate }
161*0Sstevel@tonic-gate 
162*0Sstevel@tonic-gate 
163*0Sstevel@tonic-gate static void
164*0Sstevel@tonic-gate free_searchobj( struct ldap_searchobj *so )
165*0Sstevel@tonic-gate {
166*0Sstevel@tonic-gate     if ( so != NULL ) {
167*0Sstevel@tonic-gate 	if ( so->so_objtypeprompt != NULL ) {
168*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_objtypeprompt );
169*0Sstevel@tonic-gate 	}
170*0Sstevel@tonic-gate 	if ( so->so_prompt != NULL ) {
171*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_prompt );
172*0Sstevel@tonic-gate 	}
173*0Sstevel@tonic-gate 	if ( so->so_filterprefix != NULL ) {
174*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_filterprefix );
175*0Sstevel@tonic-gate 	}
176*0Sstevel@tonic-gate 	if ( so->so_filtertag != NULL ) {
177*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_filtertag );
178*0Sstevel@tonic-gate 	}
179*0Sstevel@tonic-gate 	if ( so->so_defaultselectattr != NULL ) {
180*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_defaultselectattr );
181*0Sstevel@tonic-gate 	}
182*0Sstevel@tonic-gate 	if ( so->so_defaultselecttext != NULL ) {
183*0Sstevel@tonic-gate 	    NSLDAPI_FREE(  so->so_defaultselecttext );
184*0Sstevel@tonic-gate 	}
185*0Sstevel@tonic-gate 	if ( so->so_salist != NULL ) {
186*0Sstevel@tonic-gate 	    struct ldap_searchattr *sa, *nextsa;
187*0Sstevel@tonic-gate 	    for ( sa = so->so_salist; sa != NULL; sa = nextsa ) {
188*0Sstevel@tonic-gate 		nextsa = sa->sa_next;
189*0Sstevel@tonic-gate 		if ( sa->sa_attrlabel != NULL ) {
190*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sa->sa_attrlabel );
191*0Sstevel@tonic-gate 		}
192*0Sstevel@tonic-gate 		if ( sa->sa_attr != NULL ) {
193*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sa->sa_attr );
194*0Sstevel@tonic-gate 		}
195*0Sstevel@tonic-gate 		if ( sa->sa_selectattr != NULL ) {
196*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sa->sa_selectattr );
197*0Sstevel@tonic-gate 		}
198*0Sstevel@tonic-gate 		if ( sa->sa_selecttext != NULL ) {
199*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sa->sa_selecttext );
200*0Sstevel@tonic-gate 		}
201*0Sstevel@tonic-gate 		NSLDAPI_FREE( sa );
202*0Sstevel@tonic-gate 	    }
203*0Sstevel@tonic-gate 	}
204*0Sstevel@tonic-gate 	if ( so->so_smlist != NULL ) {
205*0Sstevel@tonic-gate 	    struct ldap_searchmatch *sm, *nextsm;
206*0Sstevel@tonic-gate 	    for ( sm = so->so_smlist; sm != NULL; sm = nextsm ) {
207*0Sstevel@tonic-gate 		nextsm = sm->sm_next;
208*0Sstevel@tonic-gate 		if ( sm->sm_matchprompt != NULL ) {
209*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sm->sm_matchprompt );
210*0Sstevel@tonic-gate 		}
211*0Sstevel@tonic-gate 		if ( sm->sm_filter != NULL ) {
212*0Sstevel@tonic-gate 		    NSLDAPI_FREE( sm->sm_filter );
213*0Sstevel@tonic-gate 		}
214*0Sstevel@tonic-gate 		NSLDAPI_FREE( sm );
215*0Sstevel@tonic-gate 	    }
216*0Sstevel@tonic-gate 	}
217*0Sstevel@tonic-gate 	NSLDAPI_FREE( so );
218*0Sstevel@tonic-gate     }
219*0Sstevel@tonic-gate }
220*0Sstevel@tonic-gate 
221*0Sstevel@tonic-gate 
222*0Sstevel@tonic-gate 
223*0Sstevel@tonic-gate struct ldap_searchobj *
224*0Sstevel@tonic-gate LDAP_CALL
225*0Sstevel@tonic-gate ldap_first_searchobj( struct ldap_searchobj *solist )
226*0Sstevel@tonic-gate {
227*0Sstevel@tonic-gate     return( solist );
228*0Sstevel@tonic-gate }
229*0Sstevel@tonic-gate 
230*0Sstevel@tonic-gate 
231*0Sstevel@tonic-gate struct ldap_searchobj *
232*0Sstevel@tonic-gate LDAP_CALL
233*0Sstevel@tonic-gate ldap_next_searchobj( struct ldap_searchobj *solist, struct ldap_searchobj *so )
234*0Sstevel@tonic-gate {
235*0Sstevel@tonic-gate     return( so == NULLSEARCHOBJ ? so : so->so_next );
236*0Sstevel@tonic-gate }
237*0Sstevel@tonic-gate 
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 
240*0Sstevel@tonic-gate static int
241*0Sstevel@tonic-gate read_next_searchobj( char **bufp, long *blenp, struct ldap_searchobj **sop,
242*0Sstevel@tonic-gate 	int soversion )
243*0Sstevel@tonic-gate {
244*0Sstevel@tonic-gate     int				i, j, tokcnt;
245*0Sstevel@tonic-gate     char			**toks;
246*0Sstevel@tonic-gate     struct ldap_searchobj	*so;
247*0Sstevel@tonic-gate     struct ldap_searchattr	**sa;
248*0Sstevel@tonic-gate     struct ldap_searchmatch	**sm;
249*0Sstevel@tonic-gate 
250*0Sstevel@tonic-gate     *sop = NULL;
251*0Sstevel@tonic-gate 
252*0Sstevel@tonic-gate     /*
253*0Sstevel@tonic-gate      * Object type prompt comes first
254*0Sstevel@tonic-gate      */
255*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
256*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
257*0Sstevel@tonic-gate 	return( tokcnt == 0 ? 0 : LDAP_SEARCHPREF_ERR_SYNTAX );
258*0Sstevel@tonic-gate     }
259*0Sstevel@tonic-gate 
260*0Sstevel@tonic-gate     if (( so = (struct ldap_searchobj *)NSLDAPI_CALLOC( 1,
261*0Sstevel@tonic-gate 	    sizeof( struct ldap_searchobj ))) == NULL ) {
262*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
263*0Sstevel@tonic-gate 	return(  LDAP_SEARCHPREF_ERR_MEM );
264*0Sstevel@tonic-gate     }
265*0Sstevel@tonic-gate     so->so_objtypeprompt = toks[ 0 ];
266*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
267*0Sstevel@tonic-gate 
268*0Sstevel@tonic-gate     /*
269*0Sstevel@tonic-gate      * if this is post-version zero, options come next
270*0Sstevel@tonic-gate      */
271*0Sstevel@tonic-gate     if ( soversion > LDAP_SEARCHPREF_VERSION_ZERO ) {
272*0Sstevel@tonic-gate 	if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) < 1 ) {
273*0Sstevel@tonic-gate 	    ldap_free_strarray( toks );
274*0Sstevel@tonic-gate 	    ldap_free_searchprefs( so );
275*0Sstevel@tonic-gate 	    return( LDAP_SEARCHPREF_ERR_SYNTAX );
276*0Sstevel@tonic-gate 	}
277*0Sstevel@tonic-gate 	for ( i = 0; toks[ i ] != NULL; ++i ) {
278*0Sstevel@tonic-gate 	    for ( j = 0; sobjoptions[ j ] != NULL; ++j ) {
279*0Sstevel@tonic-gate 		if ( strcasecmp( toks[ i ], sobjoptions[ j ] ) == 0 ) {
280*0Sstevel@tonic-gate 		    so->so_options |= sobjoptvals[ j ];
281*0Sstevel@tonic-gate 		}
282*0Sstevel@tonic-gate 	    }
283*0Sstevel@tonic-gate 	}
284*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
285*0Sstevel@tonic-gate     }
286*0Sstevel@tonic-gate 
287*0Sstevel@tonic-gate     /*
288*0Sstevel@tonic-gate      * "Fewer choices" prompt is next
289*0Sstevel@tonic-gate      */
290*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
291*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
292*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
293*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
294*0Sstevel@tonic-gate     }
295*0Sstevel@tonic-gate     so->so_prompt = toks[ 0 ];
296*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
297*0Sstevel@tonic-gate 
298*0Sstevel@tonic-gate     /*
299*0Sstevel@tonic-gate      * Filter prefix for "More Choices" searching is next
300*0Sstevel@tonic-gate      */
301*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
302*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
303*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
304*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
305*0Sstevel@tonic-gate     }
306*0Sstevel@tonic-gate     so->so_filterprefix = toks[ 0 ];
307*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
308*0Sstevel@tonic-gate 
309*0Sstevel@tonic-gate     /*
310*0Sstevel@tonic-gate      * "Fewer Choices" filter tag comes next
311*0Sstevel@tonic-gate      */
312*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
313*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
314*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
315*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
316*0Sstevel@tonic-gate     }
317*0Sstevel@tonic-gate     so->so_filtertag = toks[ 0 ];
318*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
319*0Sstevel@tonic-gate 
320*0Sstevel@tonic-gate     /*
321*0Sstevel@tonic-gate      * Selection (disambiguation) attribute comes next
322*0Sstevel@tonic-gate      */
323*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
324*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
325*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
326*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
327*0Sstevel@tonic-gate     }
328*0Sstevel@tonic-gate     so->so_defaultselectattr = toks[ 0 ];
329*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
330*0Sstevel@tonic-gate 
331*0Sstevel@tonic-gate     /*
332*0Sstevel@tonic-gate      * Label for selection (disambiguation) attribute
333*0Sstevel@tonic-gate      */
334*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
335*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
336*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
337*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
338*0Sstevel@tonic-gate     }
339*0Sstevel@tonic-gate     so->so_defaultselecttext = toks[ 0 ];
340*0Sstevel@tonic-gate     NSLDAPI_FREE( (char *)toks );
341*0Sstevel@tonic-gate 
342*0Sstevel@tonic-gate     /*
343*0Sstevel@tonic-gate      * Search scope is next
344*0Sstevel@tonic-gate      */
345*0Sstevel@tonic-gate     if (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) != 1 ) {
346*0Sstevel@tonic-gate 	ldap_free_strarray( toks );
347*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
348*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
349*0Sstevel@tonic-gate     }
350*0Sstevel@tonic-gate     if ( !strcasecmp(toks[ 0 ], "subtree" )) {
351*0Sstevel@tonic-gate 	so->so_defaultscope = LDAP_SCOPE_SUBTREE;
352*0Sstevel@tonic-gate     } else if ( !strcasecmp(toks[ 0 ], "onelevel" )) {
353*0Sstevel@tonic-gate 	so->so_defaultscope = LDAP_SCOPE_ONELEVEL;
354*0Sstevel@tonic-gate     } else if ( !strcasecmp(toks[ 0 ], "base" )) {
355*0Sstevel@tonic-gate 	so->so_defaultscope = LDAP_SCOPE_BASE;
356*0Sstevel@tonic-gate     } else {
357*0Sstevel@tonic-gate 	ldap_free_searchprefs( so );
358*0Sstevel@tonic-gate 	return( LDAP_SEARCHPREF_ERR_SYNTAX );
359*0Sstevel@tonic-gate     }
360*0Sstevel@tonic-gate     ldap_free_strarray( toks );
361*0Sstevel@tonic-gate 
362*0Sstevel@tonic-gate 
363*0Sstevel@tonic-gate     /*
364*0Sstevel@tonic-gate      * "More Choices" search option list comes next
365*0Sstevel@tonic-gate      */
366*0Sstevel@tonic-gate     sa = &( so->so_salist );
367*0Sstevel@tonic-gate     while (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
368*0Sstevel@tonic-gate 	if ( tokcnt < 5 ) {
369*0Sstevel@tonic-gate 	    ldap_free_strarray( toks );
370*0Sstevel@tonic-gate 	    ldap_free_searchprefs( so );
371*0Sstevel@tonic-gate 	    return( LDAP_SEARCHPREF_ERR_SYNTAX );
372*0Sstevel@tonic-gate 	}
373*0Sstevel@tonic-gate 	if (( *sa = ( struct ldap_searchattr * )NSLDAPI_CALLOC( 1,
374*0Sstevel@tonic-gate 		sizeof( struct ldap_searchattr ))) == NULL ) {
375*0Sstevel@tonic-gate 	    ldap_free_strarray( toks );
376*0Sstevel@tonic-gate 	    ldap_free_searchprefs( so );
377*0Sstevel@tonic-gate 	    return(  LDAP_SEARCHPREF_ERR_MEM );
378*0Sstevel@tonic-gate 	}
379*0Sstevel@tonic-gate 	( *sa )->sa_attrlabel = toks[ 0 ];
380*0Sstevel@tonic-gate 	( *sa )->sa_attr = toks[ 1 ];
381*0Sstevel@tonic-gate 	( *sa )->sa_selectattr = toks[ 3 ];
382*0Sstevel@tonic-gate 	( *sa )->sa_selecttext = toks[ 4 ];
383*0Sstevel@tonic-gate 	/* Deal with bitmap */
384*0Sstevel@tonic-gate 	( *sa )->sa_matchtypebitmap = 0;
385*0Sstevel@tonic-gate 	for ( i = strlen( toks[ 2 ] ) - 1, j = 0; i >= 0; i--, j++ ) {
386*0Sstevel@tonic-gate 	    if ( toks[ 2 ][ i ] == '1' ) {
387*0Sstevel@tonic-gate 		( *sa )->sa_matchtypebitmap |= (1 << j);
388*0Sstevel@tonic-gate 	    }
389*0Sstevel@tonic-gate 	}
390*0Sstevel@tonic-gate 	NSLDAPI_FREE( toks[ 2 ] );
391*0Sstevel@tonic-gate 	NSLDAPI_FREE( ( char * ) toks );
392*0Sstevel@tonic-gate 	sa = &(( *sa )->sa_next);
393*0Sstevel@tonic-gate     }
394*0Sstevel@tonic-gate     *sa = NULL;
395*0Sstevel@tonic-gate 
396*0Sstevel@tonic-gate     /*
397*0Sstevel@tonic-gate      * Match types are last
398*0Sstevel@tonic-gate      */
399*0Sstevel@tonic-gate     sm = &( so->so_smlist );
400*0Sstevel@tonic-gate     while (( tokcnt = ldap_next_line_tokens( bufp, blenp, &toks )) > 0 ) {
401*0Sstevel@tonic-gate 	if ( tokcnt < 2 ) {
402*0Sstevel@tonic-gate 	    ldap_free_strarray( toks );
403*0Sstevel@tonic-gate 	    ldap_free_searchprefs( so );
404*0Sstevel@tonic-gate 	    return( LDAP_SEARCHPREF_ERR_SYNTAX );
405*0Sstevel@tonic-gate 	}
406*0Sstevel@tonic-gate 	if (( *sm = ( struct ldap_searchmatch * )NSLDAPI_CALLOC( 1,
407*0Sstevel@tonic-gate 		sizeof( struct ldap_searchmatch ))) == NULL ) {
408*0Sstevel@tonic-gate 	    ldap_free_strarray( toks );
409*0Sstevel@tonic-gate 	    ldap_free_searchprefs( so );
410*0Sstevel@tonic-gate 	    return(  LDAP_SEARCHPREF_ERR_MEM );
411*0Sstevel@tonic-gate 	}
412*0Sstevel@tonic-gate 	( *sm )->sm_matchprompt = toks[ 0 ];
413*0Sstevel@tonic-gate 	( *sm )->sm_filter = toks[ 1 ];
414*0Sstevel@tonic-gate 	NSLDAPI_FREE( ( char * ) toks );
415*0Sstevel@tonic-gate 	sm = &(( *sm )->sm_next );
416*0Sstevel@tonic-gate     }
417*0Sstevel@tonic-gate     *sm = NULL;
418*0Sstevel@tonic-gate 
419*0Sstevel@tonic-gate     *sop = so;
420*0Sstevel@tonic-gate     return( 0 );
421*0Sstevel@tonic-gate }
422