1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the Netscape Public
3*7c478bd9Sstevel@tonic-gate * License Version 1.1 (the "License"); you may not use this file
4*7c478bd9Sstevel@tonic-gate * except in compliance with the License. You may obtain a copy of
5*7c478bd9Sstevel@tonic-gate * the License at http://www.mozilla.org/NPL/
6*7c478bd9Sstevel@tonic-gate *
7*7c478bd9Sstevel@tonic-gate * Software distributed under the License is distributed on an "AS
8*7c478bd9Sstevel@tonic-gate * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9*7c478bd9Sstevel@tonic-gate * implied. See the License for the specific language governing
10*7c478bd9Sstevel@tonic-gate * rights and limitations under the License.
11*7c478bd9Sstevel@tonic-gate *
12*7c478bd9Sstevel@tonic-gate * The Original Code is Mozilla Communicator client code, released
13*7c478bd9Sstevel@tonic-gate * March 31, 1998.
14*7c478bd9Sstevel@tonic-gate *
15*7c478bd9Sstevel@tonic-gate * The Initial Developer of the Original Code is Netscape
16*7c478bd9Sstevel@tonic-gate * Communications Corporation. Portions created by Netscape are
17*7c478bd9Sstevel@tonic-gate * Copyright (C) 1998-1999 Netscape Communications Corporation. All
18*7c478bd9Sstevel@tonic-gate * Rights Reserved.
19*7c478bd9Sstevel@tonic-gate *
20*7c478bd9Sstevel@tonic-gate * Contributor(s):
21*7c478bd9Sstevel@tonic-gate */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate * Copyright (c) 1994 Regents of the University of Michigan.
24*7c478bd9Sstevel@tonic-gate * All rights reserved.
25*7c478bd9Sstevel@tonic-gate *
26*7c478bd9Sstevel@tonic-gate * Redistribution and use in source and binary forms are permitted
27*7c478bd9Sstevel@tonic-gate * provided that this notice is preserved and that due credit is given
28*7c478bd9Sstevel@tonic-gate * to the University of Michigan at Ann Arbor. The name of the University
29*7c478bd9Sstevel@tonic-gate * may not be used to endorse or promote products derived from this
30*7c478bd9Sstevel@tonic-gate * software without specific prior written permission. This software
31*7c478bd9Sstevel@tonic-gate * is provided ``as is'' without express or implied warranty.
32*7c478bd9Sstevel@tonic-gate */
33*7c478bd9Sstevel@tonic-gate /*
34*7c478bd9Sstevel@tonic-gate * sort.c: LDAP library entry and value sort routines
35*7c478bd9Sstevel@tonic-gate */
36*7c478bd9Sstevel@tonic-gate
37*7c478bd9Sstevel@tonic-gate #include "ldap-int.h"
38*7c478bd9Sstevel@tonic-gate
39*7c478bd9Sstevel@tonic-gate /* This xp_qsort fixes a memory problem (ABR) on Solaris for the client.
40*7c478bd9Sstevel@tonic-gate * Server is welcome to use it too, but I wasn't sure if it
41*7c478bd9Sstevel@tonic-gate * would be ok to use XP code here. -slamm
42*7c478bd9Sstevel@tonic-gate *
43*7c478bd9Sstevel@tonic-gate * We don't want to require use of libxp when linking with libldap, so
44*7c478bd9Sstevel@tonic-gate * I'll leave use of xp_qsort as a MOZILLA_CLIENT-only thing for now. --mcs
45*7c478bd9Sstevel@tonic-gate */
46*7c478bd9Sstevel@tonic-gate #if defined(MOZILLA_CLIENT) && defined(SOLARIS)
47*7c478bd9Sstevel@tonic-gate #include "xp_qsort.h"
48*7c478bd9Sstevel@tonic-gate #else
49*7c478bd9Sstevel@tonic-gate #define XP_QSORT qsort
50*7c478bd9Sstevel@tonic-gate #endif
51*7c478bd9Sstevel@tonic-gate
52*7c478bd9Sstevel@tonic-gate typedef struct keycmp {
53*7c478bd9Sstevel@tonic-gate void *kc_arg;
54*7c478bd9Sstevel@tonic-gate LDAP_KEYCMP_CALLBACK *kc_cmp;
55*7c478bd9Sstevel@tonic-gate } keycmp_t;
56*7c478bd9Sstevel@tonic-gate
57*7c478bd9Sstevel@tonic-gate typedef struct keything {
58*7c478bd9Sstevel@tonic-gate keycmp_t *kt_cmp;
59*7c478bd9Sstevel@tonic-gate const struct berval *kt_key;
60*7c478bd9Sstevel@tonic-gate LDAPMessage *kt_msg;
61*7c478bd9Sstevel@tonic-gate } keything_t;
62*7c478bd9Sstevel@tonic-gate
63*7c478bd9Sstevel@tonic-gate static int LDAP_C LDAP_CALLBACK
ldapi_keycmp(const void * Lv,const void * Rv)64*7c478bd9Sstevel@tonic-gate ldapi_keycmp( const void *Lv, const void *Rv )
65*7c478bd9Sstevel@tonic-gate {
66*7c478bd9Sstevel@tonic-gate auto keything_t **L = (keything_t**)Lv;
67*7c478bd9Sstevel@tonic-gate auto keything_t **R = (keything_t**)Rv;
68*7c478bd9Sstevel@tonic-gate auto keycmp_t *cmp = (*L)->kt_cmp;
69*7c478bd9Sstevel@tonic-gate return cmp->kc_cmp( cmp->kc_arg, (*L)->kt_key, (*R)->kt_key );
70*7c478bd9Sstevel@tonic-gate }
71*7c478bd9Sstevel@tonic-gate
72*7c478bd9Sstevel@tonic-gate int
73*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_keysort_entries(LDAP * ld,LDAPMessage ** chain,void * arg,LDAP_KEYGEN_CALLBACK * gen,LDAP_KEYCMP_CALLBACK * cmp,LDAP_KEYFREE_CALLBACK * fre)74*7c478bd9Sstevel@tonic-gate ldap_keysort_entries(
75*7c478bd9Sstevel@tonic-gate LDAP *ld,
76*7c478bd9Sstevel@tonic-gate LDAPMessage **chain,
77*7c478bd9Sstevel@tonic-gate void *arg,
78*7c478bd9Sstevel@tonic-gate LDAP_KEYGEN_CALLBACK *gen,
79*7c478bd9Sstevel@tonic-gate LDAP_KEYCMP_CALLBACK *cmp,
80*7c478bd9Sstevel@tonic-gate LDAP_KEYFREE_CALLBACK *fre)
81*7c478bd9Sstevel@tonic-gate {
82*7c478bd9Sstevel@tonic-gate size_t count, i;
83*7c478bd9Sstevel@tonic-gate keycmp_t kc = {0};
84*7c478bd9Sstevel@tonic-gate keything_t **kt;
85*7c478bd9Sstevel@tonic-gate LDAPMessage *e, *last;
86*7c478bd9Sstevel@tonic-gate LDAPMessage **ep;
87*7c478bd9Sstevel@tonic-gate
88*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )
89*7c478bd9Sstevel@tonic-gate || chain == NULL || cmp == NULL ) {
90*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
91*7c478bd9Sstevel@tonic-gate }
92*7c478bd9Sstevel@tonic-gate
93*7c478bd9Sstevel@tonic-gate count = ldap_count_entries( ld, *chain );
94*7c478bd9Sstevel@tonic-gate
95*7c478bd9Sstevel@tonic-gate kt = (keything_t**)NSLDAPI_MALLOC( count * (sizeof(keything_t*) + sizeof(keything_t)) );
96*7c478bd9Sstevel@tonic-gate if ( kt == NULL ) {
97*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
98*7c478bd9Sstevel@tonic-gate return( -1 );
99*7c478bd9Sstevel@tonic-gate }
100*7c478bd9Sstevel@tonic-gate for ( i = 0; i < count; i++ ) {
101*7c478bd9Sstevel@tonic-gate kt[i] = i + (keything_t*)(kt + count);
102*7c478bd9Sstevel@tonic-gate }
103*7c478bd9Sstevel@tonic-gate kc.kc_arg = arg;
104*7c478bd9Sstevel@tonic-gate kc.kc_cmp = cmp;
105*7c478bd9Sstevel@tonic-gate
106*7c478bd9Sstevel@tonic-gate for ( e = *chain, i = 0; i < count; i++, e = e->lm_chain ) {
107*7c478bd9Sstevel@tonic-gate kt[i]->kt_msg = e;
108*7c478bd9Sstevel@tonic-gate kt[i]->kt_cmp = &kc;
109*7c478bd9Sstevel@tonic-gate kt[i]->kt_key = gen( arg, ld, e );
110*7c478bd9Sstevel@tonic-gate if ( kt[i]->kt_key == NULL ) {
111*7c478bd9Sstevel@tonic-gate if ( fre ) while ( i-- > 0 ) fre( arg, kt[i]->kt_key );
112*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char*)kt );
113*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
114*7c478bd9Sstevel@tonic-gate return( -1 );
115*7c478bd9Sstevel@tonic-gate }
116*7c478bd9Sstevel@tonic-gate }
117*7c478bd9Sstevel@tonic-gate last = e;
118*7c478bd9Sstevel@tonic-gate
119*7c478bd9Sstevel@tonic-gate XP_QSORT( (void*)kt, count, (size_t)sizeof(keything_t*), ldapi_keycmp );
120*7c478bd9Sstevel@tonic-gate
121*7c478bd9Sstevel@tonic-gate ep = chain;
122*7c478bd9Sstevel@tonic-gate for ( i = 0; i < count; i++ ) {
123*7c478bd9Sstevel@tonic-gate *ep = kt[i]->kt_msg;
124*7c478bd9Sstevel@tonic-gate ep = &(*ep)->lm_chain;
125*7c478bd9Sstevel@tonic-gate if ( fre ) fre( arg, kt[i]->kt_key );
126*7c478bd9Sstevel@tonic-gate }
127*7c478bd9Sstevel@tonic-gate *ep = last;
128*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char*)kt );
129*7c478bd9Sstevel@tonic-gate return( 0 );
130*7c478bd9Sstevel@tonic-gate }
131*7c478bd9Sstevel@tonic-gate
132*7c478bd9Sstevel@tonic-gate
133*7c478bd9Sstevel@tonic-gate struct entrything {
134*7c478bd9Sstevel@tonic-gate char **et_vals;
135*7c478bd9Sstevel@tonic-gate LDAPMessage *et_msg;
136*7c478bd9Sstevel@tonic-gate };
137*7c478bd9Sstevel@tonic-gate
138*7c478bd9Sstevel@tonic-gate typedef int (LDAP_C LDAP_CALLBACK LDAP_CHARCMP_CALLBACK)(char*, char*);
139*7c478bd9Sstevel@tonic-gate typedef int (LDAP_C LDAP_CALLBACK LDAP_VOIDCMP_CALLBACK)(const void*,
140*7c478bd9Sstevel@tonic-gate const void*);
141*7c478bd9Sstevel@tonic-gate
142*7c478bd9Sstevel@tonic-gate static LDAP_CHARCMP_CALLBACK *et_cmp_fn;
143*7c478bd9Sstevel@tonic-gate static LDAP_VOIDCMP_CALLBACK et_cmp;
144*7c478bd9Sstevel@tonic-gate
145*7c478bd9Sstevel@tonic-gate int
146*7c478bd9Sstevel@tonic-gate LDAP_C
147*7c478bd9Sstevel@tonic-gate LDAP_CALLBACK
ldap_sort_strcasecmp(const char ** a,const char ** b)148*7c478bd9Sstevel@tonic-gate ldap_sort_strcasecmp(
149*7c478bd9Sstevel@tonic-gate const char **a,
150*7c478bd9Sstevel@tonic-gate const char **b
151*7c478bd9Sstevel@tonic-gate )
152*7c478bd9Sstevel@tonic-gate {
153*7c478bd9Sstevel@tonic-gate /* XXXceb
154*7c478bd9Sstevel@tonic-gate * I am not 100% sure this is the way this should be handled.
155*7c478bd9Sstevel@tonic-gate * For now we will return a 0 on invalid.
156*7c478bd9Sstevel@tonic-gate */
157*7c478bd9Sstevel@tonic-gate if (NULL == a || NULL == b)
158*7c478bd9Sstevel@tonic-gate return (0);
159*7c478bd9Sstevel@tonic-gate return( strcasecmp( (char *)*a, (char *)*b ) );
160*7c478bd9Sstevel@tonic-gate }
161*7c478bd9Sstevel@tonic-gate
162*7c478bd9Sstevel@tonic-gate static int
163*7c478bd9Sstevel@tonic-gate LDAP_C
164*7c478bd9Sstevel@tonic-gate LDAP_CALLBACK
et_cmp(const void * aa,const void * bb)165*7c478bd9Sstevel@tonic-gate et_cmp(
166*7c478bd9Sstevel@tonic-gate const void *aa,
167*7c478bd9Sstevel@tonic-gate const void *bb
168*7c478bd9Sstevel@tonic-gate )
169*7c478bd9Sstevel@tonic-gate {
170*7c478bd9Sstevel@tonic-gate int i, rc;
171*7c478bd9Sstevel@tonic-gate struct entrything *a = (struct entrything *)aa;
172*7c478bd9Sstevel@tonic-gate struct entrything *b = (struct entrything *)bb;
173*7c478bd9Sstevel@tonic-gate
174*7c478bd9Sstevel@tonic-gate if ( a->et_vals == NULL && b->et_vals == NULL )
175*7c478bd9Sstevel@tonic-gate return( 0 );
176*7c478bd9Sstevel@tonic-gate if ( a->et_vals == NULL )
177*7c478bd9Sstevel@tonic-gate return( -1 );
178*7c478bd9Sstevel@tonic-gate if ( b->et_vals == NULL )
179*7c478bd9Sstevel@tonic-gate return( 1 );
180*7c478bd9Sstevel@tonic-gate
181*7c478bd9Sstevel@tonic-gate for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
182*7c478bd9Sstevel@tonic-gate if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
183*7c478bd9Sstevel@tonic-gate != 0 ) {
184*7c478bd9Sstevel@tonic-gate return( rc );
185*7c478bd9Sstevel@tonic-gate }
186*7c478bd9Sstevel@tonic-gate }
187*7c478bd9Sstevel@tonic-gate
188*7c478bd9Sstevel@tonic-gate if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL )
189*7c478bd9Sstevel@tonic-gate return( 0 );
190*7c478bd9Sstevel@tonic-gate if ( a->et_vals[i] == NULL )
191*7c478bd9Sstevel@tonic-gate return( -1 );
192*7c478bd9Sstevel@tonic-gate return( 1 );
193*7c478bd9Sstevel@tonic-gate }
194*7c478bd9Sstevel@tonic-gate
195*7c478bd9Sstevel@tonic-gate int
196*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_multisort_entries(LDAP * ld,LDAPMessage ** chain,char ** attr,LDAP_CMP_CALLBACK * cmp)197*7c478bd9Sstevel@tonic-gate ldap_multisort_entries(
198*7c478bd9Sstevel@tonic-gate LDAP *ld,
199*7c478bd9Sstevel@tonic-gate LDAPMessage **chain,
200*7c478bd9Sstevel@tonic-gate char **attr, /* NULL => sort by DN */
201*7c478bd9Sstevel@tonic-gate LDAP_CMP_CALLBACK *cmp
202*7c478bd9Sstevel@tonic-gate )
203*7c478bd9Sstevel@tonic-gate {
204*7c478bd9Sstevel@tonic-gate int i, count;
205*7c478bd9Sstevel@tonic-gate struct entrything *et;
206*7c478bd9Sstevel@tonic-gate LDAPMessage *e, *last;
207*7c478bd9Sstevel@tonic-gate LDAPMessage **ep;
208*7c478bd9Sstevel@tonic-gate
209*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld )
210*7c478bd9Sstevel@tonic-gate || chain == NULL || cmp == NULL ) {
211*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate
214*7c478bd9Sstevel@tonic-gate count = ldap_count_entries( ld, *chain );
215*7c478bd9Sstevel@tonic-gate
216*7c478bd9Sstevel@tonic-gate if ( (et = (struct entrything *)NSLDAPI_MALLOC( count *
217*7c478bd9Sstevel@tonic-gate sizeof(struct entrything) )) == NULL ) {
218*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL, NULL );
219*7c478bd9Sstevel@tonic-gate return( -1 );
220*7c478bd9Sstevel@tonic-gate }
221*7c478bd9Sstevel@tonic-gate
222*7c478bd9Sstevel@tonic-gate e = *chain;
223*7c478bd9Sstevel@tonic-gate for ( i = 0; i < count; i++ ) {
224*7c478bd9Sstevel@tonic-gate et[i].et_msg = e;
225*7c478bd9Sstevel@tonic-gate et[i].et_vals = NULL;
226*7c478bd9Sstevel@tonic-gate if ( attr == NULL ) {
227*7c478bd9Sstevel@tonic-gate char *dn;
228*7c478bd9Sstevel@tonic-gate
229*7c478bd9Sstevel@tonic-gate dn = ldap_get_dn( ld, e );
230*7c478bd9Sstevel@tonic-gate et[i].et_vals = ldap_explode_dn( dn, 1 );
231*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( dn );
232*7c478bd9Sstevel@tonic-gate } else {
233*7c478bd9Sstevel@tonic-gate int attrcnt;
234*7c478bd9Sstevel@tonic-gate char **vals;
235*7c478bd9Sstevel@tonic-gate
236*7c478bd9Sstevel@tonic-gate for ( attrcnt = 0; attr[attrcnt] != NULL; attrcnt++ ) {
237*7c478bd9Sstevel@tonic-gate vals = ldap_get_values( ld, e, attr[attrcnt] );
238*7c478bd9Sstevel@tonic-gate if ( ldap_charray_merge( &(et[i].et_vals), vals )
239*7c478bd9Sstevel@tonic-gate != 0 ) {
240*7c478bd9Sstevel@tonic-gate int j;
241*7c478bd9Sstevel@tonic-gate
242*7c478bd9Sstevel@tonic-gate /* XXX risky: ldap_value_free( vals ); */
243*7c478bd9Sstevel@tonic-gate for ( j = 0; j <= i; j++ )
244*7c478bd9Sstevel@tonic-gate ldap_value_free( et[j].et_vals );
245*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char *) et );
246*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_NO_MEMORY, NULL,
247*7c478bd9Sstevel@tonic-gate NULL );
248*7c478bd9Sstevel@tonic-gate return( -1 );
249*7c478bd9Sstevel@tonic-gate }
250*7c478bd9Sstevel@tonic-gate if ( vals != NULL ) {
251*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char *)vals );
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate }
254*7c478bd9Sstevel@tonic-gate }
255*7c478bd9Sstevel@tonic-gate
256*7c478bd9Sstevel@tonic-gate e = e->lm_chain;
257*7c478bd9Sstevel@tonic-gate }
258*7c478bd9Sstevel@tonic-gate last = e;
259*7c478bd9Sstevel@tonic-gate
260*7c478bd9Sstevel@tonic-gate et_cmp_fn = (LDAP_CHARCMP_CALLBACK *)cmp;
261*7c478bd9Sstevel@tonic-gate XP_QSORT( (void *) et, (size_t) count,
262*7c478bd9Sstevel@tonic-gate (size_t) sizeof(struct entrything), et_cmp );
263*7c478bd9Sstevel@tonic-gate
264*7c478bd9Sstevel@tonic-gate ep = chain;
265*7c478bd9Sstevel@tonic-gate for ( i = 0; i < count; i++ ) {
266*7c478bd9Sstevel@tonic-gate *ep = et[i].et_msg;
267*7c478bd9Sstevel@tonic-gate ep = &(*ep)->lm_chain;
268*7c478bd9Sstevel@tonic-gate
269*7c478bd9Sstevel@tonic-gate ldap_value_free( et[i].et_vals );
270*7c478bd9Sstevel@tonic-gate }
271*7c478bd9Sstevel@tonic-gate *ep = last;
272*7c478bd9Sstevel@tonic-gate NSLDAPI_FREE( (char *) et );
273*7c478bd9Sstevel@tonic-gate
274*7c478bd9Sstevel@tonic-gate return( 0 );
275*7c478bd9Sstevel@tonic-gate }
276*7c478bd9Sstevel@tonic-gate
277*7c478bd9Sstevel@tonic-gate int
278*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_sort_entries(LDAP * ld,LDAPMessage ** chain,char * attr,LDAP_CMP_CALLBACK * cmp)279*7c478bd9Sstevel@tonic-gate ldap_sort_entries(
280*7c478bd9Sstevel@tonic-gate LDAP *ld,
281*7c478bd9Sstevel@tonic-gate LDAPMessage **chain,
282*7c478bd9Sstevel@tonic-gate char *attr, /* NULL => sort by DN */
283*7c478bd9Sstevel@tonic-gate LDAP_CMP_CALLBACK *cmp
284*7c478bd9Sstevel@tonic-gate )
285*7c478bd9Sstevel@tonic-gate {
286*7c478bd9Sstevel@tonic-gate char *attrs[2];
287*7c478bd9Sstevel@tonic-gate
288*7c478bd9Sstevel@tonic-gate attrs[0] = attr;
289*7c478bd9Sstevel@tonic-gate attrs[1] = NULL;
290*7c478bd9Sstevel@tonic-gate return( ldap_multisort_entries( ld, chain, attr ? attrs : NULL, cmp ) );
291*7c478bd9Sstevel@tonic-gate }
292*7c478bd9Sstevel@tonic-gate
293*7c478bd9Sstevel@tonic-gate int
294*7c478bd9Sstevel@tonic-gate LDAP_CALL
ldap_sort_values(LDAP * ld,char ** vals,LDAP_VALCMP_CALLBACK * cmp)295*7c478bd9Sstevel@tonic-gate ldap_sort_values(
296*7c478bd9Sstevel@tonic-gate LDAP *ld,
297*7c478bd9Sstevel@tonic-gate char **vals,
298*7c478bd9Sstevel@tonic-gate LDAP_VALCMP_CALLBACK *cmp
299*7c478bd9Sstevel@tonic-gate )
300*7c478bd9Sstevel@tonic-gate {
301*7c478bd9Sstevel@tonic-gate int nel;
302*7c478bd9Sstevel@tonic-gate
303*7c478bd9Sstevel@tonic-gate if ( !NSLDAPI_VALID_LDAP_POINTER( ld ) || cmp == NULL ) {
304*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
305*7c478bd9Sstevel@tonic-gate }
306*7c478bd9Sstevel@tonic-gate
307*7c478bd9Sstevel@tonic-gate if ( NULL == vals)
308*7c478bd9Sstevel@tonic-gate {
309*7c478bd9Sstevel@tonic-gate LDAP_SET_LDERRNO( ld, LDAP_PARAM_ERROR, NULL, NULL );
310*7c478bd9Sstevel@tonic-gate return( LDAP_PARAM_ERROR );
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate for ( nel = 0; vals[nel] != NULL; nel++ )
313*7c478bd9Sstevel@tonic-gate ; /* NULL */
314*7c478bd9Sstevel@tonic-gate
315*7c478bd9Sstevel@tonic-gate XP_QSORT( vals, nel, sizeof(char *), (LDAP_VOIDCMP_CALLBACK *)cmp );
316*7c478bd9Sstevel@tonic-gate
317*7c478bd9Sstevel@tonic-gate return( LDAP_SUCCESS );
318*7c478bd9Sstevel@tonic-gate }
319