1 /*
2 *
3 * Portions Copyright 1998 Sun Microsystems, Inc. All rights reserved.
4 * Use is subject to license terms.
5 *
6 */
7
8 #pragma ident "%Z%%M% %I% %E% SMI"
9
10 /*
11 * Copyright (c) 1994 Regents of the University of Michigan.
12 * All rights reserved.
13 *
14 * Redistribution and use in source and binary forms are permitted
15 * provided that this notice is preserved and that due credit is given
16 * to the University of Michigan at Ann Arbor. The name of the University
17 * may not be used to endorse or promote products derived from this
18 * software without specific prior written permission. This software
19 * is provided ``as is'' without express or implied warranty.
20 *
21 * sort.c: LDAP library entry and value sort routines
22 */
23
24 #include <stdio.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <time.h>
29 #ifdef MACOS
30 #include "macos.h"
31 #else /* MACOS */
32 #ifdef DOS
33 #include <malloc.h>
34 #include "msdos.h"
35 #endif /* DOS */
36 #endif /* MACOS */
37
38 #include "lber.h"
39 #include "ldap.h"
40 #include "ldap-private.h"
41 #include "ldap-int.h"
42
43 struct entrything {
44 char **et_vals;
45 LDAPMessage *et_msg;
46 };
47
48 #ifndef NEEDPROTOS
49 static int (*et_cmp_fn)();
50 static int et_cmp();
51 #else /* !NEEDPROTOS */
52 static int (*et_cmp_fn)( char *a, char *b );
53 #ifdef SUN
54 static int et_cmp( const void *aa, const void *bb);
55 #else
56 static int et_cmp( void *aa, void *bb);
57 #endif
58 #endif /* !NEEDPROTOS */
59
60 int
ldap_sort_strcasecmp(char ** a,char ** b)61 ldap_sort_strcasecmp(
62 char **a,
63 char **b
64 )
65 {
66 return( strcasecmp( *a, *b ) );
67 }
68
69 static int
et_cmp(const void * aa,const void * bb)70 et_cmp(
71 #ifdef SUN
72 const void *aa,
73 const void *bb
74 #else
75 void *aa,
76 void *bb
77 #endif
78 )
79 {
80 int i, rc;
81 struct entrything *a = (struct entrything *)aa;
82 struct entrything *b = (struct entrything *)bb;
83
84 if ( a->et_vals == NULL && b->et_vals == NULL )
85 return( 0 );
86 if ( a->et_vals == NULL )
87 return( -1 );
88 if ( b->et_vals == NULL )
89 return( 1 );
90
91 for ( i = 0; a->et_vals[i] && b->et_vals[i]; i++ ) {
92 if ( (rc = (*et_cmp_fn)( a->et_vals[i], b->et_vals[i] ))
93 != 0 ) {
94 return( rc );
95 }
96 }
97
98 if ( a->et_vals[i] == NULL && b->et_vals[i] == NULL )
99 return( 0 );
100 if ( a->et_vals[i] == NULL )
101 return( -1 );
102 return( 1 );
103 }
104
105 int
ldap_sort_entries(LDAP * ld,LDAPMessage ** chain,char * attr,int (* cmp)())106 ldap_sort_entries(
107 LDAP *ld,
108 LDAPMessage **chain,
109 char *attr, /* NULL => sort by DN */
110 int (*cmp)()
111 )
112 {
113 int i;
114 size_t count;
115 struct entrything *et;
116 LDAPMessage *e, *last;
117 LDAPMessage **ep;
118
119 count = ldap_count_entries( ld, *chain );
120
121 if ( (et = (struct entrything *) malloc( count *
122 sizeof(struct entrything) )) == NULL ) {
123 ld->ld_errno = LDAP_NO_MEMORY;
124 return( -1 );
125 }
126
127 e = *chain;
128 for ( i = 0; i < count; i++ ) {
129 et[i].et_msg = e;
130 if ( attr == NULL ) {
131 char *dn;
132
133 dn = ldap_get_dn( ld, e );
134 et[i].et_vals = ldap_explode_dn( dn, 1 );
135 free( dn );
136 } else {
137 et[i].et_vals = ldap_get_values( ld, e, attr );
138 }
139
140 e = e->lm_chain;
141 }
142 last = e;
143
144 et_cmp_fn = cmp;
145 #ifdef SUN
146 qsort( et, count, sizeof(struct entrything), et_cmp );
147 #else
148 qsort( et, count, sizeof(struct entrything), (void *) et_cmp );
149 #endif
150
151 ep = chain;
152 for ( i = 0; i < count; i++ ) {
153 *ep = et[i].et_msg;
154 ep = &(*ep)->lm_chain;
155
156 ldap_value_free( et[i].et_vals );
157 }
158 *ep = last;
159 free( (char *) et );
160
161 return( 0 );
162 }
163
164 /* ARGSUSED */
165 int
ldap_sort_values(LDAP * ld,char ** vals,int (* cmp)())166 ldap_sort_values(
167 LDAP *ld,
168 char **vals,
169 int (*cmp)()
170 )
171 {
172 size_t nel;
173
174 for ( nel = 0; vals[nel] != NULL; nel++ )
175 ; /* NULL */
176
177 qsort( vals, nel, sizeof(char *), cmp );
178
179 return( 0 );
180 }
181