2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Andrew Tridgell 1992-2001
5 Copyright (C) Simo Sorce 2001-2002
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /****************************************************************************
25 Get the next token from a string, return False if none found
26 handles double-quotes.
27 Based on a routine by GJC@VILLAGE.COM.
28 Extensively modified by Andrew.Tridgell@anu.edu.au
29 ****************************************************************************/
30 BOOL next_token(char **ptr,char *buff,char *sep, size_t bufsize)
36 if (!ptr) return(False);
40 /* default to simple separators */
41 if (!sep) sep = " \t\n\r";
43 /* find the first non sep char */
44 while (*s && strchr_m(sep,*s)) s++;
47 if (! *s) return(False);
49 /* copy over the token */
50 for (quoted = False; len < bufsize && *s && (quoted || !strchr_m(sep,*s)); s++) {
59 *ptr = (*s) ? s+1 : s;
67 /****************************************************************************
68 This is like next_token but is not re-entrant and "remembers" the first
69 parameter so you can pass NULL. This is useful for user interface code
70 but beware the fact that it is not re-entrant!
71 ****************************************************************************/
72 static char *last_ptr=NULL;
74 BOOL next_token_nr(char **ptr,char *buff,char *sep, size_t bufsize)
77 if (!ptr) ptr = &last_ptr;
79 ret = next_token(ptr, buff, sep, bufsize);
84 static uint16 tmpbuf[sizeof(pstring)];
86 void set_first_token(char *ptr)
92 /****************************************************************************
93 Convert list of tokens to array; dependent on above routine.
94 Uses last_ptr from above - bit of a hack.
95 ****************************************************************************/
96 char **toktocliplist(int *ctok, char *sep)
102 if (!sep) sep = " \t\n\r";
104 while(*s && strchr_m(sep,*s)) s++;
107 if (!*s) return(NULL);
111 while(*s && (!strchr_m(sep,*s))) s++;
112 while(*s && strchr_m(sep,*s)) *s++=0;
118 if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
129 /*******************************************************************
130 case insensitive string compararison
131 ********************************************************************/
132 int StrCaseCmp(const char *s, const char *t)
135 unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
136 unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
137 return strcmp(buf1,buf2);
140 /*******************************************************************
141 case insensitive string compararison, length limited
142 ********************************************************************/
143 int StrnCaseCmp(const char *s, const char *t, size_t n)
146 unix_strupper(s, strlen(s)+1, buf1, sizeof(buf1));
147 unix_strupper(t, strlen(t)+1, buf2, sizeof(buf2));
148 return strncmp(buf1,buf2,n);
151 /*******************************************************************
153 ********************************************************************/
154 BOOL strequal(const char *s1, const char *s2)
156 if (s1 == s2) return(True);
157 if (!s1 || !s2) return(False);
159 return(StrCaseCmp(s1,s2)==0);
162 /*******************************************************************
163 compare 2 strings up to and including the nth char.
164 ******************************************************************/
165 BOOL strnequal(const char *s1,const char *s2,size_t n)
167 if (s1 == s2) return(True);
168 if (!s1 || !s2 || !n) return(False);
170 return(StrnCaseCmp(s1,s2,n)==0);
173 /*******************************************************************
174 compare 2 strings (case sensitive)
175 ********************************************************************/
176 BOOL strcsequal(const char *s1,const char *s2)
178 if (s1 == s2) return(True);
179 if (!s1 || !s2) return(False);
181 return(strcmp(s1,s2)==0);
184 /***************************************************************************
185 Do a case-insensitive, whitespace-ignoring string compare.
186 ***************************************************************************/
187 int strwicmp(const char *psz1, const char *psz2)
189 /* if BOTH strings are NULL, return TRUE, if ONE is NULL return */
190 /* appropriate value. */
193 else if (psz1 == NULL)
195 else if (psz2 == NULL)
198 /* sync the strings on first non-whitespace */
201 while (isspace((int)*psz1))
203 while (isspace((int)*psz2))
205 if (toupper(*psz1) != toupper(*psz2) || *psz1 == '\0'
211 return (*psz1 - *psz2);
215 /* Convert a string to upper case, but don't modify it */
217 char *strupper_static(char *s)
227 /*******************************************************************
228 convert a string to "normal" form
229 ********************************************************************/
230 void strnorm(char *s)
232 extern int case_default;
233 if (case_default == CASE_UPPER)
239 /*******************************************************************
240 check if a string is in "normal" case
241 ********************************************************************/
242 BOOL strisnormal(char *s)
244 extern int case_default;
245 if (case_default == CASE_UPPER)
246 return(!strhaslower(s));
248 return(!strhasupper(s));
252 /****************************************************************************
254 NOTE: oldc and newc must be 7 bit characters
255 ****************************************************************************/
256 void string_replace(char *s,char oldc,char newc)
258 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
259 string_replace_w(tmpbuf, UCS2_CHAR(oldc), UCS2_CHAR(newc));
260 pull_ucs2(NULL, s, tmpbuf, -1, sizeof(tmpbuf), STR_TERMINATE);
264 /*******************************************************************
265 skip past some strings in a buffer
266 ********************************************************************/
267 char *skip_string(char *buf,size_t n)
270 buf += strlen(buf) + 1;
274 /*******************************************************************
275 Count the number of characters in a string. Normally this will
276 be the same as the number of bytes in a string for single byte strings,
277 but will be different for multibyte.
278 ********************************************************************/
279 size_t str_charnum(const char *s)
281 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
282 return strlen_w(tmpbuf);
285 /*******************************************************************
286 trim the specified elements off the front and back of a string
287 ********************************************************************/
289 BOOL trim_string(char *s,const char *front,const char *back)
296 /* Ignore null or empty strings. */
297 if (!s || (s[0] == '\0'))
300 front_len = front? strlen(front) : 0;
301 back_len = back? strlen(back) : 0;
306 while (len && strncmp(s, front, front_len)==0) {
307 memcpy(s, s+front_len, (len-front_len)+1);
314 while ((len >= back_len) && strncmp(s+len-back_len,back,back_len)==0) {
315 s[len-back_len]='\0';
324 /****************************************************************************
325 does a string have any uppercase chars in it?
326 ****************************************************************************/
327 BOOL strhasupper(const char *s)
330 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
331 for(ptr=tmpbuf;*ptr;ptr++)
332 if(isupper_w(*ptr)) return True;
336 /****************************************************************************
337 does a string have any lowercase chars in it?
338 ****************************************************************************/
339 BOOL strhaslower(const char *s)
342 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
343 for(ptr=tmpbuf;*ptr;ptr++)
344 if(islower_w(*ptr)) return True;
348 /****************************************************************************
349 find the number of 'c' chars in a string
350 ****************************************************************************/
351 size_t count_chars(const char *s,char c)
355 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
356 for(count=0,ptr=tmpbuf;*ptr;ptr++) if(*ptr==UCS2_CHAR(c)) count++;
360 /*******************************************************************
361 Return True if a string consists only of one particular character.
362 ********************************************************************/
364 BOOL str_is_all(const char *s,char c)
368 if(s == NULL) return False;
369 if(!*s) return False;
371 push_ucs2(NULL, tmpbuf,s, sizeof(tmpbuf), STR_TERMINATE);
372 for(ptr=tmpbuf;*ptr;ptr++) if(*ptr!=UCS2_CHAR(c)) return False;
377 /*******************************************************************
378 safe string copy into a known length string. maxlength does not
379 include the terminating zero.
380 ********************************************************************/
382 char *safe_strcpy(char *dest,const char *src, size_t maxlength)
387 DEBUG(0,("ERROR: NULL dest in safe_strcpy\n"));
398 if (len > maxlength) {
399 DEBUG(0,("ERROR: string overflow by %d in safe_strcpy [%.50s]\n",
400 (int)(len-maxlength), src));
404 memmove(dest, src, len);
409 /*******************************************************************
410 safe string cat into a string. maxlength does not
411 include the terminating zero.
412 ********************************************************************/
414 char *safe_strcat(char *dest, const char *src, size_t maxlength)
416 size_t src_len, dest_len;
419 DEBUG(0,("ERROR: NULL dest in safe_strcat\n"));
427 src_len = strlen(src);
428 dest_len = strlen(dest);
430 if (src_len + dest_len > maxlength) {
431 DEBUG(0,("ERROR: string overflow by %d in safe_strcat [%.50s]\n",
432 (int)(src_len + dest_len - maxlength), src));
433 src_len = maxlength - dest_len;
436 memcpy(&dest[dest_len], src, src_len);
437 dest[dest_len + src_len] = 0;
441 /*******************************************************************
442 Paranoid strcpy into a buffer of given length (includes terminating
443 zero. Strips out all but 'a-Z0-9' and the character in other_safe_chars
444 and replaces with '_'. Deliberately does *NOT* check for multibyte
445 characters. Don't change it !
446 ********************************************************************/
448 char *alpha_strcpy(char *dest, const char *src, const char *other_safe_chars, size_t maxlength)
453 DEBUG(0,("ERROR: NULL dest in alpha_strcpy\n"));
463 if (len >= maxlength)
466 if (!other_safe_chars)
467 other_safe_chars = "";
469 for(i = 0; i < len; i++) {
470 int val = (src[i] & 0xff);
471 if(isupper(val) || islower(val) || isdigit(val) || strchr_m(other_safe_chars, val))
482 /****************************************************************************
483 Like strncpy but always null terminates. Make sure there is room!
484 The variable n should always be one less than the available size.
485 ****************************************************************************/
487 char *StrnCpy(char *dest,const char *src,size_t n)
490 if (!dest) return(NULL);
495 while (n-- && (*d++ = *src++)) ;
500 /****************************************************************************
501 like strncpy but copies up to the character marker. always null terminates.
502 returns a pointer to the character marker in the source string (src).
503 ****************************************************************************/
504 char *strncpyn(char *dest, const char *src,size_t n, char c)
509 p = strchr_m(src, c);
512 DEBUG(5, ("strncpyn: separator character (%c) not found\n", c));
516 str_len = PTR_DIFF(p, src);
517 strncpy(dest, src, MIN(n, str_len));
518 dest[str_len] = '\0';
524 /*************************************************************
525 Routine to get hex characters and turn them into a 16 byte array.
526 the array can be variable length, and any non-hex-numeric
527 characters are skipped. "0xnn" or "0Xnn" is specially catered
530 valid examples: "0A5D15"; "0x15, 0x49, 0xa2"; "59\ta9\te3\n"
532 **************************************************************/
533 size_t strhex_to_str(char *p, size_t len, const char *strhex)
536 size_t num_chars = 0;
537 unsigned char lonybble, hinybble;
538 char *hexchars = "0123456789ABCDEF";
539 char *p1 = NULL, *p2 = NULL;
541 for (i = 0; i < len && strhex[i] != 0; i++)
543 if (strnequal(hexchars, "0x", 2))
545 i++; /* skip two chars */
549 if (!(p1 = strchr_m(hexchars, toupper(strhex[i]))))
554 i++; /* next hex digit */
556 if (!(p2 = strchr_m(hexchars, toupper(strhex[i]))))
561 /* get the two nybbles */
562 hinybble = PTR_DIFF(p1, hexchars);
563 lonybble = PTR_DIFF(p2, hexchars);
565 p[num_chars] = (hinybble << 4) | lonybble;
574 /****************************************************************************
575 check if a string is part of a list
576 ****************************************************************************/
577 BOOL in_list(char *s,char *list,BOOL casesensitive)
582 if (!list) return(False);
584 while (next_token(&p,tok,LIST_SEP,sizeof(tok))) {
586 if (strcmp(tok,s) == 0)
589 if (StrCaseCmp(tok,s) == 0)
596 /* this is used to prevent lots of mallocs of size 1 */
597 static char *null_string = NULL;
599 /****************************************************************************
600 set a string value, allocing the space for the string
601 ****************************************************************************/
602 static BOOL string_init(char **dest,const char *src)
613 if((null_string = (char *)malloc(1)) == NULL) {
614 DEBUG(0,("string_init: malloc fail for null_string.\n"));
623 (*dest) = (char *)malloc(l+1);
624 if ((*dest) == NULL) {
625 DEBUG(0,("Out of memory in string_init\n"));
634 /****************************************************************************
636 ****************************************************************************/
637 void string_free(char **s)
639 if (!s || !(*s)) return;
640 if (*s == null_string)
645 /****************************************************************************
646 set a string value, allocing the space for the string, and deallocating any
648 ****************************************************************************/
649 BOOL string_set(char **dest,const char *src)
653 return(string_init(dest,src));
657 /****************************************************************************
658 substitute a string for a pattern in another string. Make sure there is
661 This routine looks for pattern in s and replaces it with
662 insert. It may do multiple replacements.
664 any of " ; ' $ or ` in the insert string are replaced with _
665 if len==0 then the string cannot be extended. This is different from the old
666 use of len==0 which was for no length checks to be done.
667 ****************************************************************************/
669 void string_sub(char *s,const char *pattern, const char *insert, size_t len)
674 if (!insert || !pattern || !*pattern || !s)
677 ls = (ssize_t)strlen(s);
678 lp = (ssize_t)strlen(pattern);
679 li = (ssize_t)strlen(insert);
682 len = ls + 1; /* len is number of *bytes* */
684 while (lp <= ls && (p = strstr(s,pattern))) {
685 if (ls + (li-lp) >= len) {
686 DEBUG(0,("ERROR: string overflow by %d in string_sub(%.50s, %d)\n",
687 (int)(ls + (li-lp) - len),
692 memmove(p+li,p+lp,strlen(p+lp)+1);
715 void fstring_sub(char *s,const char *pattern,const char *insert)
717 string_sub(s, pattern, insert, sizeof(fstring));
720 void pstring_sub(char *s,const char *pattern,const char *insert)
722 string_sub(s, pattern, insert, sizeof(pstring));
725 /* similar to string_sub, but it will accept only allocated strings
726 * and may realloc them so pay attention at what you pass on no
727 * pointers inside strings, no pstrings or const must be passed
731 char *realloc_string_sub(char *string, const char *pattern, const char *insert)
735 ssize_t ls,lp,li,ld, i;
737 if (!insert || !pattern || !*pattern || !string || !*string)
744 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
747 ls = (ssize_t)strlen(s);
748 lp = (ssize_t)strlen(pattern);
749 li = (ssize_t)strlen(insert);
768 while ((p = strstr(s,pattern))) {
770 char *t = Realloc(string, ls + ld + 1);
772 DEBUG(0, ("realloc_string_sub: out of memory!\n"));
780 memmove(p+li,p+lp,strlen(p+lp)+1);
790 /****************************************************************************
791 similar to string_sub() but allows for any character to be substituted.
793 if len==0 then the string cannot be extended. This is different from the old
794 use of len==0 which was for no length checks to be done.
795 ****************************************************************************/
797 void all_string_sub(char *s,const char *pattern,const char *insert, size_t len)
802 if (!insert || !pattern || !s)
805 ls = (ssize_t)strlen(s);
806 lp = (ssize_t)strlen(pattern);
807 li = (ssize_t)strlen(insert);
813 len = ls + 1; /* len is number of *bytes* */
815 while (lp <= ls && (p = strstr(s,pattern))) {
816 if (ls + (li-lp) >= len) {
817 DEBUG(0,("ERROR: string overflow by %d in all_string_sub(%.50s, %d)\n",
818 (int)(ls + (li-lp) - len),
823 memmove(p+li,p+lp,strlen(p+lp)+1);
825 memcpy(p, insert, li);
831 /****************************************************************************
832 similar to all_string_sub but for unicode strings.
833 return a new allocate unicode string.
834 similar to string_sub() but allows for any character to be substituted.
836 ****************************************************************************/
838 smb_ucs2_t *all_string_sub_w(const smb_ucs2_t *s, const smb_ucs2_t *pattern,
839 const smb_ucs2_t *insert)
842 const smb_ucs2_t *sp;
843 size_t lr, lp, li, lt;
845 if (!insert || !pattern || !*pattern || !s) return NULL;
847 lt = (size_t)strlen_w(s);
848 lp = (size_t)strlen_w(pattern);
849 li = (size_t)strlen_w(insert);
852 const smb_ucs2_t *st = s;
854 while ((sp = strstr_w(st, pattern))) {
860 r = rp = (smb_ucs2_t *)malloc((lt + 1)*(sizeof(smb_ucs2_t)));
862 DEBUG(0, ("all_string_sub_w: out of memory!\n"));
866 while ((sp = strstr_w(s, pattern))) {
867 memcpy(rp, s, (sp - s));
868 rp += ((sp - s) / sizeof(smb_ucs2_t));
869 memcpy(rp, insert, (li * sizeof(smb_ucs2_t)));
873 lr = ((rp - r) / sizeof(smb_ucs2_t));
875 memcpy(rp, s, ((lt - lr) * sizeof(smb_ucs2_t)));
883 smb_ucs2_t *all_string_sub_wa(smb_ucs2_t *s, const char *pattern,
888 if (!insert || !pattern || !s) return NULL;
889 push_ucs2(NULL, p, pattern, sizeof(wpstring) - 1, STR_TERMINATE);
890 push_ucs2(NULL, i, insert, sizeof(wpstring) - 1, STR_TERMINATE);
891 return all_string_sub_w(s, p, i);
894 /****************************************************************************
895 Splits out the front and back at a separator.
896 ****************************************************************************/
898 void split_at_last_component(char *path, char *front, char sep, char *back)
900 char *p = strrchr_m(path, sep);
906 pstrcpy(front, path);
918 /****************************************************************************
919 Write an octal as a string.
920 ****************************************************************************/
922 char *octal_string(int i)
927 slprintf(ret, sizeof(ret)-1, "0%o", i);
932 /****************************************************************************
933 Truncate a string at a specified length.
934 ****************************************************************************/
936 char *string_truncate(char *s, int length)
938 if (s && strlen(s) > length)
943 /****************************************************************************
944 Strchr and strrchr_m are very hard to do on general multi-byte strings.
945 We convert via ucs2 for now.
946 ****************************************************************************/
948 char *strchr_m(const char *s, char c)
954 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
955 p = strchr_w(ws, UCS2_CHAR(c));
959 pull_ucs2_pstring(s2, ws);
960 return (char *)(s+strlen(s2));
963 char *strrchr_m(const char *s, char c)
969 push_ucs2(NULL, ws, s, sizeof(ws), STR_TERMINATE);
970 p = strrchr_w(ws, UCS2_CHAR(c));
974 pull_ucs2_pstring(s2, ws);
975 return (char *)(s+strlen(s2));
978 /*******************************************************************
979 Convert a string to lower case.
980 ********************************************************************/
982 void strlower_m(char *s)
984 /* this is quite a common operation, so we want it to be
985 fast. We optimise for the ascii case, knowing that all our
986 supported multi-byte character sets are ascii-compatible
987 (ie. they match for the first 128 chars) */
989 while (*s && !(((unsigned char)s[0]) & 0x7F))
990 *s++ = tolower((unsigned char)*s);
995 /* I assume that lowercased string takes the same number of bytes
996 * as source string even in UTF-8 encoding. (VIV) */
997 unix_strlower(s,strlen(s)+1,s,strlen(s)+1);
1000 /*******************************************************************
1001 Duplicate convert a string to lower case.
1002 ********************************************************************/
1004 char *strdup_lower(const char *s)
1006 char *t = strdup(s);
1008 DEBUG(0, ("strdup_lower: Out of memory!\n"));
1015 /*******************************************************************
1016 Convert a string to upper case.
1017 ********************************************************************/
1019 void strupper_m(char *s)
1021 /* this is quite a common operation, so we want it to be
1022 fast. We optimise for the ascii case, knowing that all our
1023 supported multi-byte character sets are ascii-compatible
1024 (ie. they match for the first 128 chars) */
1026 while (*s && !(((unsigned char)s[0]) & 0x7F))
1027 *s++ = toupper((unsigned char)*s);
1032 /* I assume that lowercased string takes the same number of bytes
1033 * as source string even in multibyte encoding. (VIV) */
1034 unix_strupper(s,strlen(s)+1,s,strlen(s)+1);
1037 /*******************************************************************
1038 Convert a string to upper case.
1039 ********************************************************************/
1041 char *strdup_upper(const char *s)
1043 char *t = strdup(s);
1045 DEBUG(0, ("strdup_upper: Out of memory!\n"));
1053 return a RFC2254 binary string representation of a buffer
1054 used in LDAP filters
1057 char *binary_string(char *buf, int len)
1061 const char *hex = "0123456789ABCDEF";
1062 s = malloc(len * 3 + 1);
1065 for (j=i=0;i<len;i++) {
1067 s[j+1] = hex[((unsigned char)buf[i]) >> 4];
1068 s[j+2] = hex[((unsigned char)buf[i]) & 0xF];
1075 /* Just a typesafety wrapper for snprintf into a pstring */
1077 int pstr_sprintf(pstring s, const char *fmt, ...)
1083 ret = vsnprintf(s, PSTRING_LEN, fmt, ap);
1088 /* Just a typesafety wrapper for snprintf into a fstring */
1090 int fstr_sprintf(fstring s, const char *fmt, ...)
1096 ret = vsnprintf(s, FSTRING_LEN, fmt, ap);
1101 #ifndef HAVE_STRNDUP
1102 /*******************************************************************
1103 Some platforms don't have strndup.
1104 ********************************************************************/
1106 char *strndup(const char *s, size_t n)
1121 #ifndef HAVE_STRNLEN
1122 /*******************************************************************
1123 some platforms don't have strnlen
1124 ********************************************************************/
1125 size_t strnlen(const char *s, size_t n)
1128 for (i=0; s[i] && i<n; i++)
1134 /***********************************************************
1135 List of Strings manipulation functions
1136 ***********************************************************/
1138 #define S_LIST_ABS 16 /* List Allocation Block Size */
1140 char **str_list_make(const char *string, const char *sep)
1142 char **list, **rlist;
1147 if (!string || !*string)
1151 DEBUG(0,("str_list_make: Unable to allocate memory"));
1154 if (!sep) sep = LIST_SEP;
1160 while (next_token(&str, tok, sep, sizeof(tok))) {
1162 lsize += S_LIST_ABS;
1163 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1165 DEBUG(0,("str_list_make: Unable to allocate memory"));
1166 str_list_free(&list);
1171 memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
1174 list[num] = strdup(tok);
1176 DEBUG(0,("str_list_make: Unable to allocate memory"));
1177 str_list_free(&list);
1189 BOOL str_list_copy(char ***dest, char **src)
1191 char **list, **rlist;
1203 lsize += S_LIST_ABS;
1204 rlist = (char **)Realloc(list, ((sizeof(char **)) * (lsize +1)));
1206 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1207 str_list_free(&list);
1211 memset (&list[num], 0, ((sizeof(char **)) * (S_LIST_ABS +1)));
1214 list[num] = strdup(src[num]);
1216 DEBUG(0,("str_list_copy: Unable to allocate memory"));
1217 str_list_free(&list);
1228 /* return true if all the elemnts of the list matches exactly */
1230 BOOL str_list_compare(char **list1, char **list2)
1234 if (!list1 || !list2)
1235 return (list1 == list2);
1237 for (num = 0; list1[num]; num++) {
1240 if (!strcsequal(list1[num], list2[num]))
1244 return False; /* if list2 has more elements than list1 fail */
1249 void str_list_free(char ***list)
1253 if (!list || !*list)
1256 for(; *tlist; tlist++)
1261 BOOL str_list_substitute(char **list, const char *pattern, const char *insert)
1264 ssize_t ls, lp, li, ld, i, d;
1273 lp = (ssize_t)strlen(pattern);
1274 li = (ssize_t)strlen(insert);
1279 ls = (ssize_t)strlen(s);
1281 while ((p = strstr(s, pattern))) {
1285 t = (char *) malloc(ls +ld +1);
1287 DEBUG(0,("str_list_substitute: Unable to allocate memory"));
1290 memcpy(t, *list, d);
1291 memcpy(t +d +li, p +lp, ls -d -lp +1);
1298 for (i = 0; i < li; i++) {
1299 switch (insert[i]) {
1311 t[d +i] = insert[i];