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(¤t_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