1 /*        $NetBSD: charray.c,v 1.3 2021/08/14 16:14:55 christos Exp $ */
2 
3 /* charray.c - routines for dealing with char * arrays */
4 /* $OpenLDAP$ */
5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
6  *
7  * Copyright 1998-2021 The OpenLDAP Foundation.
8  * All rights reserved.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted only as authorized by the OpenLDAP
12  * Public License.
13  *
14  * A copy of this license is available in the file LICENSE in the
15  * top-level directory of the distribution or, alternatively, at
16  * <http://www.OpenLDAP.org/license.html>.
17  */
18 
19 #include <sys/cdefs.h>
20 __RCSID("$NetBSD: charray.c,v 1.3 2021/08/14 16:14:55 christos Exp $");
21 
22 #include "portable.h"
23 
24 #include <stdio.h>
25 
26 #include <ac/string.h>
27 #include <ac/socket.h>
28 
29 #include "ldap-int.h"
30 
31 int
ldap_charray_add(char *** a,const char * s)32 ldap_charray_add(
33     char  ***a,
34     const char *s
35 )
36 {
37           int       n;
38 
39           if ( *a == NULL ) {
40                     *a = (char **) LDAP_MALLOC( 2 * sizeof(char *) );
41                     n = 0;
42 
43                     if( *a == NULL ) {
44                               return -1;
45                     }
46 
47           } else {
48                     char **new;
49 
50                     for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
51                               ;         /* NULL */
52                     }
53 
54                     new = (char **) LDAP_REALLOC( (char *) *a,
55                         (n + 2) * sizeof(char *) );
56 
57                     if( new == NULL ) {
58                               /* caller is required to call ldap_charray_free(*a) */
59                               return -1;
60                     }
61 
62                     *a = new;
63           }
64 
65           (*a)[n] = LDAP_STRDUP(s);
66 
67           if( (*a)[n] == NULL ) {
68                     return 1;
69           }
70 
71           (*a)[++n] = NULL;
72 
73           return 0;
74 }
75 
76 int
ldap_charray_merge(char *** a,char ** s)77 ldap_charray_merge(
78     char  ***a,
79     char  **s
80 )
81 {
82           int       i, n, nn;
83           char **aa;
84 
85           for ( n = 0; *a != NULL && (*a)[n] != NULL; n++ ) {
86                     ;         /* NULL */
87           }
88           for ( nn = 0; s[nn] != NULL; nn++ ) {
89                     ;         /* NULL */
90           }
91 
92           aa = (char **) LDAP_REALLOC( (char *) *a, (n + nn + 1) * sizeof(char *) );
93 
94           if( aa == NULL ) {
95                     return -1;
96           }
97 
98           *a = aa;
99 
100           for ( i = 0; i < nn; i++ ) {
101                     (*a)[n + i] = LDAP_STRDUP(s[i]);
102 
103                     if( (*a)[n + i] == NULL ) {
104                               for( --i ; i >= 0 ; i-- ) {
105                                         LDAP_FREE( (*a)[n + i] );
106                                         (*a)[n + i] = NULL;
107                               }
108                               return -1;
109                     }
110           }
111 
112           (*a)[n + nn] = NULL;
113           return 0;
114 }
115 
116 void
ldap_charray_free(char ** a)117 ldap_charray_free( char **a )
118 {
119           char      **p;
120 
121           if ( a == NULL ) {
122                     return;
123           }
124 
125           for ( p = a; *p != NULL; p++ ) {
126                     if ( *p != NULL ) {
127                               LDAP_FREE( *p );
128                     }
129           }
130 
131           LDAP_FREE( (char *) a );
132 }
133 
134 int
ldap_charray_inlist(char ** a,const char * s)135 ldap_charray_inlist(
136     char  **a,
137     const char *s
138 )
139 {
140           int       i;
141 
142           if( a == NULL ) return 0;
143 
144           for ( i=0; a[i] != NULL; i++ ) {
145                     if ( strcasecmp( s, a[i] ) == 0 ) {
146                               return 1;
147                     }
148           }
149 
150           return 0;
151 }
152 
153 char **
ldap_charray_dup(char ** a)154 ldap_charray_dup( char **a )
155 {
156           int       i;
157           char      **new;
158 
159           for ( i = 0; a[i] != NULL; i++ )
160                     ;         /* NULL */
161 
162           new = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
163 
164           if( new == NULL ) {
165                     return NULL;
166           }
167 
168           for ( i = 0; a[i] != NULL; i++ ) {
169                     new[i] = LDAP_STRDUP( a[i] );
170 
171                     if( new[i] == NULL ) {
172                               for( --i ; i >= 0 ; i-- ) {
173                                         LDAP_FREE( new[i] );
174                               }
175                               LDAP_FREE( new );
176                               return NULL;
177                     }
178           }
179           new[i] = NULL;
180 
181           return( new );
182 }
183 
184 char **
ldap_str2charray(const char * str_in,const char * brkstr)185 ldap_str2charray( const char *str_in, const char *brkstr )
186 {
187           char      **res;
188           char      *str, *s;
189           char      *lasts;
190           int       i;
191 
192           /* protect the input string from strtok */
193           str = LDAP_STRDUP( str_in );
194           if( str == NULL ) {
195                     return NULL;
196           }
197 
198           i = 1;
199           for ( s = str; ; LDAP_UTF8_INCR(s) ) {
200                     s = ldap_utf8_strpbrk( s, brkstr );
201                     if ( !s ) break;
202                     i++;
203           }
204 
205           res = (char **) LDAP_MALLOC( (i + 1) * sizeof(char *) );
206 
207           if( res == NULL ) {
208                     LDAP_FREE( str );
209                     return NULL;
210           }
211 
212           i = 0;
213 
214           for ( s = ldap_utf8_strtok( str, brkstr, &lasts );
215                     s != NULL;
216                     s = ldap_utf8_strtok( NULL, brkstr, &lasts ) )
217           {
218                     res[i] = LDAP_STRDUP( s );
219 
220                     if(res[i] == NULL) {
221                               for( --i ; i >= 0 ; i-- ) {
222                                         LDAP_FREE( res[i] );
223                               }
224                               LDAP_FREE( res );
225                               LDAP_FREE( str );
226                               return NULL;
227                     }
228 
229                     i++;
230           }
231 
232           res[i] = NULL;
233 
234           LDAP_FREE( str );
235           return( res );
236 }
237 
ldap_charray2str(char ** a,const char * sep)238 char * ldap_charray2str( char **a, const char *sep )
239 {
240           char *s, **v, *p;
241           int len;
242           int slen;
243 
244           if( sep == NULL ) sep = " ";
245 
246           slen = strlen( sep );
247           len = 0;
248 
249           for ( v = a; *v != NULL; v++ ) {
250                     len += strlen( *v ) + slen;
251           }
252 
253           if ( len == 0 ) {
254                     return NULL;
255           }
256 
257           /* trim extra sep len */
258           len -= slen;
259 
260           s = LDAP_MALLOC ( len + 1 );
261 
262           if ( s == NULL ) {
263                     return NULL;
264           }
265 
266           p = s;
267           for ( v = a; *v != NULL; v++ ) {
268                     if ( v != a ) {
269                               strncpy( p, sep, slen );
270                               p += slen;
271                     }
272 
273                     len = strlen( *v );
274                     strncpy( p, *v, len );
275                     p += len;
276           }
277 
278           *p = '\0';
279           return s;
280 }
281