r4524: converted a few bits of samr.idl to use enum properly
[samba.git] / source4 / lib / util_strlist.c
1 /* 
2    Unix SMB/CIFS implementation.
3    
4    Copyright (C) Andrew Tridgell 1992-2004
5    Copyright (C) Simo Sorce      2001-2002
6    Copyright (C) Martin Pool     2003
7    
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 2 of the License, or
11    (at your option) any later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "includes.h"
24 #include "system/network.h"
25
26 /**
27  List of Strings manipulation functions
28 **/
29
30 #define S_LIST_ABS 16 /* List Allocation Block Size */
31
32 char **str_list_make(const char *string, const char *sep)
33 {
34         char **list, **rlist;
35         const char *str;
36         char *s;
37         int num, lsize;
38         pstring tok;
39         
40         if (!string || !*string)
41                 return NULL;
42         s = strdup(string);
43         if (!s) {
44                 DEBUG(0,("str_list_make: Unable to allocate memory"));
45                 return NULL;
46         }
47         if (!sep) sep = LIST_SEP;
48         
49         num = lsize = 0;
50         list = NULL;
51         
52         str = s;
53         while (next_token(&str, tok, sep, sizeof(tok))) {               
54                 if (num == lsize) {
55                         lsize += S_LIST_ABS;
56                         rlist = realloc_p(list, char *, lsize + 1);
57                         if (!rlist) {
58                                 DEBUG(0,("str_list_make: Unable to allocate memory"));
59                                 str_list_free(&list);
60                                 SAFE_FREE(s);
61                                 return NULL;
62                         } else
63                                 list = rlist;
64                         memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
65                 }
66                 
67                 list[num] = strdup(tok);
68                 if (!list[num]) {
69                         DEBUG(0,("str_list_make: Unable to allocate memory"));
70                         str_list_free(&list);
71                         SAFE_FREE(s);
72                         return NULL;
73                 }
74         
75                 num++;  
76         }
77         
78         SAFE_FREE(s);
79         return list;
80 }
81
82 BOOL str_list_copy(char ***dest, const char **src)
83 {
84         char **list, **rlist;
85         int num, lsize;
86         
87         *dest = NULL;
88         if (!src)
89                 return False;
90         
91         num = lsize = 0;
92         list = NULL;
93                 
94         while (src[num]) {
95                 if (num == lsize) {
96                         lsize += S_LIST_ABS;
97                         rlist = realloc_p(list, char *, lsize + 1);
98                         if (!rlist) {
99                                 DEBUG(0,("str_list_copy: Unable to re-allocate memory"));
100                                 str_list_free(&list);
101                                 return False;
102                         } else
103                                 list = rlist;
104                         memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
105                 }
106                 
107                 list[num] = strdup(src[num]);
108                 if (!list[num]) {
109                         DEBUG(0,("str_list_copy: Unable to allocate memory"));
110                         str_list_free(&list);
111                         return False;
112                 }
113
114                 num++;
115         }
116         
117         *dest = list;
118         return True;    
119 }
120
121 /**
122    Return true if all the elements of the list match exactly.
123  **/
124 BOOL str_list_compare(char **list1, char **list2)
125 {
126         int num;
127         
128         if (!list1 || !list2)
129                 return (list1 == list2); 
130         
131         for (num = 0; list1[num]; num++) {
132                 if (!list2[num])
133                         return False;
134                 if (!strcsequal(list1[num], list2[num]))
135                         return False;
136         }
137         if (list2[num])
138                 return False; /* if list2 has more elements than list1 fail */
139         
140         return True;
141 }
142
143 void str_list_free(char ***list)
144 {
145         char **tlist;
146         
147         if (!list || !*list)
148                 return;
149         tlist = *list;
150         for(; *tlist; tlist++)
151                 SAFE_FREE(*tlist);
152         SAFE_FREE(*list);
153 }
154
155 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
156 {
157         char *p, *s, *t;
158         ssize_t ls, lp, li, ld, i, d;
159
160         if (!list)
161                 return False;
162         if (!pattern)
163                 return False;
164         if (!insert)
165                 return False;
166
167         lp = (ssize_t)strlen(pattern);
168         li = (ssize_t)strlen(insert);
169         ld = li -lp;
170                         
171         while (*list) {
172                 s = *list;
173                 ls = (ssize_t)strlen(s);
174
175                 while ((p = strstr(s, pattern))) {
176                         t = *list;
177                         d = p -t;
178                         if (ld) {
179                                 t = (char *) malloc(ls +ld +1);
180                                 if (!t) {
181                                         DEBUG(0,("str_list_substitute: Unable to allocate memory"));
182                                         return False;
183                                 }
184                                 memcpy(t, *list, d);
185                                 memcpy(t +d +li, p +lp, ls -d -lp +1);
186                                 SAFE_FREE(*list);
187                                 *list = t;
188                                 ls += ld;
189                                 s = t +d +li;
190                         }
191                         
192                         for (i = 0; i < li; i++) {
193                                 switch (insert[i]) {
194                                         case '`':
195                                         case '"':
196                                         case '\'':
197                                         case ';':
198                                         case '$':
199                                         case '%':
200                                         case '\r':
201                                         case '\n':
202                                                 t[d +i] = '_';
203                                                 break;
204                                         default:
205                                                 t[d +i] = insert[i];
206                                 }
207                         }       
208                 }
209                 
210                 list++;
211         }
212         
213         return True;
214 }
215
216
217 #define IPSTR_LIST_SEP  ","
218
219 /**
220  * Add ip string representation to ipstr list. Used also
221  * as part of @function ipstr_list_make
222  *
223  * @param ipstr_list pointer to string containing ip list;
224  *        MUST BE already allocated and IS reallocated if necessary
225  * @param ipstr_size pointer to current size of ipstr_list (might be changed
226  *        as a result of reallocation)
227  * @param ip IP address which is to be added to list
228  * @return pointer to string appended with new ip and possibly
229  *         reallocated to new length
230  **/
231
232 char* ipstr_list_add(char** ipstr_list, const struct ipv4_addr *ip)
233 {
234         char* new_ipstr = NULL;
235         
236         /* arguments checking */
237         if (!ipstr_list || !ip) return NULL;
238
239         /* attempt to convert ip to a string and append colon separator to it */
240         if (*ipstr_list) {
241                 asprintf(&new_ipstr, "%s%s%s", *ipstr_list, IPSTR_LIST_SEP,sys_inet_ntoa(*ip));
242                 SAFE_FREE(*ipstr_list);
243         } else {
244                 asprintf(&new_ipstr, "%s", sys_inet_ntoa(*ip));
245         }
246         *ipstr_list = new_ipstr;
247         return *ipstr_list;
248 }
249
250 /**
251  * Allocate and initialise an ipstr list using ip adresses
252  * passed as arguments.
253  *
254  * @param ipstr_list pointer to string meant to be allocated and set
255  * @param ip_list array of ip addresses to place in the list
256  * @param ip_count number of addresses stored in ip_list
257  * @return pointer to allocated ip string
258  **/
259  
260 char* ipstr_list_make(char** ipstr_list, const struct ipv4_addr* ip_list, int ip_count)
261 {
262         int i;
263         
264         /* arguments checking */
265         if (!ip_list && !ipstr_list) return 0;
266
267         *ipstr_list = NULL;
268         
269         /* process ip addresses given as arguments */
270         for (i = 0; i < ip_count; i++)
271                 *ipstr_list = ipstr_list_add(ipstr_list, &ip_list[i]);
272         
273         return (*ipstr_list);
274 }
275
276
277 /**
278  * Parse given ip string list into array of ip addresses
279  * (as in_addr structures)
280  *
281  * @param ipstr ip string list to be parsed 
282  * @param ip_list pointer to array of ip addresses which is
283  *        allocated by this function and must be freed by caller
284  * @return number of succesfully parsed addresses
285  **/
286  
287 int ipstr_list_parse(const char* ipstr_list, struct ipv4_addr** ip_list)
288 {
289         fstring token_str;
290         int count;
291
292         if (!ipstr_list || !ip_list) return 0;
293         
294         for (*ip_list = NULL, count = 0;
295              next_token(&ipstr_list, token_str, IPSTR_LIST_SEP, FSTRING_LEN);
296              count++) {
297              
298                 struct ipv4_addr addr;
299
300                 /* convert single token to ip address */
301                 if ( (addr.addr = sys_inet_addr(token_str)) == INADDR_NONE )
302                         break;
303                 
304                 /* prepare place for another in_addr structure */
305                 *ip_list = realloc_p(*ip_list, struct ipv4_addr, count + 1);
306                 if (!*ip_list) return -1;
307                 
308                 (*ip_list)[count] = addr;
309         }
310         
311         return count;
312 }
313
314
315 /**
316  * Safely free ip string list
317  *
318  * @param ipstr_list ip string list to be freed
319  **/
320
321 void ipstr_list_free(char* ipstr_list)
322 {
323         SAFE_FREE(ipstr_list);
324 }