xref: /onnv-gate/usr/src/lib/libldap4/common/sortctrl.c (revision 3857:21b9b714e4ab)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  *
3*3857Sstevel  * Copyright 1999 Sun Microsystems, Inc.  All rights reserved.
4*3857Sstevel  * Use is subject to license terms.
50Sstevel@tonic-gate  *
60Sstevel@tonic-gate  *
70Sstevel@tonic-gate  * Comments:
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  */
100Sstevel@tonic-gate 
110Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
120Sstevel@tonic-gate 
130Sstevel@tonic-gate #include <stdio.h>
140Sstevel@tonic-gate #include <string.h>
150Sstevel@tonic-gate #include <ctype.h>
160Sstevel@tonic-gate 
170Sstevel@tonic-gate #include "lber.h"
180Sstevel@tonic-gate #include "ldap.h"
190Sstevel@tonic-gate #include "ldap-private.h"
200Sstevel@tonic-gate #include "ldap-int.h"
210Sstevel@tonic-gate 
220Sstevel@tonic-gate static int count_tokens(char *s);
230Sstevel@tonic-gate static int isattrdescchar(char c);
240Sstevel@tonic-gate static int read_next_token(char **s, LDAPsortkey **key);
250Sstevel@tonic-gate 
260Sstevel@tonic-gate 
ldap_create_sort_control(LDAP * ld,LDAPsortkey ** sortKeyList,const char ctl_iscritical,LDAPControl ** ctrlp)270Sstevel@tonic-gate int ldap_create_sort_control(LDAP *ld, LDAPsortkey **sortKeyList,
280Sstevel@tonic-gate 	const char ctl_iscritical, LDAPControl **ctrlp)
290Sstevel@tonic-gate {
300Sstevel@tonic-gate 	BerElement *ber;
310Sstevel@tonic-gate 	int i, rc;
320Sstevel@tonic-gate 
330Sstevel@tonic-gate 	if (NULL == ld) {
340Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
350Sstevel@tonic-gate 	}
360Sstevel@tonic-gate 
370Sstevel@tonic-gate 	if (sortKeyList == NULL || ctrlp == NULL) {
380Sstevel@tonic-gate 		ld->ld_errno = LDAP_PARAM_ERROR;
390Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
400Sstevel@tonic-gate 	}
410Sstevel@tonic-gate 
420Sstevel@tonic-gate 	/* create a ber package to hold the controlValue */
430Sstevel@tonic-gate 	if ((ber = alloc_ber_with_options(ld)) == NULLBER) {
440Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
450Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
460Sstevel@tonic-gate 	}
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 	/* encode the start of the sequence of sequences into the ber */
490Sstevel@tonic-gate 	if (ber_printf(ber, "{") == -1) {
500Sstevel@tonic-gate 		goto encoding_error_exit;
510Sstevel@tonic-gate 	}
520Sstevel@tonic-gate 
530Sstevel@tonic-gate 	/*
540Sstevel@tonic-gate 	 * the sort control value will be encoded as a sequence of sequences
550Sstevel@tonic-gate 	 * which are each encoded as one of the following: {s} or {sts} or
560Sstevel@tonic-gate 	 * {stb} or {ststb} since the orderingRule and reverseOrder flag are
570Sstevel@tonic-gate 	 * both optional
580Sstevel@tonic-gate 	 */
590Sstevel@tonic-gate 	for (i = 0; sortKeyList[i] != NULL; i++) {
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 		/* encode the attributeType into the ber */
620Sstevel@tonic-gate 		if (ber_printf(ber, "{s", (sortKeyList[i])->sk_attrtype)
630Sstevel@tonic-gate 		    == -1) {
640Sstevel@tonic-gate 			goto encoding_error_exit;
650Sstevel@tonic-gate 		}
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 		/* encode the optional orderingRule into the ber */
680Sstevel@tonic-gate 		if ((sortKeyList[i])->sk_matchruleoid != NULL) {
690Sstevel@tonic-gate 			if (ber_printf(ber, "ts", LDAP_TAG_SK_MATCHRULE,
700Sstevel@tonic-gate 			    (sortKeyList[i])->sk_matchruleoid)
710Sstevel@tonic-gate 			    == -1) {
720Sstevel@tonic-gate 				goto encoding_error_exit;
730Sstevel@tonic-gate 			}
740Sstevel@tonic-gate 		}
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 		/* Encode the optional reverseOrder flag into the ber. */
770Sstevel@tonic-gate 		/* If the flag is false, it should be absent. */
780Sstevel@tonic-gate 		if ((sortKeyList[i])->sk_reverseorder) {
790Sstevel@tonic-gate 			if (ber_printf(ber, "tb}", LDAP_TAG_SK_REVERSE,
800Sstevel@tonic-gate 			    (sortKeyList[i])->sk_reverseorder) == -1) {
810Sstevel@tonic-gate 				goto encoding_error_exit;
820Sstevel@tonic-gate 			}
830Sstevel@tonic-gate 		} else {
840Sstevel@tonic-gate 			if (ber_printf(ber, "}") == -1) {
850Sstevel@tonic-gate 				goto encoding_error_exit;
860Sstevel@tonic-gate 			}
870Sstevel@tonic-gate 		}
880Sstevel@tonic-gate 	}
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	/* encode the end of the sequence of sequences into the ber */
910Sstevel@tonic-gate 	if (ber_printf(ber, "}") == -1) {
920Sstevel@tonic-gate 		goto encoding_error_exit;
930Sstevel@tonic-gate 	}
940Sstevel@tonic-gate 
950Sstevel@tonic-gate 	rc = ldap_build_control(LDAP_CONTROL_SORTREQUEST, ber, 1,
960Sstevel@tonic-gate 	    ctl_iscritical, ctrlp);
970Sstevel@tonic-gate 	ld->ld_errno = rc;
980Sstevel@tonic-gate 	return (rc);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate encoding_error_exit:
1010Sstevel@tonic-gate 	ld->ld_errno = LDAP_ENCODING_ERROR;
1020Sstevel@tonic-gate 	ber_free(ber, 1);
1030Sstevel@tonic-gate 	return (LDAP_ENCODING_ERROR);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 
ldap_parse_sort_control(LDAP * ld,LDAPControl ** ctrlp,unsigned long * result,char ** attribute)1070Sstevel@tonic-gate int ldap_parse_sort_control(LDAP *ld, LDAPControl **ctrlp,
1080Sstevel@tonic-gate 	unsigned long *result, char **attribute)
1090Sstevel@tonic-gate {
1100Sstevel@tonic-gate 	BerElement *ber;
1110Sstevel@tonic-gate 	int i, foundSortControl;
1120Sstevel@tonic-gate 	LDAPControl *sortCtrlp;
1130Sstevel@tonic-gate 	unsigned int len;
1140Sstevel@tonic-gate 	char *attr;
1150Sstevel@tonic-gate 	int tag;
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	if ((NULL == ld) || (result == NULL) ||
1180Sstevel@tonic-gate 		(attribute == NULL)) {
1190Sstevel@tonic-gate 	    return (LDAP_PARAM_ERROR);
1200Sstevel@tonic-gate 	}
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	/* find the sortControl in the list of controls if it exists */
1240Sstevel@tonic-gate 	if (ctrlp == NULL) {
1250Sstevel@tonic-gate 		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
1260Sstevel@tonic-gate 		return (LDAP_CONTROL_NOT_FOUND);
1270Sstevel@tonic-gate 	}
1280Sstevel@tonic-gate 	foundSortControl = 0;
1290Sstevel@tonic-gate 	for (i = 0; ((ctrlp[i] != NULL) && (!foundSortControl)); i++) {
1300Sstevel@tonic-gate 		foundSortControl = !(strcmp(ctrlp[i]->ldctl_oid,
1310Sstevel@tonic-gate 			LDAP_CONTROL_SORTRESPONSE));
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 	if (!foundSortControl) {
1340Sstevel@tonic-gate 		ld->ld_errno = LDAP_CONTROL_NOT_FOUND;
1350Sstevel@tonic-gate 		return (LDAP_CONTROL_NOT_FOUND);
1360Sstevel@tonic-gate 	} else {
1370Sstevel@tonic-gate 		/* let local var point to the sortControl */
1380Sstevel@tonic-gate 		sortCtrlp = ctrlp[i-1];
1390Sstevel@tonic-gate 	}
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	/*
1420Sstevel@tonic-gate 	 * allocate a Ber element with the contents of the sort_control's
1430Sstevel@tonic-gate 	 * struct berval
1440Sstevel@tonic-gate 	 */
1450Sstevel@tonic-gate 	if ((ber = ber_init(&sortCtrlp->ldctl_value)) == NULL) {
1460Sstevel@tonic-gate 		ld->ld_errno = LDAP_NO_MEMORY;
1470Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
1480Sstevel@tonic-gate 	}
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	/* decode the result from the Berelement */
1510Sstevel@tonic-gate 	if (ber_scanf(ber, "{i", result) == LBER_ERROR) {
1520Sstevel@tonic-gate 		ld->ld_errno = LDAP_DECODING_ERROR;
1530Sstevel@tonic-gate 		ber_free(ber, 1);
1540Sstevel@tonic-gate 		return (LDAP_DECODING_ERROR);
1550Sstevel@tonic-gate 	}
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	/*
1580Sstevel@tonic-gate 	 * if the server returned one, decode the attribute from the Ber element
1590Sstevel@tonic-gate 	 */
1600Sstevel@tonic-gate 	if (ber_peek_tag(ber, &len) == LDAP_TAG_SR_ATTRTYPE) {
1610Sstevel@tonic-gate 		if (ber_scanf(ber, "ta", &tag, &attr) == LBER_ERROR) {
1620Sstevel@tonic-gate 			ld->ld_errno = LDAP_DECODING_ERROR;
1630Sstevel@tonic-gate 			ber_free(ber, 1);
1640Sstevel@tonic-gate 			return (LDAP_DECODING_ERROR);
1650Sstevel@tonic-gate 		}
1660Sstevel@tonic-gate 		*attribute = attr;
1670Sstevel@tonic-gate 	} else {
1680Sstevel@tonic-gate 		*attribute = NULL;
1690Sstevel@tonic-gate 	}
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 	if (ber_scanf(ber, "}") == LBER_ERROR) {
1720Sstevel@tonic-gate 		ld->ld_errno = LDAP_DECODING_ERROR;
1730Sstevel@tonic-gate 		ber_free(ber, 1);
1740Sstevel@tonic-gate 		return (LDAP_DECODING_ERROR);
1750Sstevel@tonic-gate 	}
1760Sstevel@tonic-gate 
1770Sstevel@tonic-gate 	/* the ber encoding is no longer needed */
1780Sstevel@tonic-gate 	ber_free(ber, 1);
1790Sstevel@tonic-gate 	return (LDAP_SUCCESS);
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate 
1820Sstevel@tonic-gate 
1830Sstevel@tonic-gate /*
1840Sstevel@tonic-gate  * Routines for the manipulation of string-representations of sort control
1850Sstevel@tonic-gate  * keylists
1860Sstevel@tonic-gate  */
count_tokens(char * s)1870Sstevel@tonic-gate static int count_tokens(char *s)
1880Sstevel@tonic-gate {
1890Sstevel@tonic-gate 	int count = 0;
1900Sstevel@tonic-gate 	char *p = s;
1910Sstevel@tonic-gate 	int whitespace = 1;
1920Sstevel@tonic-gate 	/*
1930Sstevel@tonic-gate 	 * Loop along the string counting the number of times we see the
1940Sstevel@tonic-gate 	 * beginning of non-whitespace. This tells us
1950Sstevel@tonic-gate 	 * the number of tokens in the string
1960Sstevel@tonic-gate 	 */
1970Sstevel@tonic-gate 	while (*p != '\0') {
1980Sstevel@tonic-gate 		if (whitespace) {
1990Sstevel@tonic-gate 			if (!isspace(*p)) {
2000Sstevel@tonic-gate 				whitespace = 0;
2010Sstevel@tonic-gate 				count++;
2020Sstevel@tonic-gate 			}
2030Sstevel@tonic-gate 		} else {
2040Sstevel@tonic-gate 			if (isspace(*p)) {
2050Sstevel@tonic-gate 				whitespace = 1;
2060Sstevel@tonic-gate 			}
2070Sstevel@tonic-gate 		}
2080Sstevel@tonic-gate 		p++;
2090Sstevel@tonic-gate 	}
2100Sstevel@tonic-gate 	return (count);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate /* Is this character a valid attribute description character ? */
isattrdescchar(char c)2150Sstevel@tonic-gate static int isattrdescchar(char c)
2160Sstevel@tonic-gate {
2170Sstevel@tonic-gate 	/* Alphanumeric chars are in */
2180Sstevel@tonic-gate 	if (isalnum(c)) {
2190Sstevel@tonic-gate 		return (1);
2200Sstevel@tonic-gate 	}
2210Sstevel@tonic-gate 	/* As is ';' */
2220Sstevel@tonic-gate 	if (';' == c) {
2230Sstevel@tonic-gate 		return (1);
2240Sstevel@tonic-gate 	}
2250Sstevel@tonic-gate 	/* Everything else is out */
2260Sstevel@tonic-gate 	return (0);
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 
read_next_token(char ** s,LDAPsortkey ** key)2300Sstevel@tonic-gate static int read_next_token(char **s, LDAPsortkey **key)
2310Sstevel@tonic-gate {
2320Sstevel@tonic-gate 	char c = 0;
2330Sstevel@tonic-gate 	char *pos = *s;
2340Sstevel@tonic-gate 	int retval = 0;
2350Sstevel@tonic-gate 	LDAPsortkey *new_key = NULL;
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	char *matchrule_source = NULL;
2380Sstevel@tonic-gate 	int matchrule_size = 0;
2390Sstevel@tonic-gate 	char *attrdesc_source = NULL;
2400Sstevel@tonic-gate 	int attrdesc_size = 0;
2410Sstevel@tonic-gate 	int reverse = 0;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	int state = 0;
2440Sstevel@tonic-gate 
2450Sstevel@tonic-gate 	while (((c = *pos++) != '\0') && (state != 4)) {
2460Sstevel@tonic-gate 		switch (state) {
2470Sstevel@tonic-gate 		case 0:
2480Sstevel@tonic-gate 		/* case where we've not seen the beginning of the attr yet */
2490Sstevel@tonic-gate 			/* If we still see whitespace, nothing to do */
2500Sstevel@tonic-gate 			if (!isspace(c)) {
2510Sstevel@tonic-gate 				/* Otherwise, something to look at */
2520Sstevel@tonic-gate 				/* Is it a minus sign ? */
2530Sstevel@tonic-gate 				if ('-' == c) {
2540Sstevel@tonic-gate 					reverse = 1;
2550Sstevel@tonic-gate 				} else {
2560Sstevel@tonic-gate 					attrdesc_source = pos - 1;
2570Sstevel@tonic-gate 					state = 1;
2580Sstevel@tonic-gate 				}
2590Sstevel@tonic-gate 			}
2600Sstevel@tonic-gate 			break;
2610Sstevel@tonic-gate 		case 1:
2620Sstevel@tonic-gate 		/*
2630Sstevel@tonic-gate 		 * case where we've seen the beginning of the attr, but not
2640Sstevel@tonic-gate 		 * the end
2650Sstevel@tonic-gate 		 */
2660Sstevel@tonic-gate 			/* Is this char either whitespace or a ':' ? */
2670Sstevel@tonic-gate 			if (isspace(c) || (':' == c)) {
2680Sstevel@tonic-gate 				attrdesc_size = (pos - attrdesc_source) - 1;
2690Sstevel@tonic-gate 				if (':' == c) {
2700Sstevel@tonic-gate 					state = 2;
2710Sstevel@tonic-gate 				} else {
2720Sstevel@tonic-gate 					state = 4;
2730Sstevel@tonic-gate 				}
2740Sstevel@tonic-gate 			}
2750Sstevel@tonic-gate 			break;
2760Sstevel@tonic-gate 		case 2:
2770Sstevel@tonic-gate 		/*
2780Sstevel@tonic-gate 		 * case where we've seen the end of the attr and want the
2790Sstevel@tonic-gate 		 * beginning of match rule
2800Sstevel@tonic-gate 		 */
2810Sstevel@tonic-gate 			if (!isspace(c)) {
2820Sstevel@tonic-gate 				matchrule_source = pos - 1;
2830Sstevel@tonic-gate 				state = 3;
2840Sstevel@tonic-gate 			} else {
2850Sstevel@tonic-gate 				state = 4;
2860Sstevel@tonic-gate 			}
2870Sstevel@tonic-gate 			break;
2880Sstevel@tonic-gate 		case 3:
2890Sstevel@tonic-gate 		/*
2900Sstevel@tonic-gate 		 * case where we've seen the beginning of match rule and
2910Sstevel@tonic-gate 		 * want to find the end
2920Sstevel@tonic-gate 		 */
2930Sstevel@tonic-gate 			if (isspace(c)) {
2940Sstevel@tonic-gate 				matchrule_size = (pos - matchrule_source) - 1;
2950Sstevel@tonic-gate 				state = 4;
2960Sstevel@tonic-gate 			}
2970Sstevel@tonic-gate 			break;
2980Sstevel@tonic-gate 		default:
2990Sstevel@tonic-gate 			break;
3000Sstevel@tonic-gate 		}
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	if (3 == state) {
3040Sstevel@tonic-gate 		/*
3050Sstevel@tonic-gate 		 * means we fell off the end of the string looking for the
3060Sstevel@tonic-gate 		 * end of the marching rule
3070Sstevel@tonic-gate 		 */
3080Sstevel@tonic-gate 		matchrule_size = (pos - matchrule_source) - 1;
3090Sstevel@tonic-gate 	}
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	if (1 == state) {
3120Sstevel@tonic-gate 		/*
3130Sstevel@tonic-gate 		 * means we fell of the end of the string looking for the
3140Sstevel@tonic-gate 		 * end of the attribute
3150Sstevel@tonic-gate 		 */
3160Sstevel@tonic-gate 		attrdesc_size = (pos - attrdesc_source) - 1;
3170Sstevel@tonic-gate 	}
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 	if (NULL == attrdesc_source)  {
3200Sstevel@tonic-gate 		/* Didn't find anything */
3210Sstevel@tonic-gate 		return (-1);
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	new_key = (LDAPsortkey*)malloc(sizeof (LDAPsortkey));
3250Sstevel@tonic-gate 	if (0 == new_key) {
3260Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
3270Sstevel@tonic-gate 	}
3280Sstevel@tonic-gate 
3290Sstevel@tonic-gate 	/* Allocate the strings */
3300Sstevel@tonic-gate 	new_key->sk_attrtype = (char *)malloc(attrdesc_size + 1);
3310Sstevel@tonic-gate 	if (NULL != matchrule_source) {
3320Sstevel@tonic-gate 		new_key->sk_matchruleoid = (char *)malloc(matchrule_size + 1);
3330Sstevel@tonic-gate 	} else {
3340Sstevel@tonic-gate 		new_key->sk_matchruleoid = NULL;
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 	/* Copy over the strings */
3370Sstevel@tonic-gate 	memcpy(new_key->sk_attrtype, attrdesc_source, attrdesc_size);
3380Sstevel@tonic-gate 	*(new_key->sk_attrtype + attrdesc_size) = '\0';
3390Sstevel@tonic-gate 	if (NULL != matchrule_source) {
3400Sstevel@tonic-gate 		memcpy(new_key->sk_matchruleoid, matchrule_source,
3410Sstevel@tonic-gate 			matchrule_size);
3420Sstevel@tonic-gate 		*(new_key->sk_matchruleoid + matchrule_size) = '\0';
3430Sstevel@tonic-gate 	}
3440Sstevel@tonic-gate 
3450Sstevel@tonic-gate 	new_key->sk_reverseorder = reverse;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	*s = pos - 1;
3480Sstevel@tonic-gate 	*key = new_key;
3490Sstevel@tonic-gate 	return (retval);
3500Sstevel@tonic-gate }
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate int
ldap_create_sort_keylist(LDAPsortkey *** sortKeyList,char * string_rep)3540Sstevel@tonic-gate ldap_create_sort_keylist(LDAPsortkey ***sortKeyList, char *string_rep)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate 	int count = 0;
3570Sstevel@tonic-gate 	LDAPsortkey **pointer_array = NULL;
3580Sstevel@tonic-gate 	char *current_position = NULL;
3590Sstevel@tonic-gate 	char *s = NULL;
3600Sstevel@tonic-gate 	int retval = 0;
3610Sstevel@tonic-gate 	int i = 0;
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 	/* Figure out how many there are */
3640Sstevel@tonic-gate 	if (NULL == string_rep) {
3650Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 	if (NULL == sortKeyList) {
3680Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
3690Sstevel@tonic-gate 	}
3700Sstevel@tonic-gate 	count = count_tokens(string_rep);
3710Sstevel@tonic-gate 	if (0 == count) {
3720Sstevel@tonic-gate 		*sortKeyList = NULL;
3730Sstevel@tonic-gate 		return (LDAP_PARAM_ERROR);
3740Sstevel@tonic-gate 	}
3750Sstevel@tonic-gate 	/* Allocate enough memory for the pointers */
3760Sstevel@tonic-gate 	pointer_array = (LDAPsortkey**)malloc(sizeof (LDAPsortkey*)
3770Sstevel@tonic-gate 	    * (count + 1));
3780Sstevel@tonic-gate 	if (NULL == pointer_array) {
3790Sstevel@tonic-gate 		return (LDAP_NO_MEMORY);
3800Sstevel@tonic-gate 	}
3810Sstevel@tonic-gate 	/*
3820Sstevel@tonic-gate 	 * Now walk along the string, allocating and filling in the
3830Sstevel@tonic-gate 	 * LDAPsearchkey structure
3840Sstevel@tonic-gate 	 */
3850Sstevel@tonic-gate 	current_position = string_rep;
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate 	for (i = 0; i < count; i++) {
3880Sstevel@tonic-gate 		if (0 != (retval = read_next_token(&current_position,
3890Sstevel@tonic-gate 			&(pointer_array[i])))) {
3900Sstevel@tonic-gate 			pointer_array[count] = NULL;
3910Sstevel@tonic-gate 			ldap_free_sort_keylist(pointer_array);
3920Sstevel@tonic-gate 			*sortKeyList = NULL;
3930Sstevel@tonic-gate 			return (retval);
3940Sstevel@tonic-gate 		}
3950Sstevel@tonic-gate 	}
3960Sstevel@tonic-gate 	pointer_array[count] = NULL;
3970Sstevel@tonic-gate 	*sortKeyList = pointer_array;
3980Sstevel@tonic-gate 	return (LDAP_SUCCESS);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate void
ldap_free_sort_keylist(LDAPsortkey ** sortKeyList)4030Sstevel@tonic-gate ldap_free_sort_keylist(LDAPsortkey **sortKeyList)
4040Sstevel@tonic-gate {
4050Sstevel@tonic-gate 	LDAPsortkey *this_one = NULL;
4060Sstevel@tonic-gate 	int i = 0;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	if (NULL == sortKeyList) {
4090Sstevel@tonic-gate 		return;
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	/* Walk down the list freeing the LDAPsortkey structures */
4130Sstevel@tonic-gate 	for (this_one = sortKeyList[0]; this_one;
4140Sstevel@tonic-gate 		this_one = sortKeyList[++i]) {
4150Sstevel@tonic-gate 		/* Free the strings, if present */
4160Sstevel@tonic-gate 		if (NULL != this_one->sk_attrtype) {
4170Sstevel@tonic-gate 			free(this_one->sk_attrtype);
4180Sstevel@tonic-gate 		}
4190Sstevel@tonic-gate 		if (NULL != this_one->sk_matchruleoid) {
4200Sstevel@tonic-gate 			free(this_one->sk_matchruleoid);
4210Sstevel@tonic-gate 		}
4220Sstevel@tonic-gate 		free(this_one);
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate 	/* Free the pointer list */
4250Sstevel@tonic-gate 	free(sortKeyList);
4260Sstevel@tonic-gate }
427