1 #pragma ident   "%Z%%M% %I%     %E% SMI"
   2 
   3 /*
   4  * kadmin/ldap_util/kdb5_ldap_list.c
   5  */
   6 
   7 /* Copyright (c) 2004-2005, Novell, Inc.
   8  * All rights reserved.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions are met:
  12  *
  13  *   * Redistributions of source code must retain the above copyright notice,
  14  *       this list of conditions and the following disclaimer.
  15  *   * Redistributions in binary form must reproduce the above copyright
  16  *       notice, this list of conditions and the following disclaimer in the
  17  *       documentation and/or other materials provided with the distribution.
  18  *   * The copyright holder's name is not used to endorse or promote products
  19  *       derived from this software without specific prior written permission.
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31  * POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 /*
  35  * Miscellaneous functions for managing the string and integer lists
  36  */
  37 
  38 #include <k5-int.h>
  39 #include "kdb5_ldap_list.h"
  40 
  41 /*
  42  * Counts the number of entries in the given array of strings
  43  */
  44 int list_count_str_array(char **list)
  45 {
  46     int i = 0;
  47 
  48     if (list == NULL)
  49         return 0;
  50 
  51     for (i = 0; *list != NULL; list++) {
  52         i++;
  53     }
  54 
  55     return i;
  56 }
  57 
  58 
  59 /*
  60  * Counts the number of entries in the given array of integers
  61  */
  62 int list_count_int_array(int *list)
  63 {
  64     int i = 0;
  65 
  66     if (list == NULL)
  67         return 0;
  68 
  69     for (i = 0; *list != END_OF_LIST; list++) {
  70         i++;
  71     }
  72 
  73     return i;
  74 }
  75 
  76 
  77 /*
  78  * Frees the entries in a given list and not the list pointer
  79  */
  80 void krb5_free_list_entries(list)
  81     char **list;
  82 {
  83     if (list == NULL)
  84         return;
  85     for (; *list != NULL; list++) {
  86         free(*list);
  87         *list = NULL;
  88     }
  89 
  90     return;
  91 }
  92 
  93 
  94 /*
  95  * Tokenize the given string based on the delimiter provided
  96  * and return the result as a list
  97  */
  98 krb5_error_code
  99 krb5_parse_list(buffer, delimiter, list)
 100     char *buffer;
 101     char *delimiter;
 102     char **list;
 103 {
 104     char *str = NULL;
 105     char *token = NULL;
 106     char *ptrptr = NULL;
 107     char **plist = list;
 108     krb5_error_code retval = 0;
 109     int count = 0;
 110 
 111     if ((buffer == NULL) || (list == NULL) || (delimiter == NULL)) {
 112         return EINVAL;
 113     }
 114 
 115     str = strdup(buffer);
 116     if (str == NULL)
 117         return ENOMEM;
 118 
 119     token = strtok_r(str, delimiter, &ptrptr);
 120     for (count = 1; ((token != NULL) && (count < MAX_LIST_ENTRIES));
 121          plist++, count++) {
 122         *plist = strdup(token);
 123         if (*plist == NULL) {
 124             retval = ENOMEM;
 125             goto cleanup;
 126         }
 127         token = strtok_r(NULL, delimiter, &ptrptr);
 128     }
 129     *plist = NULL;
 130 
 131 cleanup:
 132     if (str) {
 133         free(str);
 134         str = NULL;
 135     }
 136     if (retval)
 137         krb5_free_list_entries(list);
 138 
 139     return retval;
 140 }
 141 
 142 
 143 int compare_int(m1, m2)
 144     const void *m1;
 145     const void *m2;
 146 {
 147     int mi1 = *(const int *)m1;
 148     int mi2 = *(const int *)m2;
 149 
 150     return (mi1 - mi2);
 151 }
 152 
 153 
 154 /*
 155  * Modifies the destination list to contain or not to contain the
 156  * entries present in the source list, depending on the mode
 157  * (ADD or DELETE).
 158  */
 159 void list_modify_str_array(destlist, sourcelist, mode)
 160     char ***destlist;
 161     const char **sourcelist;
 162     int mode;
 163 {
 164     char **dlist = NULL, **tmplist = NULL;
 165     const char **slist = NULL;
 166     int dcount = 0, scount = 0, copycount = 0;
 167     int found = 0;
 168 
 169     if ((destlist == NULL) || (*destlist == NULL) || (sourcelist == NULL))
 170         return;
 171 
 172     /* We need to add every entry present in the source list to
 173      * the destination list */
 174     if (mode == LIST_MODE_ADD) {
 175         /* Traverse throught the end of destlist for appending */
 176         for (dlist = *destlist, dcount = 0; *dlist != NULL;
 177              dlist++, dcount++) {
 178             ;   /* NULL statement */
 179         }
 180         /* Count the number of entries in the source list */
 181         for (slist = sourcelist, scount = 0; *slist != NULL;
 182              slist++, scount++) {
 183             ;   /* NULL statement */
 184         }
 185         /* Reset the slist pointer to the start of source list */
 186         slist = sourcelist;
 187 
 188         /* Now append the source list to the existing destlist */
 189         if ((dcount + scount) < MAX_LIST_ENTRIES)
 190             copycount = scount;
 191         else
 192             /* Leave the last entry for list terminator(=NULL) */
 193             copycount = (MAX_LIST_ENTRIES -1) - dcount;
 194 
 195         memcpy(dlist, slist, (sizeof(char *) * copycount));
 196         dlist += copycount;
 197         *dlist = NULL;
 198     } else if (mode == LIST_MODE_DELETE) {
 199         /* We need to delete every entry present in the source list
 200          * from the destination list */
 201         for (slist = sourcelist; *slist != NULL; slist++) {
 202             for (dlist = *destlist; *dlist != NULL; dlist++) {
 203                 found = 0; /* value not found */
 204                 /* DN is case insensitive string */
 205                 if (strcasecmp(*dlist, *slist) == 0) {
 206                     found = 1;
 207                     free(*dlist);
 208                     /* Advance the rest of the entries by one */
 209                     for (tmplist = dlist; *tmplist != NULL; tmplist++) {
 210                         *tmplist = *(tmplist+1);
 211                     }
 212                     break;
 213                 }
 214             }
 215         }
 216     }
 217 
 218     return;
 219 }
 220 
 221 
 222 /*
 223  * Modifies the destination list to contain or not to contain the
 224  * entries present in the source list, depending on the mode
 225  * (ADD or DELETE). where the list is array of integers.
 226  */
 227 int list_modify_int_array(destlist, sourcelist, mode)
 228     int *destlist;
 229     const int *sourcelist;
 230     int mode;
 231 {
 232     int *dlist = NULL, *tmplist = NULL;
 233     const int *slist = NULL;
 234     int dcount = 0, scount = 0, copycount = 0;
 235     int tcount = 0;
 236 
 237     if ((destlist == NULL) || (sourcelist == NULL))
 238         return 0;
 239 
 240     /* We need to add every entry present in the source list to the
 241      * destination list */
 242     if (mode == LIST_MODE_ADD) {
 243         /* Traverse throught the end of destlist for appending */
 244         for (dlist = destlist, dcount = 0; *dlist != END_OF_LIST;
 245              dlist++, dcount++)
 246             ;   /* NULL statement */
 247 
 248         /* Count the number of entries in the source list */
 249         for (slist = sourcelist, scount = 0; *slist != END_OF_LIST;
 250              slist++, scount++)
 251             ;   /* NULL statement */
 252 
 253         /* Reset the slist pointer to the start of source list */
 254         slist = sourcelist;
 255 
 256         /* Now append the source list to the existing destlist */
 257         if ((dcount + scount) < MAX_LIST_ENTRIES)
 258             copycount = scount;
 259         else
 260             /* Leave the last entry for list terminator(=NULL) */
 261             copycount = (MAX_LIST_ENTRIES -1) - dcount;
 262 
 263         memcpy(dlist, slist, (sizeof(int) * copycount));
 264         dlist += copycount;
 265         *dlist = END_OF_LIST;
 266         tcount = dcount + copycount;
 267     } else if (mode == LIST_MODE_DELETE) {
 268         /* We need to delete every entry present in the source list from
 269          * the destination list */
 270         for (slist = sourcelist; *slist != END_OF_LIST; slist++) {
 271             for (dlist = destlist; *dlist != END_OF_LIST; dlist++) {
 272                 if (*dlist == *slist) {
 273                     /* Advance the rest of the entries by one */
 274                     for (tmplist = dlist; *tmplist != END_OF_LIST; tmplist++) {
 275                         *tmplist = *(tmplist+1);
 276                     }
 277                     break;
 278                 }
 279             }
 280         }
 281         /* count the number of entries */
 282         for (dlist = destlist, tcount = 0; *dlist != END_OF_LIST; dlist++) {
 283             tcount++;
 284         }
 285     }
 286 
 287     return tcount;
 288 }
 289